Re: [PATCH v2 5/5] PCI: qcom: Add support for configuring BDF to SID mapping for SM8250

2020-09-30 Thread Manivannan Sadhasivam
Hi Stan,

On Thu, Oct 01, 2020 at 12:46:46AM +0300, Stanimir Varbanov wrote:
> Hi Mani,
> 
> On 9/30/20 6:09 PM, Manivannan Sadhasivam wrote:
> > For SM8250, we need to write the BDF to SID mapping in PCIe controller
> > register space for proper working. This is accomplished by extracting
> > the BDF and SID values from "iommu-map" property in DT and writing those
> > in the register address calculated from the hash value of BDF. In case
> > of collisions, the index of the next entry will also be written.
> 
> This describes what the patch is doing. But why? Is that done in the
> other DWC low-level drivers or this is qcom specialty?
> 

AFAIK, only some NXP SoCs deal with similar kind of mapping but right now
this is a Qcom only stuff.

> > 
> > For the sake of it, let's introduce a "config_sid" callback and do it
> > conditionally for SM8250.
> > 
> > Signed-off-by: Manivannan Sadhasivam 
> > ---
> >  drivers/pci/controller/dwc/Kconfig |   1 +
> >  drivers/pci/controller/dwc/pcie-qcom.c | 138 +
> >  2 files changed, 139 insertions(+)
> > 

[...]

> > +
> > +/* sid info structure */
> > +struct qcom_pcie_sid_info_t {
> 
> why _t postfix? Maybe qcom_pcie_sid ?
> 

Just to differentiate the struct name and its variable. But I can
remove the _t suffix.

> SID - Stream ID ?
> 

Yes! Will expand in commit message also.

> > +   u16 bdf;
> > +   u8 pcie_sid;
> > +   u8 hash;
> > +   u32 smmu_sid;
> > +   u32 value;
> >  };
> >  
> >  struct qcom_pcie {
> > @@ -193,6 +208,8 @@ struct qcom_pcie {
> > struct phy *phy;
> > struct gpio_desc *reset;
> > const struct qcom_pcie_ops *ops;
> > +   struct qcom_pcie_sid_info_t *sid_info;
> > +   u32 sid_info_len;
> > int gen;
> >  };
> >  
> > @@ -1257,6 +1274,120 @@ static int qcom_pcie_link_up(struct dw_pcie *pci)
> > return !!(val & PCI_EXP_LNKSTA_DLLLA);
> >  }
> >  
> > +static int qcom_pcie_get_iommu_map(struct qcom_pcie *pcie)
> > +{
> > +   /* iommu map structure */
> > +   struct {
> > +   u32 bdf;
> > +   u32 phandle;
> > +   u32 smmu_sid;
> > +   u32 smmu_sid_len;
> > +   } *map;
> > +   struct device *dev = pcie->pci->dev;
> > +   int i, size = 0;
> > +   u32 smmu_sid_base;
> > +
> > +   of_get_property(dev->of_node, "iommu-map", );
> > +   if (!size)
> > +   return 0;
> > +
> > +   map = kzalloc(size, GFP_KERNEL);
> > +   if (!map)
> > +   return -ENOMEM;
> > +
> > +   of_property_read_u32_array(dev->of_node,
> > +   "iommu-map", (u32 *)map, size / sizeof(u32));
> 
> iommu-map is a standard DT property why we have to parse it manually?
> 

So right now we don't have a way to pass this information from DT. And there
is no IOMMU API to parse the fields also. We need to extract this information
to program the hash tables (BDF, SID) as the mapping between BDF and SID is not
1:1 in SM8250.

Perhaps I can add this information in commit message.

> > +
> > +   pcie->sid_info_len = size / (sizeof(*map));
> > +   pcie->sid_info = devm_kcalloc(dev, pcie->sid_info_len,
> > +   sizeof(*pcie->sid_info), GFP_KERNEL);
> > +   if (!pcie->sid_info) {
> > +   kfree(map);
> > +   return -ENOMEM;
> > +   }
> > +
> > +   /* Extract the SMMU SID base from the first entry of iommu-map */
> > +   smmu_sid_base = map[0].smmu_sid;
> > +   for (i = 0; i < pcie->sid_info_len; i++) {
> > +   pcie->sid_info[i].bdf = map[i].bdf;
> > +   pcie->sid_info[i].smmu_sid = map[i].smmu_sid;
> > +   pcie->sid_info[i].pcie_sid =
> > +   pcie->sid_info[i].smmu_sid - smmu_sid_base;
> > +   }
> > +
> > +   kfree(map);
> > +
> > +   return 0;
> > +}
> > +
> > +static int qcom_pcie_config_sid_sm8250(struct qcom_pcie *pcie)
> > +{
> > +   void __iomem *bdf_to_sid_base = pcie->parf +
> > +   PCIE20_PARF_BDF_TO_SID_TABLE_N;
> > +   u8 qcom_pcie_crc8_table[CRC8_TABLE_SIZE];
> > +   int ret, i;
> > +
> > +   ret = qcom_pcie_get_iommu_map(pcie);
> > +   if (ret)
> > +   return ret;
> > +
> > +   if (!pcie->sid_info)
> > +   return 0;
> > +
> > +   crc8_populate_msb(qcom_pcie_crc8_table, QCOM_PCIE_CRC8_POLYNOMIAL);
> > +
> > +   /* Registers need to be zero out first */
> > +   memset_io(bdf_to_sid_base, 0, CRC8_TABLE_SIZE * sizeof(u32));
> > +
> > +   /* Initial setup for boot */
> 
> Could you elaborate more what the code below is trying to achieve. Is
> that connected to bootloaders?
> 

No. This is trying to program the hash tables for initial boot but I think this
doesn't make sense here as it will be done all the time. I'll just remove this
comment.

Thanks,
Mani


[GIT PULL]: soundwire updates for v5.10-rc1

2020-09-30 Thread Vinod Koul
Hi Greg,

Please pull to receive updates for soundwire subsystem.

The following changes since commit 9123e3a74ec7b934a4a099e98af6a61c2f80bbf5:

  Linux 5.9-rc1 (2020-08-16 13:04:57 -0700)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire.git 
tags/soundwire-5.10-rc1

for you to fetch changes up to 0173f525b2c1b02a51784e2119d434593235aed1:

  soundwire: sysfs: add slave status and device number before probe (2020-09-28 
11:17:43 +0530)


soundwire updates for 5.10-rc1

This round of update includes:
 - Generic bandwidth allocation algorithm from Intel folks
 - PM support for Intel chipsets
 - Updates to Intel drivers which makes sdw usable on latest laptops
 - Support for MMIO SDW controllers found in QC chipsets
 - Update to subsystem to use helpers in bitfield.h to manage register
   bits


Bard Liao (4):
  soundwire: master: enable pm runtime
  soundwire: intel: reinitialize IP+DSP in .prepare(), but only when 
resuming
  soundwire: intel: fix intel_suspend/resume defined but not used warning
  soundwire: Add generic bandwidth allocation algorithm

Dan Carpenter (1):
  soundwire: remove an unnecessary NULL check

Jonathan Marek (5):
  soundwire: qcom: fix abh/ahb typo
  soundwire: qcom: avoid dependency on CONFIG_SLIMBUS
  soundwire: qcom: add support for mmio soundwire master devices
  soundwire: qcom: add v1.5.1 compatible
  soundwire: qcom: fix SLIBMUS/SLIMBUS typo

Pierre-Louis Bossart (39):
  soundwire: intel: Add basic power management support
  soundwire: intel: add pm_runtime support
  soundwire: intel: reset pm_runtime status during system resume
  soundwire: intel: fix race condition on system resume
  soundwire: intel: call helper to reset Slave states on resume
  soundwire: intel: pm_runtime idle scheduling
  soundwire: intel: add CLK_STOP_TEARDOWN for pm_runtime suspend
  soundwire: intel: add CLK_STOP_NOT_ALLOWED support
  soundwire: intel_init: handle power rail dependencies for clock stop mode
  soundwire: intel: support clock_stop mode without quirks
  ASoC: codecs: soundwire: remove port_ready[] usage from codecs.
  soundwire: add definition for maximum number of ports
  soundwire: fix port_ready[] dynamic allocation in mipi_disco
  soundwire: intel: disable shim wake on suspend
  soundwire: intel: ignore software command retries
  soundwire: intel: add multi-link support
  soundwire: intel: add missing support for all clock stop modes
  soundwire: bus: update multi-link definition with hw sync details
  soundwire: intel: add multi-link hw_synchronization information
  soundwire: stream: enable hw_sync as needed by hardware
  soundwire: intel: add error log for clock-stop invalid configs
  soundwire: intel: pass link_mask information to each master
  soundwire: intel: don't manage link power individually
  soundwire: stream: fix NULL/IS_ERR confusion
  soundwire: intel: fix NULL/ERR_PTR confusion
  soundwire: intel: remove .trigger operation
  soundwire: intel: remove stream handling from .prepare and .hw_free
  soundwire: cadence: fix race condition between suspend and Slave device 
alerts
  ASoC/soundwire: bus: use property to set interrupt masks
  soundwire: bus: filter-out unwanted interrupt reports
  soundwire: slave: add first_interrupt_done status
  soundwire: bus: use quirk to filter out invalid parity errors
  ASoC: codecs: realtek-soundwire: ignore initial PARITY errors
  soundwire: bus: export broadcast read/write capability for tests
  soundwire: cadence: add parity error injection through debugfs
  soundwire: enable Data Port test modes
  soundwire: intel: enable test modes
  soundwire: cadence: add data port test fail interrupt
  soundwire: sysfs: add slave status and device number before probe

Rander Wang (2):
  soundwire: intel: add CLK_STOP_BUS_RESET support
  soundwire: intel: refine runtime pm for SDW_INTEL_CLK_STOP_BUS_RESET

Srinivas Kandagatla (4):
  soundwire: qcom: clear BIT FIELDs before value set.
  soundwire: qcom: add support to block packing mode
  soundwire: qcom: get max rows and cols info from compatible
  soundwire: bus: add enumerated Slave device to device list

Vinod Koul (11):
  soundwire: define and use addr bit masks
  soundwire: bus: use FIELD_GET()
  soundwire: slave: use SDW_DISCO_LINK_ID()
  soundwire: stream: use FIELD_{GET|PREP}
  soundwire: qcom : use FIELD_{GET|PREP}
  soundwire: cadence: use FIELD_{GET|PREP}
  soundwire: intel: use FIELD_{GET|PREP}
  soundwire: intel_init: use FIELD_{GET|PREP}
  soundwire: remove SDW_REG_SHIFT()
  soundwire: cadence: use u32p_replace_bits
  soundwire: intel: use 

Re: [musl] [PATCH 1/1] linux/sysinfo.h: Add guarder for struct sysinfo

2020-09-30 Thread Petr Vorel
Hi Rich,

...
> I don't think this is the right way to do it. It prevents getting
> access to the kernel uapi structure (which may be wanted) if you're
> not using glibc or if you include kernel headers before any libc
> headers. Rather, , whose only real purpose is
> providing this structure to legacy applications that don't know the
> renamed name for it, should not be implicitly included by other
> headers. There's an existing thread on the topic but I don't have the
> link handy. IIRC I proposed moving the alignment macros or whatever
> other useful stuff is in  to a separate header and
> getting rid of all the indirect inclusions of .

Thanks for a review and tip!

Kind regards,
Petr


[rcu:rcu/next] BUILD SUCCESS c6769e4694d8035cf1bf18e0d63406cde469639a

2020-09-30 Thread kernel test robot
powerpc  allmodconfig
powerpc   allnoconfig
i386 randconfig-a003-20200930
i386 randconfig-a002-20200930
i386 randconfig-a006-20200930
i386 randconfig-a005-20200930
i386 randconfig-a004-20200930
i386 randconfig-a001-20200930
x86_64   randconfig-a015-20200930
x86_64   randconfig-a013-20200930
x86_64   randconfig-a012-20200930
x86_64   randconfig-a016-20200930
x86_64   randconfig-a014-20200930
x86_64   randconfig-a011-20200930
i386 randconfig-a011-20200930
i386 randconfig-a015-20200930
i386 randconfig-a012-20200930
i386 randconfig-a014-20200930
i386 randconfig-a016-20200930
i386 randconfig-a013-20200930
riscvnommu_k210_defconfig
riscvallyesconfig
riscvnommu_virt_defconfig
riscv allnoconfig
riscv   defconfig
riscv  rv32_defconfig
riscvallmodconfig
x86_64   rhel
x86_64   allyesconfig
x86_64rhel-7.6-kselftests
x86_64  defconfig
x86_64   rhel-8.3
x86_64  kexec

clang tested configs:
x86_64   randconfig-a001-20200930
x86_64   randconfig-a005-20200930
x86_64   randconfig-a003-20200930
x86_64   randconfig-a004-20200930
x86_64   randconfig-a002-20200930
x86_64   randconfig-a006-20200930

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-...@lists.01.org


Re: [PATCH v2 4/4] mtd: spi-nor: implement OTP support for Winbond and similar flashes

2020-09-30 Thread Heiko Thiery
HI Michael,

Am Sa., 12. Sept. 2020 um 00:26 Uhr schrieb Michael Walle :
>
> Use the new OTP ops to implement OTP access on Winbond flashes. Most
> Winbond flashes provides up to four different OTP areas ("Security
> Registers"). Newer flashes uses the first OTP area for SFDP data. Thus,
> for these flashes only the last three areas are handled and the first
> one is left untouched.
>
> This was tested on a Winbond W25Q32JW as well as on a W25Q32FW.
>
> Signed-off-by: Michael Walle 

Reviewed-by: Heiko Thiery 

> ---
>  drivers/mtd/spi-nor/core.c| 161 ++
>  drivers/mtd/spi-nor/core.h|   4 +
>  drivers/mtd/spi-nor/winbond.c |  18 +++-
>  include/linux/mtd/spi-nor.h   |  10 +++
>  4 files changed, 191 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
> index 348db19958e9..c150e3b6ee44 100644
> --- a/drivers/mtd/spi-nor/core.c
> +++ b/drivers/mtd/spi-nor/core.c
> @@ -2997,6 +2997,167 @@ int spi_nor_otp_is_locked_scur(struct spi_nor *nor, 
> unsigned int region)
> return *scur & SCUR_LDSO;
>  }
>
> +/**
> + * spi_nor_otp_read_secr() - read OTP data
> + * @nor:   pointer to 'struct spi_nor'
> + * @from:   offset to read from
> + * @len:number of bytes to read
> + * @buf:pointer to dst buffer
> + *
> + * Read OTP data by using the SPINOR_OP_RSECR commands. This method is used 
> on
> + * GigaDevice and Winbond flashes.
> + *
> + * Return: number of bytes read successfully, -errno otherwise
> + */
> +int spi_nor_otp_read_secr(struct spi_nor *nor, loff_t addr, uint64_t len, u8 
> *buf)
> +{
> +   u8 addr_width, read_opcode, read_dummy;
> +   struct spi_mem_dirmap_desc *rdesc;
> +   enum spi_nor_protocol read_proto;
> +   int ret;
> +
> +   read_opcode = nor->read_opcode;
> +   addr_width = nor->addr_width;
> +   read_dummy = nor->read_dummy;
> +   read_proto = nor->read_proto;
> +   rdesc = nor->dirmap.rdesc;
> +
> +   nor->read_opcode = SPINOR_OP_RSECR;
> +   nor->addr_width = 3;
> +   nor->read_dummy = 8;
> +   nor->read_proto = SNOR_PROTO_1_1_1;
> +   nor->dirmap.rdesc = NULL;
> +
> +   ret = spi_nor_read_data(nor, addr, len, buf);
> +
> +   nor->read_opcode = read_opcode;
> +   nor->addr_width = addr_width;
> +   nor->read_dummy = read_dummy;
> +   nor->read_proto = read_proto;
> +   nor->dirmap.rdesc = rdesc;
> +
> +   return ret;
> +}
> +
> +/**
> + * spi_nor_otp_write_secr() - write OTP data
> + * @nor:pointer to 'struct spi_nor'
> + * @to: offset to write to
> + * @len:number of bytes to write
> + * @buf:pointer to src buffer
> + *
> + * Write OTP data by using the SPINOR_OP_PSECR commands. This method is used 
> on
> + * GigaDevice and Winbond flashes.
> + *
> + * Return: number of bytes written successfully, -errno otherwise
> + */
> +int spi_nor_otp_write_secr(struct spi_nor *nor, loff_t addr, uint64_t len, 
> u8 *buf)
> +{
> +   enum spi_nor_protocol write_proto;
> +   struct spi_mem_dirmap_desc *wdesc;
> +   u8 addr_width, program_opcode;
> +   int ret;
> +
> +   program_opcode = nor->program_opcode;
> +   addr_width = nor->addr_width;
> +   write_proto = nor->write_proto;
> +   wdesc = nor->dirmap.wdesc;
> +
> +   nor->program_opcode = SPINOR_OP_PSECR;
> +   nor->addr_width = 3;
> +   nor->write_proto = SNOR_PROTO_1_1_1;
> +   nor->dirmap.wdesc = NULL;
> +
> +   /*
> +* We only support a write to one single page. For now all winbond
> +* flashes only have one page per OTP region.
> +*/
> +   ret = spi_nor_write_enable(nor);
> +   if (ret)
> +   goto out;
> +
> +   ret = spi_nor_write_data(nor, addr, len, buf);
> +   if (ret < 0)
> +   goto out;
> +
> +   ret = spi_nor_wait_till_ready(nor);
> +
> +out:
> +   nor->program_opcode = program_opcode;
> +   nor->addr_width = addr_width;
> +   nor->write_proto = write_proto;
> +   nor->dirmap.wdesc = wdesc;
> +
> +   return ret;
> +}
> +
> +static int spi_nor_otp_lock_bit_cr(unsigned int region)
> +{
> +   static const int lock_bits[] = { SR2_LB1, SR2_LB2, SR2_LB3 };
> +
> +   if (region >= ARRAY_SIZE(lock_bits))
> +   return -EINVAL;
> +
> +   return lock_bits[region];
> +}
> +
> +/**
> + * spi_nor_otp_lock_sr2() - lock the OTP region
> + * @nor:pointer to 'struct spi_nor'
> + * @region: OTP region
> + *
> + * Lock the OTP region by writing the status register-2. This method is used 
> on
> + * GigaDevice and Winbond flashes.
> + *
> + * Return: 0 on success, -errno otherwise.
> + */
> +int spi_nor_otp_lock_sr2(struct spi_nor *nor, unsigned int region)
> +{
> +   int lock_bit;
> +   u8 *sr2 = nor->bouncebuf;
> +   int ret;
> +
> +   lock_bit = spi_nor_otp_lock_bit_cr(region);
> +   if (lock_bit < 0)
> +   return 

Re: [PATCH 3/3] drm/ingenic: Alloc cached GEM buffers with dma_alloc_noncoherent

2020-09-30 Thread Christoph Hellwig
On Wed, Sep 30, 2020 at 07:16:44PM +0200, Paul Cercueil wrote:
> It turns out that if you want to mmap GEM buffers fully cached, then
> they should be allocated as such as well. Who would have known?
> 
> Introduce a custom .dumb_create callback, that will behave just like
> drm_gem_cma_dumb_create(), except that it will allocate the GEM buffer
> using dma_alloc_noncoherent() if non-coherent memory is what we want.

I think you want to merge this with patch 2, then change patch 2 to
still use dma_alloc_wc for the !ingenic_drm_cached_gem_buf and to
get the phys address using virt_to_phys for the
ingenic_drm_cached_gem_buf instead of abusing the dma address in
->paddr.  The free side also needs to use
dma_free_noncoherent.

> +static int ingenic_drm_gem_cma_dumb_create(struct drm_file *file_priv,
> +struct drm_device *drm,
> +struct drm_mode_create_dumb *args)
> +{
> + /*
> +  * This is basically a copy of drm_gem_cma_dumb_create, which supports
> +  * creating fully cached GEM buffers.
> +  */

What about adding this to the core GEM code instead?  We'll probaby
run into other potential users as well.


Re: [PATCH 9/9] perf tools: Align buildid list output for short build ids

2020-09-30 Thread Ian Rogers
On Wed, Sep 30, 2020 at 10:15 AM Jiri Olsa  wrote:
>
> With shorter md5 build ids we need to align their
> paths properly with other build ids:
>
>   $ perf buildid-list
>   17f4e448cc746582ea1881528deb549f7fdb3fd5 [kernel.kallsyms]
>   a50e350e97c43b4708d09bcd85ebfff7 .../tools/perf/buildid-ex-md5
>   1805c738c8f3ec0f47b7ea09080c28f34d18a82b /usr/lib64/ld-2.31.so
>
> Signed-off-by: Jiri Olsa 

Acked-by: Ian Rogers 

Thanks,
Ian

> ---
>  tools/perf/util/dso.c  | 2 +-
>  tools/perf/util/dso.h  | 1 -
>  tools/perf/util/dsos.c | 6 --
>  3 files changed, 5 insertions(+), 4 deletions(-)
>
> diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
> index ca965845b35e..55c11e854fe4 100644
> --- a/tools/perf/util/dso.c
> +++ b/tools/perf/util/dso.c
> @@ -1369,7 +1369,7 @@ int dso__kernel_module_get_build_id(struct dso *dso,
> return 0;
>  }
>
> -size_t dso__fprintf_buildid(struct dso *dso, FILE *fp)
> +static size_t dso__fprintf_buildid(struct dso *dso, FILE *fp)
>  {
> char sbuild_id[SBUILD_ID_SIZE];
>
> diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
> index f926c96bf230..d8cb4f5680a4 100644
> --- a/tools/perf/util/dso.h
> +++ b/tools/perf/util/dso.h
> @@ -362,7 +362,6 @@ struct dso *machine__findnew_kernel(struct machine 
> *machine, const char *name,
>
>  void dso__reset_find_symbol_cache(struct dso *dso);
>
> -size_t dso__fprintf_buildid(struct dso *dso, FILE *fp);
>  size_t dso__fprintf_symbols_by_name(struct dso *dso, FILE *fp);
>  size_t dso__fprintf(struct dso *dso, FILE *fp);
>
> diff --git a/tools/perf/util/dsos.c b/tools/perf/util/dsos.c
> index 87161e431830..183a81d5b2f9 100644
> --- a/tools/perf/util/dsos.c
> +++ b/tools/perf/util/dsos.c
> @@ -287,10 +287,12 @@ size_t __dsos__fprintf_buildid(struct list_head *head, 
> FILE *fp,
> size_t ret = 0;
>
> list_for_each_entry(pos, head, node) {
> +   char sbuild_id[SBUILD_ID_SIZE];
> +
> if (skip && skip(pos, parm))
> continue;
> -   ret += dso__fprintf_buildid(pos, fp);
> -   ret += fprintf(fp, " %s\n", pos->long_name);
> +   build_id__sprintf(>bid, sbuild_id);
> +   ret += fprintf(fp, "%-40s %s\n", sbuild_id, pos->long_name);
> }
> return ret;
>  }
> --
> 2.26.2
>


Re: [PATCH v2 4/5] PCI: qcom: Add SM8250 SoC support

2020-09-30 Thread Manivannan Sadhasivam
Hi Stan,

On Thu, Oct 01, 2020 at 12:56:28AM +0300, Stanimir Varbanov wrote:
> Hi Mani,
> 
> On 9/30/20 6:09 PM, Manivannan Sadhasivam wrote:
> > The PCIe IP on SM8250 SoC is similar to the one used on SDM845. Hence
> > the support is added reusing the members of ops_2_7_0. The key
> > difference between ops_2_7_0 and ops_sm8250 is the config_sid callback,
> > which will be added in successive commit.
> > 
> > Signed-off-by: Manivannan Sadhasivam 
> > ---
> >  drivers/pci/controller/dwc/pcie-qcom.c | 11 +++
> >  1 file changed, 11 insertions(+)
> > 
> > diff --git a/drivers/pci/controller/dwc/pcie-qcom.c 
> > b/drivers/pci/controller/dwc/pcie-qcom.c
> > index 3aac77a295ba..44db91861b47 100644
> > --- a/drivers/pci/controller/dwc/pcie-qcom.c
> > +++ b/drivers/pci/controller/dwc/pcie-qcom.c
> > @@ -1359,6 +1359,16 @@ static const struct qcom_pcie_ops ops_2_7_0 = {
> > .post_deinit = qcom_pcie_post_deinit_2_7_0,
> >  };
> >  
> > +/* Qcom IP rev.: 1.9.0 */
> > +static const struct qcom_pcie_ops ops_sm8250 = {
> 
> This breaks the policy compatible -> ops_X_Y_Z. Could you introduce new
> method config_sid and check into for compatible qcom,pcie-sm8250 string
> there?
> 

I thought about it but during previous submission review Bjorn mentioned that
this config_sid got introduced in SM8150 and there might be chances that future
SoCs could also use it. That's why I was inclined to introduce a new ops instead
of checking for the compatible.

And the reason to use "sm8250" instead of IP revision is that I can't find the
Synopsys IP revision for this. But if you strongly prefer IP revision then I can
just use "ops_1_9_0"!

Thanks,
Mani

> > +   .get_resources = qcom_pcie_get_resources_2_7_0,
> > +   .init = qcom_pcie_init_2_7_0,
> > +   .deinit = qcom_pcie_deinit_2_7_0,
> > +   .ltssm_enable = qcom_pcie_2_3_2_ltssm_enable,
> > +   .post_init = qcom_pcie_post_init_2_7_0,
> > +   .post_deinit = qcom_pcie_post_deinit_2_7_0,
> > +};
> > +
> >  static const struct dw_pcie_ops dw_pcie_ops = {
> > .link_up = qcom_pcie_link_up,
> >  };
> > @@ -1476,6 +1486,7 @@ static const struct of_device_id qcom_pcie_match[] = {
> > { .compatible = "qcom,pcie-ipq4019", .data = _2_4_0 },
> > { .compatible = "qcom,pcie-qcs404", .data = _2_4_0 },
> > { .compatible = "qcom,pcie-sdm845", .data = _2_7_0 },
> > +   { .compatible = "qcom,pcie-sm8250", .data = _sm8250 },
> > { }
> >  };
> >  
> > 
> 
> -- 
> regards,
> Stan


Re: [PATCH v2 3/4] mtd: spi-nor: implement OTP support for Macronix and similar flashes

2020-09-30 Thread Heiko Thiery
Hi Michael,

Am Sa., 12. Sept. 2020 um 00:26 Uhr schrieb Michael Walle :
>
> Use the new OTP ops to implement OTP access on Macronix flashes. The
> Macronix flashes provides one OTP area which is either programmed with
> an electrical serial number and locked by the factory or is empty and can
> be locked by the user. To keep things simple and because most devices
> will have unprogrammed OTP areas, we treat both options as user regions.
> If there will actually be an ESN preprogrammed, it will appear as a
> locked user region.
>
> This was tested on a Macronix MX25L6405D as well as on a Adesto
> AT25SL321.
>
> Signed-off-by: Michael Walle 

Reviewed-by: Heiko Thiery 

> ---
>  drivers/mtd/spi-nor/atmel.c|  13 ++-
>  drivers/mtd/spi-nor/core.c | 170 +
>  drivers/mtd/spi-nor/core.h |   9 ++
>  drivers/mtd/spi-nor/macronix.c |  13 ++-
>  include/linux/mtd/spi-nor.h|   6 ++
>  5 files changed, 209 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mtd/spi-nor/atmel.c b/drivers/mtd/spi-nor/atmel.c
> index 3f5f21a473a6..1688c9989c6b 100644
> --- a/drivers/mtd/spi-nor/atmel.c
> +++ b/drivers/mtd/spi-nor/atmel.c
> @@ -19,7 +19,8 @@ static const struct flash_info atmel_parts[] = {
> { "at25df641",  INFO(0x1f4800, 0, 64 * 1024, 128, SECT_4K) },
>
> { "at25sl321",  INFO(0x1f4216, 0, 64 * 1024, 64,
> -SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) 
> },
> +SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
> +OTP_INFO1(512, 0) },
>
> { "at26f004",   INFO(0x1f0400, 0, 64 * 1024,  8, SECT_4K) },
> { "at26df081a", INFO(0x1f4501, 0, 64 * 1024, 16, SECT_4K) },
> @@ -29,9 +30,19 @@ static const struct flash_info atmel_parts[] = {
> { "at45db081d", INFO(0x1f2500, 0, 64 * 1024, 16, SECT_4K) },
>  };
>
> +static const struct spi_nor_otp_ops atmel_otp_ops = {
> +   .read = spi_nor_otp_read_otp_mode,
> +   .write = spi_nor_otp_write_otp_mode,
> +   .lock = spi_nor_otp_lock_scur,
> +   .is_locked = spi_nor_otp_is_locked_scur,
> +};
> +
>  static void atmel_default_init(struct spi_nor *nor)
>  {
> nor->flags |= SNOR_F_HAS_LOCK;
> +
> +   if (nor->params->otp_info.n_otps)
> +   nor->params->otp_ops = _otp_ops;
>  }
>
>  static const struct spi_nor_fixups atmel_fixups = {
> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
> index 4244f98e4948..348db19958e9 100644
> --- a/drivers/mtd/spi-nor/core.c
> +++ b/drivers/mtd/spi-nor/core.c
> @@ -2828,6 +2828,176 @@ static int spi_nor_unlock_all(struct spi_nor *nor)
> return 0;
>  }
>
> +/**
> + * spi_nor_set_secured_otp_mode() - Set secured OTP mode
> + * @nor:   pointer to 'struct spi_nor'.
> + * @enable:true to enter the secured OTP mode, false to exit the secured
> + * OTP mode.
> + *
> + * Enter and exit OTP mode by using the command SPINOR_OP_ENSO (B1h) and
> + * SPINOR_EP_EXSO (C1h) command.
> + *
> + * Return: 0 on success, -errno otherwise.
> + */
> +static int spi_nor_set_secured_otp_mode(struct spi_nor *nor, bool enable)
> +{
> +   u8 cmd = enable ? SPINOR_OP_ENSO : SPINOR_OP_EXSO;
> +   int ret;
> +
> +   ret = spi_nor_simple_cmd(nor, cmd);
> +   if (ret)
> +   dev_dbg(nor->dev, "error %d setting secured OTP mode\n", ret);
> +
> +   return ret;
> +}
> +
> +/**
> + * spi_nor_read_scur() - Read the Security Register using the 
> SPINOR_OP_RDSCUR (2Bh) command.
> + * @nor:   pointer to 'struct spi_nor'
> + * @scur:  pointer to a DMA-able buffer where the value of the
> + * Security Register will be written.
> + *
> + * Return: 0 on success, -errno otherwise.
> + */
> +static int spi_nor_read_scur(struct spi_nor *nor, u8 *scur)
> +{
> +   int ret;
> +
> +   ret = spi_nor_simple_cmd_din(nor, SPINOR_OP_RDSCUR, scur, 1);
> +   if (ret)
> +   dev_dbg(nor->dev, "error %d reading SCUR\n", ret);
> +
> +   return ret;
> +}
> +
> +/**
> + * spi_nor_write_scur() - Write the Security Register using the 
> SPINOR_OP_WRSCUR (2Fh) command.
> + * @nor:   pointer to 'struct spi_nor'
> + *
> + * This register contains only one OTP bit. The command doesn't take any
> + * arguments. In fact it _must not_ take any arugments. Otherwise the command
> + * is ignored.
> + *
> + * Return: 0 on success, -errno otherwise.
> + */
> +static int spi_nor_write_scur(struct spi_nor *nor)
> +{
> +   int ret;
> +
> +   ret = spi_nor_simple_cmd(nor, SPINOR_OP_WRSCUR);
> +   if (ret)
> +   dev_dbg(nor->dev, "error %d writing SCUR\n", ret);
> +
> +   return ret;
> +}
> +
> +/**
> + * spi_nor_otp_read_otp_mode() - read OTP data
> + * @nor:   pointer to 'struct spi_nor'
> + * @from:   offset to read from
> + * @len:number of bytes to read
> + * @buf:pointer to dst buffer
> + *
> + * Read OTP data by using the ENSO and EXSO 

Re: [PATCH v2 2/4] mtd: spi-nor: add OTP support

2020-09-30 Thread Heiko Thiery
Hi Michael,

Am Sa., 12. Sept. 2020 um 00:26 Uhr schrieb Michael Walle :
>
> Implement the MTD callbacks for the OTP methods for the SPI NOR
> subsystem.
>
> Usually, the OTP area of a SPI flash can be accessed like the normal
> memory, eg by offset addressing; except that you either have to use
> special read/write commands (Winbond) or you have to enter (and exit) a
> specific OTP mode (Macronix, Micron). Sometimes there are individual
> regions, which might have individual offsets. Therefore, it is possible
> to specify the starting address of the first regions as well as the
> distance between two regions (Winbond).
>
> Additionally, the regions might be locked down. Once locked, no further
> write access is possible.
>
> Cc: Rahul Bedarkar 
> Signed-off-by: Michael Walle 

Reviewed-by: Heiko Thiery 

> ---
>  drivers/mtd/chips/Kconfig  |   2 +-
>  drivers/mtd/spi-nor/core.c | 143 +
>  drivers/mtd/spi-nor/core.h |  48 +
>  3 files changed, 192 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig
> index aef14990e5f7..3b7ba9448118 100644
> --- a/drivers/mtd/chips/Kconfig
> +++ b/drivers/mtd/chips/Kconfig
> @@ -152,7 +152,7 @@ config MTD_CFI_I8
>
>  config MTD_OTP
> bool "Protection Registers aka one-time programmable (OTP) bits"
> -   depends on MTD_CFI_ADV_OPTIONS
> +   depends on MTD_CFI_ADV_OPTIONS || MTD_SPI_NOR
> default n
> help
>   This enables support for reading, writing and locking so called
> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
> index b06b160a5c9c..4244f98e4948 100644
> --- a/drivers/mtd/spi-nor/core.c
> +++ b/drivers/mtd/spi-nor/core.c
> @@ -2689,6 +2689,12 @@ static void spi_nor_info_init_params(struct spi_nor 
> *nor)
> spi_nor_set_erase_type(>erase_type[i], info->sector_size,
>SPINOR_OP_SE);
> spi_nor_init_uniform_erase_map(map, erase_mask, params->size);
> +
> +   /* OTP parameters */
> +   nor->params->otp_info.otp_size = info->otp_size;
> +   nor->params->otp_info.n_otps = info->n_otps;
> +   nor->params->otp_info.otp_start_addr = info->otp_start_addr;
> +   nor->params->otp_info.otp_addr_offset = info->otp_addr_offset;
>  }
>
>  /**
> @@ -2972,6 +2978,127 @@ static const struct flash_info 
> *spi_nor_get_flash_info(struct spi_nor *nor,
> return info;
>  }
>
> +static loff_t spi_nor_otp_region_start(struct spi_nor *nor, int region)
> +{
> +   struct spi_nor_otp_info *info = >params->otp_info;
> +
> +   return info->otp_start_addr + region * info->otp_addr_offset;
> +}
> +
> +static loff_t spi_nor_otp_region_end(struct spi_nor *nor, int region)
> +{
> +   struct spi_nor_otp_info *info = >params->otp_info;
> +
> +   return spi_nor_otp_region_start(nor, region) + info->otp_size - 1;
> +}
> +
> +static int spi_nor_mtd_otp_info(struct mtd_info *mtd, size_t len,
> +   size_t *retlen, struct otp_info *buf)
> +{
> +   struct spi_nor *nor = mtd_to_spi_nor(mtd);
> +   int locked;
> +   int i;
> +
> +   for (i = 0; i < nor->params->otp_info.n_otps; i++) {
> +   buf[i].start = spi_nor_otp_region_start(nor, i);
> +   buf[i].length = nor->params->otp_info.otp_size;
> +
> +   locked = nor->params->otp_ops->is_locked(nor, i);
> +   if (locked < 0)
> +   return locked;
> +
> +   buf[i].locked = !!locked;
> +   }
> +
> +   *retlen = nor->params->otp_info.n_otps * sizeof(*buf);
> +
> +   return 0;
> +}
> +
> +static int spi_nor_otp_addr_to_region(struct spi_nor *nor, loff_t addr)
> +{
> +   int i;
> +
> +   for (i = 0; i < nor->params->otp_info.n_otps; i++)
> +   if (addr >= spi_nor_otp_region_start(nor, i) &&
> +   addr <= spi_nor_otp_region_end(nor, i))
> +   return i;
> +
> +   return -EINVAL;
> +}
> +
> +static int spi_nor_mtd_otp_read_write(struct mtd_info *mtd, loff_t ofs,
> + size_t len, size_t *retlen, u_char *buf,
> + bool is_write)
> +{
> +   struct spi_nor *nor = mtd_to_spi_nor(mtd);
> +   int region;
> +   int ret;
> +
> +   *retlen = 0;
> +
> +   region = spi_nor_otp_addr_to_region(nor, ofs);
> +   if (region < 0)
> +   return 0;
> +
> +   if (ofs < spi_nor_otp_region_start(nor, region))
> +   return 0;
> +
> +   if ((ofs + len - 1) > spi_nor_otp_region_end(nor, region))
> +   return 0;
> +
> +   ret = spi_nor_lock_and_prep(nor);
> +
> +   if (is_write)
> +   ret = nor->params->otp_ops->write(nor, ofs, len, buf);
> +   else
> +   ret = nor->params->otp_ops->read(nor, ofs, len, buf);
> +
> +   spi_nor_unlock_and_unprep(nor);
> +
> +   if (ret < 0)
> + 

Re: [PATCH 2/3] drm/ingenic: Update code to mmap GEM buffers cached

2020-09-30 Thread Christoph Hellwig
On Wed, Sep 30, 2020 at 07:16:43PM +0200, Paul Cercueil wrote:
> The DMA API changed at the same time commit 37054fc81443 ("gpu/drm:
> ingenic: Add option to mmap GEM buffers cached") was added. Rework the
> code to work with the new DMA API.
> 
> Signed-off-by: Paul Cercueil 
> ---
>  drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 24 +++
>  1 file changed, 7 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c 
> b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
> index 0225dc1f5eb8..07a1da7266e4 100644
> --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
> +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
> @@ -526,12 +526,10 @@ void ingenic_drm_sync_data(struct device *dev,
>  struct drm_plane_state *state)
>  {
>   const struct drm_format_info *finfo = state->fb->format;
> - struct ingenic_drm *priv = dev_get_drvdata(dev);
>   struct drm_atomic_helper_damage_iter iter;
>   unsigned int offset, i;
>   struct drm_rect clip;
>   dma_addr_t paddr;
> - void *addr;
>  
>   if (!ingenic_drm_cached_gem_buf)
>   return;
> @@ -541,12 +539,11 @@ void ingenic_drm_sync_data(struct device *dev,
>   drm_atomic_for_each_plane_damage(, ) {
>   for (i = 0; i < finfo->num_planes; i++) {
>   paddr = drm_fb_cma_get_gem_addr(state->fb, state, i);
> - addr = phys_to_virt(paddr);

No on the old code: drm_fb_cma_get_gem_addr returns a dma_addr_t, so
this was already pretty broken..

> @@ -766,14 +763,6 @@ static int ingenic_drm_gem_mmap(struct drm_gem_object 
> *obj,
>   struct vm_area_struct *vma)
>  {
>   struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(obj);
>  
>   /*
>* Clear the VM_PFNMAP flag that was set by drm_gem_mmap(), and set the
> @@ -784,12 +773,13 @@ static int ingenic_drm_gem_mmap(struct drm_gem_object 
> *obj,
>   vma->vm_pgoff = 0;
>   vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
>  
> + if (!ingenic_drm_cached_gem_buf)
> + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
>  
> + return remap_pfn_range(vma, vma->vm_start,
> +cma_obj->paddr >> PAGE_SHIFT,
> +vma->vm_end - vma->vm_start,
> +vma->vm_page_prot);

both ->vaddr and ->paddr come from dma_alloc_wc as far as I can tell,
and despite the confusing name ->paddr is a dma_addr_t.  So this can't
work at all.  If you allocate memory using dma_alloc_wc you need to
map it using dma_alloc_wc.


Re: [PATCH 8/9] perf tools: Add size to struct perf_record_header_build_id

2020-09-30 Thread Ian Rogers
On Wed, Sep 30, 2020 at 10:15 AM Jiri Olsa  wrote:
>
> We do not store size with build ids in perf data,
> but there's enough space to do it. Adding misc bit
> PERF_RECORD_MISC_BUILD_ID_SIZE to mark build id event
> with size.
>
> With this fix the dso with md5 build id will have correct
> build id data and will be usable for debuginfod processing
> if needed (coming in following patches).
>
> Signed-off-by: Jiri Olsa 

Acked-by: Ian Rogers 

Thanks,
Ian

> ---
>  tools/lib/perf/include/perf/event.h | 12 +++-
>  tools/perf/util/build-id.c  |  8 +---
>  tools/perf/util/header.c| 10 +++---
>  3 files changed, 23 insertions(+), 7 deletions(-)
>
> diff --git a/tools/lib/perf/include/perf/event.h 
> b/tools/lib/perf/include/perf/event.h
> index a6dbba6b9073..988c539bedb6 100644
> --- a/tools/lib/perf/include/perf/event.h
> +++ b/tools/lib/perf/include/perf/event.h
> @@ -201,10 +201,20 @@ struct perf_record_header_tracing_data {
> __u32size;
>  };
>
> +#define PERF_RECORD_MISC_BUILD_ID_SIZE (1 << 15)
> +
>  struct perf_record_header_build_id {
> struct perf_event_header header;
> pid_tpid;
> -   __u8 build_id[24];
> +   union {
> +   __u8 build_id[24];
> +   struct {
> +   __u8 data[20];
> +   __u8 size;
> +   __u8 reserved1__;
> +   __u16reserved2__;
> +   };
> +   };
> char filename[];
>  };
>
> diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
> index b5648735f01f..8763772f1095 100644
> --- a/tools/perf/util/build-id.c
> +++ b/tools/perf/util/build-id.c
> @@ -296,7 +296,7 @@ char *dso__build_id_filename(const struct dso *dso, char 
> *bf, size_t size,
> continue;   \
> else
>
> -static int write_buildid(const char *name, size_t name_len, u8 *build_id,
> +static int write_buildid(const char *name, size_t name_len, struct build_id 
> *bid,
>  pid_t pid, u16 misc, struct feat_fd *fd)
>  {
> int err;
> @@ -307,7 +307,9 @@ static int write_buildid(const char *name, size_t 
> name_len, u8 *build_id,
> len = PERF_ALIGN(len, NAME_ALIGN);
>
> memset(, 0, sizeof(b));
> -   memcpy(_id, build_id, BUILD_ID_SIZE);
> +   memcpy(, bid->data, bid->size);
> +   b.size = (u8) bid->size;
> +   misc |= PERF_RECORD_MISC_BUILD_ID_SIZE;
> b.pid = pid;
> b.header.misc = misc;
> b.header.size = sizeof(b) + len;
> @@ -354,7 +356,7 @@ static int machine__write_buildid_table(struct machine 
> *machine,
> in_kernel = pos->kernel ||
> is_kernel_module(name,
> PERF_RECORD_MISC_CPUMODE_UNKNOWN);
> -   err = write_buildid(name, name_len, pos->bid.data, 
> machine->pid,
> +   err = write_buildid(name, name_len, >bid, machine->pid,
> in_kernel ? kmisc : umisc, fd);
> if (err)
> break;
> diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
> index 21243adbb9fd..8da3886f10a8 100644
> --- a/tools/perf/util/header.c
> +++ b/tools/perf/util/header.c
> @@ -2083,8 +2083,12 @@ static int __event_process_build_id(struct 
> perf_record_header_build_id *bev,
> if (dso != NULL) {
> char sbuild_id[SBUILD_ID_SIZE];
> struct build_id bid;
> +   size_t size = BUILD_ID_SIZE;
>
> -   build_id__init(, bev->build_id, BUILD_ID_SIZE);
> +   if (bev->header.misc & PERF_RECORD_MISC_BUILD_ID_SIZE)
> +   size = bev->size;
> +
> +   build_id__init(, bev->data, size);
> dso__set_build_id(dso, );
>
> if (dso_space != DSO_SPACE__USER) {
> @@ -2098,8 +2102,8 @@ static int __event_process_build_id(struct 
> perf_record_header_build_id *bev,
> }
>
> build_id__sprintf(>bid, sbuild_id);
> -   pr_debug("build id event received for %s: %s\n",
> -dso->long_name, sbuild_id);
> +   pr_debug("build id event received for %s: %s [%lu]\n",
> +dso->long_name, sbuild_id, size);
> dso__put(dso);
> }
>
> --
> 2.26.2
>


Re: [PATCH v1] i2c: npcm7xx: Support changing bus speed using debugfs.

2020-09-30 Thread Tali Perry
On Wed, Sep 30, 2020 at 12:31 PM Andy Shevchenko
 wrote:
>
> On Wed, Sep 30, 2020 at 10:13:42AM +0300, Tali Perry wrote:
> > Systems that can dinamically add and remove slave devices
>
> dynamically
>
> > often need to change the bus speed in runtime.
>
> > This patch exposes the bus frequency to the user.
>
> Expose the bus frequency to the user.
>
> > This feature can also be used for test automation.
>
> In general I think that DT overlays or so should be user rather than this.
> If we allow to change bus speed settings for debugging purposes it might make
> sense to do this on framework level for all drivers which support that (via
> additional callback or so).

Do you mean adding something like this:

struct i2c_algorithm {
/*
* If an adapter algorithm can't do I2C-level access, set master_xfer
* to NULL. If an adapter algorithm can do SMBus access, set
* smbus_xfer. If set to NULL, the SMBus protocol is simulated
* using common I2C messages.
*
* master_xfer should return the number of messages successfully
* processed, or a negative value on error
*/
int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs,
  int num);

int (*set_speed)(struct i2c_adapter *adap, unsigned int speed);

/* To determine what the adapter supports */
u32 (*functionality)(struct i2c_adapter *adap);

...
};

And expose this feature in functionality?


>
> > Fixes: 56a1485b102e (i2c: npcm7xx: Add Nuvoton NPCM I2C controller driver)
> > Signed-off-by: Tali Perry 
> > ---
> >  drivers/i2c/busses/i2c-npcm7xx.c | 36 
> >  1 file changed, 36 insertions(+)
> >
> > diff --git a/drivers/i2c/busses/i2c-npcm7xx.c 
> > b/drivers/i2c/busses/i2c-npcm7xx.c
> > index 2ad166355ec9..44e2340c1893 100644
> > --- a/drivers/i2c/busses/i2c-npcm7xx.c
> > +++ b/drivers/i2c/busses/i2c-npcm7xx.c
> > @@ -2208,6 +2208,41 @@ static const struct i2c_algorithm npcm_i2c_algo = {
> >  /* i2c debugfs directory: used to keep health monitor of i2c devices */
> >  static struct dentry *npcm_i2c_debugfs_dir;
> >
> > +static int i2c_speed_get(void *data, u64 *val)
> > +{
> > + struct npcm_i2c *bus = data;
> > +
> > + *val = (u64)bus->bus_freq;
> > + return 0;
> > +}
> > +
> > +static int i2c_speed_set(void *data, u64 val)
> > +{
> > + struct npcm_i2c *bus = data;
> > + int ret;
> > +
> > + if (val < (u64)I2C_FREQ_MIN_HZ || val > (u64)I2C_FREQ_MAX_HZ)
> > + return -EINVAL;
> > +
> > + if (val == (u64)bus->bus_freq)
> > + return 0;
> > +
> > + i2c_lock_bus(>adap, I2C_LOCK_ROOT_ADAPTER);
> > +
> > + npcm_i2c_int_enable(bus, false);
> > +
> > + ret = npcm_i2c_init_module(bus, I2C_MASTER, (u32)val);
> > +
> > + i2c_unlock_bus(>adap, I2C_LOCK_ROOT_ADAPTER);
>
> While all these explicit castings?
>
> > +
> > + if (ret)
> > + return -EAGAIN;
> > +
> > + return 0;
> > +}
>
> > +
>
> No need to have this blank line
>
> > +DEFINE_DEBUGFS_ATTRIBUTE(i2c_clock_ops, i2c_speed_get, i2c_speed_set, 
> > "%lld\n");
> > +
> >  static void npcm_i2c_init_debugfs(struct platform_device *pdev,
> > struct npcm_i2c *bus)
> >  {
> > @@ -2223,6 +2258,7 @@ static void npcm_i2c_init_debugfs(struct 
> > platform_device *pdev,
> >   debugfs_create_u64("rec_succ_cnt", 0444, d, >rec_succ_cnt);
> >   debugfs_create_u64("rec_fail_cnt", 0444, d, >rec_fail_cnt);
> >   debugfs_create_u64("timeout_cnt", 0444, d, >timeout_cnt);
> > + debugfs_create_file("i2c_speed", 0644, d, bus, _clock_ops);
> >
> >   bus->debugfs = d;
> >  }
>
> --
> With Best Regards,
> Andy Shevchenko
>
>


Re: [PATCH v2 2/3] tracing: Fix parse_synth_field() error handling

2020-09-30 Thread Masami Hiramatsu
Hi Tom,

On Wed, 30 Sep 2020 13:40:51 -0500
Tom Zanussi  wrote:

> synth_field_size() returns either a positive size or an error (zero or
> a negative value). However, the existing code assumes the only error
> value is 0. It doesn't handle negative error codes, as it assigns
> directly to field->size (a size_t; unsigned), thereby interpreting the
> error code as a valid size instead.
> 
> Do the test before assignment to field->size.

This looks good to me. And I guess it is a kind of bugfix which should be 
backported?
(doesn't this need a Fixes tag?)

Reviewed-by: Masami Hiramatsu 

Thank you,

> 
> [ axelrasmus...@google.com: changelog addition, first paragraph above ]
> 
> Signed-off-by: Tom Zanussi 
> ---
>  kernel/trace/trace_events_synth.c | 6 --
>  1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/kernel/trace/trace_events_synth.c 
> b/kernel/trace/trace_events_synth.c
> index a9cd7793f7ea..fa8a99828f41 100644
> --- a/kernel/trace/trace_events_synth.c
> +++ b/kernel/trace/trace_events_synth.c
> @@ -465,6 +465,7 @@ static struct synth_field *parse_synth_field(int argc, 
> const char **argv,
>   struct synth_field *field;
>   const char *prefix = NULL, *field_type = argv[0], *field_name, *array;
>   int len, ret = 0;
> + ssize_t size;
>  
>   if (field_type[0] == ';')
>   field_type++;
> @@ -520,11 +521,12 @@ static struct synth_field *parse_synth_field(int argc, 
> const char **argv,
>   field->type[len - 1] = '\0';
>   }
>  
> - field->size = synth_field_size(field->type);
> - if (!field->size) {
> + size = synth_field_size(field->type);
> + if (size <= 0) {
>   ret = -EINVAL;
>   goto free;
>   }
> + field->size = size;
>  
>   if (synth_field_is_string(field->type))
>   field->is_string = true;
> -- 
> 2.17.1
> 


-- 
Masami Hiramatsu 


Re: [PATCH 7/9] perf tools: Pass build_id object to dso__build_id_equal

2020-09-30 Thread Ian Rogers
On Wed, Sep 30, 2020 at 10:15 AM Jiri Olsa  wrote:
>
> Passing build_id object to dso__build_id_equal, so we can
> properly check build id with different size than sha1.
>
> Signed-off-by: Jiri Olsa 

Acked-by: Ian Rogers 

Thanks,
Ian

> ---
>  tools/perf/util/dso.c| 5 +++--
>  tools/perf/util/dso.h| 2 +-
>  tools/perf/util/symbol-elf.c | 8 ++--
>  tools/perf/util/symbol.c | 2 +-
>  4 files changed, 11 insertions(+), 6 deletions(-)
>
> diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
> index 4415ce83150b..ca965845b35e 100644
> --- a/tools/perf/util/dso.c
> +++ b/tools/perf/util/dso.c
> @@ -1332,9 +1332,10 @@ void dso__set_build_id(struct dso *dso, struct 
> build_id *bid)
> dso->has_build_id = 1;
>  }
>
> -bool dso__build_id_equal(const struct dso *dso, u8 *build_id)
> +bool dso__build_id_equal(const struct dso *dso, struct build_id *bid)
>  {
> -   return memcmp(dso->bid.data, build_id, sizeof(dso->bid.data)) == 0;
> +   return dso->bid.size == bid->size &&
> +  memcmp(dso->bid.data, bid->data, dso->bid.size) == 0;
>  }
>
>  void dso__read_running_kernel_build_id(struct dso *dso, struct machine 
> *machine)
> diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
> index 5a5678dbdaa5..f926c96bf230 100644
> --- a/tools/perf/util/dso.h
> +++ b/tools/perf/util/dso.h
> @@ -261,7 +261,7 @@ void dso__set_sorted_by_name(struct dso *dso);
>  void dso__sort_by_name(struct dso *dso);
>
>  void dso__set_build_id(struct dso *dso, struct build_id *bid);
> -bool dso__build_id_equal(const struct dso *dso, u8 *build_id);
> +bool dso__build_id_equal(const struct dso *dso, struct build_id *bid);
>  void dso__read_running_kernel_build_id(struct dso *dso,
>struct machine *machine);
>  int dso__kernel_module_get_build_id(struct dso *dso, const char *root_dir);
> diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
> index 97a55f162ea5..44dd86a4f25f 100644
> --- a/tools/perf/util/symbol-elf.c
> +++ b/tools/perf/util/symbol-elf.c
> @@ -834,13 +834,17 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, 
> const char *name,
> /* Always reject images with a mismatched build-id: */
> if (dso->has_build_id && !symbol_conf.ignore_vmlinux_buildid) {
> u8 build_id[BUILD_ID_SIZE];
> +   struct build_id bid;
> +   int size;
>
> -   if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0) {
> +   size = elf_read_build_id(elf, build_id, BUILD_ID_SIZE);
> +   if (size <= 0) {
> dso->load_errno = DSO_LOAD_ERRNO__CANNOT_READ_BUILDID;
> goto out_elf_end;
> }
>
> -   if (!dso__build_id_equal(dso, build_id)) {
> +   build_id__init(, build_id, size);
> +   if (!dso__build_id_equal(dso, )) {
> pr_debug("%s: build id mismatch for %s.\n", __func__, 
> name);
> dso->load_errno = DSO_LOAD_ERRNO__MISMATCHING_BUILDID;
> goto out_elf_end;
> diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
> index 976632d0baa0..613885df 100644
> --- a/tools/perf/util/symbol.c
> +++ b/tools/perf/util/symbol.c
> @@ -2136,7 +2136,7 @@ static char *dso__find_kallsyms(struct dso *dso, struct 
> map *map)
> }
>
> if (sysfs__read_build_id("/sys/kernel/notes", ) == 0)
> -   is_host = dso__build_id_equal(dso, bid.data);
> +   is_host = dso__build_id_equal(dso, );
>
> /* Try a fast path for /proc/kallsyms if possible */
> if (is_host) {
> --
> 2.26.2
>


Re: [PATCH 6/9] perf tools: Pass build_id object to dso__set_build_id

2020-09-30 Thread Ian Rogers
On Wed, Sep 30, 2020 at 10:15 AM Jiri Olsa  wrote:
>
> Passing build_id object to dso__set_build_id, so it's easier
> to initialize dos's build id object.
>
> Signed-off-by: Jiri Olsa 

Acked-by: Ian Rogers 

Thanks,
Ian

> ---
>  tools/perf/util/dso.c| 4 ++--
>  tools/perf/util/dso.h| 2 +-
>  tools/perf/util/header.c | 4 +++-
>  tools/perf/util/symbol-minimal.c | 2 +-
>  tools/perf/util/symbol.c | 2 +-
>  5 files changed, 8 insertions(+), 6 deletions(-)
>
> diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
> index 2f7f01ead9a1..4415ce83150b 100644
> --- a/tools/perf/util/dso.c
> +++ b/tools/perf/util/dso.c
> @@ -1326,9 +1326,9 @@ void dso__put(struct dso *dso)
> dso__delete(dso);
>  }
>
> -void dso__set_build_id(struct dso *dso, void *build_id)
> +void dso__set_build_id(struct dso *dso, struct build_id *bid)
>  {
> -   memcpy(dso->bid.data, build_id, sizeof(dso->bid.data));
> +   dso->bid = *bid;
> dso->has_build_id = 1;
>  }
>
> diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
> index eac004210b47..5a5678dbdaa5 100644
> --- a/tools/perf/util/dso.h
> +++ b/tools/perf/util/dso.h
> @@ -260,7 +260,7 @@ bool dso__sorted_by_name(const struct dso *dso);
>  void dso__set_sorted_by_name(struct dso *dso);
>  void dso__sort_by_name(struct dso *dso);
>
> -void dso__set_build_id(struct dso *dso, void *build_id);
> +void dso__set_build_id(struct dso *dso, struct build_id *bid);
>  bool dso__build_id_equal(const struct dso *dso, u8 *build_id);
>  void dso__read_running_kernel_build_id(struct dso *dso,
>struct machine *machine);
> diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
> index fe220f01fc94..21243adbb9fd 100644
> --- a/tools/perf/util/header.c
> +++ b/tools/perf/util/header.c
> @@ -2082,8 +2082,10 @@ static int __event_process_build_id(struct 
> perf_record_header_build_id *bev,
> dso = machine__findnew_dso(machine, filename);
> if (dso != NULL) {
> char sbuild_id[SBUILD_ID_SIZE];
> +   struct build_id bid;
>
> -   dso__set_build_id(dso, >build_id);
> +   build_id__init(, bev->build_id, BUILD_ID_SIZE);
> +   dso__set_build_id(dso, );
>
> if (dso_space != DSO_SPACE__USER) {
> struct kmod_path m = { .name = NULL, };
> diff --git a/tools/perf/util/symbol-minimal.c 
> b/tools/perf/util/symbol-minimal.c
> index dba6b9e5d64e..f9eb0bee7f15 100644
> --- a/tools/perf/util/symbol-minimal.c
> +++ b/tools/perf/util/symbol-minimal.c
> @@ -349,7 +349,7 @@ int dso__load_sym(struct dso *dso, struct map *map 
> __maybe_unused,
> dso->is_64_bit = ret;
>
> if (filename__read_build_id(ss->name, ) > 0)
> -   dso__set_build_id(dso, bid.data);
> +   dso__set_build_id(dso, );
> return 0;
>  }
>
> diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
> index 369cbad09f0d..976632d0baa0 100644
> --- a/tools/perf/util/symbol.c
> +++ b/tools/perf/util/symbol.c
> @@ -1818,7 +1818,7 @@ int dso__load(struct dso *dso, struct map *map)
> is_regular_file(dso->long_name)) {
> __symbol__join_symfs(name, PATH_MAX, dso->long_name);
> if (filename__read_build_id(name, ) > 0)
> -   dso__set_build_id(dso, bid.data);
> +   dso__set_build_id(dso, );
> }
>
> /*
> --
> 2.26.2
>


Re: [PATCH 5/9] perf tools: Pass build_id object to build_id__sprintf

2020-09-30 Thread Ian Rogers
On Wed, Sep 30, 2020 at 10:15 AM Jiri Olsa  wrote:
>
> Passing build_id object to build_id__sprintf function,
> so it can operate with the proper size of build id.
>
> This will create proper md5 build id readable names,
> like following:
>   a50e350e97c43b4708d09bcd85ebfff7
>
> instead of:
>   a50e350e97c43b4708d09bcd85ebfff7
>
> Signed-off-by: Jiri Olsa 

Acked-by: Ian Rogers 

Thanks,
Ian

> ---
>  tools/perf/builtin-buildid-cache.c|  6 ++--
>  tools/perf/tests/sdt.c|  2 +-
>  tools/perf/util/annotate.c|  3 +-
>  tools/perf/util/build-id.c| 30 ---
>  tools/perf/util/build-id.h|  3 +-
>  tools/perf/util/dso.c |  6 ++--
>  tools/perf/util/header.c  |  3 +-
>  tools/perf/util/map.c |  4 +--
>  tools/perf/util/probe-event.c |  9 --
>  tools/perf/util/probe-finder.c|  8 +++--
>  .../scripting-engines/trace-event-python.c|  2 +-
>  tools/perf/util/symbol.c  |  2 +-
>  12 files changed, 43 insertions(+), 35 deletions(-)
>
> diff --git a/tools/perf/builtin-buildid-cache.c 
> b/tools/perf/builtin-buildid-cache.c
> index c3cb168d546d..a25411926e48 100644
> --- a/tools/perf/builtin-buildid-cache.c
> +++ b/tools/perf/builtin-buildid-cache.c
> @@ -186,7 +186,7 @@ static int build_id_cache__add_file(const char *filename, 
> struct nsinfo *nsi)
> return -1;
> }
>
> -   build_id__sprintf(bid.data, sizeof(bid.data), sbuild_id);
> +   build_id__sprintf(, sbuild_id);
> err = build_id_cache__add_s(sbuild_id, filename, nsi,
> false, false);
> pr_debug("Adding %s %s: %s\n", sbuild_id, filename,
> @@ -210,7 +210,7 @@ static int build_id_cache__remove_file(const char 
> *filename, struct nsinfo *nsi)
> return -1;
> }
>
> -   build_id__sprintf(bid.data, sizeof(bid.data), sbuild_id);
> +   build_id__sprintf(, sbuild_id);
> err = build_id_cache__remove_s(sbuild_id);
> pr_debug("Removing %s %s: %s\n", sbuild_id, filename,
>  err ? "FAIL" : "Ok");
> @@ -314,7 +314,7 @@ static int build_id_cache__update_file(const char 
> *filename, struct nsinfo *nsi)
> }
> err = 0;
>
> -   build_id__sprintf(bid.data, sizeof(bid.data), sbuild_id);
> +   build_id__sprintf(, sbuild_id);
> if (build_id_cache__cached(sbuild_id))
> err = build_id_cache__remove_s(sbuild_id);
>
> diff --git a/tools/perf/tests/sdt.c b/tools/perf/tests/sdt.c
> index 3ef37f739203..ed76c693f65e 100644
> --- a/tools/perf/tests/sdt.c
> +++ b/tools/perf/tests/sdt.c
> @@ -37,7 +37,7 @@ static int build_id_cache__add_file(const char *filename)
> return err;
> }
>
> -   build_id__sprintf(bid.data, sizeof(bid.data), sbuild_id);
> +   build_id__sprintf(, sbuild_id);
> err = build_id_cache__add_s(sbuild_id, filename, NULL, false, false);
> if (err < 0)
> pr_debug("Failed to add build id cache of %s\n", filename);
> diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
> index a016e1bd7b8d..6c8575e182ed 100644
> --- a/tools/perf/util/annotate.c
> +++ b/tools/perf/util/annotate.c
> @@ -1578,8 +1578,7 @@ int symbol__strerror_disassemble(struct map_symbol *ms, 
> int errnum, char *buf, s
> char *build_id_msg = NULL;
>
> if (dso->has_build_id) {
> -   build_id__sprintf(dso->bid.data,
> - sizeof(dso->bid.data), bf + 15);
> +   build_id__sprintf(>bid, bf + 15);
> build_id_msg = bf;
> }
> scnprintf(buf, buflen,
> diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
> index 1c332e78bbc3..b5648735f01f 100644
> --- a/tools/perf/util/build-id.c
> +++ b/tools/perf/util/build-id.c
> @@ -37,6 +37,7 @@
>
>  #include 
>  #include 
> +#include 
>
>  static bool no_buildid_cache;
>
> @@ -95,13 +96,13 @@ struct perf_tool build_id__mark_dso_hit_ops = {
> .ordered_events  = true,
>  };
>
> -int build_id__sprintf(const u8 *build_id, int len, char *bf)
> +int build_id__sprintf(const struct build_id *build_id, char *bf)
>  {
> char *bid = bf;
> -   const u8 *raw = build_id;
> -   int i;
> +   const u8 *raw = build_id->data;
> +   size_t i;
>
> -   for (i = 0; i < len; ++i) {
> +   for (i = 0; i < build_id->size; ++i) {
> sprintf(bid, "%02x", *raw);
> ++raw;
> bid += 2;
> @@ -125,7 +126,7 @@ int sysfs__sprintf_build_id(const char *root_dir, char 
> *sbuild_id)
> if (ret < 0)
> return ret;
>
> -   return build_id__sprintf(bid.data, sizeof(bid.data), sbuild_id);
> +   return build_id__sprintf(, 

Re: [PATCH v2] ARM: kprobes: Avoid fortify_panic() when copying optprobe template

2020-09-30 Thread Masami Hiramatsu
On Thu,  1 Oct 2020 13:59:27 +0930
Andrew Jeffery  wrote:

> Setting both CONFIG_KPROBES=y and CONFIG_FORTIFY_SOURCE=y on ARM leads
> to a panic in memcpy() when injecting a kprobe despite the fixes found
> in commit e46daee53bb5 ("ARM: 8806/1: kprobes: Fix false positive with
> FORTIFY_SOURCE") and commit 0ac569bf6a79 ("ARM: 8834/1: Fix: kprobes:
> optimized kprobes illegal instruction").
> 
> arch/arm/include/asm/kprobes.h effectively declares
> the target type of the optprobe_template_entry assembly label as a u32
> which leads memcpy()'s __builtin_object_size() call to determine that
> the pointed-to object is of size four. However, the symbol is used as a handle
> for the optimised probe assembly template that is at least 96 bytes in size.
> The symbol's use despite its type blows up the memcpy() in ARM's
> arch_prepare_optimized_kprobe() with a false-positive fortify_panic() when it
> should instead copy the optimised probe template into place:
> 
> ```
> $ sudo perf probe -a aspeed_g6_pinctrl_probe
> [  158.457252] detected buffer overflow in memcpy
> [  158.458069] [ cut here ]
> [  158.458283] kernel BUG at lib/string.c:1153!
> [  158.458436] Internal error: Oops - BUG: 0 [#1] SMP ARM
> [  158.458768] Modules linked in:
> [  158.459043] CPU: 1 PID: 99 Comm: perf Not tainted 
> 5.9.0-rc7-00038-gc53ebf8167e9 #158
> [  158.459296] Hardware name: Generic DT based system
> [  158.459529] PC is at fortify_panic+0x18/0x20
> [  158.459658] LR is at __irq_work_queue_local+0x3c/0x74
> [  158.459831] pc : [<8047451c>]lr : [<8020ecd4>]psr: 6013
> [  158.460032] sp : be2d1d50  ip : be2d1c58  fp : be2d1d5c
> [  158.460174] r10: 0006  r9 :   r8 : 0060
> [  158.460348] r7 : 8011e434  r6 : b9e0b800  r5 : 7f00  r4 : b9fe4f0c
> [  158.460557] r3 : 80c04cc8  r2 :   r1 : be7c03cc  r0 : 0022
> [  158.460801] Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment 
> none
> [  158.461037] Control: 10c5387d  Table: b9cd806a  DAC: 0051
> [  158.461251] Process perf (pid: 99, stack limit = 0x81c71a69)
> [  158.461472] Stack: (0xbe2d1d50 to 0xbe2d2000)
> [  158.461757] 1d40: be2d1d84 be2d1d60 
> 8011e724 80474510
> [  158.462104] 1d60: b9e0b800 b9fe4f0c  b9fe4f14 80c8ec80 be235000 
> be2d1d9c be2d1d88
> [  158.462436] 1d80: 801cee44 8011e57c b9fe4f0c  be2d1dc4 be2d1da0 
> 801d0ad0 801cedec
> [  158.462742] 1da0:   b9fe4f00 ffea  be235000 
> be2d1de4 be2d1dc8
> [  158.463087] 1dc0: 80204604 801d0738   b9fe4004 ffea 
> be2d1e94 be2d1de8
> [  158.463428] 1de0: 80205434 80204570 00385c00    
> be2d1e14 be2d1e08
> [  158.463880] 1e00: 802ba014 b9fe4f00 b9e718c0 b9fe4f84 b9e71ec8 be2d1e24 
>  00385c00
> [  158.464365] 1e20:  626f7270 0065 802b905c be2d1e94 002e 
>  802b9914
> [  158.464829] 1e40: be2d1e84 be2d1e50 802b9914 8028ff78 804629d0 b9e71ec0 
> 002e b9e71ec0
> [  158.465141] 1e60: be2d1ea8 80c04cc8 0cc0 b9e713c4 0002 80205834 
> 80205834 002e
> [  158.465488] 1e80: be235000 be235000 be2d1ea4 be2d1e98 80205854 80204e94 
> be2d1ecc be2d1ea8
> [  158.465806] 1ea0: 801ee4a0 80205840 0002 80c04cc8  002e 
> 002e 
> [  158.466110] 1ec0: be2d1f0c be2d1ed0 801ee5c8 801ee428  be2d 
> 006b1fd0 0051
> [  158.466398] 1ee0:  b9eedf00 002e 80204410 006b1fd0 be2d1f60 
>  0004
> [  158.466763] 1f00: be2d1f24 be2d1f10 8020442c 801ee4c4 80205834 802c613c 
> be2d1f5c be2d1f28
> [  158.467102] 1f20: 802c60ac 8020441c be2d1fac be2d1f38 8010c764 802e9888 
> be2d1f5c b9eedf00
> [  158.467447] 1f40: b9eedf00 006b1fd0 002e  be2d1f94 be2d1f60 
> 802c634c 802c5fec
> [  158.467812] 1f60:    80c04cc8 006b1fd0 0003 
> 76f7a610 0004
> [  158.468155] 1f80: 80100284 be2d be2d1fa4 be2d1f98 802c63ec 802c62e8 
>  be2d1fa8
> [  158.468508] 1fa0: 80100080 802c63e0 006b1fd0 0003 0003 006b1fd0 
> 002e 
> [  158.468858] 1fc0: 006b1fd0 0003 76f7a610 0004 006b1fb0 0026d348 
> 0017 7ef2738c
> [  158.469202] 1fe0: 76f3431c 7ef272d8 0014ec50 76f34338 6010 0003 
>  
> [  158.469461] Backtrace:
> [  158.469683] [<80474504>] (fortify_panic) from [<8011e724>] 
> (arch_prepare_optimized_kprobe+0x1b4/0x1f8)
> [  158.470021] [<8011e570>] (arch_prepare_optimized_kprobe) from [<801cee44>] 
> (alloc_aggr_kprobe+0x64/0x70)
> [  158.470287]  r9:be235000 r8:80c8ec80 r7:b9fe4f14 r6: r5:b9fe4f0c 
> r4:b9e0b800
> [  158.470478] [<801cede0>] (alloc_aggr_kprobe) from [<801d0ad0>] 
> (register_kprobe+0x3a4/0x5a0)
> [  158.470685]  r5: r4:b9fe4f0c
> [  158.470790] [<801d072c>] (register_kprobe) from [<80204604>] 
> (__register_trace_kprobe+0xa0/0xa4)
> [  158.471001]  r9:be235000 r8: r7:ffea r6:b9fe4f00 r5: 
> r4:
> [  

Re: [PATCH 4/9] perf tools: Pass build id object to sysfs__read_build_id

2020-09-30 Thread Ian Rogers
On Wed, Sep 30, 2020 at 10:15 AM Jiri Olsa  wrote:
>
> Passing build id object to sysfs__read_build_id function,
> so it can populate the size of the build_id object.
>
> Signed-off-by: Jiri Olsa 

Acked-by: Ian Rogers 

Thanks,
Ian

> ---
>  tools/perf/util/build-id.c   |  6 +++---
>  tools/perf/util/dso.c|  6 ++
>  tools/perf/util/symbol-elf.c | 11 +--
>  tools/perf/util/symbol-minimal.c |  7 ++-
>  tools/perf/util/symbol.c |  7 +++
>  tools/perf/util/symbol.h |  2 +-
>  6 files changed, 16 insertions(+), 23 deletions(-)
>
> diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
> index 62b258aaa128..1c332e78bbc3 100644
> --- a/tools/perf/util/build-id.c
> +++ b/tools/perf/util/build-id.c
> @@ -113,7 +113,7 @@ int build_id__sprintf(const u8 *build_id, int len, char 
> *bf)
>  int sysfs__sprintf_build_id(const char *root_dir, char *sbuild_id)
>  {
> char notes[PATH_MAX];
> -   u8 build_id[BUILD_ID_SIZE];
> +   struct build_id bid;
> int ret;
>
> if (!root_dir)
> @@ -121,11 +121,11 @@ int sysfs__sprintf_build_id(const char *root_dir, char 
> *sbuild_id)
>
> scnprintf(notes, sizeof(notes), "%s/sys/kernel/notes", root_dir);
>
> -   ret = sysfs__read_build_id(notes, build_id, sizeof(build_id));
> +   ret = sysfs__read_build_id(notes, );
> if (ret < 0)
> return ret;
>
> -   return build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
> +   return build_id__sprintf(bid.data, sizeof(bid.data), sbuild_id);
>  }
>
>  int filename__sprintf_build_id(const char *pathname, char *sbuild_id)
> diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
> index d2c1ed08c879..e87fa9a71d9f 100644
> --- a/tools/perf/util/dso.c
> +++ b/tools/perf/util/dso.c
> @@ -1346,8 +1346,7 @@ void dso__read_running_kernel_build_id(struct dso *dso, 
> struct machine *machine)
> if (machine__is_default_guest(machine))
> return;
> sprintf(path, "%s/sys/kernel/notes", machine->root_dir);
> -   if (sysfs__read_build_id(path, dso->bid.data,
> -sizeof(dso->bid.data)) == 0)
> +   if (sysfs__read_build_id(path, >bid) == 0)
> dso->has_build_id = true;
>  }
>
> @@ -1365,8 +1364,7 @@ int dso__kernel_module_get_build_id(struct dso *dso,
>  "%s/sys/module/%.*s/notes/.note.gnu.build-id",
>  root_dir, (int)strlen(name) - 1, name);
>
> -   if (sysfs__read_build_id(filename, dso->bid.data,
> -sizeof(dso->bid.data)) == 0)
> +   if (sysfs__read_build_id(filename, >bid) == 0)
> dso->has_build_id = true;
>
> return 0;
> diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
> index 61d7c444e6f5..97a55f162ea5 100644
> --- a/tools/perf/util/symbol-elf.c
> +++ b/tools/perf/util/symbol-elf.c
> @@ -595,13 +595,11 @@ int filename__read_build_id(const char *filename, 
> struct build_id *bid)
>
>  #endif // HAVE_LIBBFD_BUILDID_SUPPORT
>
> -int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
> +int sysfs__read_build_id(const char *filename, struct build_id *bid)
>  {
> +   size_t size = sizeof(bid->data);
> int fd, err = -1;
>
> -   if (size < BUILD_ID_SIZE)
> -   goto out;
> -
> fd = open(filename, O_RDONLY);
> if (fd < 0)
> goto out;
> @@ -622,8 +620,9 @@ int sysfs__read_build_id(const char *filename, void 
> *build_id, size_t size)
> break;
> if (memcmp(bf, "GNU", sizeof("GNU")) == 0) {
> size_t sz = min(descsz, size);
> -   if (read(fd, build_id, sz) == (ssize_t)sz) {
> -   memset(build_id + sz, 0, size - sz);
> +   if (read(fd, bid->data, sz) == (ssize_t)sz) {
> +   memset(bid->data + sz, 0, size - sz);
> +   bid->size = sz;
> err = 0;
> break;
> }
> diff --git a/tools/perf/util/symbol-minimal.c 
> b/tools/perf/util/symbol-minimal.c
> index 5173331ee6e4..dba6b9e5d64e 100644
> --- a/tools/perf/util/symbol-minimal.c
> +++ b/tools/perf/util/symbol-minimal.c
> @@ -222,9 +222,8 @@ int filename__read_build_id(const char *filename, struct 
> build_id *bid)
> return ret;
>  }
>
> -int sysfs__read_build_id(const char *filename, void *build_id, size_t size 
> __maybe_unused)
> +int sysfs__read_build_id(const char *filename, struct build_id *bid)
>  {
> -   struct build_id bid;
> int fd;
> int ret = -1;
> struct stat stbuf;
> @@ -246,9 +245,7 @@ int sysfs__read_build_id(const char *filename, void 
> *build_id, size_t size __may
> if 

Re: [PATCH v4 5/7] clk: axi-clkgen: Respect ZYNQMP PFD/VCO frequency limits

2020-09-30 Thread Alexandru Ardelean
On Wed, Sep 30, 2020 at 8:16 PM Moritz Fischer  wrote:
>
> On Wed, Sep 30, 2020 at 08:22:23AM +0300, Alexandru Ardelean wrote:
> > On Tue, Sep 29, 2020 at 6:30 PM Moritz Fischer  wrote:
> > >
> > > Hi Alexandru,
> > >
> > > On Tue, Sep 29, 2020 at 05:44:15PM +0300, Alexandru Ardelean wrote:
> > > > From: Mathias Tausen 
> > > >
> > > > Since axi-clkgen is now supported on ZYNQMP, make sure the max/min
> > > > frequencies of the PFD and VCO are respected.
> > > >
> > > > Signed-off-by: Mathias Tausen 
> > > > Signed-off-by: Alexandru Ardelean 
> > >
> > > This patch still does not cover the PCIe Zynq plugged into ZynqMP linux
> > > machine case.
> > >
> > > > ---
> > > >  drivers/clk/clk-axi-clkgen.c | 9 +
> > > >  1 file changed, 9 insertions(+)
> > > >
> > > > diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c
> > > > index 4342b7735590..2319bb1c5c08 100644
> > > > --- a/drivers/clk/clk-axi-clkgen.c
> > > > +++ b/drivers/clk/clk-axi-clkgen.c
> > > > @@ -108,12 +108,21 @@ static uint32_t axi_clkgen_lookup_lock(unsigned 
> > > > int m)
> > > >   return 0x1f1f00fa;
> > > >  }
> > > >
> > > > +#ifdef ARCH_ZYNQMP
> > > > +static const struct axi_clkgen_limits axi_clkgen_default_limits = {
> > > > + .fpfd_min = 1,
> > > > + .fpfd_max = 45,
> > > > + .fvco_min = 80,
> > > > + .fvco_max = 160,
> > > > +};
> > > > +#else
> > > >  static const struct axi_clkgen_limits axi_clkgen_default_limits = {
> > > >   .fpfd_min = 1,
> > > >   .fpfd_max = 30,
> > > >   .fvco_min = 60,
> > > >   .fvco_max = 120,
> > > >  };
> > > > +#endif
> > >
> > > I still don't understand this. You have a way to determine which fabric
> > > you are looking at with the FPGA info. Why not:
> > >
> > > [..] axi_clkgen_zynqmp_default_limits = {
> > > };
> > >
> > > [..] axi_clkgen_default_limits = {
> > > };
> > >
> > > Set them based on what you read back, i.e. determine which fabric you
> > > are looking at *per clock gen* and use that info, rather than making a
> > > compile time decision to support only one of them.
> > >
> > > Generally speaking #ifdef $ARCH should be a last resort solution.
> >
> > The support for reading back the fabric parameters is implemented in
> > the AXI CLKGEN PCORE version starting with 5.0.a
> > Links:
> > https://github.com/analogdevicesinc/hdl/commits/master/library/common/up_clkgen.v
> > https://github.com/analogdevicesinc/hdl/commit/66823682b63c1037abdc3fc1dd4d4e63d3cfbc1a
> > https://github.com/analogdevicesinc/hdl/commit/7dcb2050c7946fab5ea5a273eda7c53ea7b969a6
> >
> > Before that version, these details aren't there, so the best you can
> > do is assume compile-time ARCH defaults.
>
> This is a property of the instance and not of the driver. If you can't
> query the hardware to figure out what you're looking at, but have
> different behaviours, please use different compatible strings and make
> the default limits platform data.
>
> Something like this:
>
> static const struct of_device_id axi_clkgen_ids[] = {
> {
> .compatible = "foo-zynqmp",
> .data = _default_limits,
> },
> {
> .compatible = "bar-zynq",
> .data = _default_limits,
> },
>
> { },
> };
>

oh, apologies for not thinking about this;
i'll spin this up

thanks
Alex

> And pull the info out in your probe function, then you can have both
> configurations and select via device-tree.
>
> Thanks,
> Moritz


Re: [PATCH 3/9] perf tools: Pass build_id object to filename__read_build_id

2020-09-30 Thread Ian Rogers
On Wed, Sep 30, 2020 at 10:15 AM Jiri Olsa  wrote:
>
> Passing build_id object to filename__read_build_id function,
> so it can populate the size of the build_id object.
>
> Changing filename__read_build_id code for both elf/non-elf
> code.
>
> Signed-off-by: Jiri Olsa 

Acked-by: Ian Rogers 

Thanks,
Ian

> ---
>  tools/perf/builtin-buildid-cache.c | 25 +++---
>  tools/perf/builtin-inject.c|  3 +--
>  tools/perf/tests/pe-file-parsing.c | 10 -
>  tools/perf/tests/sdt.c |  6 +++---
>  tools/perf/util/build-id.c |  8 +++
>  tools/perf/util/dsos.c |  3 +--
>  tools/perf/util/symbol-elf.c   | 16 --
>  tools/perf/util/symbol-minimal.c   | 34 +-
>  tools/perf/util/symbol.c   |  6 +++---
>  tools/perf/util/symbol.h   |  3 ++-
>  10 files changed, 59 insertions(+), 55 deletions(-)
>
> diff --git a/tools/perf/builtin-buildid-cache.c 
> b/tools/perf/builtin-buildid-cache.c
> index a523c629f321..c3cb168d546d 100644
> --- a/tools/perf/builtin-buildid-cache.c
> +++ b/tools/perf/builtin-buildid-cache.c
> @@ -174,19 +174,19 @@ static int build_id_cache__add_kcore(const char 
> *filename, bool force)
>  static int build_id_cache__add_file(const char *filename, struct nsinfo *nsi)
>  {
> char sbuild_id[SBUILD_ID_SIZE];
> -   u8 build_id[BUILD_ID_SIZE];
> +   struct build_id bid;
> int err;
> struct nscookie nsc;
>
> nsinfo__mountns_enter(nsi, );
> -   err = filename__read_build_id(filename, _id, sizeof(build_id));
> +   err = filename__read_build_id(filename, );
> nsinfo__mountns_exit();
> if (err < 0) {
> pr_debug("Couldn't read a build-id in %s\n", filename);
> return -1;
> }
>
> -   build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
> +   build_id__sprintf(bid.data, sizeof(bid.data), sbuild_id);
> err = build_id_cache__add_s(sbuild_id, filename, nsi,
> false, false);
> pr_debug("Adding %s %s: %s\n", sbuild_id, filename,
> @@ -196,21 +196,21 @@ static int build_id_cache__add_file(const char 
> *filename, struct nsinfo *nsi)
>
>  static int build_id_cache__remove_file(const char *filename, struct nsinfo 
> *nsi)
>  {
> -   u8 build_id[BUILD_ID_SIZE];
> char sbuild_id[SBUILD_ID_SIZE];
> +   struct build_id bid;
> struct nscookie nsc;
>
> int err;
>
> nsinfo__mountns_enter(nsi, );
> -   err = filename__read_build_id(filename, _id, sizeof(build_id));
> +   err = filename__read_build_id(filename, );
> nsinfo__mountns_exit();
> if (err < 0) {
> pr_debug("Couldn't read a build-id in %s\n", filename);
> return -1;
> }
>
> -   build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
> +   build_id__sprintf(bid.data, sizeof(bid.data), sbuild_id);
> err = build_id_cache__remove_s(sbuild_id);
> pr_debug("Removing %s %s: %s\n", sbuild_id, filename,
>  err ? "FAIL" : "Ok");
> @@ -274,17 +274,16 @@ static int build_id_cache__purge_all(void)
>  static bool dso__missing_buildid_cache(struct dso *dso, int parm 
> __maybe_unused)
>  {
> char filename[PATH_MAX];
> -   u8 build_id[BUILD_ID_SIZE];
> +   struct build_id bid;
>
> if (dso__build_id_filename(dso, filename, sizeof(filename), false) &&
> -   filename__read_build_id(filename, build_id,
> -   sizeof(build_id)) != sizeof(build_id)) {
> +   filename__read_build_id(filename, ) == -1) {
> if (errno == ENOENT)
> return false;
>
> pr_warning("Problems with %s file, consider removing it from 
> the cache\n",
>filename);
> -   } else if (memcmp(dso->bid.data, build_id, sizeof(dso->bid.data))) {
> +   } else if (memcmp(dso->bid.data, bid.data, bid.size)) {
> pr_warning("Problems with %s file, consider removing it from 
> the cache\n",
>filename);
> }
> @@ -300,14 +299,14 @@ static int build_id_cache__fprintf_missing(struct 
> perf_session *session, FILE *f
>
>  static int build_id_cache__update_file(const char *filename, struct nsinfo 
> *nsi)
>  {
> -   u8 build_id[BUILD_ID_SIZE];
> char sbuild_id[SBUILD_ID_SIZE];
> +   struct build_id bid;
> struct nscookie nsc;
>
> int err;
>
> nsinfo__mountns_enter(nsi, );
> -   err = filename__read_build_id(filename, _id, sizeof(build_id));
> +   err = filename__read_build_id(filename, );
> nsinfo__mountns_exit();
> if (err < 0) {
> pr_debug("Couldn't read a build-id in %s\n", filename);
> @@ -315,7 +314,7 @@ static int build_id_cache__update_file(const char 
> *filename, struct nsinfo *nsi)
> }
> err = 0;
>
> - 

Re: dma-coherent property for PCIe Root

2020-09-30 Thread Jon Masters

On 9/14/20 1:23 AM, Valmiki wrote:

Hi All,

How does "dma-coherent" property will work for PCIe as RC on an
ARM SOC ?
Because the end point device drivers are the one which will request dma 
buffers and Root port driver doesn't involve in data path of end point

except for handling interrupts.

How does EP DMA buffers will be hardware coherent if RC driver exposes
dma-coherent property ?


This simply means that the RC supports maintaining coherency, it doesn't 
mean that the RC driver does anything. It's a property of the hardware.


Jon.

--
Computer Architect


Re: [PATCH v2 3/3] doc: dev-tools: kselftest.rst: Update examples and paths

2020-09-30 Thread Naresh Kamboju
On Tue, 29 Sep 2020 at 01:56, Kees Cook  wrote:
>
> Update the installation commands and path details, detail the new
> options available in the run_kselftests.sh script.
>
> Signed-off-by: Kees Cook 

Reviewed-by: Naresh Kamboju 

> ---
>  Documentation/dev-tools/kselftest.rst | 35 +--
>  1 file changed, 22 insertions(+), 13 deletions(-)
>
> diff --git a/Documentation/dev-tools/kselftest.rst 
> b/Documentation/dev-tools/kselftest.rst
> index 469d115a95f1..a901def730d9 100644
> --- a/Documentation/dev-tools/kselftest.rst
> +++ b/Documentation/dev-tools/kselftest.rst
> @@ -125,32 +125,41 @@ Note that some tests will require root privileges.
>  Install selftests
>  =
>
> -You can use the kselftest_install.sh tool to install selftests in the
> -default location, which is tools/testing/selftests/kselftest, or in a
> -user specified location.
> +You can use the "install" target of "make" (which calls the 
> `kselftest_install.sh`
> +tool) to install selftests in the default location 
> (`tools/testing/selftests/kselftest_install`),
> +or in a user specified location via the `INSTALL_PATH` "make" variable.
>
>  To install selftests in default location::
>
> -   $ cd tools/testing/selftests
> -   $ ./kselftest_install.sh
> +   $ make -C tools/testing/selftests install
>
>  To install selftests in a user specified location::
>
> -   $ cd tools/testing/selftests
> -   $ ./kselftest_install.sh install_dir
> +   $ make -C tools/testing/selftests install INSTALL_PATH=/some/other/path
>
>  Running installed selftests
>  ===
>
> -Kselftest install as well as the Kselftest tarball provide a script
> -named "run_kselftest.sh" to run the tests.
> +Found in the install directory, as well as in the Kselftest tarball,
> +is a script named `run_kselftest.sh` to run the tests.
>
>  You can simply do the following to run the installed Kselftests. Please
>  note some tests will require root privileges::
>
> -   $ cd kselftest
> +   $ cd kselftest_install
> $ ./run_kselftest.sh
>
> +To see the list of available tests, the `-l` option can be used::
> +
> +   $ ./run_kselftest.sh -l
> +
> +The `-c` option can be used to run all the tests from a test collection, or
> +the `-t` option for specific single tests. Either can be used multiple 
> times::
> +
> +   $ ./run_kselftest.sh -c bpf -c seccomp -t timers:posix_timers -t 
> timer:nanosleep
> +
> +For other features see the script usage output, seen with the `-h` option.
> +
>  Packaging selftests
>  ===
>
> @@ -160,9 +169,9 @@ different system. To package selftests, run::
> $ make -C tools/testing/selftests gen_tar
>
>  This generates a tarball in the `INSTALL_PATH/kselftest-packages` directory. 
> By
> -default, `.gz` format is used. The tar format can be overridden by specifying
> -a `FORMAT` make variable. Any value recognized by `tar's auto-compress`_ 
> option
> -is supported, such as::
> +default, `.gz` format is used. The tar compression format can be overridden 
> by
> +specifying a `FORMAT` make variable. Any value recognized by `tar's 
> auto-compress`_
> +option is supported, such as::
>
>  $ make -C tools/testing/selftests gen_tar FORMAT=.xz
>
> --
> 2.25.1
>

- Naresh


Re: [PATCH v2 2/3] selftests/run_kselftest.sh: Make each test individually selectable

2020-09-30 Thread Naresh Kamboju
On Tue, 29 Sep 2020 at 01:56, Kees Cook  wrote:
>
> Currently with run_kselftest.sh there is no way to choose which test
> we could run. All the tests listed in kselftest-list.txt are all run
> every time. This patch enhanced the run_kselftest.sh to make the test
> collections (or tests) individually selectable. e.g.:
>
> $ ./run_kselftest.sh -c seccomp -t timers:posix_timers -t timers:nanosleep
>
> Additionally adds a way to list all known tests with "-l", usage
> with "-h", and perform a dry run without running tests with "-n".
>
> Co-developed-by: Hangbin Liu 
> Signed-off-by: Hangbin Liu 
> Signed-off-by: Kees Cook 

Tested-by: Naresh Kamboju 

- Naresh


Re: [PATCH v2 1/3] selftests: Extract run_kselftest.sh and generate stand-alone test list

2020-09-30 Thread Naresh Kamboju
On Tue, 29 Sep 2020 at 01:56, Kees Cook  wrote:
>
> Instead of building a script on the fly (which just repeats the same
> thing for each test collection), move the script out of the Makefile and
> into run_kselftest.sh, which reads kselftest-list.txt.
>
> Adjust the emit_tests target to report each test on a separate line so
> that test running tools (e.g. LAVA) can easily remove individual
> tests (for example, as seen in [1]).
>
> [1] 
> https://github.com/Linaro/test-definitions/pull/208/commits/2e7b62155e4998e54ac0587704932484d4ff84c8
>
> Signed-off-by: Kees Cook 

Tested-by: Naresh Kamboju 

- Naresh


Re: [PATCH blk-next 0/2] Delete the get_vector_affinity leftovers

2020-09-30 Thread Leon Romanovsky
On Tue, Sep 29, 2020 at 12:13:56PM +0300, Leon Romanovsky wrote:
> From: Leon Romanovsky 
>
> There are no drivers that implement .get_vector_affinity(), so delete
> the RDMA function and simplify block code.
>
> Thanks
>
> P.S. Probably it should go through block tree.
>
> Leon Romanovsky (2):
>   blk-mq-rdma: Delete not-used multi-queue RDMA map queue code
>   RDMA/core: Delete not-implemented get_vector_affinity

Jens, Keith

How can we progress here?

Thanks

>
>  block/Kconfig|  5 
>  block/Makefile   |  1 -
>  block/blk-mq-rdma.c  | 44 
>  drivers/infiniband/core/device.c |  1 -
>  drivers/nvme/host/rdma.c |  7 ++---
>  include/linux/blk-mq-rdma.h  | 11 
>  include/rdma/ib_verbs.h  | 23 -
>  7 files changed, 2 insertions(+), 90 deletions(-)
>  delete mode 100644 block/blk-mq-rdma.c
>  delete mode 100644 include/linux/blk-mq-rdma.h
>
> --
> 2.26.2
>


Litmus test for question from Al Viro

2020-09-30 Thread Paul E. McKenney
Hello!

Al Viro posted the following query:



 fun question regarding barriers, if you have time for that
 V->A = V->B = 1;

 CPU1:
 to_free = NULL
 spin_lock()
 if (!smp_load_acquire(>B))
 to_free = V
 V->A = 0
 spin_unlock()
 kfree(to_free)

 CPU2:
 to_free = V;
 if (READ_ONCE(V->A)) {
 spin_lock()
 if (V->A)
 to_free = NULL
 smp_store_release(>B, 0);
 spin_unlock()
 }
 kfree(to_free);
 1) is it guaranteed that V will be freed exactly once and that
  no accesses to *V will happen after freeing it?
 2) do we need smp_store_release() there?  I.e. will anything
  break if it's replaced with plain V->B = 0?



Of course herd7 supports neither structures nor arrays, but I was
crazy enough to try individual variables with made-up address and data
dependencies.  This litmus test must also detect use-after-free bugs,
but a simple variable should be able to do that.  So here is a
prototype:



C C-viro-2020.09.29a

{
int a = 1;
int b = 1;
int v = 1;
}


P0(int *a, int *b, int *v, spinlock_t *l)
{
int r0;
int r1;
int r2 = 2;
int r8;
int r9a = 2;
int r9b = 2;

r0 = 0;
spin_lock(l);
r9a = READ_ONCE(*v); // Use after free?
r8 = r9a - r9a; // Restore address dependency
r8 = b + r8;
r1 = smp_load_acquire(r8);
if (r1 == 0)
r0 = 1;
r9b = READ_ONCE(*v); // Use after free?
WRITE_ONCE(*a, r9b - r9b); // Use data dependency
spin_unlock(l);
if (r0) {
r2 = READ_ONCE(*v);
WRITE_ONCE(*v, 0); /* kfree(). */
}
}

P1(int *a, int *b, int *v, spinlock_t *l)
{
int r0;
int r1;
int r1a;
int r2 = 2;
int r8;
int r9a = 2;
int r9b = 2;
int r9c = 2;

r0 = READ_ONCE(*v);
r9a = r0; // Use after free?
r8 = r9a - r9a; // Restore address dependency
r8 = a + r8;
r1 = READ_ONCE(*r8);
if (r1) {
spin_lock(l);
r9b = READ_ONCE(*v); // Use after free?
r8 = r9b - r9b; // Restore address dependency
r8 = a + r8;
r1a = READ_ONCE(*r8);
if (r1a)
r0 = 0;
r9c = READ_ONCE(*v); // Use after free?
smp_store_release(b, r9c - rc9); // Use data dependency
spin_unlock(l);
}
if (r0) {
r2 = READ_ONCE(*v);
WRITE_ONCE(*v, 0); /* kfree(). */
}
}

locations [a;b;v;0:r1;0:r8;1:r1;1:r8]
exists (0:r0=1:r0 \/ (* Both or neither did kfree(). *)
v=1 \/ (* Neither did kfree, redundant check. *)
0:r2=0 \/ 1:r2=0 \/  (* Both did kfree, redundant check. *)
0:r9a=0 \/ 0:r9b=0 \/ 1:r9a=0 \/ (* CPU1 use after free. *)
1:r9b=0 \/ 1:r9c=0) (* CPU2 use after free. *)



This "exists" clause is satisfied:



$ herd7 -conf linux-kernel.cfg 
~/paper/scalability/LWNLinuxMM/litmus/manual/kernel/C-viro-2020.09.29a.litmus
Test C-viro-2020.09.29a Allowed
States 5
0:r0=0; 0:r1=1; 0:r2=2; 0:r8=b; 0:r9a=0; 0:r9b=0; 1:r0=1; 1:r1=0; 1:r2=1; 
1:r8=a; 1:r9a=1; 1:r9b=2; 1:r9c=2; a=0; b=1; v=0;
0:r0=0; 0:r1=1; 0:r2=2; 0:r8=b; 0:r9a=1; 0:r9b=0; 1:r0=1; 1:r1=0; 1:r2=1; 
1:r8=a; 1:r9a=1; 1:r9b=2; 1:r9c=2; a=0; b=1; v=0;
0:r0=0; 0:r1=1; 0:r2=2; 0:r8=b; 0:r9a=1; 0:r9b=1; 1:r0=0; 1:r1=1; 1:r2=2; 
1:r8=a; 1:r9a=1; 1:r9b=1; 1:r9c=1; a=0; b=1; v=1;
0:r0=0; 0:r1=1; 0:r2=2; 0:r8=b; 0:r9a=1; 0:r9b=1; 1:r0=1; 1:r1=0; 1:r2=1; 
1:r8=a; 1:r9a=1; 1:r9b=2; 1:r9c=2; a=0; b=1; v=0;
0:r0=0; 0:r1=1; 0:r2=2; 0:r8=b; 0:r9a=1; 0:r9b=1; 1:r0=1; 1:r1=1; 1:r2=1; 
1:r8=a; 1:r9a=1; 1:r9b=1; 1:r9c=1; a=0; b=1; v=0;
Ok
Witnesses
Positive: 3 Negative: 2
Condition exists (0:r0=1:r0 \/ v=1 \/ 0:r2=0 \/ 1:r2=0 \/ 0:r9a=0 \/ 0:r9b=0 \/ 
1:r9a=0 \/ 1:r9b=0 \/ 1:r9c=0)
Observation C-viro-2020.09.29a Sometimes 3 2
Time C-viro-2020.09.29a 14.33
Hash=89f74abff4de682ee0bea8ee6dd53134



So did we end up with herd7 not respecting "fake" dependencies like
those shown above, or have I just messed up the translation from Al's
example to the litmus test?  (Given one thing and another over the past
couple of days, my guess would be that I just messed up the translation,
especially given that I don't see a reference to fake dependencies in
the 

RE: [PATCH 5/8] usb: cdns3: Changed type of gadget_dev in cdns structure

2020-09-30 Thread Pawel Laszczak
>
>On 20-09-28 14:27:38, Pawel Laszczak wrote:
>> Patch changes the type for gadget_dev pointer in cdns structure from
>> pointer to cdns3_device structure to void pointer.
>> This filed is in reusable code and after this change it will be used to
>> point to both cdns3_device or cdnsp_device objects.
>>
>> Signed-off-by: Pawel Laszczak 
>> ---
>>  drivers/usb/cdns3/core.h   | 4 ++--
>>  drivers/usb/cdns3/gadget.c | 6 ++
>>  2 files changed, 8 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/usb/cdns3/core.h b/drivers/usb/cdns3/core.h
>> index 0c6e14683b36..267923904a37 100644
>> --- a/drivers/usb/cdns3/core.h
>> +++ b/drivers/usb/cdns3/core.h
>> @@ -55,7 +55,7 @@ struct cdns_role_driver {
>>   * @roles: array of supported roles for this controller
>>   * @role: current role
>>   * @host_dev: the child host device pointer for cdns core
>> - * @gadget_dev: the child gadget device pointer for cdns3 core
>> + * @gadget_dev: the child gadget device pointer
>>   * @usb2_phy: pointer to USB2 PHY
>>   * @usb3_phy: pointer to USB3 PHY
>>   * @mutex: the mutex for concurrent code at driver
>> @@ -87,7 +87,7 @@ struct cdns {
>>  struct cdns_role_driver *roles[USB_ROLE_DEVICE + 1];
>>  enum usb_role   role;
>>  struct platform_device  *host_dev;
>> -struct cdns3_device *gadget_dev;
>> +void*gadget_dev;
>>  struct phy  *usb2_phy;
>>  struct phy  *usb3_phy;
>>  /* mutext used in workqueue*/
>> diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c
>> index 26f68182e65e..f9cbc84bbfb8 100644
>> --- a/drivers/usb/cdns3/gadget.c
>> +++ b/drivers/usb/cdns3/gadget.c
>> @@ -3177,7 +3177,9 @@ static int __cdns3_gadget_init(struct cdns *cdns)
>>  static int cdns3_gadget_suspend(struct cdns *cdns, bool do_wakeup)
>>  {
>>  struct cdns3_device *priv_dev = cdns->gadget_dev;
>> +unsigned long flags;
>>
>> +spin_lock_irqsave(_dev->lock, flags);
>
>unrelated changes?

It's needed but this patch has missing removing this line from:
cdns3_suspend/cdns3_resume from core.c file. 
It exists in patch 2 (usb: cdns3: Split core.c into cdns3-plat and core.c file).
I will correct this patch. 

I had to move this spin_lock because in core.c we don't know the 
cdns->gadget_dev type (void * gadget_dev).

Thanks,
Pawel Laszczak

>
>>  cdns3_disconnect_gadget(priv_dev);
>>
>>  priv_dev->gadget.speed = USB_SPEED_UNKNOWN;
>> @@ -3186,6 +3188,7 @@ static int cdns3_gadget_suspend(struct cdns *cdns, 
>> bool do_wakeup)
>>
>>  /* disable interrupt for device */
>>  writel(0, _dev->regs->usb_ien);
>> +spin_unlock_irqrestore(_dev->lock, flags);
>>
>>  return 0;
>>  }
>> @@ -3193,11 +3196,14 @@ static int cdns3_gadget_suspend(struct cdns *cdns, 
>> bool do_wakeup)
>>  static int cdns3_gadget_resume(struct cdns *cdns, bool hibernated)
>>  {
>>  struct cdns3_device *priv_dev = cdns->gadget_dev;
>> +unsigned long flags;
>>
>>  if (!priv_dev->gadget_driver)
>>  return 0;
>>
>> +spin_lock_irqsave(_dev->lock, flags);
>
>ditto
>
>>  cdns3_gadget_config(priv_dev);
>> +spin_unlock_irqrestore(_dev->lock, flags);
>>
>>  return 0;
>>  }
>> --
>> 2.17.1
>>
>
>--
>
>Thanks,
>Peter Chen


Re: [PATCH] mmc: core: don't set limits.discard_granularity as 0

2020-09-30 Thread Coly Li
On 2020/10/1 01:23, Adrian Hunter wrote:
> On 30/09/20 7:08 pm, Coly Li wrote:
>> In mmc_queue_setup_discard() the mmc driver queue's discard_granularity
>> might be set as 0 (when card->pref_erase > max_discard) while the mmc
>> device still declares to support discard operation. This is buggy and
>> triggered the following kernel warning message,
>>
>> WARNING: CPU: 0 PID: 135 at __blkdev_issue_discard+0x200/0x294
>> CPU: 0 PID: 135 Comm: f2fs_discard-17 Not tainted 5.9.0-rc6 #1
>> Hardware name: Google Kevin (DT)
>> pstate: 0005 (nzcv daif -PAN -UAO BTYPE=--)
>> pc : __blkdev_issue_discard+0x200/0x294
>> lr : __blkdev_issue_discard+0x54/0x294
>> sp : 800011dd3b10
>> x29: 800011dd3b10 x28:  x27: 800011dd3cc4 x26: 
>> 800011dd3e18 x25: 0004e69b x24: 0c40 x23: 
>> f1deaaf0 x22: f2849200 x21: 002734d8 x20: 
>> 0008 x19:  x18:  x17: 
>>  x16:  x15:  x14: 
>> 0394 x13:  x12:  x11: 
>>  x10: 08b0 x9 : 800011dd3cb0 x8 : 
>> 0004e69b x7 :  x6 : f1926400 x5 : 
>> f1940800 x4 :  x3 : 0c40 x2 : 
>> 0008 x1 : 002734d8 x0 :  Call trace:
>> __blkdev_issue_discard+0x200/0x294
>> __submit_discard_cmd+0x128/0x374
>> __issue_discard_cmd_orderly+0x188/0x244
>> __issue_discard_cmd+0x2e8/0x33c
>> issue_discard_thread+0xe8/0x2f0
>> kthread+0x11c/0x120
>> ret_from_fork+0x10/0x1c
>> ---[ end trace e4c8023d33dfe77a ]---
>>
>> This patch fixes the issue by setting discard_granularity as SECTOR_SIZE
>> instead of 0 when (card->pref_erase > max_discard) is true. Now no more
>> complain from __blkdev_issue_discard() for the improper value of discard
>> granularity.
>>
>> Fixes: commit e056a1b5b67b ("mmc: queue: let host controllers specify 
>> maximum discard timeout")
> 
> That "Fixes" tag is a bit misleading.  For some time, the block layer had
> no problem with discard_granularity of zero, and blk_bio_discard_split()
> still doesn't (see below).
> 
> static struct bio *blk_bio_discard_split(struct request_queue *q,
>struct bio *bio,
>struct bio_set *bs,
>unsigned *nsegs)
> {
>   unsigned int max_discard_sectors, granularity;
>   int alignment;
>   sector_t tmp;
>   unsigned split_sectors;
> 
>   *nsegs = 1;
> 
>   /* Zero-sector (unknown) and one-sector granularities are the same.  */
>   granularity = max(q->limits.discard_granularity >> 9, 1U);
> 

>From Documentation/block/queue-sysfs.rst, the discard_granularity is
described as,

discard_granularity (RO)

This shows the size of internal allocation of the device in bytes, if
reported by the device. A value of '0' means device does not support
the discard functionality.


And from Documentation/ABI/testing/sysfs-block, the discard_granularity
is described as,

What:   /sys/block//queue/discard_granularity
Date:   May 2011
Contact:Martin K. Petersen 
Description:
Devices that support discard functionality may
internally allocate space using units that are bigger
than the logical block size. The discard_granularity
parameter indicates the size of the internal allocation
unit in bytes if reported by the device. Otherwise the
discard_granularity will be set to match the device's
physical block size. A discard_granularity of 0 means
that the device does not support discard functionality.


Therefore I took it as a bug when a driver sets its queue
discard_granularity as 0 but still announces to support discard operation.

But if you don't like the Fixes: tag, it is OK for me to remove it in
next version.

(CC Martin because he is the origin of the above information)

Thanks.

Coly Li


[PATCH v2] ARM: kprobes: Avoid fortify_panic() when copying optprobe template

2020-09-30 Thread Andrew Jeffery
Setting both CONFIG_KPROBES=y and CONFIG_FORTIFY_SOURCE=y on ARM leads
to a panic in memcpy() when injecting a kprobe despite the fixes found
in commit e46daee53bb5 ("ARM: 8806/1: kprobes: Fix false positive with
FORTIFY_SOURCE") and commit 0ac569bf6a79 ("ARM: 8834/1: Fix: kprobes:
optimized kprobes illegal instruction").

arch/arm/include/asm/kprobes.h effectively declares
the target type of the optprobe_template_entry assembly label as a u32
which leads memcpy()'s __builtin_object_size() call to determine that
the pointed-to object is of size four. However, the symbol is used as a handle
for the optimised probe assembly template that is at least 96 bytes in size.
The symbol's use despite its type blows up the memcpy() in ARM's
arch_prepare_optimized_kprobe() with a false-positive fortify_panic() when it
should instead copy the optimised probe template into place:

```
$ sudo perf probe -a aspeed_g6_pinctrl_probe
[  158.457252] detected buffer overflow in memcpy
[  158.458069] [ cut here ]
[  158.458283] kernel BUG at lib/string.c:1153!
[  158.458436] Internal error: Oops - BUG: 0 [#1] SMP ARM
[  158.458768] Modules linked in:
[  158.459043] CPU: 1 PID: 99 Comm: perf Not tainted 
5.9.0-rc7-00038-gc53ebf8167e9 #158
[  158.459296] Hardware name: Generic DT based system
[  158.459529] PC is at fortify_panic+0x18/0x20
[  158.459658] LR is at __irq_work_queue_local+0x3c/0x74
[  158.459831] pc : [<8047451c>]lr : [<8020ecd4>]psr: 6013
[  158.460032] sp : be2d1d50  ip : be2d1c58  fp : be2d1d5c
[  158.460174] r10: 0006  r9 :   r8 : 0060
[  158.460348] r7 : 8011e434  r6 : b9e0b800  r5 : 7f00  r4 : b9fe4f0c
[  158.460557] r3 : 80c04cc8  r2 :   r1 : be7c03cc  r0 : 0022
[  158.460801] Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
[  158.461037] Control: 10c5387d  Table: b9cd806a  DAC: 0051
[  158.461251] Process perf (pid: 99, stack limit = 0x81c71a69)
[  158.461472] Stack: (0xbe2d1d50 to 0xbe2d2000)
[  158.461757] 1d40: be2d1d84 be2d1d60 
8011e724 80474510
[  158.462104] 1d60: b9e0b800 b9fe4f0c  b9fe4f14 80c8ec80 be235000 
be2d1d9c be2d1d88
[  158.462436] 1d80: 801cee44 8011e57c b9fe4f0c  be2d1dc4 be2d1da0 
801d0ad0 801cedec
[  158.462742] 1da0:   b9fe4f00 ffea  be235000 
be2d1de4 be2d1dc8
[  158.463087] 1dc0: 80204604 801d0738   b9fe4004 ffea 
be2d1e94 be2d1de8
[  158.463428] 1de0: 80205434 80204570 00385c00    
be2d1e14 be2d1e08
[  158.463880] 1e00: 802ba014 b9fe4f00 b9e718c0 b9fe4f84 b9e71ec8 be2d1e24 
 00385c00
[  158.464365] 1e20:  626f7270 0065 802b905c be2d1e94 002e 
 802b9914
[  158.464829] 1e40: be2d1e84 be2d1e50 802b9914 8028ff78 804629d0 b9e71ec0 
002e b9e71ec0
[  158.465141] 1e60: be2d1ea8 80c04cc8 0cc0 b9e713c4 0002 80205834 
80205834 002e
[  158.465488] 1e80: be235000 be235000 be2d1ea4 be2d1e98 80205854 80204e94 
be2d1ecc be2d1ea8
[  158.465806] 1ea0: 801ee4a0 80205840 0002 80c04cc8  002e 
002e 
[  158.466110] 1ec0: be2d1f0c be2d1ed0 801ee5c8 801ee428  be2d 
006b1fd0 0051
[  158.466398] 1ee0:  b9eedf00 002e 80204410 006b1fd0 be2d1f60 
 0004
[  158.466763] 1f00: be2d1f24 be2d1f10 8020442c 801ee4c4 80205834 802c613c 
be2d1f5c be2d1f28
[  158.467102] 1f20: 802c60ac 8020441c be2d1fac be2d1f38 8010c764 802e9888 
be2d1f5c b9eedf00
[  158.467447] 1f40: b9eedf00 006b1fd0 002e  be2d1f94 be2d1f60 
802c634c 802c5fec
[  158.467812] 1f60:    80c04cc8 006b1fd0 0003 
76f7a610 0004
[  158.468155] 1f80: 80100284 be2d be2d1fa4 be2d1f98 802c63ec 802c62e8 
 be2d1fa8
[  158.468508] 1fa0: 80100080 802c63e0 006b1fd0 0003 0003 006b1fd0 
002e 
[  158.468858] 1fc0: 006b1fd0 0003 76f7a610 0004 006b1fb0 0026d348 
0017 7ef2738c
[  158.469202] 1fe0: 76f3431c 7ef272d8 0014ec50 76f34338 6010 0003 
 
[  158.469461] Backtrace:
[  158.469683] [<80474504>] (fortify_panic) from [<8011e724>] 
(arch_prepare_optimized_kprobe+0x1b4/0x1f8)
[  158.470021] [<8011e570>] (arch_prepare_optimized_kprobe) from [<801cee44>] 
(alloc_aggr_kprobe+0x64/0x70)
[  158.470287]  r9:be235000 r8:80c8ec80 r7:b9fe4f14 r6: r5:b9fe4f0c 
r4:b9e0b800
[  158.470478] [<801cede0>] (alloc_aggr_kprobe) from [<801d0ad0>] 
(register_kprobe+0x3a4/0x5a0)
[  158.470685]  r5: r4:b9fe4f0c
[  158.470790] [<801d072c>] (register_kprobe) from [<80204604>] 
(__register_trace_kprobe+0xa0/0xa4)
[  158.471001]  r9:be235000 r8: r7:ffea r6:b9fe4f00 r5: 
r4:
[  158.471188] [<80204564>] (__register_trace_kprobe) from [<80205434>] 
(trace_kprobe_create+0x5ac/0x9ac)
[  158.471408]  r7:ffea r6:b9fe4004 r5: r4:
[  158.471553] [<80204e88>] (trace_kprobe_create) from [<80205854>] 

Re: [PATCH v6 0/5] Add shared workqueue support for idxd driver

2020-09-30 Thread Vinod Koul
Hi Dave,

On 30-09-20, 15:19, Dave Jiang wrote:
> 
> 
> On 9/24/2020 2:51 PM, Borislav Petkov wrote:
> > On Thu, Sep 24, 2020 at 02:32:35PM -0700, Dave Jiang wrote:
> > > Hi Vinod,
> > > Looks like we are cleared on the x86 patches for this series with sign 
> > > offs
> > > from maintainer Boris. Please consider the series for 5.10 inclusion. 
> > > Thank
> > > you!
> > 
> > As I said here, I'd strongly suggest we do this:
> > 
> > https://lists.01.org/hyperkitty/list/kbuild-...@lists.01.org/thread/5FKNWNCCRV3AXUAEXUGQFF4EDQNANF3F/
> > 
> > and Vinod should merge the x86/pasid branch. Otherwise is his branch
> > and incomplete you could not have tested it properly.
> > 
> 
> Hi Vinod,
> Just checking to see if you have any objections or concerns with respect to
> this series. We are hoping it can be queued for the 5.10 merge if there are
> no objections. Thanks!

I was out for last few days, so haven't checked on this yet, but given
that we are very close to merge widow I fear it is bit late to merge
this late. I will go thru the series today though..

Thanks
-- 
~Vinod


DONATION ..... 211

2020-09-30 Thread L. Wanczyk.
Hello,

I'm Mrs. Mavis Wanczyk, the mega winner of $758 Million in Mega Millions
Jackpot, I am donating to 5 random individuals if you get this email then
your email was selected after a spin ball. I have spread most of my wealth
over a number of charities and organizations. I have voluntarily decided to
donate the sum of $ 10 Million USD to you as one of the selected , to verify
my
winnings via YouTube page below.

WATCH ME HERE: https://www.youtube.com/watch?v=7kWnqvJM1mM

THIS IS YOUR DONATION CODE: F207162
Kindly send your direct telephone and fax number to enable me to reach you

Reply with the DONATION CODE to this email: maviswanczy...@aol.com

Hope to make you and your family happy.

Regards,
Mrs. Mavis L. Wanczyk.



Re: [PATCH V3 1/8] sysfs: Add sysfs_emit and sysfs_emit_at to format sysfs output

2020-09-30 Thread Joe Perches
On Wed, 2020-09-30 at 21:17 -0700, Kees Cook wrote:
> On Wed, Sep 30, 2020 at 01:57:40PM +0200, Greg Kroah-Hartman wrote:
> > Kees, and Rafael, I don't know if you saw this proposal from Joe for
> > sysfs files, questions below:
> 
> I'm a fan. I think the use of sprintf() in sysfs might have been one of
> my earliest complaints about unsafe code patterns in the kernel. ;)
[]
> > > + if (WARN(!buf || offset_in_page(buf),
> > > +  "invalid sysfs_emit: buf:%p\n", buf))

The dump_stack() is also going to emit pointers
so I don't see how it does anything but help
show where the buffer was.  It is hashed...

> I don't want the %p here, but otherwise, sure. I'd also make it a _ONCE
> variant:
> 
>   if (WARN_ONCE(!buf || offset_in_page(buf),
>"invalid sysfs_emit: offset_in_page(buf):%zd\n",
> buf ? offset_in_page(buf) : 0))

I don't think that helps as multiple defects can easily
exist.  Log spam in this case isn't horrible either.




Re: [PATCH V3 1/8] sysfs: Add sysfs_emit and sysfs_emit_at to format sysfs output

2020-09-30 Thread Kees Cook
On Wed, Sep 30, 2020 at 01:57:40PM +0200, Greg Kroah-Hartman wrote:
> Kees, and Rafael, I don't know if you saw this proposal from Joe for
> sysfs files, questions below:

I'm a fan. I think the use of sprintf() in sysfs might have been one of
my earliest complaints about unsafe code patterns in the kernel. ;)

> > +/**
> > + * sysfs_emit - scnprintf equivalent, aware of PAGE_SIZE buffer.
> > + * @buf:   start of PAGE_SIZE buffer.
> > + * @fmt:   format
> > + * @...:   optional arguments to @format
> > + *
> > + *
> > + * Returns number of characters written to @buf.
> > + */
> > +int sysfs_emit(char *buf, const char *fmt, ...)
> > +{
> > +   va_list args;
> > +   int len;
> > +
> > +   if (WARN(!buf || offset_in_page(buf),
> > +"invalid sysfs_emit: buf:%p\n", buf))

I don't want the %p here, but otherwise, sure. I'd also make it a _ONCE
variant:

if (WARN_ONCE(!buf || offset_in_page(buf),
 "invalid sysfs_emit: offset_in_page(buf):%zd\n",
  buf ? offset_in_page(buf) : 0))

> > +   return 0;
> > +
> > +   va_start(args, fmt);
> > +   len = vscnprintf(buf, PAGE_SIZE, fmt, args);
> > +   va_end(args);
> > +
> > +   return len;
> > +}
> > +EXPORT_SYMBOL_GPL(sysfs_emit);
> > +
> > +/**
> > + * sysfs_emit_at - scnprintf equivalent, aware of PAGE_SIZE buffer.
> > + * @buf:   start of PAGE_SIZE buffer.
> > + * @at:offset in @buf to start write in bytes
> > + * @at must be >= 0 && < PAGE_SIZE
> > + * @fmt:   format
> > + * @...:   optional arguments to @fmt
> > + *
> > + *
> > + * Returns number of characters written starting at &@buf[@at].
> > + */
> > +int sysfs_emit_at(char *buf, int at, const char *fmt, ...)
> > +{
> > +   va_list args;
> > +   int len;
> > +
> > +   if (WARN(!buf || offset_in_page(buf) || at < 0 || at >= PAGE_SIZE,
> > +"invalid sysfs_emit_at: buf:%p at:%d\n", buf, at))

Same:

if (WARN_ONCE(!buf || offset_in_page(buf) || at < 0 || at >= PAGE_SIZE,
 "invalid sysfs_emit_at: offset_in_page(buf):%zd at:%d\n",
  buf ? offset_in_page(buf) : 0, at))

> > +   return 0;
> > +
> > +   va_start(args, fmt);
> > +   len = vscnprintf(buf + at, PAGE_SIZE - at, fmt, args);
> > +   va_end(args);
> > +
> > +   return len;
> > +}
> > +EXPORT_SYMBOL_GPL(sysfs_emit_at);
> 
> These feel sane, but I'm loath to have a ton of churn for no good
> reason.

I think the churn is worth it if we remove "seemingly wrong" code
patterns from the kernel. It's especially useful, IMO, for when there
are future mutations/refactorings and we don't end up with a bare
sprintf somewhere else.

> If we make all sysfs show/store functions use these calls instead of
> sprintf(), it "feels" like that might address the objections that people
> have had in the past where they are nervous about "bare" sprintf()
> calls, right?

I would think so. This is the kind of thing we did for %n in seq_file:
remove potential foot-gun API in favor of subsystem-specific safe API.

> It also might make things easier to audit where we can see much easier
> where sysfs files are doing "foolish" things by calling sysfs_emit_at()
> a bunch of times they shouldn't be, and maybe automate the documentation
> of sysfs files in a better way.

Indeed!

> So I guess I'm asking for another developer to at least agree that this
> feels like the right way forward here.  I don't want to start down this
> path, only to roll them all back as it feels like pointless churn.

With the changes above, I'd Ack it. :)

-- 
Kees Cook


Re: [PATCH v5 03/15] misc: bcm-vk: add autoload support

2020-09-30 Thread kernel test robot
Hi Scott,

I love your patch! Yet something to improve:

[auto build test ERROR on char-misc/char-misc-testing]
[also build test ERROR on soc/for-next kees/for-next/pstore linus/master 
v5.9-rc7 next-20200930]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:
https://github.com/0day-ci/linux/commits/Scott-Branden/Add-Broadcom-VK-driver/20201001-093119
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git 
c471bf4b11c7df0f0f9f42b5aeec424dc62d0c7e
config: powerpc-allyesconfig (attached as .config)
compiler: powerpc64-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
wget 
https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# 
https://github.com/0day-ci/linux/commit/f04a1673933a1af94e44bc650533bbb271e3dcc1
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review 
Scott-Branden/Add-Broadcom-VK-driver/20201001-093119
git checkout f04a1673933a1af94e44bc650533bbb271e3dcc1
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross 
ARCH=powerpc 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot 

All errors (new ones prefixed by >>):

   drivers/misc/bcm-vk/bcm_vk_dev.c: In function 'bcm_vk_load_image_by_type':
>> drivers/misc/bcm-vk/bcm_vk_dev.c:284:8: error: implicit declaration of 
>> function 'request_partial_firmware_into_buf'; did you mean 
>> 'request_firmware_into_buf'? [-Werror=implicit-function-declaration]
 284 |  ret = request_partial_firmware_into_buf(, filename, dev,
 |^
 |request_firmware_into_buf
   cc1: some warnings being treated as errors

vim +284 drivers/misc/bcm-vk/bcm_vk_dev.c

   206  
   207  static int bcm_vk_load_image_by_type(struct bcm_vk *vk, u32 load_type,
   208   const char *filename)
   209  {
   210  struct device *dev = >pdev->dev;
   211  const struct firmware *fw = NULL;
   212  void *bufp = NULL;
   213  size_t max_buf, offset;
   214  int ret;
   215  u64 offset_codepush;
   216  u32 codepush;
   217  u32 value;
   218  dma_addr_t boot_dma_addr;
   219  bool is_stdalone;
   220  
   221  if (load_type == VK_IMAGE_TYPE_BOOT1) {
   222  /*
   223   * After POR, enable VK soft BOOTSRC so bootrom do not 
clear
   224   * the pushed image (the TCM memories).
   225   */
   226  value = vkread32(vk, BAR_0, BAR_BOOTSRC_SELECT);
   227  value |= BOOTSRC_SOFT_ENABLE;
   228  vkwrite32(vk, value, BAR_0, BAR_BOOTSRC_SELECT);
   229  
   230  codepush = CODEPUSH_BOOTSTART + CODEPUSH_BOOT1_ENTRY;
   231  offset_codepush = BAR_CODEPUSH_SBL;
   232  
   233  /* Write a 1 to request SRAM open bit */
   234  vkwrite32(vk, CODEPUSH_BOOTSTART, BAR_0, 
offset_codepush);
   235  
   236  /* Wait for VK to respond */
   237  ret = bcm_vk_wait(vk, BAR_0, BAR_BOOT_STATUS, SRAM_OPEN,
   238SRAM_OPEN, LOAD_IMAGE_TIMEOUT_MS);
   239  if (ret < 0) {
   240  dev_err(dev, "boot1 wait SRAM err - ret(%d)\n", 
ret);
   241  goto err_buf_out;
   242  }
   243  
   244  max_buf = SZ_256K;
   245  bufp = dma_alloc_coherent(dev,
   246max_buf,
   247_dma_addr, GFP_KERNEL);
   248  if (!bufp) {
   249  dev_err(dev, "Error allocating 0x%zx\n", 
max_buf);
   250  ret = -ENOMEM;
   251  goto err_buf_out;
   252  }
   253  } else if (load_type == VK_IMAGE_TYPE_BOOT2) {
   254  codepush = CODEPUSH_BOOT2_ENTRY;
   255  offset_codepush = BAR_CODEPUSH_SBI;
   256  
   257  /* Wait for VK to respond */
   258  ret = bcm_vk_wait(vk, BAR_0, BAR_BOOT_STATUS, DDR_OPEN,
   259DDR_OPEN, LOAD_IMAGE_TIMEOUT_MS);
   260  if (ret < 0) {
   261  dev_err(dev, "boot2 wait DDR open error - 
ret(%d)\n",
   262  ret);
   263  goto err_buf_out;
   264  }
   265  
   266  max_buf = SZ

Re: [PATCH v3 2/3] iommu/tegra-smmu: Rework .probe_device and .attach_dev

2020-09-30 Thread Dmitry Osipenko
01.10.2020 05:48, Nicolin Chen пишет:
> On Thu, Oct 01, 2020 at 05:06:19AM +0300, Dmitry Osipenko wrote:
>> 01.10.2020 04:26, Nicolin Chen пишет:
>>> On Thu, Oct 01, 2020 at 12:56:46AM +0300, Dmitry Osipenko wrote:
 01.10.2020 00:32, Nicolin Chen пишет:
> On Thu, Oct 01, 2020 at 12:24:25AM +0300, Dmitry Osipenko wrote:
>> ...
 It looks to me like the only reason why you need this new global API is
 because PCI devices may not have a device tree node with a phandle to
 the IOMMU. However, SMMU support for PCI will only be enabled if the
 root complex has an iommus property, right? In that case, can't we
 simply do something like this:

if (dev_is_pci(dev))
np = find_host_bridge(dev)->of_node;
else
np = dev->of_node;

 ? I'm not sure exactly what find_host_bridge() is called, but I'm 
 pretty
 sure that exists.

 Once we have that we can still iterate over the iommus property and do
 not need to rely on this global variable.
>>>
>>> I agree that it'd work. But I was hoping to simplify the code
>>> here if it's possible. Looks like we have an argument on this
>>> so I will choose to go with your suggestion above for now.
>>
>> This patch removed more lines than were added. If this will be opposite
>> for the Thierry's suggestion, then it's probably not a great suggestion.
>
> Sorry, I don't quite understand this comments. Would you please
> elaborate what's this "it" being "not a great suggestion"?
>

 I meant that you should try to implement Thierry's solution, but if the
 end result will be worse than the current patch, then you shouldn't make
 a v4, but get back to this discussion in order to choose the best option
 and make everyone agree on it.
>>>
>>> I see. Thanks for the reply. And here is a sample implementation:
>>
>> That's what I supposed to happen :) The new variant adds code and
>> complexity, while old did the opposite. Hence the old variant is clearly
>> more attractive, IMO.
> 
> I personally am not a fan of adding a path for PCI device either,
> since PCI/IOMMU cores could have taken care of it while the same
> path can't be used for other buses.
> 
> If we can't come to an agreement on globalizing mc pointer, would
> it be possible to pass tegra_mc_driver through tegra_smmu_probe()
> so we can continue to use driver_find_device_by_fwnode() as v1?
> 
> v1: https://lkml.org/lkml/2020/9/26/68
> 

I think we already agreed that it will be good to have a common helper.
So far Thierry only objected that the implementation of the helper could
be improved.


Re: [net-next PATCH v1 3/7] net: phy: Introduce fwnode_get_phy_id()

2020-09-30 Thread Calvin Johnson
On Wed, Sep 30, 2020 at 08:19:02PM +0200, Andrew Lunn wrote:
> On Wed, Sep 30, 2020 at 07:07:25PM +0100, Russell King - ARM Linux admin 
> wrote:
> > On Wed, Sep 30, 2020 at 06:34:40PM +0200, Andrew Lunn wrote:
> > > > @@ -2866,7 +2888,15 @@ EXPORT_SYMBOL_GPL(device_phy_find_device);
> > > >   */
> > > >  struct fwnode_handle *fwnode_get_phy_node(struct fwnode_handle *fwnode)
> > > >  {
> > > > -   return fwnode_find_reference(fwnode, "phy-handle", 0);
> > > > +   struct fwnode_handle *phy_node;
> > > > +
> > > > +   phy_node = fwnode_find_reference(fwnode, "phy-handle", 0);
> > > > +   if (is_acpi_node(fwnode) || !IS_ERR(phy_node))
> > > > +   return phy_node;
> > > > +   phy_node = fwnode_find_reference(fwnode, "phy", 0);
> > > > +   if (IS_ERR(phy_node))
> > > > +   phy_node = fwnode_find_reference(fwnode, "phy-device", 
> > > > 0);
> > > > +   return phy_node;
> > > 
> > > Why do you have three different ways to reference a PHY?
> > 
> > Compatibility with the DT version - note that "phy" and "phy-device"
> > are only used for non-ACPI fwnodes. This should allow us to convert
> > drivers where necessary without fear of causing DT regressions.
> 
> Ah.
> 
> A comment would be good here.

Sure. Will add comment.

Thanks
Calvin


Re: [net-next PATCH v1 2/7] net: phy: Introduce phy related fwnode functions

2020-09-30 Thread Calvin Johnson
On Wed, Sep 30, 2020 at 03:03:49PM -0700, David Miller wrote:
> From: Calvin Johnson 
> Date: Wed, 30 Sep 2020 21:34:25 +0530
> 
> > +struct phy_device *fwnode_phy_find_device(struct fwnode_handle *phy_fwnode)
> > +{
> > +   struct device *d;
> > +   struct mdio_device *mdiodev;
> 
> Please use reverse christmas tree ordering for local variables.

Sure. In next rev, I'll make sure all the patches follow this.

Thanks
Calvin


Re: [PATCH v2 10/12] dt-bindings: arm: fsl: document i.MX6DL Aristainetos boards

2020-09-30 Thread Heiko Schocher

Hello Krzysztof,

Am 30.09.2020 um 21:01 schrieb Krzysztof Kozlowski:

Document and adjust the compatibles for i.MX6DL based Aristainetos
boards from ABB.

Cc: Heiko Schocher 
Signed-off-by: Krzysztof Kozlowski 

---

Changes since v1:
1. Use ABB vendor prefix
---
  Documentation/devicetree/bindings/arm/fsl.yaml | 4 
  1 file changed, 4 insertions(+)


Thanks!

Reviewed-by: Heiko Schocher 

bye,
Heiko
--
DENX Software Engineering GmbH,  Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-52   Fax: +49-8142-66989-80   Email: h...@denx.de


linux-next: manual merge of the net-next tree with the net tree

2020-09-30 Thread Stephen Rothwell
Hi all,

Today's linux-next merge of the net-next tree got a conflict in:

  net/mptcp/protocol.h

between commit:

  1a49b2c2a501 ("mptcp: Handle incoming 32-bit DATA_FIN values")

from the net tree and commit:

  5c8c1640956e ("mptcp: add mptcp_destroy_common helper")

from the net-next tree.

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

-- 
Cheers,
Stephen Rothwell

diff --cc net/mptcp/protocol.h
index 20f04ac85409,7cfe52aeb2b8..
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@@ -387,7 -407,8 +407,8 @@@ void mptcp_data_ready(struct sock *sk, 
  bool mptcp_finish_join(struct sock *sk);
  void mptcp_data_acked(struct sock *sk);
  void mptcp_subflow_eof(struct sock *sk);
 -bool mptcp_update_rcv_data_fin(struct mptcp_sock *msk, u64 data_fin_seq);
 +bool mptcp_update_rcv_data_fin(struct mptcp_sock *msk, u64 data_fin_seq, bool 
use_64bit);
+ void mptcp_destroy_common(struct mptcp_sock *msk);
  
  void __init mptcp_token_init(void);
  static inline void mptcp_token_init_request(struct request_sock *req)


pgpYIEB09j2Gq.pgp
Description: OpenPGP digital signature


Re: [PATCH v2 11/12] ARM: dts: imx6dl: add compatibles for Aristainetos boards

2020-09-30 Thread Heiko Schocher

Hello Krzysztof,

Am 30.09.2020 um 21:01 schrieb Krzysztof Kozlowski:

The Aristainetos and Aristainetos2 boards have only SoC compatible.

Cc: Heiko Schocher 
Signed-off-by: Krzysztof Kozlowski 

---

Changes since v1:
1. Use ABB vendor prefix
---
  arch/arm/boot/dts/imx6dl-aristainetos2_4.dts | 2 +-
  arch/arm/boot/dts/imx6dl-aristainetos2_7.dts | 2 +-
  arch/arm/boot/dts/imx6dl-aristainetos_4.dts  | 2 +-
  arch/arm/boot/dts/imx6dl-aristainetos_7.dts  | 2 +-
  4 files changed, 4 insertions(+), 4 deletions(-)


Thanks!

Reviewed-by: Heiko Schocher 

bye,
Heiko
--
DENX Software Engineering GmbH,  Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-52   Fax: +49-8142-66989-80   Email: h...@denx.de


linux-next: manual merge of the net-next tree with the net tree

2020-09-30 Thread Stephen Rothwell
Hi all,

Today's linux-next merge of the net-next tree got a conflict in:

  net/mptcp/protocol.c

between commit:

  917944da3bfc ("mptcp: Consistently use READ_ONCE/WRITE_ONCE with 
msk->ack_seq")

from the net tree and commit:

  8268ed4c9d19 ("mptcp: introduce and use mptcp_try_coalesce()")
  ab174ad8ef76 ("mptcp: move ooo skbs into msk out of order queue.")

from the net-next tree.

I fixed it up (I think - see below) and can carry the fix as
necessary. This is now fixed as far as linux-next is concerned, but any
non trivial conflicts should be mentioned to your upstream maintainer
when your tree is submitted for merging.  You may also want to consider
cooperating with the maintainer of the conflicting tree to minimise any
particularly complex conflicts.

-- 
Cheers,
Stephen Rothwell

diff --cc net/mptcp/protocol.c
index 5d747c6a610e,34c037731f35..
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@@ -112,64 -112,205 +112,205 @@@ static int __mptcp_socket_create(struc
return 0;
  }
  
- static void __mptcp_move_skb(struct mptcp_sock *msk, struct sock *ssk,
-struct sk_buff *skb,
-unsigned int offset, size_t copy_len)
+ static void mptcp_drop(struct sock *sk, struct sk_buff *skb)
+ {
+   sk_drops_add(sk, skb);
+   __kfree_skb(skb);
+ }
+ 
+ static bool mptcp_try_coalesce(struct sock *sk, struct sk_buff *to,
+  struct sk_buff *from)
+ {
+   bool fragstolen;
+   int delta;
+ 
+   if (MPTCP_SKB_CB(from)->offset ||
+   !skb_try_coalesce(to, from, , ))
+   return false;
+ 
+   pr_debug("colesced seq %llx into %llx new len %d new end seq %llx",
+MPTCP_SKB_CB(from)->map_seq, MPTCP_SKB_CB(to)->map_seq,
+to->len, MPTCP_SKB_CB(from)->end_seq);
+   MPTCP_SKB_CB(to)->end_seq = MPTCP_SKB_CB(from)->end_seq;
+   kfree_skb_partial(from, fragstolen);
+   atomic_add(delta, >sk_rmem_alloc);
+   sk_mem_charge(sk, delta);
+   return true;
+ }
+ 
+ static bool mptcp_ooo_try_coalesce(struct mptcp_sock *msk, struct sk_buff *to,
+  struct sk_buff *from)
+ {
+   if (MPTCP_SKB_CB(from)->map_seq != MPTCP_SKB_CB(to)->end_seq)
+   return false;
+ 
+   return mptcp_try_coalesce((struct sock *)msk, to, from);
+ }
+ 
+ /* "inspired" by tcp_data_queue_ofo(), main differences:
+  * - use mptcp seqs
+  * - don't cope with sacks
+  */
+ static void mptcp_data_queue_ofo(struct mptcp_sock *msk, struct sk_buff *skb)
  {
struct sock *sk = (struct sock *)msk;
-   struct sk_buff *tail;
+   struct rb_node **p, *parent;
+   u64 seq, end_seq, max_seq;
+   struct sk_buff *skb1;
+   int space;
+ 
+   seq = MPTCP_SKB_CB(skb)->map_seq;
+   end_seq = MPTCP_SKB_CB(skb)->end_seq;
+   space = tcp_space(sk);
+   max_seq = space > 0 ? space + msk->ack_seq : msk->ack_seq;
+ 
+   pr_debug("msk=%p seq=%llx limit=%llx empty=%d", msk, seq, max_seq,
+RB_EMPTY_ROOT(>out_of_order_queue));
+   if (after64(seq, max_seq)) {
+   /* out of window */
+   mptcp_drop(sk, skb);
+   MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_NODSSWINDOW);
+   return;
+   }
  
-   __skb_unlink(skb, >sk_receive_queue);
+   p = >out_of_order_queue.rb_node;
+   MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_OFOQUEUE);
+   if (RB_EMPTY_ROOT(>out_of_order_queue)) {
+   rb_link_node(>rbnode, NULL, p);
+   rb_insert_color(>rbnode, >out_of_order_queue);
+   msk->ooo_last_skb = skb;
+   goto end;
+   }
  
-   skb_ext_reset(skb);
-   skb_orphan(skb);
-   WRITE_ONCE(msk->ack_seq, msk->ack_seq + copy_len);
+   /* with 2 subflows, adding at end of ooo queue is quite likely
+* Use of ooo_last_skb avoids the O(Log(N)) rbtree lookup.
+*/
+   if (mptcp_ooo_try_coalesce(msk, msk->ooo_last_skb, skb)) {
+   MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_OFOMERGE);
+   MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_OFOQUEUETAIL);
+   return;
+   }
  
-   tail = skb_peek_tail(>sk_receive_queue);
-   if (offset == 0 && tail) {
-   bool fragstolen;
-   int delta;
+   /* Can avoid an rbtree lookup if we are adding skb after ooo_last_skb */
+   if (!before64(seq, MPTCP_SKB_CB(msk->ooo_last_skb)->end_seq)) {
+   MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_OFOQUEUETAIL);
+   parent = >ooo_last_skb->rbnode;
+   p = >rb_right;
+   goto insert;
+   }
  
-   if (skb_try_coalesce(tail, skb, , )) {
-   kfree_skb_partial(skb, fragstolen);
-   atomic_add(delta, >sk_rmem_alloc);
-   sk_mem_charge(sk, delta);
+   /* Find place to insert this segment. Handle overlaps on the way. */

Re: [PATCH v2 09/12] dt-bindings: vendor-prefixes: add ABB

2020-09-30 Thread Heiko Schocher

Hello Krzysztof,

Am 30.09.2020 um 21:01 schrieb Krzysztof Kozlowski:

Document binding for ABB.

Cc: Heiko Schocher 
Signed-off-by: Krzysztof Kozlowski 

---

Changes since v1:
1. Use ABB vendor prefix
---
  Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++
  1 file changed, 2 insertions(+)


Thanks!

Reviewed-by: Heiko Schocher 

bye,
Heiko
--
DENX Software Engineering GmbH,  Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-52   Fax: +49-8142-66989-80   Email: h...@denx.de


Re: [PATCH v6 4/4] bus: mhi: Add userspace client interface driver

2020-09-30 Thread Hemant Kumar

Hi Loic,

On 9/22/20 4:10 AM, Loic Poulain wrote:

Hi Hemant,

See comments inline, but globally, the locking and ref counting is
more complicated than it should be.

On Wed, 16 Sep 2020 at 21:57, Hemant Kumar  wrote:


This MHI client driver allows userspace clients to transfer
raw data between MHI device and host using standard file operations.
Device file node is created with format

/dev/mhi__

Currently it supports LOOPBACK channel.

Signed-off-by: Hemant Kumar 
---
  drivers/bus/mhi/Kconfig  |  13 +
  drivers/bus/mhi/Makefile |   4 +
  drivers/bus/mhi/uci.c| 657 +++
  3 files changed, 674 insertions(+)
  create mode 100644 drivers/bus/mhi/uci.c

diff --git a/drivers/bus/mhi/Kconfig b/drivers/bus/mhi/Kconfig
index 6a217ff..8aebe8b 100644
--- a/drivers/bus/mhi/Kconfig
+++ b/drivers/bus/mhi/Kconfig
@@ -20,3 +20,16 @@ config MHI_BUS_DEBUG
  Enable debugfs support for use with the MHI transport. Allows
  reading and/or modifying some values within the MHI controller
  for debug and test purposes.
+
+config MHI_UCI
+   tristate "MHI UCI"
+   depends on MHI_BUS
+   help
+MHI based userspace client interface driver is used for transferring
+raw data between host and device using standard file operations from
+userspace. Open, read, write, and close operations are supported
+by this driver. Please check mhi_uci_match_table for all supported
+channels that are exposed to userspace.
+
+To compile this driver as a module, choose M here: the module will be
+called mhi_uci.
diff --git a/drivers/bus/mhi/Makefile b/drivers/bus/mhi/Makefile
index 19e6443..80feefb 100644
--- a/drivers/bus/mhi/Makefile
+++ b/drivers/bus/mhi/Makefile
@@ -1,2 +1,6 @@
  # core layer
  obj-y += core/
+
+# MHI client
+mhi_uci-y := uci.o
+obj-$(CONFIG_MHI_UCI) += mhi_uci.o
diff --git a/drivers/bus/mhi/uci.c b/drivers/bus/mhi/uci.c
new file mode 100644
index 000..d6758f2
--- /dev/null
+++ b/drivers/bus/mhi/uci.c
@@ -0,0 +1,657 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.*/
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DEVICE_NAME "mhi"
+#define MHI_UCI_DRIVER_NAME "mhi_uci"
+#define MAX_UCI_MINORS (128)
+
+static DEFINE_IDR(uci_idr);
+static DEFINE_MUTEX(uci_idr_mutex);
+static struct class *uci_dev_class;
+static int uci_dev_major;
+
+/**
+ * struct uci_chan - MHI channel for a uci device
+ * @wq: wait queue for reader/writer
+ * @lock: spin lock
+ * @pending: list of rx buffers userspace is waiting to read
+ * @cur_buf: current buffer userspace is reading
+ * @rx_size: size of the current rx buffer userspace is reading
+ */
+struct uci_chan {
+   wait_queue_head_t wq;
+
+   /* protects pending and cur_buf members in bh context */
+   spinlock_t lock;
+
+   struct list_head pending;
+   struct uci_buf *cur_buf;
+   size_t rx_size;
+};
+
+/**
+ * struct uci_buf - uci buffer
+ * @data: data buffer
+ * @len: length of data buffer
+ * @node: list node of the uci buffer
+ */
+struct uci_buf {
+   void *data;
+   size_t len;
+   struct list_head node;
+};
+
+/**
+ * struct uci_dev - MHI uci device
+ * @minor: uci device node minor number
+ * @mhi_dev: associated mhi device object
+ * @chan: MHI channel name
+ * @lock: mutex lock
+ * @ul_chan: uplink uci channel object
+ * @dl_chan: downlink uci channel object
+ * @mtu: max tx buffer length
+ * @actual_mtu: maximum size of incoming buffer
+ * @open: open called for device node
+ * @enabled: uci device probed
+ * @ref_count: uci_dev reference count
+ */
+struct uci_dev {
+   unsigned int minor;
+   struct mhi_device *mhi_dev;
+   const char *chan;
+
+   /* protects uci_dev struct members */
+   struct mutex lock;
+
+   struct uci_chan ul_chan;
+   struct uci_chan dl_chan;
+   size_t mtu;
+   size_t actual_mtu;
+   bool enabled;
+   struct kref ref_count;
+};
+
+static int mhi_queue_inbound(struct uci_dev *udev)
+{
+   struct mhi_device *mhi_dev = udev->mhi_dev;
+   struct device *dev = _dev->dev;
+   size_t mtu = udev->mtu;
+   size_t actual_mtu = udev->actual_mtu;
+   int nr_trbs, i, ret = -EIO;
+   void *buf;
+   struct uci_buf *uci_buf;
+
+   nr_trbs = mhi_get_no_free_descriptors(mhi_dev, DMA_FROM_DEVICE);
+
+   for (i = 0; i < nr_trbs; i++) {
+   buf = kmalloc(mtu, GFP_KERNEL);
+   if (!buf)
+   return -ENOMEM;
+
+   uci_buf = buf + actual_mtu;
+   uci_buf->data = buf;
+
+   dev_dbg(dev, "Allocated buf %d of %d size %ld\n", i, nr_trbs,
+   actual_mtu);
+
+   ret = mhi_queue_buf(mhi_dev, DMA_FROM_DEVICE, buf, actual_mtu,
+   MHI_EOT);
+   if (ret) {
+   kfree(buf);
+ 

[PATCH 1/2] dt-bindings: phy: Allow defining the SATA AFE TX amplitude

2020-09-30 Thread Florian Fainelli
Document a new property which allows the selection of the SATA AFE TX
amplitude in milli Volts. Possible values are 400, 500, 600 and 800mV.

Signed-off-by: Florian Fainelli 
---
 Documentation/devicetree/bindings/phy/brcm-sata-phy.txt | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/phy/brcm-sata-phy.txt 
b/Documentation/devicetree/bindings/phy/brcm-sata-phy.txt
index c03ad2198410..e5abbace93a3 100644
--- a/Documentation/devicetree/bindings/phy/brcm-sata-phy.txt
+++ b/Documentation/devicetree/bindings/phy/brcm-sata-phy.txt
@@ -38,6 +38,9 @@ Sub-nodes optional properties:
 - brcm,rxaeq-value: when 'rxaeq-mode' is set to "manual", provides the RX
   equalizer value that should be used. Allowed range is 0..63.
 
+- brcm,tx-amplitude-millivolt: transmit amplitude voltage in millivolt.
+  Possible values are 400, 500, 600 or 800 mV.
+
 Example
sata-phy@f0458100 {
compatible = "brcm,bcm7445-sata-phy", "brcm,phy-sata3";
-- 
2.25.1



[PATCH 2/2] phy: phy-brcm-sata: Allow configuration SATA AFE TX amplitude

2020-09-30 Thread Florian Fainelli
Read the 'brcm,tx-amplitude-millivolt' property from Device Tree and
propagate its value into the appropriate test transmit register to
change the TX amplitude.

Signed-off-by: Florian Fainelli 
---
 drivers/phy/broadcom/phy-brcm-sata.c | 32 
 1 file changed, 32 insertions(+)

diff --git a/drivers/phy/broadcom/phy-brcm-sata.c 
b/drivers/phy/broadcom/phy-brcm-sata.c
index 18251f232172..7be3586b16cb 100644
--- a/drivers/phy/broadcom/phy-brcm-sata.c
+++ b/drivers/phy/broadcom/phy-brcm-sata.c
@@ -65,6 +65,7 @@ struct brcm_sata_port {
bool ssc_en;
enum brcm_sata_phy_rxaeq_mode rxaeq_mode;
u32 rxaeq_val;
+   u32 tx_amplitude_val;
 };
 
 struct brcm_sata_phy {
@@ -84,6 +85,10 @@ enum sata_phy_regs {
BLOCK0_SPARE_OOB_CLK_SEL_MASK   = 0x3,
BLOCK0_SPARE_OOB_CLK_SEL_REFBY2 = 0x1,
 
+   BLOCK1_REG_BANK = 0x10,
+   BLOCK1_TEST_TX  = 0x83,
+   BLOCK1_TEST_TX_AMP_SHIFT= 12,
+
PLL_REG_BANK_0  = 0x050,
PLL_REG_BANK_0_PLLCONTROL_0 = 0x81,
PLLCONTROL_0_FREQ_DET_RESTART   = BIT(13),
@@ -379,6 +384,29 @@ static int brcm_stb_sata_16nm_ssc_init(struct 
brcm_sata_port *port)
brcm_sata_phy_wr(port, RXPMD_REG_BANK, RXPMD_RX_FREQ_MON_CONTROL1,
 ~tmp, RXPMD_MON_CORRECT_EN | value);
 
+   tmp = GENMASK(15, 12);
+   switch (port->tx_amplitude_val) {
+   case 400:
+   value = BIT(12) | BIT(13);
+   break;
+   case 500:
+   value = BIT(13);
+   break;
+   case 600:
+   value = BIT(12);
+   break;
+   case 800:
+   value = 0;
+   break;
+   default:
+   value = tmp;
+   break;
+   }
+
+   if (value != tmp)
+   brcm_sata_phy_wr(port, BLOCK1_REG_BANK, BLOCK1_TEST_TX, ~tmp,
+value);
+
/* Turn on/off SSC */
brcm_sata_phy_wr(port, TX_REG_BANK, TX_ACTRL5, ~TX_ACTRL5_SSC_EN,
 port->ssc_en ? TX_ACTRL5_SSC_EN : 0);
@@ -791,6 +819,10 @@ static int brcm_sata_phy_probe(struct platform_device 
*pdev)
if (port->rxaeq_mode == RXAEQ_MODE_MANUAL)
of_property_read_u32(child, "brcm,rxaeq-value",
 >rxaeq_val);
+
+   of_property_read_u32(child, "brcm,tx-amplitude-millivolt",
+>tx_amplitude_val);
+
port->ssc_en = of_property_read_bool(child, "brcm,enable-ssc");
if (IS_ERR(port->phy)) {
dev_err(dev, "failed to create PHY\n");
-- 
2.25.1



[PATCH 0/2] phy: phy-brcm-sata: Allow configuration SATA AFE TX amplitude

2020-09-30 Thread Florian Fainelli
Hi Kishon,

This patch series allows the configuration of the Broadcom SATA PHY TX
amplitude which may be required in order to meet specific tests.

Thanks!

Florian Fainelli (2):
  dt-bindings: phy: Allow defining the SATA AFE TX amplitude
  phy: phy-brcm-sata: Allow configuration SATA AFE TX amplitude

 .../devicetree/bindings/phy/brcm-sata-phy.txt |  3 ++
 drivers/phy/broadcom/phy-brcm-sata.c  | 32 +++
 2 files changed, 35 insertions(+)

-- 
2.25.1



[PATCH net-next v2] net: dsa: Support bridge 802.1Q while untagging

2020-09-30 Thread Florian Fainelli
The intent of 412a1526d067 ("net: dsa: untag the bridge pvid from rx
skbs") is to transparently untag the bridge's default_pvid when the
Ethernet switch can only support egress tagged of that default_pvid
towards the CPU port.

Prior to this commit, users would have to configure an 802.1Q upper on
the bridge master device when the bridge is configured with
vlan_filtering=0 in order to pop the VLAN tag:

ip link add name br0 type bridge vlan_filtering 0
ip link add link br0 name br0.1 type vlan id 1

After this commit we added support for managing a switch port 802.1Q
upper but those are not usually added as bridge members, and if they do,
they do not actually require any special management, the data path would
pop the desired VLAN tag accordingly.

What we want to preserve is that use case and to manage when the user
creates that 802.1Q upper for the bridge port.

While we are it, call __vlan_find_dev_deep_rcu() which makes use the
VLAN group array which is faster.

As soon as we return the VLAN tagged SKB though it will be used by the
following call path:

netif_receive_skb_list_internal
  -> __netif_receive_skb_list_core
-> __netif_receive_skb_core
  -> vlan_do_receive()

which uses skb->vlan_proto, if we do not set it to the appropriate VLAN
protocol, we will leave it set to what the DSA master has set
(ETH_P_XDSA).

Fixes: 412a1526d067 ("net: dsa: untag the bridge pvid from rx skbs")
Signed-off-by: Florian Fainelli 
---
Changes in v2:

- removed unused list_head iter argument

 net/dsa/dsa_priv.h | 11 ---
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 0348dbab4131..b4aafb2e90fa 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -205,7 +205,6 @@ static inline struct sk_buff *dsa_untag_bridge_pvid(struct 
sk_buff *skb)
struct net_device *br = dp->bridge_dev;
struct net_device *dev = skb->dev;
struct net_device *upper_dev;
-   struct list_head *iter;
u16 vid, pvid, proto;
int err;
 
@@ -247,12 +246,10 @@ static inline struct sk_buff 
*dsa_untag_bridge_pvid(struct sk_buff *skb)
 * supports because vlan_filtering is 0. In that case, we should
 * definitely keep the tag, to make sure it keeps working.
 */
-   netdev_for_each_upper_dev_rcu(dev, upper_dev, iter) {
-   if (!is_vlan_dev(upper_dev))
-   continue;
-
-   if (vid == vlan_dev_vlan_id(upper_dev))
-   return skb;
+   upper_dev = __vlan_find_dev_deep_rcu(br, htons(proto), vid);
+   if (upper_dev) {
+   skb->vlan_proto = vlan_dev_vlan_proto(upper_dev);
+   return skb;
}
 
__vlan_hwaccel_clear_tag(skb);
-- 
2.25.1



Re: [PATCH v2] pipe: Fix memory leaks in create_pipe_files()

2020-09-30 Thread Eric Biggers
On Wed, Sep 30, 2020 at 10:52:55PM -0400, Qian Cai wrote:
> diff --git a/include/linux/watch_queue.h b/include/linux/watch_queue.h
> index 5e08db2adc31..20665fbe0552 100644
> --- a/include/linux/watch_queue.h
> +++ b/include/linux/watch_queue.h
> @@ -123,5 +123,9 @@ static inline void remove_watch_list(struct watch_list 
> *wlist, u64 id)
>  #define watch_sizeof(STRUCT) (sizeof(STRUCT) << WATCH_INFO_LENGTH__SHIFT)
>  
>  #endif
> +static inline int watch_queue_init(struct pipe_inode_info *pipe)
> +{
> + return -ENOPKG;
> +}

This needs to be conditional on !CONFIG_WATCH_QUEUE.

- Eric


Re: kernel BUG at mm/mmap.c:LINE!

2020-09-30 Thread Souptick Joarder
On Fri, Sep 4, 2020 at 12:39 AM syzbot
 wrote:
>
> Hello,
>
> syzbot found the following issue on:
>
> HEAD commit:1127b219 Merge tag 'fallthrough-fixes-5.9-rc3' of git://gi..
> git tree:   upstream
> console output: https://syzkaller.appspot.com/x/log.txt?x=136d098e90
> kernel config:  https://syzkaller.appspot.com/x/.config?x=978db74cb30aa994
> dashboard link: https://syzkaller.appspot.com/bug?extid=721b657f8f01708b291b
> compiler:   gcc (GCC) 10.1.0-syz 20200507
>
> Unfortunately, I don't have any reproducer for this issue yet.
>
> IMPORTANT: if you fix the issue, please add the following tag to the commit:
> Reported-by: syzbot+721b657f8f01708b2...@syzkaller.appspotmail.com
>
> start_brk 558decf56000 brk 558ded16 start_stack 7ffd20847a70
> arg_start 7ffd20847e89 arg_end 7ffd20847ea4 env_start 7ffd20847ea4 env_end 
> 7ffd20847fdd
> binfmt 89cdcb60 flags 200cd core_state 
> ioctx_table 
> [ cut here ]
> kernel BUG at mm/mmap.c:427!
> invalid opcode:  [#1] PREEMPT SMP KASAN
> CPU: 0 PID: 28867 Comm: systemd-udevd Not tainted 5.9.0-rc2-syzkaller #0
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS 
> Google 01/01/2011
> RIP: 0010:validate_mm+0x617/0x800 mm/mmap.c:427
> Code: cf f5 cd ff 44 89 e6 bf ff ff ff ff e8 42 f2 cd ff 41 83 fc ff 0f 85 86 
> 1b 01 00 e8 b3 f5 cd ff 48 8b 7c 24 18 e8 d9 59 fc ff <0f> 0b e8 a2 f5 cd ff 
> 48 8b 54 24 28 48 b8 00 00 00 00 00 fc ff df
> RSP: 0018:c90015d6fd98 EFLAGS: 00010286
> RAX: 038d RBX: 004f RCX: 
> RDX: 8880475ac380 RSI: 815dafc7 RDI: f52002badf52
> RBP:  R08: 038d R09: 8880ae6318e7
> R10:  R11: 0001 R12: 0001
> R13:  R14:  R15: 
> FS:  7fb1b935a8c0() GS:8880ae60() knlGS:
> CS:  0010 DS:  ES:  CR0: 80050033
> CR2: 7ffd20959990 CR3: 000217691000 CR4: 001526f0
> DR0:  DR1:  DR2: 
> DR3:  DR6: fffe0ff0 DR7: 0400
> Call Trace:
>  remove_vma_list mm/mmap.c:2616 [inline]
>  __do_munmap+0x899/0x1170 mm/mmap.c:2869
>  __vm_munmap+0xe6/0x180 mm/mmap.c:2889
>  __do_sys_munmap mm/mmap.c:2915 [inline]
>  __se_sys_munmap mm/mmap.c:2911 [inline]
>  __x64_sys_munmap+0x62/0x80 mm/mmap.c:2911
>  do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46
>  entry_SYSCALL_64_after_hwframe+0x44/0xa9
> RIP: 0033:0x7fb1b81d66e7
> Code: c7 c0 ff ff ff ff eb 8d 48 8b 15 ac 47 2b 00 f7 d8 64 89 02 e9 5b ff ff 
> ff 66 2e 0f 1f 84 00 00 00 00 00 b8 0b 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 
> 01 c3 48 8b 0d 81 47 2b 00 f7 d8 64 89 01 48
> RSP: 002b:7ffd20846cd8 EFLAGS: 0206 ORIG_RAX: 000b
> RAX: ffda RBX: 558decf56100 RCX: 7fb1b81d66e7
> RDX: 0080 RSI: 0080ccec RDI: 7fb1b7064000
> RBP: 558debda4d18 R08: 558decf6a3c0 R09: 
> R10:  R11: 0206 R12: 558decf560e0
> R13:  R14: 0003 R15: 000e
> Modules linked in:
> ---[ end trace 76a00ebdfa09cc52 ]---
> RIP: 0010:validate_mm+0x617/0x800 mm/mmap.c:427
> Code: cf f5 cd ff 44 89 e6 bf ff ff ff ff e8 42 f2 cd ff 41 83 fc ff 0f 85 86 
> 1b 01 00 e8 b3 f5 cd ff 48 8b 7c 24 18 e8 d9 59 fc ff <0f> 0b e8 a2 f5 cd ff 
> 48 8b 54 24 28 48 b8 00 00 00 00 00 fc ff df
> RSP: 0018:c90015d6fd98 EFLAGS: 00010286
> RAX: 038d RBX: 004f RCX: 
> RDX: 8880475ac380 RSI: 815dafc7 RDI: f52002badf52
> RBP:  R08: 038d R09: 8880ae6318e7
> R10:  R11: 0001 R12: 0001
> R13:  R14:  R15: 
> FS:  7fb1b935a8c0() GS:8880ae60() knlGS:
> CS:  0010 DS:  ES:  CR0: 80050033
> CR2: 7fad09fed000 CR3: 000217691000 CR4: 001526f0
> DR0:  DR1:  DR2: 
> DR3:  DR6: fffe0ff0 DR7: 0400
>
>

CONFIG_DEBUG_VM_RB=y is set.

[ 1882.597004][T28867] mmap: backwards 1, forwards 3
[ 1882.605532][T28867] mm 88804eeff640 mmap 888094849318
seqnum 1 task_size 140737488351232

Looks like we hit panic due to below code.

static int browse_rb(struct mm_struct *mm) {
...
if (i != j) {
pr_emerg("backwards %d, forwards %d\n", j, i);
bug = 1;
}
...
}


Re: [External] Re: [RFC PATCH 05/24] mm/hugetlb: Introduce nr_free_vmemmap_pages in the struct hstate

2020-09-30 Thread Muchun Song
On Thu, Oct 1, 2020 at 6:41 AM Mike Kravetz  wrote:
>
> On 9/15/20 5:59 AM, Muchun Song wrote:
> > If the size of hugetlb page is 2MB, we need 512 struct page structures
> > (8 pages) to be associated with it. As far as I know, we only use the
> > first 3 struct page structures and only read the compound_dtor members
>
> Actually, the first 4 pages can be used if CONFIG_CGROUP_HUGETLB.

Right, thanks.

> /*
>  * Minimum page order trackable by hugetlb cgroup.
>  * At least 4 pages are necessary for all the tracking information.
>  * The second tail page (hpage[2]) is the fault usage cgroup.
>  * The third tail page (hpage[3]) is the reservation usage cgroup.
>  */
> #define HUGETLB_CGROUP_MIN_ORDER2
>
> However, this still easily fits within the first page of struct page
> structures.
>
> > of the remaining struct page structures. For tail page, the value of
> > compound_dtor is the same. So we can reuse first tail page. We map the
> > virtual addresses of the remaining 6 tail pages to the first tail page,
> > and then free these 6 pages. Therefore, we need to reserve at least 2
> > pages as vmemmap areas.
>
> I got confused the first time I read the above sentences.  Perhaps it
> should be more explicit with something like:
>
> For tail pages, the value of compound_dtor is the same. So we can reuse
> first page of tail page structs. We map the virtual addresses of the
> remaining 6 pages of tail page structs to the first tail page struct,
> and then free these 6 pages. Therefore, we need to reserve at least 2
> pages as vmemmap areas.

Sorry for my poor English. Thanks for your suggestions. I can apply this.

>
> It still does not sound great, but hopefully avoids some confusion.
> --
> Mike Kravetz
>
> > So we introduce a new nr_free_vmemmap_pages field in the hstate to
> > indicate how many vmemmap pages associated with a hugetlb page that we
> > can free to buddy system.
> >
> > Signed-off-by: Muchun Song 
> > ---
> >  include/linux/hugetlb.h |  3 +++
> >  mm/hugetlb.c| 35 +++
> >  2 files changed, 38 insertions(+)
> >
> > diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
> > index d5cc5f802dd4..eed3dd3bd626 100644
> > --- a/include/linux/hugetlb.h
> > +++ b/include/linux/hugetlb.h
> > @@ -492,6 +492,9 @@ struct hstate {
> >   unsigned int nr_huge_pages_node[MAX_NUMNODES];
> >   unsigned int free_huge_pages_node[MAX_NUMNODES];
> >   unsigned int surplus_huge_pages_node[MAX_NUMNODES];
> > +#ifdef CONFIG_HUGETLB_PAGE_FREE_VMEMMAP
> > + unsigned int nr_free_vmemmap_pages;
> > +#endif
> >  #ifdef CONFIG_CGROUP_HUGETLB
> >   /* cgroup control files */
> >   struct cftype cgroup_files_dfl[7];
> > diff --git a/mm/hugetlb.c b/mm/hugetlb.c
> > index 81a41aa080a5..f1b2b733b49b 100644
> > --- a/mm/hugetlb.c
> > +++ b/mm/hugetlb.c
> > @@ -1292,6 +1292,39 @@ static inline void 
> > destroy_compound_gigantic_page(struct page *page,
> >   unsigned int order) { }
> >  #endif
> >
> > +#ifdef CONFIG_HUGETLB_PAGE_FREE_VMEMMAP
> > +#define RESERVE_VMEMMAP_NR   2U
> > +
> > +static inline unsigned int nr_free_vmemmap(struct hstate *h)
> > +{
> > + return h->nr_free_vmemmap_pages;
> > +}
> > +
> > +static void __init hugetlb_vmemmap_init(struct hstate *h)
> > +{
> > + unsigned int order = huge_page_order(h);
> > + unsigned int vmemmap_pages;
> > +
> > + vmemmap_pages = ((1 << order) * sizeof(struct page)) >> PAGE_SHIFT;
> > + /*
> > +  * The head page and the first tail page not free to buddy system,
> > +  * the others page will map to the first tail page. So there are
> > +  * (@vmemmap_pages - RESERVE_VMEMMAP_NR) pages can be freed.
> > +  */
> > + if (vmemmap_pages > RESERVE_VMEMMAP_NR)
> > + h->nr_free_vmemmap_pages = vmemmap_pages - RESERVE_VMEMMAP_NR;
> > + else
> > + h->nr_free_vmemmap_pages = 0;
> > +
> > + pr_info("HugeTLB: can free %d vmemmap pages for %s\n",
> > + h->nr_free_vmemmap_pages, h->name);
> > +}
> > +#else
> > +static inline void hugetlb_vmemmap_init(struct hstate *h)
> > +{
> > +}
> > +#endif
> > +
> >  static void update_and_free_page(struct hstate *h, struct page *page)
> >  {
> >   int i;
> > @@ -3285,6 +3318,8 @@ void __init hugetlb_add_hstate(unsigned int order)
> >   snprintf(h->name, HSTATE_NAME_LEN, "hugepages-%lukB",
> >   huge_page_size(h)/1024);
> >
> > + hugetlb_vmemmap_init(h);
> > +
> >   parsed_hstate = h;
> >  }
> >
> >



-- 
Yours,
Muchun


Re: [PATCH v3 2/3] iommu/tegra-smmu: Rework .probe_device and .attach_dev

2020-09-30 Thread Nicolin Chen
On Thu, Oct 01, 2020 at 05:06:19AM +0300, Dmitry Osipenko wrote:
> 01.10.2020 04:26, Nicolin Chen пишет:
> > On Thu, Oct 01, 2020 at 12:56:46AM +0300, Dmitry Osipenko wrote:
> >> 01.10.2020 00:32, Nicolin Chen пишет:
> >>> On Thu, Oct 01, 2020 at 12:24:25AM +0300, Dmitry Osipenko wrote:
>  ...
> >> It looks to me like the only reason why you need this new global API is
> >> because PCI devices may not have a device tree node with a phandle to
> >> the IOMMU. However, SMMU support for PCI will only be enabled if the
> >> root complex has an iommus property, right? In that case, can't we
> >> simply do something like this:
> >>
> >>if (dev_is_pci(dev))
> >>np = find_host_bridge(dev)->of_node;
> >>else
> >>np = dev->of_node;
> >>
> >> ? I'm not sure exactly what find_host_bridge() is called, but I'm 
> >> pretty
> >> sure that exists.
> >>
> >> Once we have that we can still iterate over the iommus property and do
> >> not need to rely on this global variable.
> >
> > I agree that it'd work. But I was hoping to simplify the code
> > here if it's possible. Looks like we have an argument on this
> > so I will choose to go with your suggestion above for now.
> 
>  This patch removed more lines than were added. If this will be opposite
>  for the Thierry's suggestion, then it's probably not a great suggestion.
> >>>
> >>> Sorry, I don't quite understand this comments. Would you please
> >>> elaborate what's this "it" being "not a great suggestion"?
> >>>
> >>
> >> I meant that you should try to implement Thierry's solution, but if the
> >> end result will be worse than the current patch, then you shouldn't make
> >> a v4, but get back to this discussion in order to choose the best option
> >> and make everyone agree on it.
> > 
> > I see. Thanks for the reply. And here is a sample implementation:
> 
> That's what I supposed to happen :) The new variant adds code and
> complexity, while old did the opposite. Hence the old variant is clearly
> more attractive, IMO.

I personally am not a fan of adding a path for PCI device either,
since PCI/IOMMU cores could have taken care of it while the same
path can't be used for other buses.

If we can't come to an agreement on globalizing mc pointer, would
it be possible to pass tegra_mc_driver through tegra_smmu_probe()
so we can continue to use driver_find_device_by_fwnode() as v1?

v1: https://lkml.org/lkml/2020/9/26/68


linux-next: build failure after merge of the hwmon-staging tree

2020-09-30 Thread Stephen Rothwell
Hi all,

After merging the hwmon-staging tree, today's linux-next build (x86_64
allmodconfig) failed like this:

drivers/hwmon/pmbus/mp2975.c: In function 'mp2975_probe':
drivers/hwmon/pmbus/mp2975.c:740:32: error: passing argument 2 of 
'pmbus_do_probe' from incompatible pointer type 
[-Werror=incompatible-pointer-types]
  740 |  return pmbus_do_probe(client, id, info);
  |^~
  ||
  |const struct i2c_device_id *
In file included from drivers/hwmon/pmbus/mp2975.c:13:
drivers/hwmon/pmbus/pmbus.h:492:73: note: expected 'struct pmbus_driver_info *' 
but argument is of type 'const struct i2c_device_id *'
  492 | int pmbus_do_probe(struct i2c_client *client, struct pmbus_driver_info 
*info);
  |   
~~^~~~
drivers/hwmon/pmbus/mp2975.c:740:9: error: too many arguments to function 
'pmbus_do_probe'
  740 |  return pmbus_do_probe(client, id, info);
  | ^~
In file included from drivers/hwmon/pmbus/mp2975.c:13:
drivers/hwmon/pmbus/pmbus.h:492:5: note: declared here
  492 | int pmbus_do_probe(struct i2c_client *client, struct pmbus_driver_info 
*info);
  | ^~

Caused by commit

  dd38ac315b23 ("hwmon: (pmbus) Add support for MPS Multi-phase mp2975 
controller")

I have used the hwmon-staging tree from next-20200930 for today.

-- 
Cheers,
Stephen Rothwell


pgpJIgwuA93e8.pgp
Description: OpenPGP digital signature


[PATCH v2] pipe: Fix memory leaks in create_pipe_files()

2020-09-30 Thread Qian Cai
Calling pipe2() with O_NOTIFICATION_PIPE could results in memory leaks
in an error path or CONFIG_WATCH_QUEUE=n. Plug them.

unreferenced object 0xc0141114a0d8 (size 992):
  comm "trinity-c61", pid 1353192, jiffies 4296255779 (age 25989.560s)
  hex dump (first 32 bytes):
80 11 00 00 e8 03 00 00 00 00 00 00 00 00 00 00  
ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  
  backtrace:
[] kmem_cache_alloc+0x1b4/0x470
[<9502e5d5>] alloc_inode+0xd0/0x130
[] new_inode_pseudo+0x1c/0x80
new_inode_pseudo at fs/inode.c:932
[<0c01d1d6>] create_pipe_files+0x48/0x2d0
get_pipe_inode at fs/pipe.c:874
(inlined by) create_pipe_files at fs/pipe.c:914
[] __do_pipe_flags+0x50/0x120
__do_pipe_flags at fs/pipe.c:965
[<03941e42>] do_pipe2+0x3c/0x100
do_pipe2 at fs/pipe.c:1013
[] sys_pipe2+0x1c/0x30
__se_sys_pipe2 at fs/pipe.c:1028
[] system_call_exception+0xf8/0x1d0
[<1c6b0740>] system_call_common+0xe8/0x218
unreferenced object 0xc01f575ce600 (size 512):
  comm "trinity-c61", pid 1353192, jiffies 4296255779 (age 25989.560s)
  hex dump (first 32 bytes):
00 00 00 00 00 00 00 00 00 00 00 00 ad 4e ad de  .N..
ff ff ff ff 00 00 00 00 ff ff ff ff ff ff ff ff  
  backtrace:
[] kmem_cache_alloc_trace+0x1c4/0x2d0
[<61cbc9cb>] alloc_pipe_info+0x88/0x2c0
kmalloc at include/linux/slab.h:554
(inlined by) kzalloc at include/linux/slab.h:666
(inlined by) alloc_pipe_info at fs/pipe.c:793
[] create_pipe_files+0x6c/0x2d0
get_pipe_inode at fs/pipe.c:883
(inlined by) create_pipe_files at fs/pipe.c:914
[] __do_pipe_flags+0x50/0x120
[<03941e42>] do_pipe2+0x3c/0x100
[] sys_pipe2+0x1c/0x30
[] system_call_exception+0xf8/0x1d0
[<1c6b0740>] system_call_common+0xe8/0x218
unreferenced object 0xc00d94f20400 (size 1024):
  comm "trinity-c61", pid 1353192, jiffies 4296255779 (age 25989.560s)
  hex dump (first 32 bytes):
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  
  backtrace:
[] __kmalloc+0x1e4/0x330
[<130e8cc8>] alloc_pipe_info+0x154/0x2c0
kmalloc_array at include/linux/slab.h:594
(inlined by) kcalloc at include/linux/slab.h:605
(inlined by) alloc_pipe_info at fs/pipe.c:810
[] create_pipe_files+0x6c/0x2d0
[] __do_pipe_flags+0x50/0x120
[<03941e42>] do_pipe2+0x3c/0x100
[] sys_pipe2+0x1c/0x30
[] system_call_exception+0xf8/0x1d0
[<1c6b0740>] system_call_common+0xe8/0x218

Fixes: c73be61cede5 ("pipe: Add general notification queue support")
Signed-off-by: Qian Cai 
---
 fs/pipe.c   | 11 +--
 include/linux/watch_queue.h |  4 
 2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/fs/pipe.c b/fs/pipe.c
index 60dbee457143..6fbfbb8f32e1 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -913,19 +913,18 @@ int create_pipe_files(struct file **res, int flags)
 {
struct inode *inode = get_pipe_inode();
struct file *f;
+   int ret;
 
if (!inode)
return -ENFILE;
 
if (flags & O_NOTIFICATION_PIPE) {
-#ifdef CONFIG_WATCH_QUEUE
-   if (watch_queue_init(inode->i_pipe) < 0) {
+   ret = watch_queue_init(inode->i_pipe);
+   if (ret < 0) {
+   free_pipe_info(inode->i_pipe);
iput(inode);
-   return -ENOMEM;
+   return ret;
}
-#else
-   return -ENOPKG;
-#endif
}
 
f = alloc_file_pseudo(inode, pipe_mnt, "",
diff --git a/include/linux/watch_queue.h b/include/linux/watch_queue.h
index 5e08db2adc31..20665fbe0552 100644
--- a/include/linux/watch_queue.h
+++ b/include/linux/watch_queue.h
@@ -123,5 +123,9 @@ static inline void remove_watch_list(struct watch_list 
*wlist, u64 id)
 #define watch_sizeof(STRUCT) (sizeof(STRUCT) << WATCH_INFO_LENGTH__SHIFT)
 
 #endif
+static inline int watch_queue_init(struct pipe_inode_info *pipe)
+{
+   return -ENOPKG;
+}
 
 #endif /* _LINUX_WATCH_QUEUE_H */
-- 
2.28.0



Re: [PATCH v5 00/15] Add Broadcom VK driver

2020-09-30 Thread Florian Fainelli




On 9/30/2020 6:27 PM, Scott Branden wrote:

This patch series drops previous patches in [1]
that were incorporated by Kees Cook into patch series
"Introduce partial kernel_read_file() support" [2].

Remaining patches are contained in this series to add Broadcom VK driver.
(which depends on request_firmware_into_buf API addition in
other patch series [2] being applied first).

Please note this patch series will not compile without [2].

[1] 
https://lore.kernel.org/lkml/20200706232309.12010-1-scott.bran...@broadcom.com/
[2] https://lore.kernel.org/lkml/20200729175845.1745471-1-keesc...@chromium.org/


Disclaimer: I am well aware that it is the complete wild west right now 
as far as accelerators go and that every vendor (that I happen to work 
for, just not in the same group as Scott) is just seeking to get their 
drivers included upstream and hopefully for good reasons.


From a cursory look however, it sounds like there could be a little 
better re-utilization of standards, standard framework and interfaces:


- about 2/3 of your sysfs attributes should incline you to implement a 
HWMON device, not a complicated one, but anything that indicates 
current, power, temperature, alerts etc. should be considered


- cannot the firmware loading be supported over remoteproc somehow?

- could not the TTY interface be using virtio or an existing UART?

- what is the format of the message over BAR2 that you expose in patch 13?

Is there a reference user-space implementation that you can link to this 
patch submission in case people are curious?


Thanks
--
Florian


Re: [PATCH v5 15/15] misc: bcm-vk: add ttyVK support

2020-09-30 Thread Florian Fainelli




On 9/30/2020 6:28 PM, Scott Branden wrote:

Add ttyVK support to driver to allow console access to VK card from host.

Device node will be in the follow form /dev/bcm-vk.x_ttyVKy where:
x is the instance of the VK card
y is the tty device number on the VK card

Signed-off-by: Scott Branden 


Was it not possible to:

- emulate a standard 8250 UART and just expose an additional bar + MSI 
vector such that one could get a debug UART out of this device with 
little to no work on the host side?


- or use virtio console and implement virtio on the firmware that runs 
on VK?


It's not a lot of code, but it just feels like this should not have to 
be done at all.

--
Florian


Re: [PATCH v5 11/15] misc: bcm-vk: add BCM_VK_QSTATS

2020-09-30 Thread Florian Fainelli




On 9/30/2020 6:28 PM, Scott Branden wrote:

Add BCM_VK_QSTATS Kconfig option to allow for enabling debug VK
queue statistics.

These statistics keep track of max, abs_max, and average for the
messages queues.

Co-developed-by: Desmond Yan 
Signed-off-by: Desmond Yan 
Signed-off-by: Scott Branden 
---


[snip]


+#if defined(CONFIG_BCM_VK_QSTATS)
+   /* clear qstats */
+   for (i = 0; i < VK_MSGQ_MAX_NR; i++) {
+   memset(>to_v_msg_chan.qstats[i].qcnts, 0,
+  sizeof(vk->to_v_msg_chan.qstats[i].qcnts));
+   memset(>to_h_msg_chan.qstats[i].qcnts, 0,
+  sizeof(vk->to_h_msg_chan.qstats[i].qcnts));
+   }
+#endif
/* clear 4096 bits of bitmap */
bitmap_clear(vk->bmap, 0, VK_MSG_ID_BITMAP_SIZE);


It was not clear from looking at this patch how are the statistics 
exposed and how does one actually get them?

--
Florian


Re: [PATCH v5 12/15] misc: bcm-vk: add sysfs interface

2020-09-30 Thread Florian Fainelli




On 9/30/2020 6:28 PM, Scott Branden wrote:

Add sysfs support to query the VK card status and monitor sense points.
The vk-card-status and vk-card-mon details are provided in the README
file in the bcm-vk driver directory.

Co-developed-by: Desmond Yan 
Signed-off-by: Desmond Yan 
Signed-off-by: Scott Branden 
---


[snip]


+vk-card-status/
+   bus ---> device PCIe bus
+   card_state  ---> summary of current card states
+   chip_id
+   firmware_status ---> summary of all firmware status
+   firmware_version---> summary of all firmware versions
+   freq_core_mhz   ---> running frequency in mHz
+   freq_mem_mhz---> memory frequency in mHz
+   mem_size_mb ---> memory size in MByte
+   os_state---> current running state
+   reset_reason---> last reset reason
+   rev_boot1   ---> boot1 firmware revision
+   rev_boot2   ---> boot2 firmware revision
+   rev_driver  ---> host driver revision
+   rev_flash_rom   ---> Flash ROM revision
+   sotp_boot1_rev_id   ---> minimum boot1 revision required
+   sotp_boot2_rev_id   ---> minimum boot2 revision required
+   sotp_dauth_1---> authentication key hash
+   sotp_dauth_1_valid  ---> authentication key validity
+   sotp_dauth_1_active_status -> authentication key active or not
+   sotp_dauth_2
+   sotp_dauth_2_valid
+   sotp_dauth_2_active_status
+   sotp_dauth_3
+   sotp_dauth_3_valid
+   sotp_dauth_3_active_status
+   sotp_dauth_4
+   sotp_dauth_4_valid
+   sotp_dauth_4_active_status
+   temp_threshold_lower_c  ---> thermal low threshold in Celsius
+   temp_threshold_upper_c  ---> thermal high threshold in Celsius
+   uptime_s---> os up time in seconds
+
+vk-card-mon/
+   alert_afbc_busy ---> AFBC block stuck
+   alert_ecc   ---> uncorrectable ECC error(s) occurred
+   alert_ecc_warn  ---> correctable ECC error(s) occurred
+   alert_heartbeat_fail---> host detects heartbeat discontinuation
+from card
+   alert_high_temp ---> high temperature threshold crossed
+   alert_intf_ver_fail ---> interface not compatible based on version
+   alert_low_temp_warn ---> low temperature threshold crossed
+   alert_malloc_fail_warn  ---> mem allocation failure(s) occurred
+   alert_pcie_down ---> host detect pcie intf going down
+   alert_ssim_busy ---> ssim block busy
+   alert_sys_fault ---> system fault
+   alert_wdog_timeout  ---> watchdog timeout


Almost all of these should be supported using the HWMON framework 
instead of custom attributes that do not follow the HWMON naming 
conventions.



+   firmware_status_reg
+   mem_ecc ---> correctable ECC error count
+   mem_uecc---> uncorrectable ECC error count


Implementing an EDAC driver would be a bit overkill unless you have a 
way to signal ECC errors towards the host?



+   boot_status_reg ---> boot status of card
+   pwr_state   ---> power state, 1-full, 2-reduced, 3-lowest
+   temperature_sensor_1_c  ---> CPU die temperature in Celsius
+   temperature_sensor_2_c  ---> DDR0 temperature in Celsius
+   temperature_sensor_3_c  ---> DDR1 temperature in Celsius


Likewise.


+   utilization ---> runtime video transcoding consumption 
summary
+   utilization_pix ---> percentage of pixel processing used
+   utilization_pix_used---> pixel processing used
+   utilization_pix_max ---> max pixel processing value which maps 100% 
load
+   utilization_codec   ---> percentage of codec sessions used
+   utilization_codec_used  ---> codec sessions currently used
+   utilization_codec_max   ---> max codec sessions allowed
+   voltage_18_mv   ---> 1.8v voltage rail in mv
+   voltage_33_mv   ---> 3.3v voltage rail in mv


Likewise


+
+The sysfs entry supports only the read operation.


entries.
--
Florian


Re: dsa: mv88e6xxx: serdes link without phy

2020-09-30 Thread Chris Packham

On 1/10/20 2:24 pm, Andrew Lunn wrote:
>>       port@8 {
>>       reg = <8>;
>>       label = "internal8";
>>       phy-mode = "rgmii-id";
>>       fixed-link {
>>       speed = <1000>;
>>       full-duplex;
>>       };
>>       };
>>       port@9 {
>>       reg = <9>;
>>       label = "internal9";
>>       phy-mode = "rgmii-id";
>>       fixed-link {
>>       speed = <1000>;
>>       full-duplex;
>>       };
>>       };
>> The problem is that by declaring ports 8 & 9 as fixed link the driver
>> sets the ForcedLink in the PCS control register. Which mostly works.
>> Except if I add a chassis controller while the system is running (or one
>> is rebooted) then the newly added controller doesn't see a link on the
>> serdes.
> Hi Chris
>
> You say SERDES here, but in DT you have rgmii-id?
Yeah that's mostly because it was copied from the CPU port (which is 
RGMII with internal delay). The Marvell datasheet says "SERDES" so I 
wasn't really sure what to put here
> Can you run 1000Base-X over these links?
With some reading "1000base-x" does seem the right thing to say here. 
It's even what is reflected in the CMODE field for those ports.
> If you can, it is probably
> worth chatting to Russell King about using inband-signalling, and what
> is needed to make it work without having back to back SFPs. If i
> remember correctly, Russell has said not much is actually needed.

That'd be ideal. The sticking point seems to be allowing it to have no PHY.


Re: For review: seccomp_user_notif(2) manual page

2020-09-30 Thread Jann Horn
On Thu, Oct 1, 2020 at 3:52 AM Jann Horn  wrote:
> On Thu, Oct 1, 2020 at 1:25 AM Tycho Andersen  wrote:
> > On Thu, Oct 01, 2020 at 01:11:33AM +0200, Jann Horn wrote:
> > > On Thu, Oct 1, 2020 at 1:03 AM Tycho Andersen  wrote:
> > > > On Wed, Sep 30, 2020 at 10:34:51PM +0200, Michael Kerrisk (man-pages) 
> > > > wrote:
> > > > > On 9/30/20 5:03 PM, Tycho Andersen wrote:
> > > > > > On Wed, Sep 30, 2020 at 01:07:38PM +0200, Michael Kerrisk 
> > > > > > (man-pages) wrote:
> > > > > >>┌─┐
> > > > > >>│FIXME│
> > > > > >>├─┤
> > > > > >>│From my experiments,  it  appears  that  if  a  SEC‐ │
> > > > > >>│COMP_IOCTL_NOTIF_RECV   is  done  after  the  target │
> > > > > >>│process terminates, then the ioctl()  simply  blocks │
> > > > > >>│(rather than returning an error to indicate that the │
> > > > > >>│target process no longer exists).│
> > > > > >
> > > > > > Yeah, I think Christian wanted to fix this at some point,
> > > > >
> > > > > Do you have a pointer that discussion? I could not find it with a
> > > > > quick search.
> > > > >
> > > > > > but it's a
> > > > > > bit sticky to do.
> > > > >
> > > > > Can you say a few words about the nature of the problem?
> > > >
> > > > I remembered wrong, it's actually in the tree: 99cdb8b9a573 ("seccomp:
> > > > notify about unused filter"). So maybe there's a bug here?
> > >
> > > That thing only notifies on ->poll, it doesn't unblock ioctls; and
> > > Michael's sample code uses SECCOMP_IOCTL_NOTIF_RECV to wait. So that
> > > commit doesn't have any effect on this kind of usage.
> >
> > Yes, thanks. And the ones stuck in RECV are waiting on a semaphore so
> > we don't have a count of all of them, unfortunately.
> >
> > We could maybe look inside the wait_list, but that will probably make
> > people angry :)
>
> The easiest way would probably be to open-code the semaphore-ish part,
> and let the semaphore and poll share the waitqueue. The current code
> kind of mirrors the semaphore's waitqueue in the wqh - open-coding the
> entire semaphore would IMO be cleaner than that. And it's not like
> semaphore semantics are even a good fit for this code anyway.
>
> Let's see... if we didn't have the existing UAPI to worry about, I'd
> do it as follows (*completely* untested). That way, the ioctl would
> block exactly until either there actually is a request to deliver or
> there are no more users of the filter. The problem is that if we just
> apply this patch, existing users of SECCOMP_IOCTL_NOTIF_RECV that use
> an event loop and don't set O_NONBLOCK will be screwed. So we'd
> probably also have to add some stupid counter in place of the
> semaphore's counter that we can use to preserve the old behavior of
> returning -ENOENT once for each cancelled request. :(
>
> I guess this is a nice point in favor of Michael's usual complaint
> that if there are no man pages for a feature by the time the feature
> lands upstream, there's a higher chance that the UAPI will suck
> forever...

And I guess this would be the UAPI-compatible version - not actually
as terrible as I thought it might be. Do y'all want this? If so, feel
free to either turn this into a proper patch with Co-developed-by, or
tell me that I should do it and I'll try to get around to turning it
into something proper.

diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index 676d4af62103..d08c453fcc2c 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -138,7 +138,7 @@ struct seccomp_kaddfd {
  * @notifications: A list of struct seccomp_knotif elements.
  */
 struct notification {
-   struct semaphore request;
+   bool canceled_reqs;
u64 next_id;
struct list_head notifications;
 };
@@ -859,7 +859,6 @@ static int seccomp_do_user_notification(int this_syscall,
list_add(, >notif->notifications);
INIT_LIST_HEAD();

-   up(>notif->request);
wake_up_poll(>wqh, EPOLLIN | EPOLLRDNORM);
mutex_unlock(>notify_lock);

@@ -901,8 +900,20 @@ static int seccomp_do_user_notification(int this_syscall,
 * *reattach* to a notifier right now. If one is added, we'll need to
 * keep track of the notif itself and make sure they match here.
 */
-   if (match->notif)
+   if (match->notif) {
list_del();
+
+   /*
+* We are stuck with a UAPI that requires that after a spurious
+* wakeup, SECCOMP_IOCTL_NOTIF_RECV must return immediately.
+* This is the tracking for that, keeping track of whether we
+* canceled a request after waking waiters, but before userspace
+* picked up the notification.
+*/
+   if (n.state == SECCOMP_NOTIFY_INIT)
+   

[PATCH 00/25] ASoC: sun8i-codec: support for AIF2 and AIF3

2020-09-30 Thread Samuel Holland
This series adds support the other two AIFs present in the sun8i codec,
which can be used for codec2codec DAI links.

This series first cleans up the DAPM component driver so there is an
organized place to put the new widgets. Then it fills out the DAI
driver, removing assumptions that were made for AIF1 (16 bits, 2
channels, certain clock inversions). Some new logic is required to
handle 3 DAIs and the ADC/DAC sharing the same clock. Finally, it adds
the new DAIs, and hooks them up with DAPM widgets and routes per the
hardware topology.

To minimize the number of patches in this series, related device tree
patches (increasing #sound-dai-cells, adding new DAI links) will be sent
separately.

Samuel Holland (25):
  ASoC: sun8i-codec: Set up clock tree at probe time
  ASoC: sun8i-codec: Swap module clock/reset dependencies
  ASoC: sun8i-codec: Sort DAPM controls, widgets, and routes
  ASoC: sun8i-codec: Consistently name DAPM widgets and routes
  ASoC: sun8i-codec: Correct DAPM widget types
  ASoC: sun8i-codec: Fix AIF widget channel references
  ASoC: sun8i-codec: Enable AIF mono/stereo control
  ASoC: sun8i-codec: Use snd_soc_dai_get_drvdata
  ASoC: sun8i-codec: Prepare to extend the DAI driver
  ASoC: sun8i-codec: Program format before clock inversion
  ASoC: sun8i-codec: Enable all supported clock inversions
  ASoC: sun8i-codec: Program the correct word size
  ASoC: sun8i-codec: Round up the LRCK divisor
  ASoC: sun8i-codec: Correct the BCLK divisor calculation
  ASoC: sun8i-codec: Support the TDM slot binding
  ASoC: sun8i-codec: Enforce symmetric DAI parameters
  ASoC: sun8i-codec: Enable all supported sample rates
  ASoC: sun8i-codec: Automatically set the system sample rate
  ASoC: sun8i-codec: Constrain to compatible sample rates
  ASoC: sun8i-codec: Protect the clock rate while streams are open
  ASoC: sun8i-codec: Require an exact BCLK divisor match
  ASoC: sun8i-codec: Enable all supported PCM formats
  ASoC: sun8i-codec: Generalize AIF clock control
  ASoC: sun8i-codec: Add a DAI, widgets, and routes for AIF2
  ASoC: sun8i-codec: Add a DAI, widgets, and routes for AIF3

 sound/soc/sunxi/sun8i-codec.c | 1135 ++---
 1 file changed, 894 insertions(+), 241 deletions(-)

-- 
2.26.2



[PATCH 05/25] ASoC: sun8i-codec: Correct DAPM widget types

2020-09-30 Thread Samuel Holland
Whie the aif_in and aif_out widget types are handled exactly the same in
the core DAPM code, a future widget event hook will need the correct
widget type to derive the associated substream. Clean up the widget type
for that reason, and so these widgets will match newly-added widgets for
the other AIFs.

Signed-off-by: Samuel Holland 
---
 sound/soc/sunxi/sun8i-codec.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index 30fe27648254..d0028883950c 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -405,22 +405,22 @@ static const struct snd_soc_dapm_widget 
sun8i_codec_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("ADC",
SUN8I_ADC_DIG_CTRL,
SUN8I_ADC_DIG_CTRL_ENAD, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("DAC",
SUN8I_DAC_DIG_CTRL,
SUN8I_DAC_DIG_CTRL_ENDA, 0, NULL, 0),
 
/* AIF "ADC" Outputs */
-   SND_SOC_DAPM_AIF_IN("AIF1 AD0L", "Capture", 0,
-   SUN8I_AIF1_ADCDAT_CTRL,
-   SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_ENA, 0),
-   SND_SOC_DAPM_AIF_IN("AIF1 AD0R", "Capture", 0,
-   SUN8I_AIF1_ADCDAT_CTRL,
-   SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_ENA, 0),
+   SND_SOC_DAPM_AIF_OUT("AIF1 AD0L", "Capture", 0,
+SUN8I_AIF1_ADCDAT_CTRL,
+SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_ENA, 0),
+   SND_SOC_DAPM_AIF_OUT("AIF1 AD0R", "Capture", 0,
+SUN8I_AIF1_ADCDAT_CTRL,
+SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_ENA, 0),
 
/* AIF "ADC" Mixers */
SOC_MIXER_ARRAY("AIF1 AD0L Mixer", SND_SOC_NOPM, 0, 0,
sun8i_aif1_ad0_mixer_controls),
SOC_MIXER_ARRAY("AIF1 AD0R Mixer", SND_SOC_NOPM, 0, 0,
sun8i_aif1_ad0_mixer_controls),
 
/* AIF "DAC" Inputs */
-- 
2.26.2



[PATCH 15/25] ASoC: sun8i-codec: Support the TDM slot binding

2020-09-30 Thread Samuel Holland
Now that BCLK and LRCK rate calculations can handle any
hardware-supported slot width and number of slots, enable
support for overriding these parameters from the device tree.

Signed-off-by: Samuel Holland 
---
 sound/soc/sunxi/sun8i-codec.c | 28 ++--
 1 file changed, 26 insertions(+), 2 deletions(-)

diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index 78feed37aa42..0a53dc0c34d0 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -94,25 +94,31 @@
 #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK  GENMASK(5, 4)
 #define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK  GENMASK(3, 2)
 
 enum {
AIF1,
NAIFS
 };
 
+struct sun8i_codec_aif {
+   unsigned intslots;
+   unsigned intslot_width;
+};
+
 struct sun8i_codec_quirks {
bool legacy_widgets : 1;
bool lrck_inversion : 1;
 };
 
 struct sun8i_codec {
struct regmap   *regmap;
struct clk  *clk_module;
const struct sun8i_codec_quirks *quirks;
+   struct sun8i_codec_aif  aifs[NAIFS];
 };
 
 static int sun8i_codec_runtime_resume(struct device *dev)
 {
struct sun8i_codec *scodec = dev_get_drvdata(dev);
int ret;
 
regcache_cache_only(scodec->regmap, false);
@@ -256,16 +262,32 @@ static int sun8i_codec_set_fmt(struct snd_soc_dai *dai, 
unsigned int fmt)
 
regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
   SUN8I_AIF1CLK_CTRL_AIF1_CLK_INV_MASK,
   value << SUN8I_AIF1CLK_CTRL_AIF1_CLK_INV);
 
return 0;
 }
 
+static int sun8i_codec_set_tdm_slot(struct snd_soc_dai *dai,
+   unsigned int tx_mask, unsigned int rx_mask,
+   int slots, int slot_width)
+{
+   struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);
+   struct sun8i_codec_aif *aif = >aifs[dai->id];
+
+   if (slot_width && !is_power_of_2(slot_width))
+   return -EINVAL;
+
+   aif->slots = slots;
+   aif->slot_width = slot_width;
+
+   return 0;
+}
+
 struct sun8i_codec_clk_div {
u8  div;
u8  val;
 };
 
 static const struct sun8i_codec_clk_div sun8i_codec_bclk_div[] = {
{ .div = 1, .val = 0 },
{ .div = 2, .val = 1 },
@@ -316,18 +338,19 @@ static int sun8i_codec_get_lrck_div_order(unsigned int 
slots,
return order_base_2(div);
 }
 
 static int sun8i_codec_hw_params(struct snd_pcm_substream *substream,
 struct snd_pcm_hw_params *params,
 struct snd_soc_dai *dai)
 {
struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);
-   unsigned int slots = params_channels(params);
-   unsigned int slot_width = params_width(params);
+   struct sun8i_codec_aif *aif = >aifs[dai->id];
+   unsigned int slots = aif->slots ?: params_channels(params);
+   unsigned int slot_width = aif->slot_width ?: params_width(params);
int lrck_div_order, sample_rate, word_size;
u8 bclk_div;
 
/* word size */
switch (params_width(params)) {
case 8:
word_size = 0x0;
break;
@@ -371,16 +394,17 @@ static int sun8i_codec_hw_params(struct snd_pcm_substream 
*substream,
   SUN8I_SYS_SR_CTRL_AIF1_FS_MASK,
   sample_rate << SUN8I_SYS_SR_CTRL_AIF1_FS);
 
return 0;
 }
 
 static const struct snd_soc_dai_ops sun8i_codec_dai_ops = {
.set_fmt= sun8i_codec_set_fmt,
+   .set_tdm_slot   = sun8i_codec_set_tdm_slot,
.hw_params  = sun8i_codec_hw_params,
 };
 
 static struct snd_soc_dai_driver sun8i_codec_dais[] = {
{
.name   = "sun8i-codec-aif1",
.id = AIF1,
.ops= _codec_dai_ops,
-- 
2.26.2



[PATCH 17/25] ASoC: sun8i-codec: Enable all supported sample rates

2020-09-30 Thread Samuel Holland
The system sample rate programmed into the hardware is really a clock
divider from SYSCLK to the ADC and DAC. Since we support two SYSCLK
frequencies, we can use all sample rates corresponding to one of those
frequencies divided by any available divisor.

This commit enables support for those sample rates. It also stops
advertising support for a 64 kHz sample rate, which is not supported.

Signed-off-by: Samuel Holland 
---
 sound/soc/sunxi/sun8i-codec.c | 17 ++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index f21274530a0e..f4b2a7cc9810 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -89,16 +89,23 @@
 #define SUN8I_SYS_SR_CTRL_AIF1_FS_MASK GENMASK(15, 12)
 #define SUN8I_SYS_SR_CTRL_AIF2_FS_MASK GENMASK(11, 8)
 #define SUN8I_AIF1CLK_CTRL_AIF1_CLK_INV_MASK   GENMASK(14, 13)
 #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK  GENMASK(12, 9)
 #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK  GENMASK(8, 6)
 #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK  GENMASK(5, 4)
 #define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK  GENMASK(3, 2)
 
+#define SUN8I_CODEC_PCM_RATES  (SNDRV_PCM_RATE_8000_48000|\
+SNDRV_PCM_RATE_88200 |\
+SNDRV_PCM_RATE_96000 |\
+SNDRV_PCM_RATE_176400|\
+SNDRV_PCM_RATE_192000|\
+SNDRV_PCM_RATE_KNOT)
+
 enum {
AIF1,
NAIFS
 };
 
 struct sun8i_codec_aif {
unsigned intslots;
unsigned intslot_width;
@@ -142,37 +149,41 @@ static int sun8i_codec_runtime_suspend(struct device *dev)
return 0;
 }
 
 static int sun8i_codec_get_hw_rate(struct snd_pcm_hw_params *params)
 {
unsigned int rate = params_rate(params);
 
switch (rate) {
-   case 8000:
case 7350:
+   case 8000:
return 0x0;
case 11025:
return 0x1;
case 12000:
return 0x2;
+   case 14700:
case 16000:
return 0x3;
case 22050:
return 0x4;
case 24000:
return 0x5;
+   case 29400:
case 32000:
return 0x6;
case 44100:
return 0x7;
case 48000:
return 0x8;
+   case 88200:
case 96000:
return 0x9;
+   case 176400:
case 192000:
return 0xa;
default:
return -EINVAL;
}
 }
 
 static int sun8i_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
@@ -408,26 +419,26 @@ static struct snd_soc_dai_driver sun8i_codec_dais[] = {
.name   = "sun8i-codec-aif1",
.id = AIF1,
.ops= _codec_dai_ops,
/* capture capabilities */
.capture = {
.stream_name= "AIF1 Capture",
.channels_min   = 1,
.channels_max   = 2,
-   .rates  = SNDRV_PCM_RATE_8000_192000,
+   .rates  = SUN8I_CODEC_PCM_RATES,
.formats= SNDRV_PCM_FMTBIT_S16_LE,
.sig_bits   = 24,
},
/* playback capabilities */
.playback = {
.stream_name= "AIF1 Playback",
.channels_min   = 1,
.channels_max   = 2,
-   .rates  = SNDRV_PCM_RATE_8000_192000,
+   .rates  = SUN8I_CODEC_PCM_RATES,
.formats= SNDRV_PCM_FMTBIT_S16_LE,
},
.symmetric_rates= true,
.symmetric_channels = true,
.symmetric_samplebits   = true,
},
 };
 
-- 
2.26.2



[PATCH 13/25] ASoC: sun8i-codec: Round up the LRCK divisor

2020-09-30 Thread Samuel Holland
The codec supports only power-of-two BCLK/LRCK divisors. If either the
slot width or the number of slots is not a power of two, the LRCK
divisor must be rounded up to provide enough space. To do that, use
order_base_2 (instead of ilog2, which rounds down).

Since the rounded divisor is also needed for setting the SYSCLK/BCLK
divisor, return the order base 2 instead of fully calculating the
hardware register encoding.

Signed-off-by: Samuel Holland 
---
 sound/soc/sunxi/sun8i-codec.c | 22 --
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index e7f01a4b4001..779853d023fe 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -300,33 +300,35 @@ static u8 sun8i_codec_get_bclk_div(struct sun8i_codec 
*scodec,
best_diff = diff;
best_val = bdiv->val;
}
}
 
return best_val;
 }
 
-static int sun8i_codec_get_lrck_div(unsigned int channels,
-   unsigned int word_size)
+static int sun8i_codec_get_lrck_div_order(unsigned int slots,
+ unsigned int slot_width)
 {
-   unsigned int div = word_size * channels;
+   unsigned int div = slots * slot_width;
 
if (div < 16 || div > 256)
return -EINVAL;
 
-   return ilog2(div) - 4;
+   return order_base_2(div);
 }
 
 static int sun8i_codec_hw_params(struct snd_pcm_substream *substream,
 struct snd_pcm_hw_params *params,
 struct snd_soc_dai *dai)
 {
struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);
-   int lrck_div, sample_rate, word_size;
+   unsigned int slots = params_channels(params);
+   unsigned int slot_width = params_width(params);
+   int lrck_div_order, sample_rate, word_size;
u8 bclk_div;
 
/* word size */
switch (params_width(params)) {
case 8:
word_size = 0x0;
break;
case 16:
@@ -346,24 +348,24 @@ static int sun8i_codec_hw_params(struct snd_pcm_substream 
*substream,
   SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK,
   word_size << SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ);
 
bclk_div = sun8i_codec_get_bclk_div(scodec, params_rate(params), 16);
regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
   SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK,
   bclk_div << SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV);
 
-   lrck_div = sun8i_codec_get_lrck_div(params_channels(params),
-   params_physical_width(params));
-   if (lrck_div < 0)
-   return lrck_div;
+   /* LRCK divider (BCLK/LRCK ratio) */
+   lrck_div_order = sun8i_codec_get_lrck_div_order(slots, slot_width);
+   if (lrck_div_order < 0)
+   return lrck_div_order;
 
regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
   SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK,
-  lrck_div << SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV);
+  (lrck_div_order - 4) << 
SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV);
 
sample_rate = sun8i_codec_get_hw_rate(params);
if (sample_rate < 0)
return sample_rate;
 
regmap_update_bits(scodec->regmap, SUN8I_SYS_SR_CTRL,
   SUN8I_SYS_SR_CTRL_AIF1_FS_MASK,
   sample_rate << SUN8I_SYS_SR_CTRL_AIF1_FS);
-- 
2.26.2



[PATCH 02/25] ASoC: sun8i-codec: Swap module clock/reset dependencies

2020-09-30 Thread Samuel Holland
This matches the module power-up/down sequence from the vendor's driver.

While updating these widgets/routes, reorder them to match the register
and bit layout of the hardware. This puts them in the same place in the
widget and route arrays (previously they were at opposite ends), and it
makes it easier to track which parts of which registers are implemented.

Signed-off-by: Samuel Holland 
---
 sound/soc/sunxi/sun8i-codec.c | 72 +++
 1 file changed, 39 insertions(+), 33 deletions(-)

diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index 407f0fedc4ed..6887a2e897f4 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -373,16 +373,38 @@ static const struct snd_soc_dapm_widget 
sun8i_codec_dapm_widgets[] = {
 
SND_SOC_DAPM_SUPPLY("AIF1CLK",
SUN8I_SYSCLK_CTL,
SUN8I_SYSCLK_CTL_AIF1CLK_ENA, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("SYSCLK",
SUN8I_SYSCLK_CTL,
SUN8I_SYSCLK_CTL_SYSCLK_ENA, 0, NULL, 0),
 
+   /* Module Clocks */
+   SND_SOC_DAPM_SUPPLY("CLK AIF1",
+   SUN8I_MOD_CLK_ENA,
+   SUN8I_MOD_CLK_ENA_AIF1, 0, NULL, 0),
+   SND_SOC_DAPM_SUPPLY("CLK ADC",
+   SUN8I_MOD_CLK_ENA,
+   SUN8I_MOD_CLK_ENA_ADC, 0, NULL, 0),
+   SND_SOC_DAPM_SUPPLY("CLK DAC",
+   SUN8I_MOD_CLK_ENA,
+   SUN8I_MOD_CLK_ENA_DAC, 0, NULL, 0),
+
+   /* Module Resets */
+   SND_SOC_DAPM_SUPPLY("RST AIF1",
+   SUN8I_MOD_RST_CTL,
+   SUN8I_MOD_RST_CTL_AIF1, 0, NULL, 0),
+   SND_SOC_DAPM_SUPPLY("RST ADC",
+   SUN8I_MOD_RST_CTL,
+   SUN8I_MOD_RST_CTL_ADC, 0, NULL, 0),
+   SND_SOC_DAPM_SUPPLY("RST DAC",
+   SUN8I_MOD_RST_CTL,
+   SUN8I_MOD_RST_CTL_DAC, 0, NULL, 0),
+
/* Digital parts of the DACs and ADC */
SND_SOC_DAPM_SUPPLY("DAC", SUN8I_DAC_DIG_CTRL, SUN8I_DAC_DIG_CTRL_ENDA,
0, NULL, 0),
SND_SOC_DAPM_SUPPLY("ADC", SUN8I_ADC_DIG_CTRL, SUN8I_ADC_DIG_CTRL_ENAD,
0, NULL, 0),
 
/* AIF "DAC" Inputs */
SND_SOC_DAPM_AIF_IN("AIF1 DA0L", "Playback", 0,
@@ -412,60 +434,44 @@ static const struct snd_soc_dapm_widget 
sun8i_codec_dapm_widgets[] = {
SOC_MIXER_ARRAY("Left Digital DAC Mixer", SND_SOC_NOPM, 0, 0,
sun8i_dac_mixer_controls),
SOC_MIXER_ARRAY("Right Digital DAC Mixer", SND_SOC_NOPM, 0, 0,
sun8i_dac_mixer_controls),
SOC_MIXER_ARRAY("Left Digital ADC Mixer", SND_SOC_NOPM, 0, 0,
sun8i_input_mixer_controls),
SOC_MIXER_ARRAY("Right Digital ADC Mixer", SND_SOC_NOPM, 0, 0,
sun8i_input_mixer_controls),
-
-   /* Clocks */
-   SND_SOC_DAPM_SUPPLY("MODCLK AIF1", SUN8I_MOD_CLK_ENA,
-   SUN8I_MOD_CLK_ENA_AIF1, 0, NULL, 0),
-   SND_SOC_DAPM_SUPPLY("MODCLK DAC", SUN8I_MOD_CLK_ENA,
-   SUN8I_MOD_CLK_ENA_DAC, 0, NULL, 0),
-   SND_SOC_DAPM_SUPPLY("MODCLK ADC", SUN8I_MOD_CLK_ENA,
-   SUN8I_MOD_CLK_ENA_ADC, 0, NULL, 0),
-
-   /* Module reset */
-   SND_SOC_DAPM_SUPPLY("RST AIF1", SUN8I_MOD_RST_CTL,
-   SUN8I_MOD_RST_CTL_AIF1, 0, NULL, 0),
-   SND_SOC_DAPM_SUPPLY("RST DAC", SUN8I_MOD_RST_CTL,
-   SUN8I_MOD_RST_CTL_DAC, 0, NULL, 0),
-   SND_SOC_DAPM_SUPPLY("RST ADC", SUN8I_MOD_RST_CTL,
-   SUN8I_MOD_RST_CTL_ADC, 0, NULL, 0),
 };
 
 static const struct snd_soc_dapm_route sun8i_codec_dapm_routes[] = {
/* Clock Routes */
{ "AIF1CLK", NULL, "mod" },
 
{ "SYSCLK", NULL, "AIF1CLK" },
 
-   { "RST AIF1", NULL, "AIF1CLK" },
-   { "RST AIF1", NULL, "SYSCLK" },
-   { "MODCLK AIF1", NULL, "RST AIF1" },
-   { "AIF1 AD0L", NULL, "MODCLK AIF1" },
-   { "AIF1 AD0R", NULL, "MODCLK AIF1" },
-   { "AIF1 DA0L", NULL, "MODCLK AIF1" },
-   { "AIF1 DA0R", NULL, "MODCLK AIF1" },
-
-   { "RST DAC", NULL, "SYSCLK" },
-   { "MODCLK DAC", NULL, "RST DAC" },
-   { "DAC", NULL, "MODCLK DAC" },
-   { "DACL", NULL, "DAC" },
-   { "DACR", NULL, "DAC" },
-
-   { "RST ADC", NULL, "SYSCLK" },
-   { "MODCLK ADC", NULL, "RST ADC" },
-   { "ADC", NULL, "MODCLK ADC" },
+   { "CLK AIF1", NULL, "AIF1CLK" },
+   { "CLK AIF1", NULL, "SYSCLK" },
+   { "RST AIF1", NULL, "CLK AIF1" },
+   { "AIF1 AD0L", NULL, "RST AIF1" },
+   { "AIF1 AD0R", NULL, "RST AIF1" },
+   { "AIF1 DA0L", NULL, "RST AIF1" },
+   { "AIF1 DA0R", NULL, "RST AIF1" },
+
+   { "CLK ADC", NULL, "SYSCLK" },
+   { "RST 

[PATCH 14/25] ASoC: sun8i-codec: Correct the BCLK divisor calculation

2020-09-30 Thread Samuel Holland
Previously, the BCLK divisor calculation assumed a power-of-two slot
width and exactly two slots. In order to support the TDM slot binding
and 20/24-bit word sizes, those assumptions must be removed.

Due to hardware limitations, the BCLK/LRCK ratio is not as simple as
"slot_width * slots". However, the correct value is already calculated
elsewhere in this function, since it must also be programmed into the
hardware. Reuse that value to calculate the correct SYSCLK/BCLK divisor.

Signed-off-by: Samuel Holland 
---
 sound/soc/sunxi/sun8i-codec.c | 17 +
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index 779853d023fe..78feed37aa42 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -279,21 +279,21 @@ static const struct sun8i_codec_clk_div 
sun8i_codec_bclk_div[] = {
{ .div = 48,.val = 9 },
{ .div = 64,.val = 10 },
{ .div = 96,.val = 11 },
{ .div = 128,   .val = 12 },
{ .div = 192,   .val = 13 },
 };
 
 static u8 sun8i_codec_get_bclk_div(struct sun8i_codec *scodec,
-  unsigned int rate,
-  unsigned int word_size)
+  unsigned int lrck_div_order,
+  unsigned int sample_rate)
 {
unsigned long clk_rate = clk_get_rate(scodec->clk_module);
-   unsigned int div = clk_rate / rate / word_size / 2;
+   unsigned int div = clk_rate / sample_rate >> lrck_div_order;
unsigned int best_val = 0, best_diff = ~0;
int i;
 
for (i = 0; i < ARRAY_SIZE(sun8i_codec_bclk_div); i++) {
const struct sun8i_codec_clk_div *bdiv = 
_codec_bclk_div[i];
unsigned int diff = abs(bdiv->div - div);
 
if (diff < best_diff) {
@@ -343,30 +343,31 @@ static int sun8i_codec_hw_params(struct snd_pcm_substream 
*substream,
default:
return -EINVAL;
}
 
regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
   SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK,
   word_size << SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ);
 
-   bclk_div = sun8i_codec_get_bclk_div(scodec, params_rate(params), 16);
-   regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
-  SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK,
-  bclk_div << SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV);
-
/* LRCK divider (BCLK/LRCK ratio) */
lrck_div_order = sun8i_codec_get_lrck_div_order(slots, slot_width);
if (lrck_div_order < 0)
return lrck_div_order;
 
regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
   SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK,
   (lrck_div_order - 4) << 
SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV);
 
+   /* BCLK divider (SYSCLK/BCLK ratio) */
+   bclk_div = sun8i_codec_get_bclk_div(scodec, lrck_div_order, 
params_rate(params));
+   regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
+  SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK,
+  bclk_div << SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV);
+
sample_rate = sun8i_codec_get_hw_rate(params);
if (sample_rate < 0)
return sample_rate;
 
regmap_update_bits(scodec->regmap, SUN8I_SYS_SR_CTRL,
   SUN8I_SYS_SR_CTRL_AIF1_FS_MASK,
   sample_rate << SUN8I_SYS_SR_CTRL_AIF1_FS);
 
-- 
2.26.2



[PATCH 11/25] ASoC: sun8i-codec: Enable all supported clock inversions

2020-09-30 Thread Samuel Holland
When using the I2S, LEFT_J, or RIGHT_J format, the hardware supports
independent BCLK and LRCK inversion control. When using DSP_A or DSP_B,
LRCK inversion is not supported. The register bit is repurposed to
select between DSP_A and DSP_B. Extend the driver to support this.

Signed-off-by: Samuel Holland 
---
 sound/soc/sunxi/sun8i-codec.c | 57 +++
 1 file changed, 37 insertions(+), 20 deletions(-)

diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index 0b713b2a2028..506420fb355c 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -39,18 +39,17 @@
 #define SUN8I_MOD_RST_CTL_AIF1 15
 #define SUN8I_MOD_RST_CTL_ADC  3
 #define SUN8I_MOD_RST_CTL_DAC  2
 #define SUN8I_SYS_SR_CTRL  0x018
 #define SUN8I_SYS_SR_CTRL_AIF1_FS  12
 #define SUN8I_SYS_SR_CTRL_AIF2_FS  8
 #define SUN8I_AIF1CLK_CTRL 0x040
 #define SUN8I_AIF1CLK_CTRL_AIF1_MSTR_MOD   15
-#define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_INV   14
-#define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_INV   13
+#define SUN8I_AIF1CLK_CTRL_AIF1_CLK_INV13
 #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV   9
 #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV   6
 #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ   4
 #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_16(1 << 4)
 #define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT   2
 #define SUN8I_AIF1_ADCDAT_CTRL 0x044
 #define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_ENA   15
 #define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_ENA   14
@@ -85,16 +84,17 @@
 #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA1R10
 #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF2DACR9
 #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_ADCR8
 
 #define SUN8I_SYSCLK_CTL_AIF1CLK_SRC_MASK  GENMASK(9, 8)
 #define SUN8I_SYSCLK_CTL_AIF2CLK_SRC_MASK  GENMASK(5, 4)
 #define SUN8I_SYS_SR_CTRL_AIF1_FS_MASK GENMASK(15, 12)
 #define SUN8I_SYS_SR_CTRL_AIF2_FS_MASK GENMASK(11, 8)
+#define SUN8I_AIF1CLK_CTRL_AIF1_CLK_INV_MASK   GENMASK(14, 13)
 #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK  GENMASK(12, 9)
 #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK  GENMASK(8, 6)
 #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK  GENMASK(5, 4)
 #define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK  GENMASK(3, 2)
 
 enum {
AIF1,
NAIFS
@@ -168,17 +168,17 @@ static int sun8i_codec_get_hw_rate(struct 
snd_pcm_hw_params *params)
default:
return -EINVAL;
}
 }
 
 static int sun8i_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);
-   u32 format, value;
+   u32 format, invert, value;
 
/* clock masters */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS: /* Codec slave, DAI master */
value = 0x1;
break;
case SND_SOC_DAIFMT_CBM_CFM: /* Codec Master, DAI slave */
value = 0x0;
@@ -197,55 +197,72 @@ static int sun8i_codec_set_fmt(struct snd_soc_dai *dai, 
unsigned int fmt)
break;
case SND_SOC_DAIFMT_LEFT_J:
format = 0x1;
break;
case SND_SOC_DAIFMT_RIGHT_J:
format = 0x2;
break;
case SND_SOC_DAIFMT_DSP_A:
+   format = 0x3;
+   invert = 0x0; /* Set LRCK_INV to 0 */
+   break;
case SND_SOC_DAIFMT_DSP_B:
format = 0x3;
+   invert = 0x1; /* Set LRCK_INV to 1 */
break;
default:
return -EINVAL;
}
regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
   SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK,
   format << SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT);
 
/* clock inversion */
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF: /* Normal */
value = 0x0;
break;
-   case SND_SOC_DAIFMT_IB_IF: /* Inversion */
+   case SND_SOC_DAIFMT_NB_IF: /* Inverted LRCK */
value = 0x1;
break;
+   case SND_SOC_DAIFMT_IB_NF: /* Inverted BCLK */
+   value = 0x2;
+   break;
+   case SND_SOC_DAIFMT_IB_IF: /* Both inverted */
+   value = 0x3;
+   break;
default:
return -EINVAL;
}
-   regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
-  BIT(SUN8I_AIF1CLK_CTRL_AIF1_BCLK_INV),
-  value << SUN8I_AIF1CLK_CTRL_AIF1_BCLK_INV);
 
-   /*
-* It appears that the DAI and the codec in the A33 SoC don't
-  

[PATCH 22/25] ASoC: sun8i-codec: Enable all supported PCM formats

2020-09-30 Thread Samuel Holland
Now that the DAI clock setup is correct for all hardware-supported PCM
formats, we can enable them in the driver. With the appropriate support
in the CPU DAI driver, this allows userspace to access the additional
formats.

Since this codec is connected to the CPU via a DAI, not directly, we do
not care if the CPU DAI is using 3-byte or 4-byte formats, so we can
support them both.

Signed-off-by: Samuel Holland 
---
 sound/soc/sunxi/sun8i-codec.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index d8ce84533ddb..032a3f714dbb 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -91,16 +91,23 @@
 #define SUN8I_AIF1CLK_CTRL_AIF1_CLK_INV_MASK   GENMASK(14, 13)
 #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK  GENMASK(12, 9)
 #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK  GENMASK(8, 6)
 #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK  GENMASK(5, 4)
 #define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK  GENMASK(3, 2)
 
 #define SUN8I_CODEC_PASSTHROUGH_SAMPLE_RATE 48000
 
+#define SUN8I_CODEC_PCM_FORMATS(SNDRV_PCM_FMTBIT_S8 |\
+SNDRV_PCM_FMTBIT_S16_LE |\
+SNDRV_PCM_FMTBIT_S20_LE |\
+SNDRV_PCM_FMTBIT_S24_LE |\
+SNDRV_PCM_FMTBIT_S20_3LE|\
+SNDRV_PCM_FMTBIT_S24_3LE)
+
 #define SUN8I_CODEC_PCM_RATES  (SNDRV_PCM_RATE_8000_48000|\
 SNDRV_PCM_RATE_88200 |\
 SNDRV_PCM_RATE_96000 |\
 SNDRV_PCM_RATE_176400|\
 SNDRV_PCM_RATE_192000|\
 SNDRV_PCM_RATE_KNOT)
 
 enum {
@@ -531,26 +538,26 @@ static struct snd_soc_dai_driver sun8i_codec_dais[] = {
.id = AIF1,
.ops= _codec_dai_ops,
/* capture capabilities */
.capture = {
.stream_name= "AIF1 Capture",
.channels_min   = 1,
.channels_max   = 2,
.rates  = SUN8I_CODEC_PCM_RATES,
-   .formats= SNDRV_PCM_FMTBIT_S16_LE,
+   .formats= SUN8I_CODEC_PCM_FORMATS,
.sig_bits   = 24,
},
/* playback capabilities */
.playback = {
.stream_name= "AIF1 Playback",
.channels_min   = 1,
.channels_max   = 2,
.rates  = SUN8I_CODEC_PCM_RATES,
-   .formats= SNDRV_PCM_FMTBIT_S16_LE,
+   .formats= SUN8I_CODEC_PCM_FORMATS,
},
.symmetric_rates= true,
.symmetric_channels = true,
.symmetric_samplebits   = true,
},
 };
 
 static int sun8i_codec_aif_event(struct snd_soc_dapm_widget *w,
-- 
2.26.2



[PATCH 21/25] ASoC: sun8i-codec: Require an exact BCLK divisor match

2020-09-30 Thread Samuel Holland
Now that we guarantee that SYSCLK is running at the optimal rate when
hw_params succeeds, and that it will continue running at that rate,
SYSCLK will always be an integer multiple of BCLK. So we can always
pick the exact divider, not just the closest divider.

Signed-off-by: Samuel Holland 
---
 sound/soc/sunxi/sun8i-codec.c | 22 ++
 1 file changed, 10 insertions(+), 12 deletions(-)

diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index 86065bee7cd3..d8ce84533ddb 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -384,35 +384,31 @@ static const struct sun8i_codec_clk_div 
sun8i_codec_bclk_div[] = {
{ .div = 32,.val = 8 },
{ .div = 48,.val = 9 },
{ .div = 64,.val = 10 },
{ .div = 96,.val = 11 },
{ .div = 128,   .val = 12 },
{ .div = 192,   .val = 13 },
 };
 
-static u8 sun8i_codec_get_bclk_div(unsigned int sysclk_rate,
-  unsigned int lrck_div_order,
-  unsigned int sample_rate)
+static int sun8i_codec_get_bclk_div(unsigned int sysclk_rate,
+   unsigned int lrck_div_order,
+   unsigned int sample_rate)
 {
unsigned int div = sysclk_rate / sample_rate >> lrck_div_order;
-   unsigned int best_val = 0, best_diff = ~0;
int i;
 
for (i = 0; i < ARRAY_SIZE(sun8i_codec_bclk_div); i++) {
const struct sun8i_codec_clk_div *bdiv = 
_codec_bclk_div[i];
-   unsigned int diff = abs(bdiv->div - div);
 
-   if (diff < best_diff) {
-   best_diff = diff;
-   best_val = bdiv->val;
-   }
+   if (bdiv->div == div)
+   return bdiv->val;
}
 
-   return best_val;
+   return -EINVAL;
 }
 
 static int sun8i_codec_get_lrck_div_order(unsigned int slots,
  unsigned int slot_width)
 {
unsigned int div = slots * slot_width;
 
if (div < 16 || div > 256)
@@ -431,18 +427,17 @@ static int sun8i_codec_hw_params(struct snd_pcm_substream 
*substream,
 struct snd_soc_dai *dai)
 {
struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);
struct sun8i_codec_aif *aif = >aifs[dai->id];
unsigned int sample_rate = params_rate(params);
unsigned int slots = aif->slots ?: params_channels(params);
unsigned int slot_width = aif->slot_width ?: params_width(params);
unsigned int sysclk_rate = sun8i_codec_get_sysclk_rate(sample_rate);
-   int lrck_div_order, ret, word_size;
-   u8 bclk_div;
+   int bclk_div, lrck_div_order, ret, word_size;
 
/* word size */
switch (params_width(params)) {
case 8:
word_size = 0x0;
break;
case 16:
word_size = 0x1;
@@ -467,16 +462,19 @@ static int sun8i_codec_hw_params(struct snd_pcm_substream 
*substream,
return lrck_div_order;
 
regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
   SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK,
   (lrck_div_order - 4) << 
SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV);
 
/* BCLK divider (SYSCLK/BCLK ratio) */
bclk_div = sun8i_codec_get_bclk_div(sysclk_rate, lrck_div_order, 
sample_rate);
+   if (bclk_div < 0)
+   return bclk_div;
+
regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
   SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK,
   bclk_div << SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV);
 
/* SYSCLK rate */
if (aif->open_streams) {
ret = clk_set_rate(scodec->clk_module, sysclk_rate);
if (ret < 0)
-- 
2.26.2



[PATCH 10/25] ASoC: sun8i-codec: Program format before clock inversion

2020-09-30 Thread Samuel Holland
The LRCK inversion bit has a different meaning in DSP mode: it selects
between DSP A and DSP B formats. To support this, we need to know if
the selected format is a DSP format. One easy way to do this is to set
the format field before the inversion fields.

Signed-off-by: Samuel Holland 
---
 sound/soc/sunxi/sun8i-codec.c | 46 +--
 1 file changed, 23 insertions(+), 23 deletions(-)

diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index 346f699c2e86..0b713b2a2028 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -168,33 +168,55 @@ static int sun8i_codec_get_hw_rate(struct 
snd_pcm_hw_params *params)
default:
return -EINVAL;
}
 }
 
 static int sun8i_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);
-   u32 value;
+   u32 format, value;
 
/* clock masters */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS: /* Codec slave, DAI master */
value = 0x1;
break;
case SND_SOC_DAIFMT_CBM_CFM: /* Codec Master, DAI slave */
value = 0x0;
break;
default:
return -EINVAL;
}
regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
   BIT(SUN8I_AIF1CLK_CTRL_AIF1_MSTR_MOD),
   value << SUN8I_AIF1CLK_CTRL_AIF1_MSTR_MOD);
 
+   /* DAI format */
+   switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+   case SND_SOC_DAIFMT_I2S:
+   format = 0x0;
+   break;
+   case SND_SOC_DAIFMT_LEFT_J:
+   format = 0x1;
+   break;
+   case SND_SOC_DAIFMT_RIGHT_J:
+   format = 0x2;
+   break;
+   case SND_SOC_DAIFMT_DSP_A:
+   case SND_SOC_DAIFMT_DSP_B:
+   format = 0x3;
+   break;
+   default:
+   return -EINVAL;
+   }
+   regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
+  SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK,
+  format << SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT);
+
/* clock inversion */
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF: /* Normal */
value = 0x0;
break;
case SND_SOC_DAIFMT_IB_IF: /* Inversion */
value = 0x1;
break;
@@ -215,38 +237,16 @@ static int sun8i_codec_set_fmt(struct snd_soc_dai *dai, 
unsigned int fmt)
 * that the codec probably gets it backward, and we have to
 * invert the value here.
 */
value ^= scodec->quirks->lrck_inversion;
regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
   BIT(SUN8I_AIF1CLK_CTRL_AIF1_LRCK_INV),
   value << SUN8I_AIF1CLK_CTRL_AIF1_LRCK_INV);
 
-   /* DAI format */
-   switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
-   case SND_SOC_DAIFMT_I2S:
-   value = 0x0;
-   break;
-   case SND_SOC_DAIFMT_LEFT_J:
-   value = 0x1;
-   break;
-   case SND_SOC_DAIFMT_RIGHT_J:
-   value = 0x2;
-   break;
-   case SND_SOC_DAIFMT_DSP_A:
-   case SND_SOC_DAIFMT_DSP_B:
-   value = 0x3;
-   break;
-   default:
-   return -EINVAL;
-   }
-   regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
-  SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK,
-  value << SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT);
-
return 0;
 }
 
 struct sun8i_codec_clk_div {
u8  div;
u8  val;
 };
 
-- 
2.26.2



[PATCH 04/25] ASoC: sun8i-codec: Consistently name DAPM widgets and routes

2020-09-30 Thread Samuel Holland
This cleans up the mixer widget names. The AIF1 AD0 Mixer names were
previously wrong -- they do not control the digital side of the ADC. The
DAC mixer widgets were not wrong, but they were verbose and did not
match the naming scheme of the other widgets.

The mixer controls are not renamed because they are exposed to
userspace.

Signed-off-by: Samuel Holland 
---
 sound/soc/sunxi/sun8i-codec.c | 32 
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index d14243c434f9..30fe27648254 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -413,19 +413,19 @@ static const struct snd_soc_dapm_widget 
sun8i_codec_dapm_widgets[] = {
SND_SOC_DAPM_AIF_IN("AIF1 AD0L", "Capture", 0,
SUN8I_AIF1_ADCDAT_CTRL,
SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_ENA, 0),
SND_SOC_DAPM_AIF_IN("AIF1 AD0R", "Capture", 0,
SUN8I_AIF1_ADCDAT_CTRL,
SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_ENA, 0),
 
/* AIF "ADC" Mixers */
-   SOC_MIXER_ARRAY("Left Digital ADC Mixer", SND_SOC_NOPM, 0, 0,
+   SOC_MIXER_ARRAY("AIF1 AD0L Mixer", SND_SOC_NOPM, 0, 0,
sun8i_aif1_ad0_mixer_controls),
-   SOC_MIXER_ARRAY("Right Digital ADC Mixer", SND_SOC_NOPM, 0, 0,
+   SOC_MIXER_ARRAY("AIF1 AD0R Mixer", SND_SOC_NOPM, 0, 0,
sun8i_aif1_ad0_mixer_controls),
 
/* AIF "DAC" Inputs */
SND_SOC_DAPM_AIF_IN("AIF1 DA0L", "Playback", 0,
SUN8I_AIF1_DACDAT_CTRL,
SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_ENA, 0),
SND_SOC_DAPM_AIF_IN("AIF1 DA0R", "Playback", 0,
SUN8I_AIF1_DACDAT_CTRL,
@@ -435,19 +435,19 @@ static const struct snd_soc_dapm_widget 
sun8i_codec_dapm_widgets[] = {
SND_SOC_DAPM_ADC("ADCL", NULL, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0),
 
/* DAC Outputs (connected to analog codec DAPM context) */
SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0),
 
/* DAC Mixers */
-   SOC_MIXER_ARRAY("Left Digital DAC Mixer", SND_SOC_NOPM, 0, 0,
+   SOC_MIXER_ARRAY("DACL Mixer", SND_SOC_NOPM, 0, 0,
sun8i_dac_mixer_controls),
-   SOC_MIXER_ARRAY("Right Digital DAC Mixer", SND_SOC_NOPM, 0, 0,
+   SOC_MIXER_ARRAY("DACR Mixer", SND_SOC_NOPM, 0, 0,
sun8i_dac_mixer_controls),
 };
 
 static const struct snd_soc_dapm_route sun8i_codec_dapm_routes[] = {
/* Clock Routes */
{ "AIF1CLK", NULL, "mod" },
 
{ "SYSCLK", NULL, "AIF1CLK" },
@@ -468,36 +468,36 @@ static const struct snd_soc_dapm_route 
sun8i_codec_dapm_routes[] = {
 
{ "CLK DAC", NULL, "SYSCLK" },
{ "RST DAC", NULL, "CLK DAC" },
{ "DAC", NULL, "RST DAC" },
{ "DACL", NULL, "DAC" },
{ "DACR", NULL, "DAC" },
 
/* AIF "ADC" Output Routes */
-   { "AIF1 AD0L", NULL, "Left Digital ADC Mixer" },
-   { "AIF1 AD0R", NULL, "Right Digital ADC Mixer" },
+   { "AIF1 AD0L", NULL, "AIF1 AD0L Mixer" },
+   { "AIF1 AD0R", NULL, "AIF1 AD0R Mixer" },
 
/* AIF "ADC" Mixer Routes */
-   { "Left Digital ADC Mixer", "AIF1 Slot 0 Digital ADC Capture Switch", 
"AIF1 DA0L" },
-   { "Left Digital ADC Mixer", "AIF1 Data Digital ADC Capture Switch", 
"ADCL" },
+   { "AIF1 AD0L Mixer", "AIF1 Slot 0 Digital ADC Capture Switch", "AIF1 
DA0L" },
+   { "AIF1 AD0L Mixer", "AIF1 Data Digital ADC Capture Switch", "ADCL" },
 
-   { "Right Digital ADC Mixer", "AIF1 Slot 0 Digital ADC Capture Switch", 
"AIF1 DA0R" },
-   { "Right Digital ADC Mixer", "AIF1 Data Digital ADC Capture Switch", 
"ADCR" },
+   { "AIF1 AD0R Mixer", "AIF1 Slot 0 Digital ADC Capture Switch", "AIF1 
DA0R" },
+   { "AIF1 AD0R Mixer", "AIF1 Data Digital ADC Capture Switch", "ADCR" },
 
/* DAC Output Routes */
-   { "DACL", NULL, "Left Digital DAC Mixer" },
-   { "DACR", NULL, "Right Digital DAC Mixer" },
+   { "DACL", NULL, "DACL Mixer" },
+   { "DACR", NULL, "DACR Mixer" },
 
/* DAC Mixer Routes */
-   { "Left Digital DAC Mixer", "AIF1 Slot 0 Digital DAC Playback Switch", 
"AIF1 DA0L" },
-   { "Left Digital DAC Mixer", "ADC Digital DAC Playback Switch", "ADCL" },
+   { "DACL Mixer", "AIF1 Slot 0 Digital DAC Playback Switch", "AIF1 DA0L" 
},
+   { "DACL Mixer", "ADC Digital DAC Playback Switch", "ADCL" },
 
-   { "Right Digital DAC Mixer", "AIF1 Slot 0 Digital DAC Playback Switch", 
"AIF1 DA0R" },
-   { "Right Digital DAC Mixer", "ADC Digital DAC Playback Switch", "ADCR" 
},
+   { "DACR Mixer", "AIF1 Slot 0 Digital DAC Playback Switch", "AIF1 DA0R" 
},
+   { "DACR Mixer", "ADC Digital DAC Playback Switch", 

[PATCH 12/25] ASoC: sun8i-codec: Program the correct word size

2020-09-30 Thread Samuel Holland
The hardware supports 8 to 24-bit word sizes on all three of its DAIs,
only one of which is connected to the CPU DAI. Program the word size
based on the actual selected format, instead of relying on limitations
in another driver (which, incedentally, has patches pending to remove
that limitation).

Signed-off-by: Samuel Holland 
---
 sound/soc/sunxi/sun8i-codec.c | 27 ---
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index 506420fb355c..e7f01a4b4001 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -43,17 +43,16 @@
 #define SUN8I_SYS_SR_CTRL_AIF1_FS  12
 #define SUN8I_SYS_SR_CTRL_AIF2_FS  8
 #define SUN8I_AIF1CLK_CTRL 0x040
 #define SUN8I_AIF1CLK_CTRL_AIF1_MSTR_MOD   15
 #define SUN8I_AIF1CLK_CTRL_AIF1_CLK_INV13
 #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV   9
 #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV   6
 #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ   4
-#define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_16(1 << 4)
 #define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT   2
 #define SUN8I_AIF1_ADCDAT_CTRL 0x044
 #define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_ENA   15
 #define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_ENA   14
 #define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_SRC   10
 #define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_SRC   8
 #define SUN8I_AIF1_DACDAT_CTRL 0x048
 #define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_ENA   15
@@ -317,26 +316,40 @@ static int sun8i_codec_get_lrck_div(unsigned int channels,
return ilog2(div) - 4;
 }
 
 static int sun8i_codec_hw_params(struct snd_pcm_substream *substream,
 struct snd_pcm_hw_params *params,
 struct snd_soc_dai *dai)
 {
struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);
-   int sample_rate, lrck_div;
+   int lrck_div, sample_rate, word_size;
u8 bclk_div;
 
-   /*
-* The CPU DAI handles only a sample of 16 bits. Configure the
-* codec to handle this type of sample resolution.
-*/
+   /* word size */
+   switch (params_width(params)) {
+   case 8:
+   word_size = 0x0;
+   break;
+   case 16:
+   word_size = 0x1;
+   break;
+   case 20:
+   word_size = 0x2;
+   break;
+   case 24:
+   word_size = 0x3;
+   break;
+   default:
+   return -EINVAL;
+   }
+
regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
   SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK,
-  SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_16);
+  word_size << SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ);
 
bclk_div = sun8i_codec_get_bclk_div(scodec, params_rate(params), 16);
regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
   SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK,
   bclk_div << SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV);
 
lrck_div = sun8i_codec_get_lrck_div(params_channels(params),
params_physical_width(params));
-- 
2.26.2



[PATCH 18/25] ASoC: sun8i-codec: Automatically set the system sample rate

2020-09-30 Thread Samuel Holland
The sun8i codec has three clock/sample rate domains:
 - The AIF1 domain, with a sample rate equal to AIF1 LRCK
 - The AIF2 domain, with a sample rate equal to AIF2 LRCK
 - The SYSCLK domain, containing the ADC, DAC, and effects (AGC/DRC),
   with a sample rate given by a divisor from SYSCLK. The divisor is
   controlled by the AIF1_FS or AIF2_FS field in SYS_SR_CTRL, depending
   on if SYSCLK's source is AIF1CLK or AIF2CLK, respectively. The exact
   sample rate depends on if SYSCLK is running at 22.6 MHz or 24.6 MHz.

When an AIF (currently only AIF1) is active, the ADC and DAC should run
at that sample rate to avoid artifacting. Sample rate conversion is only
available when multiple AIFs are active and are routed to each other;
this means the sample rate conversion hardware usually cannot be used.

Only attach the event hook to the channel 0 AIF widgets, since we only
need one event when a DAI stream starts or stops. Channel 0 is always
brought up with a DAI stream, regardless of the number of channels in
the stream.

The ADC and DAC (along with their effects blocks) can be used even if
no AIFs are in use. In that case, we should select an appropriate sample
rate divisor, instead of keeping the last-used AIF sample rate.
44.1/48 kHz was chosen to balance audio quality and power consumption.

Since the sample rate is tied to active AIF paths, disabling pmdown_time
allows switching to the optimal sample rate immediately, instead of
after a 5 second delay.

Signed-off-by: Samuel Holland 
---
 sound/soc/sunxi/sun8i-codec.c | 103 +++---
 1 file changed, 84 insertions(+), 19 deletions(-)

diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index f4b2a7cc9810..43b4319e3d84 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -89,31 +89,36 @@
 #define SUN8I_SYS_SR_CTRL_AIF1_FS_MASK GENMASK(15, 12)
 #define SUN8I_SYS_SR_CTRL_AIF2_FS_MASK GENMASK(11, 8)
 #define SUN8I_AIF1CLK_CTRL_AIF1_CLK_INV_MASK   GENMASK(14, 13)
 #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK  GENMASK(12, 9)
 #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK  GENMASK(8, 6)
 #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK  GENMASK(5, 4)
 #define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK  GENMASK(3, 2)
 
+#define SUN8I_CODEC_PASSTHROUGH_SAMPLE_RATE 48000
+
 #define SUN8I_CODEC_PCM_RATES  (SNDRV_PCM_RATE_8000_48000|\
 SNDRV_PCM_RATE_88200 |\
 SNDRV_PCM_RATE_96000 |\
 SNDRV_PCM_RATE_176400|\
 SNDRV_PCM_RATE_192000|\
 SNDRV_PCM_RATE_KNOT)
 
 enum {
AIF1,
NAIFS
 };
 
 struct sun8i_codec_aif {
+   unsigned intsample_rate;
unsigned intslots;
unsigned intslot_width;
+   unsigned intactive_streams  : 2;
+   unsigned intopen_streams: 2;
 };
 
 struct sun8i_codec_quirks {
bool legacy_widgets : 1;
bool lrck_inversion : 1;
 };
 
 struct sun8i_codec {
@@ -144,21 +149,19 @@ static int sun8i_codec_runtime_suspend(struct device *dev)
struct sun8i_codec *scodec = dev_get_drvdata(dev);
 
regcache_cache_only(scodec->regmap, true);
regcache_mark_dirty(scodec->regmap);
 
return 0;
 }
 
-static int sun8i_codec_get_hw_rate(struct snd_pcm_hw_params *params)
+static int sun8i_codec_get_hw_rate(unsigned int sample_rate)
 {
-   unsigned int rate = params_rate(params);
-
-   switch (rate) {
+   switch (sample_rate) {
case 7350:
case 8000:
return 0x0;
case 11025:
return 0x1;
case 12000:
return 0x2;
case 14700:
@@ -181,16 +184,43 @@ static int sun8i_codec_get_hw_rate(struct 
snd_pcm_hw_params *params)
case 176400:
case 192000:
return 0xa;
default:
return -EINVAL;
}
 }
 
+static int sun8i_codec_update_sample_rate(struct sun8i_codec *scodec)
+{
+   unsigned int max_rate = 0;
+   int hw_rate, i;
+
+   for (i = AIF1; i < NAIFS; ++i) {
+   struct sun8i_codec_aif *aif = >aifs[i];
+
+   if (aif->active_streams)
+   max_rate = max(max_rate, aif->sample_rate);
+   }
+
+   /* Set the sample rate for ADC->DAC passthrough when no AIF is active. 
*/
+   if (!max_rate)
+   max_rate = SUN8I_CODEC_PASSTHROUGH_SAMPLE_RATE;
+
+   hw_rate = sun8i_codec_get_hw_rate(max_rate);
+   if (hw_rate < 0)
+   return hw_rate;
+
+   regmap_update_bits(scodec->regmap, SUN8I_SYS_SR_CTRL,
+  SUN8I_SYS_SR_CTRL_AIF1_FS_MASK,
+  hw_rate << SUN8I_SYS_SR_CTRL_AIF1_FS);
+
+   return 0;
+}
+
 static int sun8i_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
struct sun8i_codec *scodec = 

[PATCH 19/25] ASoC: sun8i-codec: Constrain to compatible sample rates

2020-09-30 Thread Samuel Holland
While another stream is active, only allow userspace to use sample rates
that are compatible with the current SYSCLK frequency. This ensures the
actual sample rate will always match what is given in hw_params.

Signed-off-by: Samuel Holland 
---
 sound/soc/sunxi/sun8i-codec.c | 59 ---
 1 file changed, 55 insertions(+), 4 deletions(-)

diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index 43b4319e3d84..501af64d43a0 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -121,16 +121,18 @@ struct sun8i_codec_quirks {
bool lrck_inversion : 1;
 };
 
 struct sun8i_codec {
struct regmap   *regmap;
struct clk  *clk_module;
const struct sun8i_codec_quirks *quirks;
struct sun8i_codec_aif  aifs[NAIFS];
+   unsigned intsysclk_rate;
+   int sysclk_refcnt;
 };
 
 static int sun8i_codec_runtime_resume(struct device *dev)
 {
struct sun8i_codec *scodec = dev_get_drvdata(dev);
int ret;
 
regcache_cache_only(scodec->regmap, false);
@@ -319,16 +321,57 @@ static int sun8i_codec_set_tdm_slot(struct snd_soc_dai 
*dai,
return -EINVAL;
 
aif->slots = slots;
aif->slot_width = slot_width;
 
return 0;
 }
 
+static const unsigned int sun8i_codec_rates[] = {
+ 7350,   8000,  11025,  12000,  14700,  16000,  22050,  24000,
+29400,  32000,  44100,  48000,  88200,  96000, 176400, 192000,
+};
+
+static const struct snd_pcm_hw_constraint_list sun8i_codec_all_rates = {
+   .list   = sun8i_codec_rates,
+   .count  = ARRAY_SIZE(sun8i_codec_rates),
+};
+
+static const struct snd_pcm_hw_constraint_list sun8i_codec_22M_rates = {
+   .list   = sun8i_codec_rates,
+   .count  = ARRAY_SIZE(sun8i_codec_rates),
+   .mask   = 0x,
+};
+
+static const struct snd_pcm_hw_constraint_list sun8i_codec_24M_rates = {
+   .list   = sun8i_codec_rates,
+   .count  = ARRAY_SIZE(sun8i_codec_rates),
+   .mask   = 0x,
+};
+
+static int sun8i_codec_startup(struct snd_pcm_substream *substream,
+  struct snd_soc_dai *dai)
+{
+   struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);
+   const struct snd_pcm_hw_constraint_list *list;
+
+   if (!scodec->sysclk_refcnt)
+   list = _codec_all_rates;
+   else if (scodec->sysclk_rate == 22579200)
+   list = _codec_22M_rates;
+   else if (scodec->sysclk_rate == 24576000)
+   list = _codec_24M_rates;
+   else
+   return -EINVAL;
+
+   return snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE, list);
+}
+
 struct sun8i_codec_clk_div {
u8  div;
u8  val;
 };
 
 static const struct sun8i_codec_clk_div sun8i_codec_bclk_div[] = {
{ .div = 1, .val = 0 },
{ .div = 2, .val = 1 },
@@ -341,22 +384,21 @@ static const struct sun8i_codec_clk_div 
sun8i_codec_bclk_div[] = {
{ .div = 32,.val = 8 },
{ .div = 48,.val = 9 },
{ .div = 64,.val = 10 },
{ .div = 96,.val = 11 },
{ .div = 128,   .val = 12 },
{ .div = 192,   .val = 13 },
 };
 
-static u8 sun8i_codec_get_bclk_div(struct sun8i_codec *scodec,
+static u8 sun8i_codec_get_bclk_div(unsigned int sysclk_rate,
   unsigned int lrck_div_order,
   unsigned int sample_rate)
 {
-   unsigned long clk_rate = clk_get_rate(scodec->clk_module);
-   unsigned int div = clk_rate / sample_rate >> lrck_div_order;
+   unsigned int div = sysclk_rate / sample_rate >> lrck_div_order;
unsigned int best_val = 0, best_diff = ~0;
int i;
 
for (i = 0; i < ARRAY_SIZE(sun8i_codec_bclk_div); i++) {
const struct sun8i_codec_clk_div *bdiv = 
_codec_bclk_div[i];
unsigned int diff = abs(bdiv->div - div);
 
if (diff < best_diff) {
@@ -383,16 +425,17 @@ static int sun8i_codec_hw_params(struct snd_pcm_substream 
*substream,
 struct snd_pcm_hw_params *params,
 struct snd_soc_dai *dai)
 {
struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);
struct sun8i_codec_aif *aif = >aifs[dai->id];
unsigned int sample_rate = params_rate(params);
unsigned int slots = aif->slots ?: params_channels(params);
unsigned int slot_width = aif->slot_width ?: params_width(params);
+   unsigned int sysclk_rate = clk_get_rate(scodec->clk_module);
int lrck_div_order, word_size;
u8 bclk_div;
 
/* word size */
switch (params_width(params)) {
case 8:
word_size = 0x0;
break;
@@ -418,46 +461,54 @@ static int 

[PATCH 20/25] ASoC: sun8i-codec: Protect the clock rate while streams are open

2020-09-30 Thread Samuel Holland
The codec's clock input is shared among all AIFs, and shared with other
audio-related hardware in the SoC, including I2S and SPDIF controllers.
To ensure sample rates selected by userspace or by codec2codec DAI links
are maintained, the clock rate must be protected while it is in use.

Signed-off-by: Samuel Holland 
---
 sound/soc/sunxi/sun8i-codec.c | 25 ++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index 501af64d43a0..86065bee7cd3 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -416,27 +416,32 @@ static int sun8i_codec_get_lrck_div_order(unsigned int 
slots,
unsigned int div = slots * slot_width;
 
if (div < 16 || div > 256)
return -EINVAL;
 
return order_base_2(div);
 }
 
+static unsigned int sun8i_codec_get_sysclk_rate(unsigned int sample_rate)
+{
+   return sample_rate % 4000 ? 22579200 : 24576000;
+}
+
 static int sun8i_codec_hw_params(struct snd_pcm_substream *substream,
 struct snd_pcm_hw_params *params,
 struct snd_soc_dai *dai)
 {
struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);
struct sun8i_codec_aif *aif = >aifs[dai->id];
unsigned int sample_rate = params_rate(params);
unsigned int slots = aif->slots ?: params_channels(params);
unsigned int slot_width = aif->slot_width ?: params_width(params);
-   unsigned int sysclk_rate = clk_get_rate(scodec->clk_module);
-   int lrck_div_order, word_size;
+   unsigned int sysclk_rate = sun8i_codec_get_sysclk_rate(sample_rate);
+   int lrck_div_order, ret, word_size;
u8 bclk_div;
 
/* word size */
switch (params_width(params)) {
case 8:
word_size = 0x0;
break;
case 16:
@@ -466,17 +471,30 @@ static int sun8i_codec_hw_params(struct snd_pcm_substream 
*substream,
   (lrck_div_order - 4) << 
SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV);
 
/* BCLK divider (SYSCLK/BCLK ratio) */
bclk_div = sun8i_codec_get_bclk_div(sysclk_rate, lrck_div_order, 
sample_rate);
regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
   SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK,
   bclk_div << SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV);
 
-   if (!aif->open_streams) {
+   /* SYSCLK rate */
+   if (aif->open_streams) {
+   ret = clk_set_rate(scodec->clk_module, sysclk_rate);
+   if (ret < 0)
+   return ret;
+   } else {
+   ret = clk_set_rate_exclusive(scodec->clk_module, sysclk_rate);
+   if (ret == -EBUSY)
+   dev_err(dai->dev, "%s: clock is busy! Sample rate %u Hz 
"
+   "conflicts with other audio streams.\n",
+   dai->name, sample_rate);
+   if (ret < 0)
+   return ret;
+
scodec->sysclk_rate = sysclk_rate;
scodec->sysclk_refcnt++;
}
 
aif->sample_rate = sample_rate;
aif->open_streams |= BIT(substream->stream);
 
return sun8i_codec_update_sample_rate(scodec);
@@ -487,16 +505,17 @@ static int sun8i_codec_hw_free(struct snd_pcm_substream 
*substream,
 {
struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);
struct sun8i_codec_aif *aif = >aifs[dai->id];
 
if (aif->open_streams != BIT(substream->stream))
goto done;
 
scodec->sysclk_refcnt--;
+   clk_rate_exclusive_put(scodec->clk_module);
 
aif->sample_rate = 0;
 
 done:
aif->open_streams &= ~BIT(substream->stream);
return 0;
 }
 
-- 
2.26.2



[PATCH 09/25] ASoC: sun8i-codec: Prepare to extend the DAI driver

2020-09-30 Thread Samuel Holland
In preparation for adding additional DAIs to this component, convert the
DAI driver definition to an array. Since this changes all of the lines
in the definition anyway, let's move it closer to the ops function
definitions, instead of on the far side of the DAPM arrays. And while
moving the DAI driver ops, rename the set_fmt hook to match the usual
naming scheme.

Give the existing DAI an explicit ID and more meaningful stream names,
so it will remain unique as more DAIs are added. The AIF widget streams
must be updated to match.

Signed-off-by: Samuel Holland 
---
 sound/soc/sunxi/sun8i-codec.c | 76 +++
 1 file changed, 42 insertions(+), 34 deletions(-)

diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index 7590c4b04d14..346f699c2e86 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -90,16 +90,21 @@
 #define SUN8I_SYSCLK_CTL_AIF2CLK_SRC_MASK  GENMASK(5, 4)
 #define SUN8I_SYS_SR_CTRL_AIF1_FS_MASK GENMASK(15, 12)
 #define SUN8I_SYS_SR_CTRL_AIF2_FS_MASK GENMASK(11, 8)
 #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK  GENMASK(12, 9)
 #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK  GENMASK(8, 6)
 #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK  GENMASK(5, 4)
 #define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK  GENMASK(3, 2)
 
+enum {
+   AIF1,
+   NAIFS
+};
+
 struct sun8i_codec_quirks {
bool legacy_widgets : 1;
bool lrck_inversion : 1;
 };
 
 struct sun8i_codec {
struct regmap   *regmap;
struct clk  *clk_module;
@@ -160,17 +165,17 @@ static int sun8i_codec_get_hw_rate(struct 
snd_pcm_hw_params *params)
return 0x9;
case 192000:
return 0xa;
default:
return -EINVAL;
}
 }
 
-static int sun8i_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+static int sun8i_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);
u32 value;
 
/* clock masters */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS: /* Codec slave, DAI master */
value = 0x1;
@@ -331,16 +336,46 @@ static int sun8i_codec_hw_params(struct snd_pcm_substream 
*substream,
 
regmap_update_bits(scodec->regmap, SUN8I_SYS_SR_CTRL,
   SUN8I_SYS_SR_CTRL_AIF1_FS_MASK,
   sample_rate << SUN8I_SYS_SR_CTRL_AIF1_FS);
 
return 0;
 }
 
+static const struct snd_soc_dai_ops sun8i_codec_dai_ops = {
+   .set_fmt= sun8i_codec_set_fmt,
+   .hw_params  = sun8i_codec_hw_params,
+};
+
+static struct snd_soc_dai_driver sun8i_codec_dais[] = {
+   {
+   .name   = "sun8i-codec-aif1",
+   .id = AIF1,
+   .ops= _codec_dai_ops,
+   /* capture capabilities */
+   .capture = {
+   .stream_name= "AIF1 Capture",
+   .channels_min   = 1,
+   .channels_max   = 2,
+   .rates  = SNDRV_PCM_RATE_8000_192000,
+   .formats= SNDRV_PCM_FMTBIT_S16_LE,
+   .sig_bits   = 24,
+   },
+   /* playback capabilities */
+   .playback = {
+   .stream_name= "AIF1 Playback",
+   .channels_min   = 1,
+   .channels_max   = 2,
+   .rates  = SNDRV_PCM_RATE_8000_192000,
+   .formats= SNDRV_PCM_FMTBIT_S16_LE,
+   },
+   },
+};
+
 static const char *const sun8i_aif_stereo_mux_enum_values[] = {
"Stereo", "Reverse Stereo", "Sum Mono", "Mix Mono"
 };
 
 static SOC_ENUM_DOUBLE_DECL(sun8i_aif1_ad0_stereo_mux_enum,
SUN8I_AIF1_ADCDAT_CTRL,
SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_SRC,
SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_SRC,
@@ -433,20 +468,20 @@ static const struct snd_soc_dapm_widget 
sun8i_codec_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("ADC",
SUN8I_ADC_DIG_CTRL,
SUN8I_ADC_DIG_CTRL_ENAD, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("DAC",
SUN8I_DAC_DIG_CTRL,
SUN8I_DAC_DIG_CTRL_ENDA, 0, NULL, 0),
 
/* AIF "ADC" Outputs */
-   SND_SOC_DAPM_AIF_OUT("AIF1 AD0L", "Capture", 0,
+   SND_SOC_DAPM_AIF_OUT("AIF1 AD0L", "AIF1 Capture", 0,
 SUN8I_AIF1_ADCDAT_CTRL,
 SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_ENA, 0),
-   SND_SOC_DAPM_AIF_OUT("AIF1 AD0R", "Capture", 1,
+   SND_SOC_DAPM_AIF_OUT("AIF1 AD0R", "AIF1 Capture", 1,
 SUN8I_AIF1_ADCDAT_CTRL,
 

[PATCH 25/25] ASoC: sun8i-codec: Add a DAI, widgets, and routes for AIF3

2020-09-30 Thread Samuel Holland
AIF3 has some differences from AIF1 and AIF2:
 - It supports mono only
 - It supports master mode only
 - It is not directly connected to any of the mixers; instead all audio
   goes through a mux with AIF2.
 - It does not have its own clock dividers; instead it reuses AIF2 BCLK.
   This means that when both AIF2 and AIF3 are active, they must run at
   the same sample rate and total frame width. Since AIF2 and AIF3 are
   only used for codec2codec DAI links, constraints are not applicable
   here; the only thing we can do when the rates don't match is report
   an error.

Make the necessary adjustments to support this AIF.

Signed-off-by: Samuel Holland 
---
 sound/soc/sunxi/sun8i-codec.c | 136 +++---
 1 file changed, 127 insertions(+), 9 deletions(-)

diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index 9fa4eca501df..344d9ad85fa6 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -29,21 +29,23 @@
 #define SUN8I_SYSCLK_CTL_AIF2CLK_SRC_PLL   (0x2 << 4)
 #define SUN8I_SYSCLK_CTL_SYSCLK_ENA3
 #define SUN8I_SYSCLK_CTL_SYSCLK_SRC0
 #define SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF1CLK(0x0 << 0)
 #define SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF2CLK(0x1 << 0)
 #define SUN8I_MOD_CLK_ENA  0x010
 #define SUN8I_MOD_CLK_ENA_AIF1 15
 #define SUN8I_MOD_CLK_ENA_AIF2 14
+#define SUN8I_MOD_CLK_ENA_AIF3 13
 #define SUN8I_MOD_CLK_ENA_ADC  3
 #define SUN8I_MOD_CLK_ENA_DAC  2
 #define SUN8I_MOD_RST_CTL  0x014
 #define SUN8I_MOD_RST_CTL_AIF1 15
 #define SUN8I_MOD_RST_CTL_AIF2 14
+#define SUN8I_MOD_RST_CTL_AIF3 13
 #define SUN8I_MOD_RST_CTL_ADC  3
 #define SUN8I_MOD_RST_CTL_DAC  2
 #define SUN8I_SYS_SR_CTRL  0x018
 #define SUN8I_SYS_SR_CTRL_AIF1_FS  12
 #define SUN8I_SYS_SR_CTRL_AIF2_FS  8
 #define SUN8I_AIF_CLK_CTRL(n)  (0x040 * (1 + (n)))
 #define SUN8I_AIF_CLK_CTRL_MSTR_MOD15
 #define SUN8I_AIF_CLK_CTRL_CLK_INV 13
@@ -84,16 +86,19 @@
 #define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF1DA0L   15
 #define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF1DA1L   14
 #define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF2DACR   13
 #define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_ADCL   12
 #define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA0R   11
 #define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA1R   10
 #define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF2DACL   9
 #define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_ADCR   8
+#define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF1  (0x0 << 0)
+#define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF2  (0x1 << 0)
+#define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF1CLK   (0x2 << 0)
 #define SUN8I_AIF3_PATH_CTRL   0x0cc
 #define SUN8I_AIF3_PATH_CTRL_AIF3_ADC_SRC  10
 #define SUN8I_AIF3_PATH_CTRL_AIF2_DAC_SRC  8
 #define SUN8I_AIF3_PATH_CTRL_AIF3_PINS_TRI 7
 #define SUN8I_ADC_DIG_CTRL 0x100
 #define SUN8I_ADC_DIG_CTRL_ENAD15
 #define SUN8I_ADC_DIG_CTRL_ADOUT_DTS   2
 #define SUN8I_ADC_DIG_CTRL_ADOUT_DLY   1
@@ -113,16 +118,17 @@
 #define SUN8I_SYSCLK_CTL_AIF2CLK_SRC_MASK  GENMASK(5, 4)
 #define SUN8I_SYS_SR_CTRL_AIF1_FS_MASK GENMASK(15, 12)
 #define SUN8I_SYS_SR_CTRL_AIF2_FS_MASK GENMASK(11, 8)
 #define SUN8I_AIF_CLK_CTRL_CLK_INV_MASKGENMASK(14, 13)
 #define SUN8I_AIF_CLK_CTRL_BCLK_DIV_MASK   GENMASK(12, 9)
 #define SUN8I_AIF_CLK_CTRL_LRCK_DIV_MASK   GENMASK(8, 6)
 #define SUN8I_AIF_CLK_CTRL_WORD_SIZ_MASK   GENMASK(5, 4)
 #define SUN8I_AIF_CLK_CTRL_DATA_FMT_MASK   GENMASK(3, 2)
+#define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_MASK  GENMASK(1, 0)
 
 #define SUN8I_CODEC_PASSTHROUGH_SAMPLE_RATE 48000
 
 #define SUN8I_CODEC_PCM_FORMATS(SNDRV_PCM_FMTBIT_S8 |\
 SNDRV_PCM_FMTBIT_S16_LE |\
 SNDRV_PCM_FMTBIT_S20_LE |\
 SNDRV_PCM_FMTBIT_S24_LE |\
 SNDRV_PCM_FMTBIT_S20_3LE|\
@@ -133,20 +139,22 @@
 SNDRV_PCM_RATE_96000 |\
 SNDRV_PCM_RATE_176400|\
 SNDRV_PCM_RATE_192000|\
 SNDRV_PCM_RATE_KNOT)
 
 enum {
AIF1,
AIF2,
+   AIF3,
NAIFS
 };
 
 struct sun8i_codec_aif {
+   unsigned intlrck_div_order;
unsigned intsample_rate;
unsigned intslots;
 

[PATCH 08/25] ASoC: sun8i-codec: Use snd_soc_dai_get_drvdata

2020-09-30 Thread Samuel Holland
Remove a level of indirection by getting the device directly from the
passed-in struct snd_soc_dai, instead of going through its component.

Signed-off-by: Samuel Holland 
---
 sound/soc/sunxi/sun8i-codec.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index 578c0c0e6330..7590c4b04d14 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -162,17 +162,17 @@ static int sun8i_codec_get_hw_rate(struct 
snd_pcm_hw_params *params)
return 0xa;
default:
return -EINVAL;
}
 }
 
 static int sun8i_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
-   struct sun8i_codec *scodec = 
snd_soc_component_get_drvdata(dai->component);
+   struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);
u32 value;
 
/* clock masters */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS: /* Codec slave, DAI master */
value = 0x1;
break;
case SND_SOC_DAIFMT_CBM_CFM: /* Codec Master, DAI slave */
@@ -294,17 +294,17 @@ static int sun8i_codec_get_lrck_div(unsigned int channels,
 
return ilog2(div) - 4;
 }
 
 static int sun8i_codec_hw_params(struct snd_pcm_substream *substream,
 struct snd_pcm_hw_params *params,
 struct snd_soc_dai *dai)
 {
-   struct sun8i_codec *scodec = 
snd_soc_component_get_drvdata(dai->component);
+   struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);
int sample_rate, lrck_div;
u8 bclk_div;
 
/*
 * The CPU DAI handles only a sample of 16 bits. Configure the
 * codec to handle this type of sample resolution.
 */
regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
-- 
2.26.2



[PATCH 07/25] ASoC: sun8i-codec: Enable AIF mono/stereo control

2020-09-30 Thread Samuel Holland
Each left/right pair of AIF input/output channels can be swapped or
combined. This is useful for sending a mono audio source to both sides
of a stereo sink, or for creating complex mixing scenarios.

Add the support to control this feature from userspace.

Signed-off-by: Samuel Holland 
---
 sound/soc/sunxi/sun8i-codec.c | 82 ---
 1 file changed, 76 insertions(+), 6 deletions(-)

diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index 2c89974243e1..578c0c0e6330 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -49,19 +49,23 @@
 #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV   9
 #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV   6
 #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ   4
 #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_16(1 << 4)
 #define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT   2
 #define SUN8I_AIF1_ADCDAT_CTRL 0x044
 #define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_ENA   15
 #define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_ENA   14
+#define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_SRC   10
+#define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_SRC   8
 #define SUN8I_AIF1_DACDAT_CTRL 0x048
 #define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_ENA   15
 #define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_ENA   14
+#define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_SRC   10
+#define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_SRC   8
 #define SUN8I_AIF1_MXR_SRC 0x04c
 #define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF1DA0L   15
 #define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACL   14
 #define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_ADCL   13
 #define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACR   12
 #define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF1DA0R   11
 #define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACR   10
 #define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_ADCR   9
@@ -327,16 +331,30 @@ static int sun8i_codec_hw_params(struct snd_pcm_substream 
*substream,
 
regmap_update_bits(scodec->regmap, SUN8I_SYS_SR_CTRL,
   SUN8I_SYS_SR_CTRL_AIF1_FS_MASK,
   sample_rate << SUN8I_SYS_SR_CTRL_AIF1_FS);
 
return 0;
 }
 
+static const char *const sun8i_aif_stereo_mux_enum_values[] = {
+   "Stereo", "Reverse Stereo", "Sum Mono", "Mix Mono"
+};
+
+static SOC_ENUM_DOUBLE_DECL(sun8i_aif1_ad0_stereo_mux_enum,
+   SUN8I_AIF1_ADCDAT_CTRL,
+   SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_SRC,
+   SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_SRC,
+   sun8i_aif_stereo_mux_enum_values);
+
+static const struct snd_kcontrol_new sun8i_aif1_ad0_stereo_mux_control =
+   SOC_DAPM_ENUM("AIF1 AD0 Stereo Capture Route",
+ sun8i_aif1_ad0_stereo_mux_enum);
+
 static const struct snd_kcontrol_new sun8i_aif1_ad0_mixer_controls[] = {
SOC_DAPM_DOUBLE("AIF1 Slot 0 Digital ADC Capture Switch",
SUN8I_AIF1_MXR_SRC,
SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF1DA0L,
SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF1DA0R, 1, 0),
SOC_DAPM_DOUBLE("AIF2 Digital ADC Capture Switch",
SUN8I_AIF1_MXR_SRC,
SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACL,
@@ -346,16 +364,26 @@ static const struct snd_kcontrol_new 
sun8i_aif1_ad0_mixer_controls[] = {
SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_ADCL,
SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_ADCR, 1, 0),
SOC_DAPM_DOUBLE("AIF2 Inv Digital ADC Capture Switch",
SUN8I_AIF1_MXR_SRC,
SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACR,
SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACL, 1, 0),
 };
 
+static SOC_ENUM_DOUBLE_DECL(sun8i_aif1_da0_stereo_mux_enum,
+   SUN8I_AIF1_DACDAT_CTRL,
+   SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_SRC,
+   SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_SRC,
+   sun8i_aif_stereo_mux_enum_values);
+
+static const struct snd_kcontrol_new sun8i_aif1_da0_stereo_mux_control =
+   SOC_DAPM_ENUM("AIF1 DA0 Stereo Playback Route",
+ sun8i_aif1_da0_stereo_mux_enum);
+
 static const struct snd_kcontrol_new sun8i_dac_mixer_controls[] = {
SOC_DAPM_DOUBLE("AIF1 Slot 0 Digital DAC Playback Switch",
SUN8I_DAC_MXR_SRC,
SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA0L,
SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA0R, 1, 0),
SOC_DAPM_DOUBLE("AIF1 Slot 1 Digital DAC Playback Switch",
SUN8I_DAC_MXR_SRC,
SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA1L,
@@ -412,22 +440,34 @@ static const struct snd_soc_dapm_widget 
sun8i_codec_dapm_widgets[] = {
/* AIF "ADC" 

[PATCH 24/25] ASoC: sun8i-codec: Add a DAI, widgets, and routes for AIF2

2020-09-30 Thread Samuel Holland
This adds support for AIF2, which is stereo and has full clocking
capability, making it very similar to AIF1.

Signed-off-by: Samuel Holland 
---
 sound/soc/sunxi/sun8i-codec.c | 215 ++
 1 file changed, 215 insertions(+)

diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index 1c34502ac47a..9fa4eca501df 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -28,20 +28,22 @@
 #define SUN8I_SYSCLK_CTL_AIF2CLK_ENA   7
 #define SUN8I_SYSCLK_CTL_AIF2CLK_SRC_PLL   (0x2 << 4)
 #define SUN8I_SYSCLK_CTL_SYSCLK_ENA3
 #define SUN8I_SYSCLK_CTL_SYSCLK_SRC0
 #define SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF1CLK(0x0 << 0)
 #define SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF2CLK(0x1 << 0)
 #define SUN8I_MOD_CLK_ENA  0x010
 #define SUN8I_MOD_CLK_ENA_AIF1 15
+#define SUN8I_MOD_CLK_ENA_AIF2 14
 #define SUN8I_MOD_CLK_ENA_ADC  3
 #define SUN8I_MOD_CLK_ENA_DAC  2
 #define SUN8I_MOD_RST_CTL  0x014
 #define SUN8I_MOD_RST_CTL_AIF1 15
+#define SUN8I_MOD_RST_CTL_AIF2 14
 #define SUN8I_MOD_RST_CTL_ADC  3
 #define SUN8I_MOD_RST_CTL_DAC  2
 #define SUN8I_SYS_SR_CTRL  0x018
 #define SUN8I_SYS_SR_CTRL_AIF1_FS  12
 #define SUN8I_SYS_SR_CTRL_AIF2_FS  8
 #define SUN8I_AIF_CLK_CTRL(n)  (0x040 * (1 + (n)))
 #define SUN8I_AIF_CLK_CTRL_MSTR_MOD15
 #define SUN8I_AIF_CLK_CTRL_CLK_INV 13
@@ -63,16 +65,39 @@
 #define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF1DA0L   15
 #define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACL   14
 #define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_ADCL   13
 #define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACR   12
 #define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF1DA0R   11
 #define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACR   10
 #define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_ADCR   9
 #define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACL   8
+#define SUN8I_AIF2_ADCDAT_CTRL 0x084
+#define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCL_ENA   15
+#define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCR_ENA   14
+#define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCL_SRC   10
+#define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCR_SRC   8
+#define SUN8I_AIF2_DACDAT_CTRL 0x088
+#define SUN8I_AIF2_DACDAT_CTRL_AIF2_DACL_ENA   15
+#define SUN8I_AIF2_DACDAT_CTRL_AIF2_DACR_ENA   14
+#define SUN8I_AIF2_DACDAT_CTRL_AIF2_DACL_SRC   10
+#define SUN8I_AIF2_DACDAT_CTRL_AIF2_DACR_SRC   8
+#define SUN8I_AIF2_MXR_SRC 0x08c
+#define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF1DA0L   15
+#define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF1DA1L   14
+#define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF2DACR   13
+#define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_ADCL   12
+#define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA0R   11
+#define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA1R   10
+#define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF2DACL   9
+#define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_ADCR   8
+#define SUN8I_AIF3_PATH_CTRL   0x0cc
+#define SUN8I_AIF3_PATH_CTRL_AIF3_ADC_SRC  10
+#define SUN8I_AIF3_PATH_CTRL_AIF2_DAC_SRC  8
+#define SUN8I_AIF3_PATH_CTRL_AIF3_PINS_TRI 7
 #define SUN8I_ADC_DIG_CTRL 0x100
 #define SUN8I_ADC_DIG_CTRL_ENAD15
 #define SUN8I_ADC_DIG_CTRL_ADOUT_DTS   2
 #define SUN8I_ADC_DIG_CTRL_ADOUT_DLY   1
 #define SUN8I_DAC_DIG_CTRL 0x120
 #define SUN8I_DAC_DIG_CTRL_ENDA15
 #define SUN8I_DAC_MXR_SRC  0x130
 #define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA0L15
@@ -107,16 +132,17 @@
 SNDRV_PCM_RATE_88200 |\
 SNDRV_PCM_RATE_96000 |\
 SNDRV_PCM_RATE_176400|\
 SNDRV_PCM_RATE_192000|\
 SNDRV_PCM_RATE_KNOT)
 
 enum {
AIF1,
+   AIF2,
NAIFS
 };
 
 struct sun8i_codec_aif {
unsigned intsample_rate;
unsigned intslots;
unsigned intslot_width;
unsigned intactive_streams  : 2;
@@ -359,16 +385,20 @@ static const struct snd_pcm_hw_constraint_list 
sun8i_codec_24M_rates = {
 };
 
 static int sun8i_codec_startup(struct snd_pcm_substream *substream,
   struct snd_soc_dai *dai)
 {
struct sun8i_codec *scodec = 

[PATCH 16/25] ASoC: sun8i-codec: Enforce symmetric DAI parameters

2020-09-30 Thread Samuel Holland
The AIFs have a single register controlling DAI parameters in both
directions, including BCLK/LRCK divisor word size. The DAIs produce only
noise or silence if any of these parameters is wrong. Therefore, we need
to enforce symmetry for these parameters, so starting a new substream
will not break an existing substream.

Signed-off-by: Samuel Holland 
---
 sound/soc/sunxi/sun8i-codec.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index 0a53dc0c34d0..f21274530a0e 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -420,16 +420,19 @@ static struct snd_soc_dai_driver sun8i_codec_dais[] = {
/* playback capabilities */
.playback = {
.stream_name= "AIF1 Playback",
.channels_min   = 1,
.channels_max   = 2,
.rates  = SNDRV_PCM_RATE_8000_192000,
.formats= SNDRV_PCM_FMTBIT_S16_LE,
},
+   .symmetric_rates= true,
+   .symmetric_channels = true,
+   .symmetric_samplebits   = true,
},
 };
 
 static const char *const sun8i_aif_stereo_mux_enum_values[] = {
"Stereo", "Reverse Stereo", "Sum Mono", "Mix Mono"
 };
 
 static SOC_ENUM_DOUBLE_DECL(sun8i_aif1_ad0_stereo_mux_enum,
-- 
2.26.2



[PATCH 23/25] ASoC: sun8i-codec: Generalize AIF clock control

2020-09-30 Thread Samuel Holland
The AIF clock control register has the same layout for all three AIFs.
The only difference between them is that AIF3 is missing some fields. We
can reuse the same register field definitions for all three registers,
and use the DAI ID to select the correct register address.

Signed-off-by: Samuel Holland 
---
 sound/soc/sunxi/sun8i-codec.c | 64 +++
 1 file changed, 34 insertions(+), 30 deletions(-)

diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index 032a3f714dbb..1c34502ac47a 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -37,23 +37,23 @@
 #define SUN8I_MOD_CLK_ENA_DAC  2
 #define SUN8I_MOD_RST_CTL  0x014
 #define SUN8I_MOD_RST_CTL_AIF1 15
 #define SUN8I_MOD_RST_CTL_ADC  3
 #define SUN8I_MOD_RST_CTL_DAC  2
 #define SUN8I_SYS_SR_CTRL  0x018
 #define SUN8I_SYS_SR_CTRL_AIF1_FS  12
 #define SUN8I_SYS_SR_CTRL_AIF2_FS  8
-#define SUN8I_AIF1CLK_CTRL 0x040
-#define SUN8I_AIF1CLK_CTRL_AIF1_MSTR_MOD   15
-#define SUN8I_AIF1CLK_CTRL_AIF1_CLK_INV13
-#define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV   9
-#define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV   6
-#define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ   4
-#define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT   2
+#define SUN8I_AIF_CLK_CTRL(n)  (0x040 * (1 + (n)))
+#define SUN8I_AIF_CLK_CTRL_MSTR_MOD15
+#define SUN8I_AIF_CLK_CTRL_CLK_INV 13
+#define SUN8I_AIF_CLK_CTRL_BCLK_DIV9
+#define SUN8I_AIF_CLK_CTRL_LRCK_DIV6
+#define SUN8I_AIF_CLK_CTRL_WORD_SIZ4
+#define SUN8I_AIF_CLK_CTRL_DATA_FMT2
 #define SUN8I_AIF1_ADCDAT_CTRL 0x044
 #define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_ENA   15
 #define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_ENA   14
 #define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_SRC   10
 #define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_SRC   8
 #define SUN8I_AIF1_DACDAT_CTRL 0x048
 #define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_ENA   15
 #define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_ENA   14
@@ -83,21 +83,21 @@
 #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA1R10
 #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF2DACR9
 #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_ADCR8
 
 #define SUN8I_SYSCLK_CTL_AIF1CLK_SRC_MASK  GENMASK(9, 8)
 #define SUN8I_SYSCLK_CTL_AIF2CLK_SRC_MASK  GENMASK(5, 4)
 #define SUN8I_SYS_SR_CTRL_AIF1_FS_MASK GENMASK(15, 12)
 #define SUN8I_SYS_SR_CTRL_AIF2_FS_MASK GENMASK(11, 8)
-#define SUN8I_AIF1CLK_CTRL_AIF1_CLK_INV_MASK   GENMASK(14, 13)
-#define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK  GENMASK(12, 9)
-#define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK  GENMASK(8, 6)
-#define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK  GENMASK(5, 4)
-#define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK  GENMASK(3, 2)
+#define SUN8I_AIF_CLK_CTRL_CLK_INV_MASKGENMASK(14, 13)
+#define SUN8I_AIF_CLK_CTRL_BCLK_DIV_MASK   GENMASK(12, 9)
+#define SUN8I_AIF_CLK_CTRL_LRCK_DIV_MASK   GENMASK(8, 6)
+#define SUN8I_AIF_CLK_CTRL_WORD_SIZ_MASK   GENMASK(5, 4)
+#define SUN8I_AIF_CLK_CTRL_DATA_FMT_MASK   GENMASK(3, 2)
 
 #define SUN8I_CODEC_PASSTHROUGH_SAMPLE_RATE 48000
 
 #define SUN8I_CODEC_PCM_FORMATS(SNDRV_PCM_FMTBIT_S8 |\
 SNDRV_PCM_FMTBIT_S16_LE |\
 SNDRV_PCM_FMTBIT_S20_LE |\
 SNDRV_PCM_FMTBIT_S24_LE |\
 SNDRV_PCM_FMTBIT_S20_3LE|\
@@ -223,32 +223,34 @@ static int sun8i_codec_update_sample_rate(struct 
sun8i_codec *scodec)
   hw_rate << SUN8I_SYS_SR_CTRL_AIF1_FS);
 
return 0;
 }
 
 static int sun8i_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);
+   u32 reg = SUN8I_AIF_CLK_CTRL(dai->id);
u32 format, invert, value;
 
/* clock masters */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS: /* Codec slave, DAI master */
value = 0x1;
break;
case SND_SOC_DAIFMT_CBM_CFM: /* Codec Master, DAI slave */
value = 0x0;
break;
default:
return -EINVAL;
}
-   regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
-  BIT(SUN8I_AIF1CLK_CTRL_AIF1_MSTR_MOD),
-  value << SUN8I_AIF1CLK_CTRL_AIF1_MSTR_MOD);
+
+   regmap_update_bits(scodec->regmap, reg,
+  

[PATCH 03/25] ASoC: sun8i-codec: Sort DAPM controls, widgets, and routes

2020-09-30 Thread Samuel Holland
Sort the remaining pieces of the DAPM driver so that they are all in the
same order among controls/widgets/routes, and so they roughly match the
register word and bit order of the hardware. This nicely separates the
AIF-related widgets from the ADC/DAC widgets, which allows the AIF
widgets to stay in a logical order as more AIFs are added to the driver.

No widgets are renamed, to ease verification that this commit makes no
functional change.

Signed-off-by: Samuel Holland 
---
 sound/soc/sunxi/sun8i-codec.c | 101 ++
 1 file changed, 53 insertions(+), 48 deletions(-)

diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index 6887a2e897f4..d14243c434f9 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -327,16 +327,35 @@ static int sun8i_codec_hw_params(struct snd_pcm_substream 
*substream,
 
regmap_update_bits(scodec->regmap, SUN8I_SYS_SR_CTRL,
   SUN8I_SYS_SR_CTRL_AIF1_FS_MASK,
   sample_rate << SUN8I_SYS_SR_CTRL_AIF1_FS);
 
return 0;
 }
 
+static const struct snd_kcontrol_new sun8i_aif1_ad0_mixer_controls[] = {
+   SOC_DAPM_DOUBLE("AIF1 Slot 0 Digital ADC Capture Switch",
+   SUN8I_AIF1_MXR_SRC,
+   SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF1DA0L,
+   SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF1DA0R, 1, 0),
+   SOC_DAPM_DOUBLE("AIF2 Digital ADC Capture Switch",
+   SUN8I_AIF1_MXR_SRC,
+   SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACL,
+   SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACR, 1, 0),
+   SOC_DAPM_DOUBLE("AIF1 Data Digital ADC Capture Switch",
+   SUN8I_AIF1_MXR_SRC,
+   SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_ADCL,
+   SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_ADCR, 1, 0),
+   SOC_DAPM_DOUBLE("AIF2 Inv Digital ADC Capture Switch",
+   SUN8I_AIF1_MXR_SRC,
+   SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACR,
+   SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACL, 1, 0),
+};
+
 static const struct snd_kcontrol_new sun8i_dac_mixer_controls[] = {
SOC_DAPM_DOUBLE("AIF1 Slot 0 Digital DAC Playback Switch",
SUN8I_DAC_MXR_SRC,
SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA0L,
SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA0R, 1, 0),
SOC_DAPM_DOUBLE("AIF1 Slot 1 Digital DAC Playback Switch",
SUN8I_DAC_MXR_SRC,
SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA1L,
@@ -344,34 +363,16 @@ static const struct snd_kcontrol_new 
sun8i_dac_mixer_controls[] = {
SOC_DAPM_DOUBLE("AIF2 Digital DAC Playback Switch", SUN8I_DAC_MXR_SRC,
SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF2DACL,
SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF2DACR, 1, 0),
SOC_DAPM_DOUBLE("ADC Digital DAC Playback Switch", SUN8I_DAC_MXR_SRC,
SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_ADCL,
SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_ADCR, 1, 0),
 };
 
-static const struct snd_kcontrol_new sun8i_input_mixer_controls[] = {
-   SOC_DAPM_DOUBLE("AIF1 Slot 0 Digital ADC Capture Switch",
-   SUN8I_AIF1_MXR_SRC,
-   SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF1DA0L,
-   SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF1DA0R, 1, 0),
-   SOC_DAPM_DOUBLE("AIF2 Digital ADC Capture Switch", SUN8I_AIF1_MXR_SRC,
-   SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACL,
-   SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACR, 1, 0),
-   SOC_DAPM_DOUBLE("AIF1 Data Digital ADC Capture Switch",
-   SUN8I_AIF1_MXR_SRC,
-   SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_ADCL,
-   SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_ADCR, 1, 0),
-   SOC_DAPM_DOUBLE("AIF2 Inv Digital ADC Capture Switch",
-   SUN8I_AIF1_MXR_SRC,
-   SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACR,
-   SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACL, 1, 0),
-};
-
 static const struct snd_soc_dapm_widget sun8i_codec_dapm_widgets[] = {
/* System Clocks */
SND_SOC_DAPM_CLOCK_SUPPLY("mod"),
 
SND_SOC_DAPM_SUPPLY("AIF1CLK",
SUN8I_SYSCLK_CTL,
SUN8I_SYSCLK_CTL_AIF1CLK_ENA, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("SYSCLK",
@@ -395,55 +396,59 @@ static const struct snd_soc_dapm_widget 
sun8i_codec_dapm_widgets[] = {
SUN8I_MOD_RST_CTL_AIF1, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("RST ADC",
SUN8I_MOD_RST_CTL,
SUN8I_MOD_RST_CTL_ADC, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("RST DAC",
SUN8I_MOD_RST_CTL,
SUN8I_MOD_RST_CTL_DAC, 0, NULL, 0),
 

[PATCH 01/25] ASoC: sun8i-codec: Set up clock tree at probe time

2020-09-30 Thread Samuel Holland
The sun8i codec is effectively an on-die variant of the X-Powers AC100
codec. The AC100 can derive its clocks from either of two I2S master
clocks or an internal PLL. For the on-die variant, Allwinner replaced
the codec's own PLL with a connection to SoC's existing PLL_AUDIO, and
they connected both I2S MCLK inputs to the same source -- which happens
to be an integer divider from the same PLL_AUDIO.

So there's actually no clocking flexibility. To run SYSCLK at the
required rate, it must be run straight from the PLL. The only choice is
whether it goes through AIF1CLK or AIF2CLK. Since both run at the same
rate, the only effect of that choice is which field in SYS_SR_CTRL
(AIF1_FS or AIF2_FS) controls the system sample rate.

Since AIFnCLK is required to bring up the corresponding DAI, and AIF1
(connected to the CPU) is used most often, let's use AIF1CLK as the
SYSCLK parent. That means we no longer need to set AIF2_FS.

Since this clock tree never changes, we can program it from the
component probe function, instead of using DAPM widgets. The DAPM
widgets unnecessarily change clock parents when the codec goes in/out
of idle and the supply widgets are powered up/down.

Signed-off-by: Samuel Holland 
---
 sound/soc/sunxi/sun8i-codec.c | 54 +++
 1 file changed, 35 insertions(+), 19 deletions(-)

diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index 178f6fb31fd4..407f0fedc4ed 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -19,20 +19,23 @@
 #include 
 
 #include 
 #include 
 #include 
 
 #define SUN8I_SYSCLK_CTL   0x00c
 #define SUN8I_SYSCLK_CTL_AIF1CLK_ENA   11
-#define SUN8I_SYSCLK_CTL_AIF1CLK_SRC_PLL   9
-#define SUN8I_SYSCLK_CTL_AIF1CLK_SRC   8
+#define SUN8I_SYSCLK_CTL_AIF1CLK_SRC_PLL   (0x2 << 8)
+#define SUN8I_SYSCLK_CTL_AIF2CLK_ENA   7
+#define SUN8I_SYSCLK_CTL_AIF2CLK_SRC_PLL   (0x2 << 4)
 #define SUN8I_SYSCLK_CTL_SYSCLK_ENA3
 #define SUN8I_SYSCLK_CTL_SYSCLK_SRC0
+#define SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF1CLK(0x0 << 0)
+#define SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF2CLK(0x1 << 0)
 #define SUN8I_MOD_CLK_ENA  0x010
 #define SUN8I_MOD_CLK_ENA_AIF1 15
 #define SUN8I_MOD_CLK_ENA_ADC  3
 #define SUN8I_MOD_CLK_ENA_DAC  2
 #define SUN8I_MOD_RST_CTL  0x014
 #define SUN8I_MOD_RST_CTL_AIF1 15
 #define SUN8I_MOD_RST_CTL_ADC  3
 #define SUN8I_MOD_RST_CTL_DAC  2
@@ -74,16 +77,18 @@
 #define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA1L14
 #define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF2DACL13
 #define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_ADCL12
 #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA0R11
 #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA1R10
 #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF2DACR9
 #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_ADCR8
 
+#define SUN8I_SYSCLK_CTL_AIF1CLK_SRC_MASK  GENMASK(9, 8)
+#define SUN8I_SYSCLK_CTL_AIF2CLK_SRC_MASK  GENMASK(5, 4)
 #define SUN8I_SYS_SR_CTRL_AIF1_FS_MASK GENMASK(15, 12)
 #define SUN8I_SYS_SR_CTRL_AIF2_FS_MASK GENMASK(11, 8)
 #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK  GENMASK(12, 9)
 #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK  GENMASK(8, 6)
 #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK  GENMASK(5, 4)
 #define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK  GENMASK(3, 2)
 
 struct sun8i_codec_quirks {
@@ -318,19 +323,16 @@ static int sun8i_codec_hw_params(struct snd_pcm_substream 
*substream,
 
sample_rate = sun8i_codec_get_hw_rate(params);
if (sample_rate < 0)
return sample_rate;
 
regmap_update_bits(scodec->regmap, SUN8I_SYS_SR_CTRL,
   SUN8I_SYS_SR_CTRL_AIF1_FS_MASK,
   sample_rate << SUN8I_SYS_SR_CTRL_AIF1_FS);
-   regmap_update_bits(scodec->regmap, SUN8I_SYS_SR_CTRL,
-  SUN8I_SYS_SR_CTRL_AIF2_FS_MASK,
-  sample_rate << SUN8I_SYS_SR_CTRL_AIF2_FS);
 
return 0;
 }
 
 static const struct snd_kcontrol_new sun8i_dac_mixer_controls[] = {
SOC_DAPM_DOUBLE("AIF1 Slot 0 Digital DAC Playback Switch",
SUN8I_DAC_MXR_SRC,
SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA0L,
@@ -361,18 +363,26 @@ static const struct snd_kcontrol_new 
sun8i_input_mixer_controls[] = {
SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_ADCR, 1, 0),
SOC_DAPM_DOUBLE("AIF2 Inv Digital ADC Capture Switch",
SUN8I_AIF1_MXR_SRC,
SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACR,

[PATCH 06/25] ASoC: sun8i-codec: Fix AIF widget channel references

2020-09-30 Thread Samuel Holland
Both the left and right side widgets referenced channel 0. This would
unnecessarily power on the right side widget (and its associated path)
when a mono stream was active.

Signed-off-by: Samuel Holland 
---
 sound/soc/sunxi/sun8i-codec.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index d0028883950c..2c89974243e1 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -408,31 +408,31 @@ static const struct snd_soc_dapm_widget 
sun8i_codec_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("DAC",
SUN8I_DAC_DIG_CTRL,
SUN8I_DAC_DIG_CTRL_ENDA, 0, NULL, 0),
 
/* AIF "ADC" Outputs */
SND_SOC_DAPM_AIF_OUT("AIF1 AD0L", "Capture", 0,
 SUN8I_AIF1_ADCDAT_CTRL,
 SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_ENA, 0),
-   SND_SOC_DAPM_AIF_OUT("AIF1 AD0R", "Capture", 0,
+   SND_SOC_DAPM_AIF_OUT("AIF1 AD0R", "Capture", 1,
 SUN8I_AIF1_ADCDAT_CTRL,
 SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_ENA, 0),
 
/* AIF "ADC" Mixers */
SOC_MIXER_ARRAY("AIF1 AD0L Mixer", SND_SOC_NOPM, 0, 0,
sun8i_aif1_ad0_mixer_controls),
SOC_MIXER_ARRAY("AIF1 AD0R Mixer", SND_SOC_NOPM, 0, 0,
sun8i_aif1_ad0_mixer_controls),
 
/* AIF "DAC" Inputs */
SND_SOC_DAPM_AIF_IN("AIF1 DA0L", "Playback", 0,
SUN8I_AIF1_DACDAT_CTRL,
SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_ENA, 0),
-   SND_SOC_DAPM_AIF_IN("AIF1 DA0R", "Playback", 0,
+   SND_SOC_DAPM_AIF_IN("AIF1 DA0R", "Playback", 1,
SUN8I_AIF1_DACDAT_CTRL,
SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_ENA, 0),
 
/* ADC Inputs (connected to analog codec DAPM context) */
SND_SOC_DAPM_ADC("ADCL", NULL, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0),
 
/* DAC Outputs (connected to analog codec DAPM context) */
-- 
2.26.2



Re: [PATCH v3 2/3] iommu/tegra-smmu: Rework .probe_device and .attach_dev

2020-09-30 Thread Dmitry Osipenko
30.09.2020 19:47, Thierry Reding пишет:
> On Wed, Sep 30, 2020 at 07:25:41PM +0300, Dmitry Osipenko wrote:
>> 30.09.2020 19:06, Thierry Reding пишет:
>>> On Wed, Sep 30, 2020 at 06:36:52PM +0300, Dmitry Osipenko wrote:
  I'...
>> +struct tegra_mc *mc = devm_tegra_get_memory_controller(dev);
>> +struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
>
> It looks to me like the only reason why you need this new global API is
> because PCI devices may not have a device tree node with a phandle to
> the IOMMU. However, SMMU support for PCI will only be enabled if the
> root complex has an iommus property, right? In that case, can't we
> simply do something like this:
>
>   if (dev_is_pci(dev))
>   np = find_host_bridge(dev)->of_node;
>   else
>   np = dev->of_node;
>
> ? I'm not sure exactly what find_host_bridge() is called, but I'm pretty
> sure that exists.
>
> Once we have that we can still iterate over the iommus property and do
> not need to rely on this global variable.

 This sounds more complicated than the current variant.

 Secondly, I'm already about to use the new tegra_get_memory_controller()
 API for all the T20/30/124/210 EMC and devfreq drivers.
>>>
>>> Why do we need it there? They seem to work fine without it right now.
>>
>> All the Tegra30/124/210 EMC drivers are already duplicating that MC
>> lookup code and only the recent T210 driver does it properly.
>>
>>> If it is required for new functionality, we can always make the dependent
>>> on a DT reference via phandle without breaking any existing code.
>>
>> That's correct, it will be also needed for the new functionality as
>> well, hence even more drivers will need to perform the MC lookup.
> 
> I don't have any issues with adding a helper if we need it from several
> different locations. But the helper should be working off of a given
> device and look up the device via the device tree node referenced by
> phandle. We already have those phandles in place for the EMC devices,
> and any other device that needs to interoperate with the MC should also
> get such a reference.
> 
>> I don't quite understand why you're asking for the phandle reference,
>> it's absolutely not needed for the MC lookup and won't work for the
> 
> We need that phandle in order to establish a link between the devices.
> Yes, you can probably do it without the phandle and just match by
> compatible string. But we don't do that for other types of devices
> either, right? For a display driver we reference the attached panel via
> phandle, but we could also just look it up via name or absolute path or
> some other heuristic. But a phandle is just a much more explicit way of
> linking the devices, so why not use it?

There are dozens variants of the panels and system could easily have
more than one panel, hence a direct lookup by phandle is a natural
choice for the panels.

While all Tegra SoCs have a single fixed MC in the system, and thus,
there is no real need to use phandle because we can't mix up MC with
anything else.

>> older DTs if DT change will be needed. Please give a detailed explanation.
> 
> New functionality doesn't have to work with older DTs.

This is fine in general, but I'm afraid that in this particular case we
will need to have a fall back anyways because otherwise it should break
the old functionality.

So I don't think that using phandle for the MC device finding is really
warrant.

Phandle is kinda more applicable for the cases where only the DT node
lookup is needed (not the lookup of the MC device driver), but even then
it is also not mandatory.

I hope you agree.


Re: [PATCH v3 2/3] iommu/tegra-smmu: Rework .probe_device and .attach_dev

2020-09-30 Thread Dmitry Osipenko
01.10.2020 04:26, Nicolin Chen пишет:
> On Thu, Oct 01, 2020 at 12:56:46AM +0300, Dmitry Osipenko wrote:
>> 01.10.2020 00:32, Nicolin Chen пишет:
>>> On Thu, Oct 01, 2020 at 12:24:25AM +0300, Dmitry Osipenko wrote:
 ...
>> It looks to me like the only reason why you need this new global API is
>> because PCI devices may not have a device tree node with a phandle to
>> the IOMMU. However, SMMU support for PCI will only be enabled if the
>> root complex has an iommus property, right? In that case, can't we
>> simply do something like this:
>>
>>  if (dev_is_pci(dev))
>>  np = find_host_bridge(dev)->of_node;
>>  else
>>  np = dev->of_node;
>>
>> ? I'm not sure exactly what find_host_bridge() is called, but I'm pretty
>> sure that exists.
>>
>> Once we have that we can still iterate over the iommus property and do
>> not need to rely on this global variable.
>
> I agree that it'd work. But I was hoping to simplify the code
> here if it's possible. Looks like we have an argument on this
> so I will choose to go with your suggestion above for now.

 This patch removed more lines than were added. If this will be opposite
 for the Thierry's suggestion, then it's probably not a great suggestion.
>>>
>>> Sorry, I don't quite understand this comments. Would you please
>>> elaborate what's this "it" being "not a great suggestion"?
>>>
>>
>> I meant that you should try to implement Thierry's solution, but if the
>> end result will be worse than the current patch, then you shouldn't make
>> a v4, but get back to this discussion in order to choose the best option
>> and make everyone agree on it.
> 
> I see. Thanks for the reply. And here is a sample implementation:

That's what I supposed to happen :) The new variant adds code and
complexity, while old did the opposite. Hence the old variant is clearly
more attractive, IMO.


Re: [PATCH 2/9] perf tools: Use build_id object in dso

2020-09-30 Thread Ian Rogers
On Wed, Sep 30, 2020 at 10:15 AM Jiri Olsa  wrote:
>
> Replace build_id byte array with struct build_id
> object and all the code that references it.
>
> The objective is to carry size together with build
> id array, so it's better to keep both together.
>
> This is preparatory change for following patches,
> and there's no functional change.
>
> Signed-off-by: Jiri Olsa 

Acked-by: Ian Rogers 

This reads a little funny but makes sense in the context of the rest
of the patch set.

Thanks,
Ian

> ---
>  tools/perf/builtin-buildid-cache.c |  2 +-
>  tools/perf/builtin-inject.c|  4 ++--
>  tools/perf/util/annotate.c |  4 ++--
>  tools/perf/util/build-id.c |  6 +++---
>  tools/perf/util/build-id.h |  5 +
>  tools/perf/util/dso.c  | 18 +-
>  tools/perf/util/dso.h  |  2 +-
>  tools/perf/util/dsos.c |  4 ++--
>  tools/perf/util/header.c   |  2 +-
>  tools/perf/util/map.c  |  4 ++--
>  tools/perf/util/probe-event.c  |  2 +-
>  .../scripting-engines/trace-event-python.c |  2 +-
>  tools/perf/util/symbol.c   |  2 +-
>  tools/perf/util/synthetic-events.c |  2 +-
>  14 files changed, 32 insertions(+), 27 deletions(-)
>
> diff --git a/tools/perf/builtin-buildid-cache.c 
> b/tools/perf/builtin-buildid-cache.c
> index 39efa51d7fb3..a523c629f321 100644
> --- a/tools/perf/builtin-buildid-cache.c
> +++ b/tools/perf/builtin-buildid-cache.c
> @@ -284,7 +284,7 @@ static bool dso__missing_buildid_cache(struct dso *dso, 
> int parm __maybe_unused)
>
> pr_warning("Problems with %s file, consider removing it from 
> the cache\n",
>filename);
> -   } else if (memcmp(dso->build_id, build_id, sizeof(dso->build_id))) {
> +   } else if (memcmp(dso->bid.data, build_id, sizeof(dso->bid.data))) {
> pr_warning("Problems with %s file, consider removing it from 
> the cache\n",
>filename);
> }
> diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
> index 6d2f410d773a..5cf32d8e3aa6 100644
> --- a/tools/perf/builtin-inject.c
> +++ b/tools/perf/builtin-inject.c
> @@ -408,8 +408,8 @@ static int dso__read_build_id(struct dso *dso)
> if (dso->has_build_id)
> return 0;
>
> -   if (filename__read_build_id(dso->long_name, dso->build_id,
> -   sizeof(dso->build_id)) > 0) {
> +   if (filename__read_build_id(dso->long_name, dso->bid.data,
> +   sizeof(dso->bid.data)) > 0) {
> dso->has_build_id = true;
> return 0;
> }
> diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
> index fc17af7ba845..a016e1bd7b8d 100644
> --- a/tools/perf/util/annotate.c
> +++ b/tools/perf/util/annotate.c
> @@ -1578,8 +1578,8 @@ int symbol__strerror_disassemble(struct map_symbol *ms, 
> int errnum, char *buf, s
> char *build_id_msg = NULL;
>
> if (dso->has_build_id) {
> -   build_id__sprintf(dso->build_id,
> - sizeof(dso->build_id), bf + 15);
> +   build_id__sprintf(dso->bid.data,
> + sizeof(dso->bid.data), bf + 15);
> build_id_msg = bf;
> }
> scnprintf(buf, buflen,
> diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
> index 31207b6e2066..7da13ddb0d50 100644
> --- a/tools/perf/util/build-id.c
> +++ b/tools/perf/util/build-id.c
> @@ -272,7 +272,7 @@ char *dso__build_id_filename(const struct dso *dso, char 
> *bf, size_t size,
> if (!dso->has_build_id)
> return NULL;
>
> -   build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
> +   build_id__sprintf(dso->bid.data, sizeof(dso->bid.data), sbuild_id);
> linkname = build_id_cache__linkname(sbuild_id, NULL, 0);
> if (!linkname)
> return NULL;
> @@ -355,7 +355,7 @@ static int machine__write_buildid_table(struct machine 
> *machine,
> in_kernel = pos->kernel ||
> is_kernel_module(name,
> PERF_RECORD_MISC_CPUMODE_UNKNOWN);
> -   err = write_buildid(name, name_len, pos->build_id, 
> machine->pid,
> +   err = write_buildid(name, name_len, pos->bid.data, 
> machine->pid,
> in_kernel ? kmisc : umisc, fd);
> if (err)
> break;
> @@ -841,7 +841,7 @@ static int dso__cache_build_id(struct dso *dso, struct 
> machine *machine)
> is_kallsyms = true;
> name = machine->mmap_name;
>   

Re: [PATCH 1/9] perf tools: Add build id shell test

2020-09-30 Thread Ian Rogers
On Wed, Sep 30, 2020 at 10:15 AM Jiri Olsa  wrote:
>
> Adding test for build id cache that adds binary
> with sha1 and md5 build ids and verifies it's
> added properly.
>
> The test updates build id cache with perf record
> and perf buildid-cache -a.
>
> Signed-off-by: Jiri Olsa 

Acked-by: Ian Rogers 

This is great! If I build perf and test from the build directory the
test gets run. If I build using O=/tmp/perf and run from that
directory then ./tests/shell isn't found and the test doesn't run.
Similarly the install directory doesn't contain the executables and so
the test is skipped. Is there any way to get the test running in these
other scenarios?

Thanks,
Ian

> ---
>  tools/perf/Makefile.perf  | 14 +
>  tools/perf/tests/shell/buildid.sh | 90 +++
>  2 files changed, 104 insertions(+)
>  create mode 100755 tools/perf/tests/shell/buildid.sh
>
> diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
> index 920d8afb9238..b2aeefa64e92 100644
> --- a/tools/perf/Makefile.perf
> +++ b/tools/perf/Makefile.perf
> @@ -126,6 +126,8 @@ include ../scripts/utilities.mak
>  #
>  # Define NO_LIBDEBUGINFOD if you do not want support debuginfod
>  #
> +# Define NO_BUILDID_EX if you do not want buildid-ex-* binaries
> +#
>
>  # As per kernel Makefile, avoid funny character set dependencies
>  unexport LC_ALL
> @@ -349,6 +351,11 @@ ifndef NO_PERF_READ_VDSOX32
>  PROGRAMS += $(OUTPUT)perf-read-vdsox32
>  endif
>
> +ifndef NO_BUILDID_EX
> +PROGRAMS += $(OUTPUT)buildid-ex-sha1
> +PROGRAMS += $(OUTPUT)buildid-ex-md5
> +endif
> +
>  LIBJVMTI = libperf-jvmti.so
>
>  ifndef NO_JVMTI
> @@ -756,6 +763,13 @@ $(OUTPUT)perf-read-vdsox32: perf-read-vdso.c 
> util/find-map.c
> $(QUIET_CC)$(CC) -mx32 $(filter -static,$(LDFLAGS)) -Wall -Werror -o 
> $@ perf-read-vdso.c
>  endif
>
> +ifndef NO_BUILDID_EX
> +$(OUTPUT)buildid-ex-sha1:
> +   $(QUIET_LINK)echo 'int main(void) { return 0; }' | $(CC) 
> -Wl,--build-id=sha1 -o $@ -x c -
> +$(OUTPUT)buildid-ex-md5:
> +   $(QUIET_LINK)echo 'int main(void) { return 0; }' | $(CC) 
> -Wl,--build-id=md5 -o $@ -x c -
> +endif
> +
>  ifndef NO_JVMTI
>  LIBJVMTI_IN := $(OUTPUT)jvmti/jvmti-in.o
>
> diff --git a/tools/perf/tests/shell/buildid.sh 
> b/tools/perf/tests/shell/buildid.sh
> new file mode 100755
> index ..57fcd28bc4bd
> --- /dev/null
> +++ b/tools/perf/tests/shell/buildid.sh
> @@ -0,0 +1,90 @@
> +#!/bin/sh
> +# build id cache operations
> +# SPDX-License-Identifier: GPL-2.0
> +
> +# skip if there are no test binaries
> +if [ ! -x buildid-ex-sha1 -a ! -x buildid-ex-md5 ]; then
> +   echo "failed: no test binaries"
> +   exit 2
> +fi
> +
> +# skip if there's no readelf
> +if [ ! -x `which readelf` ]; then
> +   echo "failed: no readelf, install binutils"
> +   exit 2
> +fi
> +
> +check()
> +{
> +   id=`readelf -n $1 2>/dev/null | grep 'Build ID' | awk '{print $3}'`
> +
> +   echo "build id: ${id}"
> +
> +   link=${build_id_dir}/.build-id/${id:0:2}/${id:2}
> +   echo "link: ${link}"
> +
> +   if [ ! -h $link ]; then
> +   echo "failed: link ${link} does not exist"
> +   exit 1
> +   fi
> +
> +   file=${build_id_dir}/.build-id/${id:0:2}/`readlink ${link}`/elf
> +   echo "file: ${file}"
> +
> +   if [ ! -x $file ]; then
> +   echo "failed: file ${file} does not exist"
> +   exit 1
> +   fi
> +
> +   diff ${file} ${1}
> +   if [ $? -ne 0 ]; then
> +   echo "failed: ${file} do not match"
> +   exit 1
> +   fi
> +
> +   echo "OK for ${1}"
> +}
> +
> +test_add()
> +{
> +   build_id_dir=$(mktemp -d /tmp/perf.debug.XXX)
> +   perf="perf --buildid-dir ${build_id_dir}"
> +
> +   ${perf} buildid-cache -v -a ${1}
> +   if [ $? -ne 0 ]; then
> +   echo "failed: add ${1} to build id cache"
> +   exit 1
> +   fi
> +
> +   check ${1}
> +
> +   rm -rf ${build_id_dir}
> +}
> +
> +test_record()
> +{
> +   data=$(mktemp /tmp/perf.data.XXX)
> +   build_id_dir=$(mktemp -d /tmp/perf.debug.XXX)
> +   perf="perf --buildid-dir ${build_id_dir}"
> +
> +   ${perf} record --buildid-all -o ${data} ${1}
> +   if [ $? -ne 0 ]; then
> +   echo "failed: record ${1}"
> +   exit 1
> +   fi
> +
> +   check ${1}
> +
> +   rm -rf ${build_id_dir}
> +   rm -rf ${data}
> +}
> +
> +# add binaries manual via perf buildid-cache -a
> +test_add buildid-ex-sha1
> +test_add buildid-ex-md5
> +
> +# add binaries via perf record post processing
> +test_record buildid-ex-sha1
> +test_record buildid-ex-md5
> +
> +exit ${err}
> --
> 2.26.2
>


Re: For review: seccomp_user_notif(2) manual page

2020-09-30 Thread Jann Horn
On Thu, Oct 1, 2020 at 1:25 AM Tycho Andersen  wrote:
> On Thu, Oct 01, 2020 at 01:11:33AM +0200, Jann Horn wrote:
> > On Thu, Oct 1, 2020 at 1:03 AM Tycho Andersen  wrote:
> > > On Wed, Sep 30, 2020 at 10:34:51PM +0200, Michael Kerrisk (man-pages) 
> > > wrote:
> > > > On 9/30/20 5:03 PM, Tycho Andersen wrote:
> > > > > On Wed, Sep 30, 2020 at 01:07:38PM +0200, Michael Kerrisk (man-pages) 
> > > > > wrote:
> > > > >>┌─┐
> > > > >>│FIXME│
> > > > >>├─┤
> > > > >>│From my experiments,  it  appears  that  if  a  SEC‐ │
> > > > >>│COMP_IOCTL_NOTIF_RECV   is  done  after  the  target │
> > > > >>│process terminates, then the ioctl()  simply  blocks │
> > > > >>│(rather than returning an error to indicate that the │
> > > > >>│target process no longer exists).│
> > > > >
> > > > > Yeah, I think Christian wanted to fix this at some point,
> > > >
> > > > Do you have a pointer that discussion? I could not find it with a
> > > > quick search.
> > > >
> > > > > but it's a
> > > > > bit sticky to do.
> > > >
> > > > Can you say a few words about the nature of the problem?
> > >
> > > I remembered wrong, it's actually in the tree: 99cdb8b9a573 ("seccomp:
> > > notify about unused filter"). So maybe there's a bug here?
> >
> > That thing only notifies on ->poll, it doesn't unblock ioctls; and
> > Michael's sample code uses SECCOMP_IOCTL_NOTIF_RECV to wait. So that
> > commit doesn't have any effect on this kind of usage.
>
> Yes, thanks. And the ones stuck in RECV are waiting on a semaphore so
> we don't have a count of all of them, unfortunately.
>
> We could maybe look inside the wait_list, but that will probably make
> people angry :)

The easiest way would probably be to open-code the semaphore-ish part,
and let the semaphore and poll share the waitqueue. The current code
kind of mirrors the semaphore's waitqueue in the wqh - open-coding the
entire semaphore would IMO be cleaner than that. And it's not like
semaphore semantics are even a good fit for this code anyway.

Let's see... if we didn't have the existing UAPI to worry about, I'd
do it as follows (*completely* untested). That way, the ioctl would
block exactly until either there actually is a request to deliver or
there are no more users of the filter. The problem is that if we just
apply this patch, existing users of SECCOMP_IOCTL_NOTIF_RECV that use
an event loop and don't set O_NONBLOCK will be screwed. So we'd
probably also have to add some stupid counter in place of the
semaphore's counter that we can use to preserve the old behavior of
returning -ENOENT once for each cancelled request. :(

I guess this is a nice point in favor of Michael's usual complaint
that if there are no man pages for a feature by the time the feature
lands upstream, there's a higher chance that the UAPI will suck
forever...



diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index 676d4af62103..f0f4c68e0bc6 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -138,7 +138,6 @@ struct seccomp_kaddfd {
  * @notifications: A list of struct seccomp_knotif elements.
  */
 struct notification {
-   struct semaphore request;
u64 next_id;
struct list_head notifications;
 };
@@ -859,7 +858,6 @@ static int seccomp_do_user_notification(int this_syscall,
list_add(, >notif->notifications);
INIT_LIST_HEAD();

-   up(>notif->request);
wake_up_poll(>wqh, EPOLLIN | EPOLLRDNORM);
mutex_unlock(>notify_lock);

@@ -1175,9 +1173,10 @@ find_notification(struct seccomp_filter *filter, u64 id)


 static long seccomp_notify_recv(struct seccomp_filter *filter,
-   void __user *buf)
+   void __user *buf, bool blocking)
 {
struct seccomp_knotif *knotif = NULL, *cur;
+   DECLARE_WAITQUEUE(wait, current);
struct seccomp_notif unotif;
ssize_t ret;

@@ -1190,11 +1189,9 @@ static long seccomp_notify_recv(struct
seccomp_filter *filter,

memset(, 0, sizeof(unotif));

-   ret = down_interruptible(>notif->request);
-   if (ret < 0)
-   return ret;
-
mutex_lock(>notify_lock);
+
+retry:
list_for_each_entry(cur, >notif->notifications, list) {
if (cur->state == SECCOMP_NOTIFY_INIT) {
knotif = cur;
@@ -1202,14 +1199,32 @@ static long seccomp_notify_recv(struct
seccomp_filter *filter,
}
}

-   /*
-* If we didn't find a notification, it could be that the task was
-* interrupted by a fatal signal between the time we were woken and
-* when we were able to acquire the rw lock.
-*/
if (!knotif) {
-   ret = -ENOENT;
-   goto out;
+   /* This has to happen before checking 

Re: [PATCH v3 2/2] Input: synaptics-rmi4 - add support for F3A

2020-09-30 Thread Andrew Duggan



On Wed, Sep 30, 2020, at 2:41 AM, Vincent Huang wrote:
> RMI4 F3A supports the touchpad GPIO function, it's designed to
> support more GPIOs and used on newer touchpads. This patch adds
> support of the touchpad buttons.
> 
> Signed-off-by: Vincent Huang 
> Reviewed-by: Hans de Goede 
> Tested-by: Hans de Goede 

Reviewed-by: Andrew Duggan 

> ---
>  drivers/input/rmi4/Kconfig  |   8 ++
>  drivers/input/rmi4/Makefile |   1 +
>  drivers/input/rmi4/rmi_bus.c|   3 +
>  drivers/input/rmi4/rmi_driver.h |   1 +
>  drivers/input/rmi4/rmi_f3a.c| 240 
>  5 files changed, 253 insertions(+)
>  create mode 100644 drivers/input/rmi4/rmi_f3a.c
> 
> diff --git a/drivers/input/rmi4/Kconfig b/drivers/input/rmi4/Kconfig
> index a212ff706f74..16119f760d11 100644
> --- a/drivers/input/rmi4/Kconfig
> +++ b/drivers/input/rmi4/Kconfig
> @@ -100,6 +100,14 @@ config RMI4_F34
> device via the firmware loader interface. This is triggered using a
> sysfs attribute.
>  
> +config RMI4_F3A
> + bool "RMI4 Function 3A (GPIO)"
> + help
> +   Say Y here if you want to add support for RMI4 function 3A.
> +
> +   Function 3A provides GPIO support for RMI4 devices. This includes
> +   support for buttons on TouchPads and ClickPads.
> +
>  config RMI4_F54
>   bool "RMI4 Function 54 (Analog diagnostics)"
>   depends on VIDEO_V4L2=y || (RMI4_CORE=m && VIDEO_V4L2=m)
> diff --git a/drivers/input/rmi4/Makefile b/drivers/input/rmi4/Makefile
> index f17631656987..02f14c846861 100644
> --- a/drivers/input/rmi4/Makefile
> +++ b/drivers/input/rmi4/Makefile
> @@ -10,6 +10,7 @@ rmi_core-$(CONFIG_RMI4_F11) += rmi_f11.o
>  rmi_core-$(CONFIG_RMI4_F12) += rmi_f12.o
>  rmi_core-$(CONFIG_RMI4_F30) += rmi_f30.o
>  rmi_core-$(CONFIG_RMI4_F34) += rmi_f34.o rmi_f34v7.o
> +rmi_core-$(CONFIG_RMI4_F3A) += rmi_f3a.o
>  rmi_core-$(CONFIG_RMI4_F54) += rmi_f54.o
>  rmi_core-$(CONFIG_RMI4_F55) += rmi_f55.o
>  
> diff --git a/drivers/input/rmi4/rmi_bus.c b/drivers/input/rmi4/rmi_bus.c
> index af706a583656..47d1b97ed6cf 100644
> --- a/drivers/input/rmi4/rmi_bus.c
> +++ b/drivers/input/rmi4/rmi_bus.c
> @@ -365,6 +365,9 @@ static struct rmi_function_handler *fn_handlers[] = {
>  #ifdef CONFIG_RMI4_F34
>   _f34_handler,
>  #endif
> +#ifdef CONFIG_RMI4_F3A
> + _f3a_handler,
> +#endif
>  #ifdef CONFIG_RMI4_F54
>   _f54_handler,
>  #endif
> diff --git a/drivers/input/rmi4/rmi_driver.h b/drivers/input/rmi4/rmi_driver.h
> index 65bfaa95e193..1c6c6086c0e5 100644
> --- a/drivers/input/rmi4/rmi_driver.h
> +++ b/drivers/input/rmi4/rmi_driver.h
> @@ -135,6 +135,7 @@ extern struct rmi_function_handler rmi_f11_handler;
>  extern struct rmi_function_handler rmi_f12_handler;
>  extern struct rmi_function_handler rmi_f30_handler;
>  extern struct rmi_function_handler rmi_f34_handler;
> +extern struct rmi_function_handler rmi_f3a_handler;
>  extern struct rmi_function_handler rmi_f54_handler;
>  extern struct rmi_function_handler rmi_f55_handler;
>  #endif
> diff --git a/drivers/input/rmi4/rmi_f3a.c b/drivers/input/rmi4/rmi_f3a.c
> new file mode 100644
> index ..11ff35f811b0
> --- /dev/null
> +++ b/drivers/input/rmi4/rmi_f3a.c
> @@ -0,0 +1,240 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2012-2020 Synaptics Incorporated
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include "rmi_driver.h"
> +
> +#define RMI_F3A_MAX_GPIO_COUNT   128
> +#define RMI_F3A_MAX_REG_SIZE DIV_ROUND_UP(RMI_F3A_MAX_GPIO_COUNT, 8)
> +
> +/* Defs for Query 0 */
> +#define RMI_F3A_GPIO_COUNT   0x7F
> +
> +#define RMI_F3A_DATA_REGS_MAX_SIZE   RMI_F3A_MAX_REG_SIZE
> +
> +#define TRACKSTICK_RANGE_START   3
> +#define TRACKSTICK_RANGE_END 6
> +
> +struct f3a_data {
> + /* Query Data */
> + u8 gpio_count;
> +
> + u8 register_count;
> +
> + u8 data_regs[RMI_F3A_DATA_REGS_MAX_SIZE];
> + u16 *gpio_key_map;
> +
> + struct input_dev *input;
> +
> + struct rmi_function *f03;
> + bool trackstick_buttons;
> +};
> +
> +static void rmi_f3a_report_button(struct rmi_function *fn,
> +   struct f3a_data *f3a, unsigned int button)
> +{
> + u16 key_code = f3a->gpio_key_map[button];
> + bool key_down = !(f3a->data_regs[0] & BIT(button));
> +
> + if (f3a->trackstick_buttons &&
> + button >= TRACKSTICK_RANGE_START &&
> + button <= TRACKSTICK_RANGE_END) {
> + rmi_f03_overwrite_button(f3a->f03, key_code, key_down);
> + } else {
> + rmi_dbg(RMI_DEBUG_FN, >dev,
> + "%s: call input report key (0x%04x) value (0x%02x)",
> + __func__, key_code, key_down);
> + input_report_key(f3a->input, key_code, key_down);
> + }
> +}
> +
> +static irqreturn_t rmi_f3a_attention(int irq, void *ctx)
> +{
> + struct rmi_function *fn = ctx;
> + struct f3a_data *f3a = 

Re: [PATCH 4.4 00/85] 4.4.238-rc1 review

2020-09-30 Thread Dan Rue
On Tue, Sep 29, 2020 at 12:59:27PM +0200, Greg Kroah-Hartman wrote:
> This is the start of the stable review cycle for the 4.4.238 release.
> There are 85 patches in this series, all will be posted as a response
> to this one.  If anyone has any issues with these being applied, please
> let me know.

Results from Linaro’s test farm.
No regressions on arm64, arm, x86_64, and i386.

Tested-by: Linux Kernel Functional Testing 

Summary


kernel: 4.4.238-rc1
git repo: 
['https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git', 
'https://gitlab.com/Linaro/lkft/mirrors/stable/linux-stable-rc']
git branch: linux-4.4.y
git commit: 0d240bae7702c50af56209b177e48d81d371b555
git describe: v4.4.237-86-g0d240bae7702
Test details: 
https://qa-reports.linaro.org/lkft/linux-stable-rc-linux-4.4.y/build/v4.4.237-86-g0d240bae7702


No regressions (compared to build v4.4.237)


No fixes (compared to build v4.4.237)

Ran 5245 total tests in the following environments and test suites.

Environments
--
- i386
- juno-r2 - arm64
- qemu_arm
- qemu_arm64
- qemu_i386
- qemu_x86_64
- x15 - arm
- x86_64
- x86-kasan

Test Suites
---
* build
* linux-log-parser
* libhugetlbfs
* ltp-cap_bounds-tests
* ltp-commands-tests
* ltp-containers-tests
* ltp-controllers-tests
* ltp-cpuhotplug-tests
* ltp-crypto-tests
* ltp-cve-tests
* ltp-dio-tests
* ltp-fcntl-locktests-tests
* ltp-filecaps-tests
* ltp-fs-tests
* ltp-fs_bind-tests
* ltp-fs_perms_simple-tests
* ltp-fsx-tests
* ltp-hugetlb-tests
* ltp-io-tests
* ltp-ipc-tests
* ltp-math-tests
* ltp-mm-tests
* ltp-nptl-tests
* ltp-pty-tests
* ltp-sched-tests
* ltp-securebits-tests
* ltp-tracing-tests
* v4l2-compliance
* ltp-syscalls-tests
* install-android-platform-tools-r2600
* network-basic-tests
* perf


Results from Linaro’s test farm.
No regressions on arm64, arm, x86_64, and i386.

Tested-by: Linux Kernel Functional Testing 

Summary


kernel: 4.4.238-rc1
git repo: https://git.linaro.org/lkft/arm64-stable-rc.git
git branch: 4.4.238-rc1-hikey-20200929-822
git commit: 1e94ff9d5cbda806b493b89b01eb99c67ec9ed4c
git describe: 4.4.238-rc1-hikey-20200929-822
Test details: 
https://qa-reports.linaro.org/lkft/linaro-hikey-stable-rc-4.4-oe/build/4.4.238-rc1-hikey-20200929-822


No regressions (compared to build 4.4.238-rc1-hikey-20200928-820)


No fixes (compared to build 4.4.238-rc1-hikey-20200928-820)

Ran 1686 total tests in the following environments and test suites.

Environments
--
- hi6220-hikey - arm64

Test Suites
---
* build
* install-android-platform-tools-r2600
* libhugetlbfs
* linux-log-parser
* ltp-cap_bounds-tests
* ltp-commands-tests
* ltp-containers-tests
* ltp-cpuhotplug-tests
* ltp-cve-tests
* ltp-dio-tests
* ltp-fcntl-locktests-tests
* ltp-filecaps-tests
* ltp-fs_bind-tests
* ltp-fs_perms_simple-tests
* ltp-fsx-tests
* ltp-hugetlb-tests
* ltp-io-tests
* ltp-ipc-tests
* ltp-math-tests
* ltp-mm-tests
* ltp-nptl-tests
* ltp-pty-tests
* ltp-sched-tests
* ltp-securebits-tests
* ltp-syscalls-tests
* perf
* spectre-meltdown-checker-test
* v4l2-compliance


--
Linaro LKFT
https://lkft.linaro.org


Re: [PATCH v3 1/2] Input: synaptics-rmi4 - rename f30_data to gpio_data

2020-09-30 Thread Andrew Duggan



On Wed, Sep 30, 2020, at 2:41 AM, Vincent Huang wrote:
> f30_data in rmi_device_platform_data could be also referenced by RMI
> function 3A, so rename it and the structure name to avoid confusion.
> 
> Signed-off-by: Vincent Huang 
> Reviewed-by: Hans de Goede 
> Tested-by: Hans de Goede 

Reviewed-by: Andrew Duggan 

> ---
>  drivers/hid/hid-rmi.c   |  2 +-
>  drivers/input/mouse/synaptics.c |  2 +-
>  drivers/input/rmi4/rmi_f30.c| 14 +++---
>  include/linux/rmi.h | 11 ++-
>  4 files changed, 15 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/hid/hid-rmi.c b/drivers/hid/hid-rmi.c
> index 9ce22acdfaca..62315e31d520 100644
> --- a/drivers/hid/hid-rmi.c
> +++ b/drivers/hid/hid-rmi.c
> @@ -722,7 +722,7 @@ static int rmi_probe(struct hid_device *hdev, const 
> struct hid_device_id *id)
>   }
>  
>   if (data->device_flags & RMI_DEVICE_HAS_PHYS_BUTTONS)
> - rmi_hid_pdata.f30_data.disable = true;
> + rmi_hid_pdata.gpio_data.disable = true;
>  
>   data->xport.dev = hdev->dev.parent;
>   data->xport.pdata = rmi_hid_pdata;
> diff --git a/drivers/input/mouse/synaptics.c 
> b/drivers/input/mouse/synaptics.c
> index 4b81b2d0fe06..8a54efd6eb95 100644
> --- a/drivers/input/mouse/synaptics.c
> +++ b/drivers/input/mouse/synaptics.c
> @@ -1752,7 +1752,7 @@ static int synaptics_create_intertouch(struct 
> psmouse *psmouse,
>   .kernel_tracking = false,
>   .topbuttonpad = topbuttonpad,
>   },
> - .f30_data = {
> + .gpio_data = {
>   .buttonpad = SYN_CAP_CLICKPAD(info->ext_cap_0c),
>   .trackstick_buttons =
>   !!SYN_CAP_EXT_BUTTONS_STICK(info->ext_cap_10),
> diff --git a/drivers/input/rmi4/rmi_f30.c b/drivers/input/rmi4/rmi_f30.c
> index a90dad1d9ac7..35045f161dc2 100644
> --- a/drivers/input/rmi4/rmi_f30.c
> +++ b/drivers/input/rmi4/rmi_f30.c
> @@ -168,17 +168,17 @@ static int rmi_f30_config(struct rmi_function *fn)
>   rmi_get_platform_data(fn->rmi_dev);
>   int error;
>  
> - /* can happen if f30_data.disable is set */
> + /* can happen if gpio_data.disable is set */
>   if (!f30)
>   return 0;
>  
> - if (pdata->f30_data.trackstick_buttons) {
> + if (pdata->gpio_data.trackstick_buttons) {
>   /* Try [re-]establish link to F03. */
>   f30->f03 = rmi_find_function(fn->rmi_dev, 0x03);
>   f30->trackstick_buttons = f30->f03 != NULL;
>   }
>  
> - if (pdata->f30_data.disable) {
> + if (pdata->gpio_data.disable) {
>   drv->clear_irq_bits(fn->rmi_dev, fn->irq_mask);
>   } else {
>   /* Write Control Register values back to device */
> @@ -245,10 +245,10 @@ static int rmi_f30_map_gpios(struct rmi_function *fn,
>   if (!rmi_f30_is_valid_button(i, f30->ctrl))
>   continue;
>  
> - if (pdata->f30_data.trackstick_buttons &&
> + if (pdata->gpio_data.trackstick_buttons &&
>   i >= TRACKSTICK_RANGE_START && i < TRACKSTICK_RANGE_END) {
>   f30->gpioled_key_map[i] = trackstick_button++;
> - } else if (!pdata->f30_data.buttonpad || !button_mapped) {
> + } else if (!pdata->gpio_data.buttonpad || !button_mapped) {
>   f30->gpioled_key_map[i] = button;
>   input_set_capability(input, EV_KEY, button++);
>   button_mapped = true;
> @@ -264,7 +264,7 @@ static int rmi_f30_map_gpios(struct rmi_function *fn,
>* but I am not sure, so use only the pdata info and the number of
>* mapped buttons.
>*/
> - if (pdata->f30_data.buttonpad || (button - BTN_LEFT == 1))
> + if (pdata->gpio_data.buttonpad || (button - BTN_LEFT == 1))
>   __set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
>  
>   return 0;
> @@ -372,7 +372,7 @@ static int rmi_f30_probe(struct rmi_function *fn)
>   struct f30_data *f30;
>   int error;
>  
> - if (pdata->f30_data.disable)
> + if (pdata->gpio_data.disable)
>   return 0;
>  
>   if (!drv_data->input) {
> diff --git a/include/linux/rmi.h b/include/linux/rmi.h
> index 7b22366d0065..00dda5381bf8 100644
> --- a/include/linux/rmi.h
> +++ b/include/linux/rmi.h
> @@ -102,15 +102,16 @@ struct rmi_2d_sensor_platform_data {
>  };
>  
>  /**
> - * struct rmi_f30_data - overrides defaults for a single F30 GPIOs/LED 
> chip.
> + * struct rmi_gpio_data - overrides defaults for a single F30/F3A 
> GPIOs/LED
> + * chip.
>   * @buttonpad - the touchpad is a buttonpad, so enable only the first 
> actual
>   * button that is found.
> - * @trackstick_buttons - Set when the function 30 is handling the 
> physical
> + * @trackstick_buttons - Set when the function 30 or 3a is handling 
> the physical
>   * buttons of the trackstick 

Re: [PATCH v5 09/15] misc: bcm-vk: add VK messaging support

2020-09-30 Thread Joe Perches
On Wed, 2020-09-30 at 18:28 -0700, Scott Branden wrote:
> Add message support in order to be able to communicate
> to VK card via message queues.

trivia:

> +/* structure that is used to faciliate displaying of register content */
> +struct bcm_vk_entry {
> + const u32 mask;
> + const u32 exp_val;
> + const char *str;
> +};
[]
> +/*
> + * alerts that could be generated from peer
> + */
> +struct bcm_vk_entry const bcm_vk_peer_err[BCM_VK_PEER_ERR_NUM] = {

const struct bcm_vk_entry

> + {ERR_LOG_UECC, ERR_LOG_UECC, "uecc"},
> + {ERR_LOG_SSIM_BUSY, ERR_LOG_SSIM_BUSY, "ssim_busy"},
> + {ERR_LOG_AFBC_BUSY, ERR_LOG_AFBC_BUSY, "afbc_busy"},
> + {ERR_LOG_HIGH_TEMP_ERR, ERR_LOG_HIGH_TEMP_ERR, "high_temp"},
> + {ERR_LOG_WDOG_TIMEOUT, ERR_LOG_WDOG_TIMEOUT, "wdog_timeout"},
> + {ERR_LOG_SYS_FAULT, ERR_LOG_SYS_FAULT, "sys_fault"},
> + {ERR_LOG_RAMDUMP, ERR_LOG_RAMDUMP, "ramdump"},
> + {ERR_LOG_MEM_ALLOC_FAIL, ERR_LOG_MEM_ALLOC_FAIL, "malloc_fail warn"},
> + {ERR_LOG_LOW_TEMP_WARN, ERR_LOG_LOW_TEMP_WARN, "low_temp warn"},
> + {ERR_LOG_ECC, ERR_LOG_ECC, "ecc"},
> +};
> +
> +/* alerts detected by the host */
> +struct bcm_vk_entry const bcm_vk_host_err[BCM_VK_HOST_ERR_NUM] = {

here too

> + {ERR_LOG_HOST_PCIE_DWN, ERR_LOG_HOST_PCIE_DWN, "PCIe_down"},
> + {ERR_LOG_HOST_HB_FAIL, ERR_LOG_HOST_HB_FAIL, "hb_fail"},
> + {ERR_LOG_HOST_INTF_V_FAIL, ERR_LOG_HOST_INTF_V_FAIL, "intf_ver_fail"},
> +};
[]
> @@ -970,6 +1251,9 @@ static int bcm_vk_probe(struct pci_dev *pdev, const 
> struct pci_device_id *ent)
>   }
>   }
>  
> + /* enable hb */
> + bcm_vk_hb_init(vk);
> +
>   dev_dbg(dev, "BCM-VK:%u created, 0x%p\n", id, vk);

Not much purpose in displaying the pointer.




[PATCH V7 3/5] platform/x86: Intel PMT class driver

2020-09-30 Thread David E. Box
From: Alexander Duyck 

Intel Platform Monitoring Technology is meant to provide a common way to
access telemetry and system metrics.

Register mappings are not provided by the driver. Instead, a GUID is read
from a header for each endpoint. The GUID identifies the device and is to
be used with an XML, provided by the vendor, to discover the available set
of metrics and their register mapping.  This allows firmware updates to
modify the register space without needing to update the driver every time
with new mappings. Firmware writes a new GUID in this case to specify the
new mapping.  Software tools with access to the associated XML file can
then interpret the changes.

The module manages access to all Intel PMT endpoints on a system,
independent of the device exporting them. It creates an intel_pmt class to
manage the devices. For each telemetry endpoint, sysfs files provide GUID
and size information as well as a pointer to the parent device the
telemetry came from. Software may discover the association between
endpoints and devices by iterating through the list in sysfs, or by looking
for the existence of the class folder under the device of interest.  A
binary sysfs attribute of the same name allows software to then read or map
the telemetry space for direct access.

Signed-off-by: Alexander Duyck 
---
 .../ABI/testing/sysfs-class-intel_pmt |  54 
 MAINTAINERS   |   1 +
 drivers/platform/x86/Kconfig  |   9 +
 drivers/platform/x86/Makefile |   1 +
 drivers/platform/x86/intel_pmt_class.c| 286 ++
 drivers/platform/x86/intel_pmt_class.h|  57 
 6 files changed, 408 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-intel_pmt
 create mode 100644 drivers/platform/x86/intel_pmt_class.c
 create mode 100644 drivers/platform/x86/intel_pmt_class.h

diff --git a/Documentation/ABI/testing/sysfs-class-intel_pmt 
b/Documentation/ABI/testing/sysfs-class-intel_pmt
new file mode 100644
index ..926b5cf95fd1
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-intel_pmt
@@ -0,0 +1,54 @@
+What:  /sys/class/intel_pmt/
+Date:  October 2020
+KernelVersion: 5.10
+Contact:   David Box 
+Description:
+   The intel_pmt/ class directory contains information for
+   devices that expose hardware telemetry using Intel Platform
+   Monitoring Technology (PMT)
+
+What:  /sys/class/intel_pmt/telem
+Date:  October 2020
+KernelVersion: 5.10
+Contact:   David Box 
+Description:
+   The telem directory contains files describing an instance of
+   a PMT telemetry device that exposes hardware telemetry. Each
+   telem directory has an associated telem file. This file
+   may be opened and mapped or read to access the telemetry space
+   of the device. The register layout of the telemetry space is
+   determined from an XML file that matches the PCI device id and
+   GUID for the device.
+
+What:  /sys/class/intel_pmt/telem/telem
+Date:  October 2020
+KernelVersion: 5.10
+Contact:   David Box 
+Description:
+   (RO) The telemetry data for this telemetry device. This file
+   may be mapped or read to obtain the data.
+
+What:  /sys/class/intel_pmt/telem/guid
+Date:  October 2020
+KernelVersion: 5.10
+Contact:   David Box 
+Description:
+   (RO) The GUID for this telemetry device. The GUID identifies
+   the version of the XML file for the parent device that is to
+   be used to get the register layout.
+
+What:  /sys/class/intel_pmt/telem/size
+Date:  October 2020
+KernelVersion: 5.10
+Contact:   David Box 
+Description:
+   (RO) The size of telemetry region in bytes that corresponds to
+   the mapping size for the telem file.
+
+What:  /sys/class/intel_pmt/telem/offset
+Date:  October 2020
+KernelVersion: 5.10
+Contact:   David Box 
+Description:
+   (RO) The offset of telemetry region in bytes that corresponds to
+   the mapping for the telem file.
diff --git a/MAINTAINERS b/MAINTAINERS
index 0f2663b1d376..47fdb8a6e151 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8950,6 +8950,7 @@ INTEL PMT DRIVER
 M: "David E. Box" 
 S: Maintained
 F: drivers/mfd/intel_pmt.c
+F: drivers/platform/x86/intel_pmt_*
 
 INTEL PRO/WIRELESS 2100, 2200BG, 2915ABG NETWORK CONNECTION SUPPORT
 M: Stanislav Yakovlev 
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 40219bba6801..82465d0e8fd3 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -1360,6 +1360,15 @@ config INTEL_PMC_CORE
- LTR Ignore
- MPHY/PLL gating status (Sunrisepoint PCH only)
 
+config INTEL_PMT_CLASS
+   

[PATCH V7 4/5] platform/x86: Intel PMT Telemetry capability driver

2020-09-30 Thread David E. Box
From: Alexander Duyck 

PMT Telemetry is a capability of the Intel Platform Monitoring Technology.
The Telemetry capability provides access to device telemetry metrics that
provide hardware performance data to users from read-only register spaces.

With this driver present the intel_pmt directory can be populated with
telem devices. These devices will contain the standard intel_pmt sysfs
data and a "telem" binary sysfs attribute which can be used to access the
telemetry data.

Co-developed-by: David E. Box 
Signed-off-by: David E. Box 
Signed-off-by: Alexander Duyck 
---
 drivers/platform/x86/Kconfig   |   8 ++
 drivers/platform/x86/Makefile  |   1 +
 drivers/platform/x86/intel_pmt_telemetry.c | 158 +
 3 files changed, 167 insertions(+)
 create mode 100644 drivers/platform/x86/intel_pmt_telemetry.c

diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 82465d0e8fd3..8eae17a57a5b 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -1369,6 +1369,14 @@ config INTEL_PMT_CLASS
  For more information, see:
  
 
+config INTEL_PMT_TELEMETRY
+   tristate "Intel Platform Monitoring Technology (PMT) Telemetry driver"
+   select INTEL_PMT_CLASS
+   help
+ The Intel Platform Monitory Technology (PMT) Telemetry driver provides
+ access to hardware telemetry metrics on devices that support the
+ feature.
+
 config INTEL_PUNIT_IPC
tristate "Intel P-Unit IPC Driver"
help
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index f4b1f87f2401..6a7b61f59ea8 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -141,6 +141,7 @@ obj-$(CONFIG_INTEL_MID_POWER_BUTTON)+= 
intel_mid_powerbtn.o
 obj-$(CONFIG_INTEL_MRFLD_PWRBTN)   += intel_mrfld_pwrbtn.o
 obj-$(CONFIG_INTEL_PMC_CORE)   += intel_pmc_core.o 
intel_pmc_core_pltdrv.o
 obj-$(CONFIG_INTEL_PMT_CLASS)  += intel_pmt_class.o
+obj-$(CONFIG_INTEL_PMT_TELEMETRY)  += intel_pmt_telemetry.o
 obj-$(CONFIG_INTEL_PUNIT_IPC)  += intel_punit_ipc.o
 obj-$(CONFIG_INTEL_SCU_IPC)+= intel_scu_ipc.o
 obj-$(CONFIG_INTEL_SCU_PCI)+= intel_scu_pcidrv.o
diff --git a/drivers/platform/x86/intel_pmt_telemetry.c 
b/drivers/platform/x86/intel_pmt_telemetry.c
new file mode 100644
index ..d4819aefdd65
--- /dev/null
+++ b/drivers/platform/x86/intel_pmt_telemetry.c
@@ -0,0 +1,158 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Intel Platform Monitory Technology Telemetry driver
+ *
+ * Copyright (c) 2020, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * Author: "David E. Box" 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "intel_pmt_class.h"
+
+#define TELEM_DEV_NAME "pmt_telemetry"
+
+#define TELEM_SIZE_OFFSET  0x0
+#define TELEM_GUID_OFFSET  0x4
+#define TELEM_BASE_OFFSET  0x8
+#define TELEM_ACCESS(v)((v) & GENMASK(3, 0))
+/* size is in bytes */
+#define TELEM_SIZE(v)  (((v) & GENMASK(27, 12)) >> 10)
+
+/* Used by client hardware to identify a fixed telemetry entry*/
+#define TELEM_CLIENT_FIXED_BLOCK_GUID  0x1000
+
+struct pmt_telem_priv {
+   int num_entries;
+   struct intel_pmt_entry  entry[];
+};
+
+static DEFINE_XARRAY_ALLOC(telem_array);
+static struct intel_pmt_namespace pmt_telem_ns = {
+   .name = "telem",
+   .xa = _array
+};
+
+/*
+ * driver initialization
+ */
+static int pmt_telem_add_entry(struct intel_pmt_entry *entry,
+  struct device *parent,
+  struct resource *disc_res)
+{
+   void __iomem *disc_table = entry->disc_table;
+   struct intel_pmt_header header;
+   int ret;
+
+   header.access_type = TELEM_ACCESS(readl(disc_table));
+   header.guid = readl(disc_table + TELEM_GUID_OFFSET);
+   header.base_offset = readl(disc_table + TELEM_BASE_OFFSET);
+
+   /* Size is measured in DWORDS, but accessor returns bytes */
+   header.size = TELEM_SIZE(readl(disc_table));
+
+   ret = intel_pmt_populate_entry(entry, , parent, disc_res);
+   if (ret)
+   return ret;
+
+   return intel_pmt_dev_create(entry, _telem_ns, parent);
+}
+
+static bool pmt_telem_region_overlaps(struct intel_pmt_entry *entry)
+{
+   u32 guid;
+
+   guid = readl(entry->disc_table + TELEM_GUID_OFFSET);
+
+   return guid == TELEM_CLIENT_FIXED_BLOCK_GUID;
+}
+
+static int pmt_telem_remove(struct platform_device *pdev)
+{
+   struct pmt_telem_priv *priv = platform_get_drvdata(pdev);
+   int i;
+
+   for (i = 0; i < priv->num_entries; i++)
+   intel_pmt_dev_destroy(>entry[i], _telem_ns);
+
+   return 0;
+}
+
+static int pmt_telem_probe(struct platform_device *pdev)
+{
+   struct pmt_telem_priv *priv;
+   bool early_hw;
+   size_t size;
+   int i, ret;

[PATCH V7 1/5] PCI: Add defines for Designated Vendor-Specific Extended Capability

2020-09-30 Thread David E. Box
Add PCIe Designated Vendor-Specific Extended Capability (DVSEC) and defines
for the header offsets. Defined in PCIe r5.0, sec 7.9.6.

Signed-off-by: David E. Box 
Acked-by: Bjorn Helgaas 
Reviewed-by: Andy Shevchenko 
---
 include/uapi/linux/pci_regs.h | 5 +
 1 file changed, 5 insertions(+)

diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
index f9701410d3b5..beafeee39e44 100644
--- a/include/uapi/linux/pci_regs.h
+++ b/include/uapi/linux/pci_regs.h
@@ -720,6 +720,7 @@
 #define PCI_EXT_CAP_ID_DPC 0x1D/* Downstream Port Containment */
 #define PCI_EXT_CAP_ID_L1SS0x1E/* L1 PM Substates */
 #define PCI_EXT_CAP_ID_PTM 0x1F/* Precision Time Measurement */
+#define PCI_EXT_CAP_ID_DVSEC   0x23/* Designated Vendor-Specific */
 #define PCI_EXT_CAP_ID_DLF 0x25/* Data Link Feature */
 #define PCI_EXT_CAP_ID_PL_16GT 0x26/* Physical Layer 16.0 GT/s */
 #define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_PL_16GT
@@ -1062,6 +1063,10 @@
 #define  PCI_L1SS_CTL1_LTR_L12_TH_SCALE0xe000  /* 
LTR_L1.2_THRESHOLD_Scale */
 #define PCI_L1SS_CTL2  0x0c/* Control 2 Register */
 
+/* Designated Vendor-Specific (DVSEC, PCI_EXT_CAP_ID_DVSEC) */
+#define PCI_DVSEC_HEADER1  0x4 /* Designated Vendor-Specific 
Header1 */
+#define PCI_DVSEC_HEADER2  0x8 /* Designated Vendor-Specific 
Header2 */
+
 /* Data Link Feature */
 #define PCI_DLF_CAP0x04/* Capabilities Register */
 #define  PCI_DLF_EXCHANGE_ENABLE   0x8000  /* Data Link Feature 
Exchange Enable */
-- 
2.20.1



[PATCH V7 0/5] Intel Platform Monitoring Technology

2020-09-30 Thread David E. Box
Intel Platform Monitoring Technology (PMT) is an architecture for
enumerating and accessing hardware monitoring capabilities on a device.
With customers increasingly asking for hardware telemetry, engineers not
only have to figure out how to measure and collect data, but also how to
deliver it and make it discoverable. The latter may be through some device
specific method requiring device specific tools to collect the data. This
in turn requires customers to manage a suite of different tools in order to
collect the differing assortment of monitoring data on their systems.  Even
when such information can be provided in kernel drivers, they may require
constant maintenance to update register mappings as they change with
firmware updates and new versions of hardware. PMT provides a solution for
discovering and reading telemetry from a device through a hardware agnostic
framework that allows for updates to systems without requiring patches to
the kernel or software tools.

PMT defines several capabilities to support collecting monitoring data from
hardware. All are discoverable as separate instances of the PCIE Designated
Vendor extended capability (DVSEC) with the Intel vendor code. The DVSEC ID
field uniquely identifies the capability. Each DVSEC also provides a BAR
offset to a header that defines capability-specific attributes, including
GUID, feature type, offset and length, as well as configuration settings
where applicable. The GUID uniquely identifies the register space of any
monitor data exposed by the capability. The GUID is associated with an XML
file from the vendor that describes the mapping of the register space along
with properties of the monitor data. This allows vendors to perform
firmware updates that can change the mapping (e.g. add new metrics) without
requiring any changes to drivers or software tools. The new mapping is
confirmed by an updated GUID, read from the hardware, which software uses
with a new XML.

The current capabilities defined by PMT are Telemetry, Watcher, and
Crashlog.  The Telemetry capability provides access to a continuous block
of read only data. The Watcher capability provides access to hardware
sampling and tracing features. Crashlog provides access to device crash
dumps.  While there is some relationship between capabilities (Watcher can
be configured to sample from the Telemetry data set) each exists as stand
alone features with no dependency on any other. The design therefore splits
them into individual, capability specific drivers. MFD is used to create
platform devices for each capability so that they may be managed by their
own driver. The PMT architecture is (for the most part) agnostic to the
type of device it can collect from. Software can determine which devices
support a PMT feature by searching through each device node entry in the
sysfs class folder. It can additionally determine if a particular device
supports a PMT feature by checking for a PMT class folder in the device
folder.

This patch set provides support for the PMT framework, along with support
for Telemetry on Tiger Lake.

Changes from V6:
- Use NULL for OOBMSM driver data instead of an empty struct.
  Rewrite the code to check for NULL driver_data.
- Fix spelling and formatting in Kconfig.
- Use MKDEV(0,0) to prevent unneeded device node from being
  created.

Changes from V5:
- Add Alder Lake and the "Out of Band Management Services
  Module (OOBMSM)" ids to the MFD driver. Transferred to this
  patch set.
- Use a single class for all PMT capabilities as suggested by
  Hans.
- Add binary attribute for telemetry driver to allow read
  syscall as suggested by Hans.
- Use the class file to hold attributes and other common code
  used by all PMT drivers.
- Add the crashlog driver to the patch set and add a mutex to
  protect access to the enable control and trigger files as
  suggested by Hans.

Changes from V4:
- Replace MFD with PMT in driver title
- Fix commit tags in chronological order
- Fix includes in alphabetical order
- Use 'raw' string instead of defines for device names
- Add an error message when returning an error code for
  unrecognized capability id
- Use dev_err instead of dev_warn for messages when returning
  an error
- Change while loop to call pci_find_next_ext_capability once
- Add missing continue in while loop
- Keep PCI platform defines using PCI_DEVICE_DATA magic tied to
  the pci_device_id table
- Comment and kernel message cleanup

Changes from V3:
- Write out full acronym for DVSEC in PCI patch commit message and
  add 'Designated' to comments
- remove unused variable caught by kernel test robot 
- Add required Co-developed-by signoffs, noted by Andy
- Allow access using new CAP_PERFMON 

[PATCH V7 5/5] platform/x86: Intel PMT Crashlog capability driver

2020-09-30 Thread David E. Box
From: Alexander Duyck 

Add support for the Intel Platform Monitoring Technology crashlog
interface. This interface provides a few sysfs values to allow for
controlling the crashlog telemetry interface as well as a character driver
to allow for mapping the crashlog memory region so that it can be accessed
after a crashlog has been recorded.

This driver is meant to only support the server version of the crashlog
which is identified as crash_type 1 with a version of zero. Currently no
other types are supported.

Signed-off-by: Alexander Duyck 
---
 .../ABI/testing/sysfs-class-intel_pmt |  65 
 drivers/platform/x86/Kconfig  |   8 +
 drivers/platform/x86/Makefile |   1 +
 drivers/platform/x86/intel_pmt_crashlog.c | 339 ++
 4 files changed, 413 insertions(+)
 create mode 100644 drivers/platform/x86/intel_pmt_crashlog.c

diff --git a/Documentation/ABI/testing/sysfs-class-intel_pmt 
b/Documentation/ABI/testing/sysfs-class-intel_pmt
index 926b5cf95fd1..67ca47123cbf 100644
--- a/Documentation/ABI/testing/sysfs-class-intel_pmt
+++ b/Documentation/ABI/testing/sysfs-class-intel_pmt
@@ -52,3 +52,68 @@ Contact: David Box 
 Description:
(RO) The offset of telemetry region in bytes that corresponds to
the mapping for the telem file.
+
+What:  /sys/class/intel_pmt/crashlog
+Date:  October 2020
+KernelVersion: 5.10
+Contact:   Alexander Duyck 
+Description:
+   The crashlog directory contains files for configuring an
+   instance of a PMT crashlog device that can perform crash data
+   recoring. Each crashlog device has an associated crashlog
+   file. This file can be opened and mapped or read to access the
+   resulting crashlog buffer. The register layout for the buffer
+   can be determined from an XML file of specified guid for the
+   parent device.
+
+What:  /sys/class/intel_pmt/crashlog/crashlog
+Date:  October 2020
+KernelVersion: 5.10
+Contact:   David Box 
+Description:
+   (RO) The crashlog buffer for this crashlog device. This file
+   may be mapped or read to obtain the data.
+
+What:  /sys/class/intel_pmt/crashlog/guid
+Date:  October 2020
+KernelVersion: 5.10
+Contact:   Alexander Duyck 
+Description:
+   (RO) The guid for this crashlog device. The guid identifies the
+   version of the XML file for the parent device that should be
+   used to determine the register layout.
+
+What:  /sys/class/intel_pmt/crashlog/size
+Date:  October 2020
+KernelVersion: 5.10
+Contact:   Alexander Duyck 
+Description:
+   (RO) The length of the result buffer in bytes that corresponds
+   to the size for the crashlog buffer.
+
+What:  /sys/class/intel_pmt/crashlog/offset
+Date:  October 2020
+KernelVersion: 5.10
+Contact:   Alexander Duyck 
+Description:
+   (RO) The offset of the buffer in bytes that corresponds
+   to the mapping for the crashlog device.
+
+What:  /sys/class/intel_pmt/crashlog/enable
+Date:  October 2020
+KernelVersion: 5.10
+Contact:   Alexander Duyck 
+Description:
+   (RW) Boolean value controlling if the crashlog functionality
+   is enabled for the crashlog device.
+
+What:  /sys/class/intel_pmt/crashlog/trigger
+Date:  October 2020
+KernelVersion: 5.10
+Contact:   Alexander Duyck 
+Description:
+   (RW) Boolean value controlling the triggering of the crashlog
+   device node. When read it provides data on if the crashlog has
+   been triggered. When written to it can be used to either clear
+   the current trigger by writing false, or to trigger a new
+   event if the trigger is not currently set.
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 8eae17a57a5b..529c5ee2eabf 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -1377,6 +1377,14 @@ config INTEL_PMT_TELEMETRY
  access to hardware telemetry metrics on devices that support the
  feature.
 
+config INTEL_PMT_CRASHLOG
+   tristate "Intel Platform Monitoring Technology (PMT) Crashlog driver"
+   select INTEL_PMT_CLASS
+   help
+ The Intel Platform Monitoring Technology (PMT) crashlog driver 
provides
+ access to hardware crashlog capabilities on devices that support the
+ feature.
+
 config INTEL_PUNIT_IPC
tristate "Intel P-Unit IPC Driver"
help
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 6a7b61f59ea8..ca82c1344977 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -142,6 +142,7 @@ obj-$(CONFIG_INTEL_MRFLD_PWRBTN)+= intel_mrfld_pwrbtn.o
 

  1   2   3   4   5   6   7   8   9   10   >