From 0b889618939f28bf447a1618f997243f82c7ff9a Mon Sep 17 00:00:00 2001 From: Odelu Kukatla Date: Tue, 27 Apr 2021 15:20:56 +0530 Subject: dt-bindings: interconnect: Add Qualcomm SC7280 DT bindings The Qualcomm SC7280 platform has several bus fabrics that could be controlled and tuned dynamically according to the bandwidth demand. Signed-off-by: Odelu Kukatla Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/1619517059-12109-2-git-send-email-okukatla@codeaurora.org Signed-off-by: Georgi Djakov --- include/dt-bindings/interconnect/qcom,sc7280.h | 165 +++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 include/dt-bindings/interconnect/qcom,sc7280.h (limited to 'include') diff --git a/include/dt-bindings/interconnect/qcom,sc7280.h b/include/dt-bindings/interconnect/qcom,sc7280.h new file mode 100644 index 000000000000..21b000443999 --- /dev/null +++ b/include/dt-bindings/interconnect/qcom,sc7280.h @@ -0,0 +1,165 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Qualcomm SC7280 interconnect IDs + * + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#ifndef __DT_BINDINGS_INTERCONNECT_QCOM_SC7280_H +#define __DT_BINDINGS_INTERCONNECT_QCOM_SC7280_H + +#define MASTER_QSPI_0 0 +#define MASTER_QUP_0 1 +#define MASTER_QUP_1 2 +#define MASTER_A1NOC_CFG 3 +#define MASTER_PCIE_0 4 +#define MASTER_PCIE_1 5 +#define MASTER_SDCC_1 6 +#define MASTER_SDCC_2 7 +#define MASTER_SDCC_4 8 +#define MASTER_UFS_MEM 9 +#define MASTER_USB2 10 +#define MASTER_USB3_0 11 +#define SLAVE_A1NOC_SNOC 12 +#define SLAVE_ANOC_PCIE_GEM_NOC 13 +#define SLAVE_SERVICE_A1NOC 14 + +#define MASTER_QDSS_BAM 0 +#define MASTER_A2NOC_CFG 1 +#define MASTER_CNOC_A2NOC 2 +#define MASTER_CRYPTO 3 +#define MASTER_IPA 4 +#define MASTER_QDSS_ETR 5 +#define SLAVE_A2NOC_SNOC 6 +#define SLAVE_SERVICE_A2NOC 7 + +#define MASTER_QUP_CORE_0 0 +#define MASTER_QUP_CORE_1 1 +#define SLAVE_QUP_CORE_0 2 +#define SLAVE_QUP_CORE_1 3 + +#define MASTER_CNOC3_CNOC2 0 +#define MASTER_QDSS_DAP 1 +#define SLAVE_AHB2PHY_SOUTH 2 +#define SLAVE_AHB2PHY_NORTH 3 +#define SLAVE_CAMERA_CFG 4 +#define SLAVE_CLK_CTL 5 +#define SLAVE_CDSP_CFG 6 +#define SLAVE_RBCPR_CX_CFG 7 +#define SLAVE_RBCPR_MX_CFG 8 +#define SLAVE_CRYPTO_0_CFG 9 +#define SLAVE_CX_RDPM 10 +#define SLAVE_DCC_CFG 11 +#define SLAVE_DISPLAY_CFG 12 +#define SLAVE_GFX3D_CFG 13 +#define SLAVE_HWKM 14 +#define SLAVE_IMEM_CFG 15 +#define SLAVE_IPA_CFG 16 +#define SLAVE_IPC_ROUTER_CFG 17 +#define SLAVE_LPASS 18 +#define SLAVE_CNOC_MSS 19 +#define SLAVE_MX_RDPM 20 +#define SLAVE_PCIE_0_CFG 21 +#define SLAVE_PCIE_1_CFG 22 +#define SLAVE_PDM 23 +#define SLAVE_PIMEM_CFG 24 +#define SLAVE_PKA_WRAPPER_CFG 25 +#define SLAVE_PMU_WRAPPER_CFG 26 +#define SLAVE_QDSS_CFG 27 +#define SLAVE_QSPI_0 28 +#define SLAVE_QUP_0 29 +#define SLAVE_QUP_1 30 +#define SLAVE_SDCC_1 31 +#define SLAVE_SDCC_2 32 +#define SLAVE_SDCC_4 33 +#define SLAVE_SECURITY 34 +#define SLAVE_TCSR 35 +#define SLAVE_TLMM 36 +#define SLAVE_UFS_MEM_CFG 37 +#define SLAVE_USB2 38 +#define SLAVE_USB3_0 39 +#define SLAVE_VENUS_CFG 40 +#define SLAVE_VSENSE_CTRL_CFG 41 +#define SLAVE_A1NOC_CFG 42 +#define SLAVE_A2NOC_CFG 43 +#define SLAVE_CNOC2_CNOC3 44 +#define SLAVE_CNOC_MNOC_CFG 45 +#define SLAVE_SNOC_CFG 46 + +#define MASTER_CNOC2_CNOC3 0 +#define MASTER_GEM_NOC_CNOC 1 +#define MASTER_GEM_NOC_PCIE_SNOC 2 +#define SLAVE_AOSS 3 +#define SLAVE_APPSS 4 +#define SLAVE_CNOC3_CNOC2 5 +#define SLAVE_CNOC_A2NOC 6 +#define SLAVE_DDRSS_CFG 7 +#define SLAVE_BOOT_IMEM 8 +#define SLAVE_IMEM 9 +#define SLAVE_PIMEM 10 +#define SLAVE_PCIE_0 11 +#define SLAVE_PCIE_1 12 +#define SLAVE_QDSS_STM 13 +#define SLAVE_TCU 14 + +#define MASTER_CNOC_DC_NOC 0 +#define SLAVE_LLCC_CFG 1 +#define SLAVE_GEM_NOC_CFG 2 + +#define MASTER_GPU_TCU 0 +#define MASTER_SYS_TCU 1 +#define MASTER_APPSS_PROC 2 +#define MASTER_COMPUTE_NOC 3 +#define MASTER_GEM_NOC_CFG 4 +#define MASTER_GFX3D 5 +#define MASTER_MNOC_HF_MEM_NOC 6 +#define MASTER_MNOC_SF_MEM_NOC 7 +#define MASTER_ANOC_PCIE_GEM_NOC 8 +#define MASTER_SNOC_GC_MEM_NOC 9 +#define MASTER_SNOC_SF_MEM_NOC 10 +#define SLAVE_MSS_PROC_MS_MPU_CFG 11 +#define SLAVE_MCDMA_MS_MPU_CFG 12 +#define SLAVE_GEM_NOC_CNOC 13 +#define SLAVE_LLCC 14 +#define SLAVE_MEM_NOC_PCIE_SNOC 15 +#define SLAVE_SERVICE_GEM_NOC_1 16 +#define SLAVE_SERVICE_GEM_NOC_2 17 +#define SLAVE_SERVICE_GEM_NOC 18 + +#define MASTER_CNOC_LPASS_AG_NOC 0 +#define SLAVE_LPASS_CORE_CFG 1 +#define SLAVE_LPASS_LPI_CFG 2 +#define SLAVE_LPASS_MPU_CFG 3 +#define SLAVE_LPASS_TOP_CFG 4 +#define SLAVE_SERVICES_LPASS_AML_NOC 5 +#define SLAVE_SERVICE_LPASS_AG_NOC 6 + +#define MASTER_LLCC 0 +#define SLAVE_EBI1 1 + +#define MASTER_CNOC_MNOC_CFG 0 +#define MASTER_VIDEO_P0 1 +#define MASTER_VIDEO_PROC 2 +#define MASTER_CAMNOC_HF 3 +#define MASTER_CAMNOC_ICP 4 +#define MASTER_CAMNOC_SF 5 +#define MASTER_MDP0 6 +#define SLAVE_MNOC_HF_MEM_NOC 7 +#define SLAVE_MNOC_SF_MEM_NOC 8 +#define SLAVE_SERVICE_MNOC 9 + +#define MASTER_CDSP_NOC_CFG 0 +#define MASTER_CDSP_PROC 1 +#define SLAVE_CDSP_MEM_NOC 2 +#define SLAVE_SERVICE_NSP_NOC 3 + +#define MASTER_A1NOC_SNOC 0 +#define MASTER_A2NOC_SNOC 1 +#define MASTER_SNOC_CFG 2 +#define MASTER_PIMEM 3 +#define MASTER_GIC 4 +#define SLAVE_SNOC_GEM_NOC_GC 5 +#define SLAVE_SNOC_GEM_NOC_SF 6 +#define SLAVE_SERVICE_SNOC 7 + +#endif -- cgit v1.2.3 From 345e9f5ca798600e44c0843646621f2804eb99f4 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 11 May 2021 11:00:45 +0800 Subject: soundwire: bus: only use CLOCK_STOP_MODE0 and fix confusions Existing devices and implementations only support the required CLOCK_STOP_MODE0. All the code related to CLOCK_STOP_MODE1 has not been tested and is highly questionable, with a clear confusion between CLOCK_STOP_MODE1 and the simple clock stop state machine. This patch removes all usages of CLOCK_STOP_MODE1 - which has no impact on any solution - and fixes the use of the simple clock stop state machine. The resulting code should be a lot more symmetrical and easier to maintain. Note that CLOCK_STOP_MODE1 is not supported in the SoundWire Device Class specification so it's rather unlikely that we need to re-add this mode later. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Guennadi Liakhovetski Reviewed-by: Rander Wang Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20210511030048.25622-2-yung-chuan.liao@linux.intel.com Signed-off-by: Vinod Koul --- drivers/soundwire/bus.c | 100 +++++++++++++++++------------------------- include/linux/soundwire/sdw.h | 2 - 2 files changed, 40 insertions(+), 62 deletions(-) (limited to 'include') diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index a9e0aa72654d..dc4033b6f2e9 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -821,26 +821,6 @@ static void sdw_modify_slave_status(struct sdw_slave *slave, mutex_unlock(&bus->bus_lock); } -static enum sdw_clk_stop_mode sdw_get_clk_stop_mode(struct sdw_slave *slave) -{ - enum sdw_clk_stop_mode mode; - - /* - * Query for clock stop mode if Slave implements - * ops->get_clk_stop_mode, else read from property. - */ - if (slave->ops && slave->ops->get_clk_stop_mode) { - mode = slave->ops->get_clk_stop_mode(slave); - } else { - if (slave->prop.clk_stop_mode1) - mode = SDW_CLK_STOP_MODE1; - else - mode = SDW_CLK_STOP_MODE0; - } - - return mode; -} - static int sdw_slave_clk_stop_callback(struct sdw_slave *slave, enum sdw_clk_stop_mode mode, enum sdw_clk_stop_type type) @@ -933,7 +913,6 @@ static int sdw_bus_wait_for_clk_prep_deprep(struct sdw_bus *bus, u16 dev_num) */ int sdw_bus_prep_clk_stop(struct sdw_bus *bus) { - enum sdw_clk_stop_mode slave_mode; bool simple_clk_stop = true; struct sdw_slave *slave; bool is_slave = false; @@ -955,10 +934,8 @@ int sdw_bus_prep_clk_stop(struct sdw_bus *bus) /* Identify if Slave(s) are available on Bus */ is_slave = true; - slave_mode = sdw_get_clk_stop_mode(slave); - slave->curr_clk_stop_mode = slave_mode; - - ret = sdw_slave_clk_stop_callback(slave, slave_mode, + ret = sdw_slave_clk_stop_callback(slave, + SDW_CLK_STOP_MODE0, SDW_CLK_PRE_PREPARE); if (ret < 0) { dev_err(&slave->dev, @@ -966,22 +943,29 @@ int sdw_bus_prep_clk_stop(struct sdw_bus *bus) return ret; } - ret = sdw_slave_clk_stop_prepare(slave, - slave_mode, true); - if (ret < 0) { - dev_err(&slave->dev, - "pre-prepare failed:%d", ret); - return ret; - } - - if (slave_mode == SDW_CLK_STOP_MODE1) + /* Only prepare a Slave device if needed */ + if (!slave->prop.simple_clk_stop_capable) { simple_clk_stop = false; + + ret = sdw_slave_clk_stop_prepare(slave, + SDW_CLK_STOP_MODE0, + true); + if (ret < 0) { + dev_err(&slave->dev, + "pre-prepare failed:%d", ret); + return ret; + } + } } /* Skip remaining clock stop preparation if no Slave is attached */ if (!is_slave) return ret; + /* + * Don't wait for all Slaves to be ready if they follow the simple + * state machine + */ if (!simple_clk_stop) { ret = sdw_bus_wait_for_clk_prep_deprep(bus, SDW_BROADCAST_DEV_NUM); @@ -998,17 +982,13 @@ int sdw_bus_prep_clk_stop(struct sdw_bus *bus) slave->status != SDW_SLAVE_ALERT) continue; - slave_mode = slave->curr_clk_stop_mode; - - if (slave_mode == SDW_CLK_STOP_MODE1) { - ret = sdw_slave_clk_stop_callback(slave, - slave_mode, - SDW_CLK_POST_PREPARE); + ret = sdw_slave_clk_stop_callback(slave, + SDW_CLK_STOP_MODE0, + SDW_CLK_POST_PREPARE); - if (ret < 0) { - dev_err(&slave->dev, - "post-prepare failed:%d", ret); - } + if (ret < 0) { + dev_err(&slave->dev, + "post-prepare failed:%d", ret); } } @@ -1059,7 +1039,6 @@ EXPORT_SYMBOL(sdw_bus_clk_stop); */ int sdw_bus_exit_clk_stop(struct sdw_bus *bus) { - enum sdw_clk_stop_mode mode; bool simple_clk_stop = true; struct sdw_slave *slave; bool is_slave = false; @@ -1081,31 +1060,33 @@ int sdw_bus_exit_clk_stop(struct sdw_bus *bus) /* Identify if Slave(s) are available on Bus */ is_slave = true; - mode = slave->curr_clk_stop_mode; - - if (mode == SDW_CLK_STOP_MODE1) { - simple_clk_stop = false; - continue; - } - - ret = sdw_slave_clk_stop_callback(slave, mode, + ret = sdw_slave_clk_stop_callback(slave, SDW_CLK_STOP_MODE0, SDW_CLK_PRE_DEPREPARE); if (ret < 0) dev_warn(&slave->dev, "clk stop deprep failed:%d", ret); - ret = sdw_slave_clk_stop_prepare(slave, mode, - false); + /* Only de-prepare a Slave device if needed */ + if (!slave->prop.simple_clk_stop_capable) { + simple_clk_stop = false; - if (ret < 0) - dev_warn(&slave->dev, - "clk stop deprep failed:%d", ret); + ret = sdw_slave_clk_stop_prepare(slave, SDW_CLK_STOP_MODE0, + false); + + if (ret < 0) + dev_warn(&slave->dev, + "clk stop deprep failed:%d", ret); + } } /* Skip remaining clock stop de-preparation if no Slave is attached */ if (!is_slave) return 0; + /* + * Don't wait for all Slaves to be ready if they follow the simple + * state machine + */ if (!simple_clk_stop) sdw_bus_wait_for_clk_prep_deprep(bus, SDW_BROADCAST_DEV_NUM); @@ -1117,8 +1098,7 @@ int sdw_bus_exit_clk_stop(struct sdw_bus *bus) slave->status != SDW_SLAVE_ALERT) continue; - mode = slave->curr_clk_stop_mode; - sdw_slave_clk_stop_callback(slave, mode, + sdw_slave_clk_stop_callback(slave, SDW_CLK_STOP_MODE0, SDW_CLK_POST_DEPREPARE); } diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index ced07f8fde87..5d93d9949653 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -624,7 +624,6 @@ struct sdw_slave_ops { int (*port_prep)(struct sdw_slave *slave, struct sdw_prepare_ch *prepare_ch, enum sdw_port_prep_ops pre_ops); - int (*get_clk_stop_mode)(struct sdw_slave *slave); int (*clk_stop)(struct sdw_slave *slave, enum sdw_clk_stop_mode mode, enum sdw_clk_stop_type type); @@ -675,7 +674,6 @@ struct sdw_slave { struct list_head node; struct completion port_ready[SDW_MAX_PORTS]; unsigned int m_port_map[SDW_MAX_PORTS]; - enum sdw_clk_stop_mode curr_clk_stop_mode; u16 dev_num; u16 dev_num_sticky; bool probed; -- cgit v1.2.3 From 448df2d8fcab6cc50e0de4679ce3afe2ece282f2 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 11 May 2021 11:00:46 +0800 Subject: soundwire: add missing kernel-doc description For some reason we never added a description for the clk_stop callback. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Guennadi Liakhovetski Reviewed-by: Rander Wang Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20210511030048.25622-3-yung-chuan.liao@linux.intel.com Signed-off-by: Vinod Koul --- include/linux/soundwire/sdw.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index 5d93d9949653..8ca736e92d5a 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -612,6 +612,7 @@ struct sdw_bus_params { * @update_status: Update Slave status * @bus_config: Update the bus config for Slave * @port_prep: Prepare the port with parameters + * @clk_stop: handle imp-def sequences before and after prepare and de-prepare */ struct sdw_slave_ops { int (*read_prop)(struct sdw_slave *sdw); -- cgit v1.2.3 From 14374fbb3f06ddaba186d608a58c07f3d48d08df Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 11 May 2021 23:07:25 +0200 Subject: misc: eeprom_93xx46: Add new 93c56 and 93c66 compatible strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These two devices have respectively 2048 and 4096 bits of storage, compared to 1024 for the 93c46. Reviewed-by: Jonathan Neuschäfer Signed-off-by: Emmanuel Gil Peyrot Link: https://lore.kernel.org/r/20210511210727.24895-3-linkmauve@linkmauve.fr Signed-off-by: Greg Kroah-Hartman --- drivers/misc/eeprom/eeprom_93xx46.c | 35 ++++++++++++++++++++++++++++++++--- include/linux/eeprom_93xx46.h | 3 +++ 2 files changed, 35 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c index ffdb8e5a26e0..29d8971ec558 100644 --- a/drivers/misc/eeprom/eeprom_93xx46.c +++ b/drivers/misc/eeprom/eeprom_93xx46.c @@ -29,14 +29,29 @@ struct eeprom_93xx46_devtype_data { unsigned int quirks; + unsigned char flags; +}; + +static const struct eeprom_93xx46_devtype_data at93c46_data = { + .flags = EE_SIZE1K, +}; + +static const struct eeprom_93xx46_devtype_data at93c56_data = { + .flags = EE_SIZE2K, +}; + +static const struct eeprom_93xx46_devtype_data at93c66_data = { + .flags = EE_SIZE4K, }; static const struct eeprom_93xx46_devtype_data atmel_at93c46d_data = { + .flags = EE_SIZE1K, .quirks = EEPROM_93XX46_QUIRK_SINGLE_WORD_READ | EEPROM_93XX46_QUIRK_INSTRUCTION_LENGTH, }; static const struct eeprom_93xx46_devtype_data microchip_93lc46b_data = { + .flags = EE_SIZE1K, .quirks = EEPROM_93XX46_QUIRK_EXTRA_READ_CYCLE, }; @@ -381,8 +396,11 @@ static void select_deassert(void *context) } static const struct of_device_id eeprom_93xx46_of_table[] = { - { .compatible = "eeprom-93xx46", }, + { .compatible = "eeprom-93xx46", .data = &at93c46_data, }, + { .compatible = "atmel,at93c46", .data = &at93c46_data, }, { .compatible = "atmel,at93c46d", .data = &atmel_at93c46d_data, }, + { .compatible = "atmel,at93c56", .data = &at93c56_data, }, + { .compatible = "atmel,at93c66", .data = &at93c66_data, }, { .compatible = "microchip,93lc46b", .data = µchip_93lc46b_data, }, {} }; @@ -432,6 +450,7 @@ static int eeprom_93xx46_probe_dt(struct spi_device *spi) const struct eeprom_93xx46_devtype_data *data = of_id->data; pd->quirks = data->quirks; + pd->flags |= data->flags; } spi->dev.platform_data = pd; @@ -461,7 +480,16 @@ static int eeprom_93xx46_probe(struct spi_device *spi) if (!edev) return -ENOMEM; - edev->size = 128; + if (pd->flags & EE_SIZE1K) + edev->size = 128; + else if (pd->flags & EE_SIZE2K) + edev->size = 256; + else if (pd->flags & EE_SIZE4K) + edev->size = 512; + else { + dev_err(&spi->dev, "unspecified size\n"); + return -EINVAL; + } if (pd->flags & EE_ADDR8) edev->addrlen = ilog2(edev->size); @@ -496,8 +524,9 @@ static int eeprom_93xx46_probe(struct spi_device *spi) if (IS_ERR(edev->nvmem)) return PTR_ERR(edev->nvmem); - dev_info(&spi->dev, "%d-bit eeprom %s\n", + dev_info(&spi->dev, "%d-bit eeprom containing %d bytes %s\n", (pd->flags & EE_ADDR8) ? 8 : 16, + edev->size, (pd->flags & EE_READONLY) ? "(readonly)" : ""); if (!(pd->flags & EE_READONLY)) { diff --git a/include/linux/eeprom_93xx46.h b/include/linux/eeprom_93xx46.h index 99580c22f91a..34c2175e6a1e 100644 --- a/include/linux/eeprom_93xx46.h +++ b/include/linux/eeprom_93xx46.h @@ -10,6 +10,9 @@ struct eeprom_93xx46_platform_data { #define EE_ADDR8 0x01 /* 8 bit addr. cfg */ #define EE_ADDR16 0x02 /* 16 bit addr. cfg */ #define EE_READONLY 0x08 /* forbid writing */ +#define EE_SIZE1K 0x10 /* 1 kb of data, that is a 93xx46 */ +#define EE_SIZE2K 0x20 /* 2 kb of data, that is a 93xx56 */ +#define EE_SIZE4K 0x40 /* 4 kb of data, that is a 93xx66 */ unsigned int quirks; /* Single word read transfers only; no sequential read. */ -- cgit v1.2.3 From 46ad057245912fc8a49e18f6f8b57f80ab8d4dc1 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 19 May 2021 18:33:14 +0200 Subject: sysfs: Add helper BIN_ATTRIBUTE_GROUPS New helper BIN_ATTRIBUTE_GROUPS() does the same as ATTRIBUTE_GROUPS(), just for binary attributes. Signed-off-by: Heiner Kallweit Link: https://lore.kernel.org/r/e20db248-ed30-cf5d-a37c-b538dceaa5b2@gmail.com Signed-off-by: Greg Kroah-Hartman --- include/linux/sysfs.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include') diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index d76a1ddf83a3..a12556a4b93a 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -162,6 +162,12 @@ static const struct attribute_group _name##_group = { \ }; \ __ATTRIBUTE_GROUPS(_name) +#define BIN_ATTRIBUTE_GROUPS(_name) \ +static const struct attribute_group _name##_group = { \ + .bin_attrs = _name##_attrs, \ +}; \ +__ATTRIBUTE_GROUPS(_name) + struct file; struct vm_area_struct; struct address_space; -- cgit v1.2.3 From 603e4922f1c81fc2ed3a87b4f91a8d3aafc7e093 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 31 May 2021 10:25:26 +0300 Subject: remove the raw driver The raw driver used to provide direct unbuffered access to block devices before O_DIRECT was invented. It has been obsolete for more than a decade. Acked-by: Greg Kroah-Hartman Acked-by: Arnd Bergmann Link: https://lore.kernel.org/lkml/Pine.LNX.4.64.0703180754060.6605@CPE00045a9c397f-CM001225dbafb6/ Signed-off-by: Christoph Hellwig Link: https://lore.kernel.org/r/20210531072526.97052-1-hch@lst.de Signed-off-by: Greg Kroah-Hartman --- drivers/char/Kconfig | 21 --- drivers/char/Makefile | 1 - drivers/char/mem.c | 1 - drivers/char/raw.c | 362 ----------------------------------------------- fs/block_dev.c | 6 +- include/linux/fs.h | 3 - include/uapi/linux/raw.h | 17 --- 7 files changed, 2 insertions(+), 409 deletions(-) delete mode 100644 drivers/char/raw.c delete mode 100644 include/uapi/linux/raw.h (limited to 'include') diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index b151e0fcdeb5..8e516aad632b 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -357,27 +357,6 @@ config NVRAM To compile this driver as a module, choose M here: the module will be called nvram. -config RAW_DRIVER - tristate "RAW driver (/dev/raw/rawN)" - depends on BLOCK - help - The raw driver permits block devices to be bound to /dev/raw/rawN. - Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O. - See the raw(8) manpage for more details. - - Applications should preferably open the device (eg /dev/hda1) - with the O_DIRECT flag. - -config MAX_RAW_DEVS - int "Maximum number of RAW devices to support (1-65536)" - depends on RAW_DRIVER - range 1 65536 - default "256" - help - The maximum number of RAW devices that are supported. - Default is 256. Increase this number in case you need lots of - raw devices. - config DEVPORT bool "/dev/port character device" depends on ISA || PCI diff --git a/drivers/char/Makefile b/drivers/char/Makefile index c7e4fc733a37..264eb398fdd4 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -8,7 +8,6 @@ obj-$(CONFIG_TTY_PRINTK) += ttyprintk.o obj-y += misc.o obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o obj-$(CONFIG_VIRTIO_CONSOLE) += virtio_console.o -obj-$(CONFIG_RAW_DRIVER) += raw.o obj-$(CONFIG_MSPEC) += mspec.o obj-$(CONFIG_UV_MMTIMER) += uv_mmtimer.o obj-$(CONFIG_IBM_BSR) += bsr.o diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 15dc54fa1d47..1c596b5cdb27 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/char/raw.c b/drivers/char/raw.c deleted file mode 100644 index 5d52a1f4738c..000000000000 --- a/drivers/char/raw.c +++ /dev/null @@ -1,362 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * linux/drivers/char/raw.c - * - * Front-end raw character devices. These can be bound to any block - * devices to provide genuine Unix raw character device semantics. - * - * We reserve minor number 0 for a control interface. ioctl()s on this - * device are used to bind the other minor numbers to block devices. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -struct raw_device_data { - dev_t binding; - struct block_device *bdev; - int inuse; -}; - -static struct class *raw_class; -static struct raw_device_data *raw_devices; -static DEFINE_MUTEX(raw_mutex); -static const struct file_operations raw_ctl_fops; /* forward declaration */ - -static int max_raw_minors = CONFIG_MAX_RAW_DEVS; - -module_param(max_raw_minors, int, 0); -MODULE_PARM_DESC(max_raw_minors, "Maximum number of raw devices (1-65536)"); - -/* - * Open/close code for raw IO. - * - * We just rewrite the i_mapping for the /dev/raw/rawN file descriptor to - * point at the blockdev's address_space and set the file handle to use - * O_DIRECT. - * - * Set the device's soft blocksize to the minimum possible. This gives the - * finest possible alignment and has no adverse impact on performance. - */ -static int raw_open(struct inode *inode, struct file *filp) -{ - const int minor = iminor(inode); - struct block_device *bdev; - int err; - - if (minor == 0) { /* It is the control device */ - filp->f_op = &raw_ctl_fops; - return 0; - } - - pr_warn_ratelimited( - "process %s (pid %d) is using the deprecated raw device\n" - "support will be removed in Linux 5.14.\n", - current->comm, current->pid); - - mutex_lock(&raw_mutex); - - /* - * All we need to do on open is check that the device is bound. - */ - err = -ENODEV; - if (!raw_devices[minor].binding) - goto out; - bdev = blkdev_get_by_dev(raw_devices[minor].binding, - filp->f_mode | FMODE_EXCL, raw_open); - if (IS_ERR(bdev)) { - err = PTR_ERR(bdev); - goto out; - } - err = set_blocksize(bdev, bdev_logical_block_size(bdev)); - if (err) - goto out1; - filp->f_flags |= O_DIRECT; - filp->f_mapping = bdev->bd_inode->i_mapping; - if (++raw_devices[minor].inuse == 1) - file_inode(filp)->i_mapping = - bdev->bd_inode->i_mapping; - filp->private_data = bdev; - raw_devices[minor].bdev = bdev; - mutex_unlock(&raw_mutex); - return 0; - -out1: - blkdev_put(bdev, filp->f_mode | FMODE_EXCL); -out: - mutex_unlock(&raw_mutex); - return err; -} - -/* - * When the final fd which refers to this character-special node is closed, we - * make its ->mapping point back at its own i_data. - */ -static int raw_release(struct inode *inode, struct file *filp) -{ - const int minor= iminor(inode); - struct block_device *bdev; - - mutex_lock(&raw_mutex); - bdev = raw_devices[minor].bdev; - if (--raw_devices[minor].inuse == 0) - /* Here inode->i_mapping == bdev->bd_inode->i_mapping */ - inode->i_mapping = &inode->i_data; - mutex_unlock(&raw_mutex); - - blkdev_put(bdev, filp->f_mode | FMODE_EXCL); - return 0; -} - -/* - * Forward ioctls to the underlying block device. - */ -static long -raw_ioctl(struct file *filp, unsigned int command, unsigned long arg) -{ - struct block_device *bdev = filp->private_data; - return blkdev_ioctl(bdev, 0, command, arg); -} - -static int bind_set(int number, u64 major, u64 minor) -{ - dev_t dev = MKDEV(major, minor); - dev_t raw = MKDEV(RAW_MAJOR, number); - struct raw_device_data *rawdev; - int err = 0; - - if (number <= 0 || number >= max_raw_minors) - return -EINVAL; - - if (MAJOR(dev) != major || MINOR(dev) != minor) - return -EINVAL; - - rawdev = &raw_devices[number]; - - /* - * This is like making block devices, so demand the - * same capability - */ - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - /* - * For now, we don't need to check that the underlying - * block device is present or not: we can do that when - * the raw device is opened. Just check that the - * major/minor numbers make sense. - */ - - if (MAJOR(dev) == 0 && dev != 0) - return -EINVAL; - - mutex_lock(&raw_mutex); - if (rawdev->inuse) { - mutex_unlock(&raw_mutex); - return -EBUSY; - } - if (rawdev->binding) - module_put(THIS_MODULE); - - rawdev->binding = dev; - if (!dev) { - /* unbind */ - device_destroy(raw_class, raw); - } else { - __module_get(THIS_MODULE); - device_destroy(raw_class, raw); - device_create(raw_class, NULL, raw, NULL, "raw%d", number); - } - mutex_unlock(&raw_mutex); - return err; -} - -static int bind_get(int number, dev_t *dev) -{ - if (number <= 0 || number >= max_raw_minors) - return -EINVAL; - *dev = raw_devices[number].binding; - return 0; -} - -/* - * Deal with ioctls against the raw-device control interface, to bind - * and unbind other raw devices. - */ -static long raw_ctl_ioctl(struct file *filp, unsigned int command, - unsigned long arg) -{ - struct raw_config_request rq; - dev_t dev; - int err; - - switch (command) { - case RAW_SETBIND: - if (copy_from_user(&rq, (void __user *) arg, sizeof(rq))) - return -EFAULT; - - return bind_set(rq.raw_minor, rq.block_major, rq.block_minor); - - case RAW_GETBIND: - if (copy_from_user(&rq, (void __user *) arg, sizeof(rq))) - return -EFAULT; - - err = bind_get(rq.raw_minor, &dev); - if (err) - return err; - - rq.block_major = MAJOR(dev); - rq.block_minor = MINOR(dev); - - if (copy_to_user((void __user *)arg, &rq, sizeof(rq))) - return -EFAULT; - - return 0; - } - - return -EINVAL; -} - -#ifdef CONFIG_COMPAT -struct raw32_config_request { - compat_int_t raw_minor; - compat_u64 block_major; - compat_u64 block_minor; -}; - -static long raw_ctl_compat_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - struct raw32_config_request __user *user_req = compat_ptr(arg); - struct raw32_config_request rq; - dev_t dev; - int err = 0; - - switch (cmd) { - case RAW_SETBIND: - if (copy_from_user(&rq, user_req, sizeof(rq))) - return -EFAULT; - - return bind_set(rq.raw_minor, rq.block_major, rq.block_minor); - - case RAW_GETBIND: - if (copy_from_user(&rq, user_req, sizeof(rq))) - return -EFAULT; - - err = bind_get(rq.raw_minor, &dev); - if (err) - return err; - - rq.block_major = MAJOR(dev); - rq.block_minor = MINOR(dev); - - if (copy_to_user(user_req, &rq, sizeof(rq))) - return -EFAULT; - - return 0; - } - - return -EINVAL; -} -#endif - -static const struct file_operations raw_fops = { - .read_iter = blkdev_read_iter, - .write_iter = blkdev_write_iter, - .fsync = blkdev_fsync, - .open = raw_open, - .release = raw_release, - .unlocked_ioctl = raw_ioctl, - .llseek = default_llseek, - .owner = THIS_MODULE, -}; - -static const struct file_operations raw_ctl_fops = { - .unlocked_ioctl = raw_ctl_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = raw_ctl_compat_ioctl, -#endif - .open = raw_open, - .owner = THIS_MODULE, - .llseek = noop_llseek, -}; - -static struct cdev raw_cdev; - -static char *raw_devnode(struct device *dev, umode_t *mode) -{ - return kasprintf(GFP_KERNEL, "raw/%s", dev_name(dev)); -} - -static int __init raw_init(void) -{ - dev_t dev = MKDEV(RAW_MAJOR, 0); - int ret; - - if (max_raw_minors < 1 || max_raw_minors > 65536) { - pr_warn("raw: invalid max_raw_minors (must be between 1 and 65536), using %d\n", - CONFIG_MAX_RAW_DEVS); - max_raw_minors = CONFIG_MAX_RAW_DEVS; - } - - raw_devices = vzalloc(array_size(max_raw_minors, - sizeof(struct raw_device_data))); - if (!raw_devices) { - printk(KERN_ERR "Not enough memory for raw device structures\n"); - ret = -ENOMEM; - goto error; - } - - ret = register_chrdev_region(dev, max_raw_minors, "raw"); - if (ret) - goto error; - - cdev_init(&raw_cdev, &raw_fops); - ret = cdev_add(&raw_cdev, dev, max_raw_minors); - if (ret) - goto error_region; - raw_class = class_create(THIS_MODULE, "raw"); - if (IS_ERR(raw_class)) { - printk(KERN_ERR "Error creating raw class.\n"); - cdev_del(&raw_cdev); - ret = PTR_ERR(raw_class); - goto error_region; - } - raw_class->devnode = raw_devnode; - device_create(raw_class, NULL, MKDEV(RAW_MAJOR, 0), NULL, "rawctl"); - - return 0; - -error_region: - unregister_chrdev_region(dev, max_raw_minors); -error: - vfree(raw_devices); - return ret; -} - -static void __exit raw_exit(void) -{ - device_destroy(raw_class, MKDEV(RAW_MAJOR, 0)); - class_destroy(raw_class); - cdev_del(&raw_cdev); - unregister_chrdev_region(MKDEV(RAW_MAJOR, 0), max_raw_minors); -} - -module_init(raw_init); -module_exit(raw_exit); -MODULE_LICENSE("GPL"); diff --git a/fs/block_dev.c b/fs/block_dev.c index 6cc4d4cfe0c2..15c448eb8226 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1669,7 +1669,7 @@ static long block_ioctl(struct file *file, unsigned cmd, unsigned long arg) * Does not take i_mutex for the write and thus is not for general purpose * use. */ -ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from) +static ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from) { struct file *file = iocb->ki_filp; struct inode *bd_inode = bdev_file_inode(file); @@ -1707,9 +1707,8 @@ ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from) blk_finish_plug(&plug); return ret; } -EXPORT_SYMBOL_GPL(blkdev_write_iter); -ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to) +static ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to) { struct file *file = iocb->ki_filp; struct inode *bd_inode = bdev_file_inode(file); @@ -1731,7 +1730,6 @@ ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to) iov_iter_reexpand(to, iov_iter_count(to) + shorted); return ret; } -EXPORT_SYMBOL_GPL(blkdev_read_iter); /* * Try to release a page associated with block device when the system diff --git a/include/linux/fs.h b/include/linux/fs.h index c3c88fdb9b2a..8652ed7cdce8 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -3242,11 +3242,8 @@ ssize_t vfs_iocb_iter_write(struct file *file, struct kiocb *iocb, struct iov_iter *iter); /* fs/block_dev.c */ -extern ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to); -extern ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from); extern int blkdev_fsync(struct file *filp, loff_t start, loff_t end, int datasync); -extern void block_sync_page(struct page *page); /* fs/splice.c */ extern ssize_t generic_file_splice_read(struct file *, loff_t *, diff --git a/include/uapi/linux/raw.h b/include/uapi/linux/raw.h deleted file mode 100644 index 47874919d0b9..000000000000 --- a/include/uapi/linux/raw.h +++ /dev/null @@ -1,17 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef __LINUX_RAW_H -#define __LINUX_RAW_H - -#include - -#define RAW_SETBIND _IO( 0xac, 0 ) -#define RAW_GETBIND _IO( 0xac, 1 ) - -struct raw_config_request -{ - int raw_minor; - __u64 block_major; - __u64 block_minor; -}; - -#endif /* __LINUX_RAW_H */ -- cgit v1.2.3 From e7555cf6c263d95d2bb2bddb5bb57c240f0d608a Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Tue, 8 Jun 2021 14:23:45 -0700 Subject: fpga: bridge: change FPGA indirect article to an Change use of 'a fpga' to 'an fpga' Signed-off-by: Tom Rix Link: https://lore.kernel.org/r/20210608212350.3029742-8-trix@redhat.com Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/fpga-bridge.c | 22 +++++++++++----------- include/linux/fpga/fpga-bridge.h | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/drivers/fpga/fpga-bridge.c b/drivers/fpga/fpga-bridge.c index e9266b2a357f..eeb71e38efa7 100644 --- a/drivers/fpga/fpga-bridge.c +++ b/drivers/fpga/fpga-bridge.c @@ -85,14 +85,14 @@ err_dev: } /** - * of_fpga_bridge_get - get an exclusive reference to a fpga bridge + * of_fpga_bridge_get - get an exclusive reference to an fpga bridge * - * @np: node pointer of a FPGA bridge + * @np: node pointer of an FPGA bridge * @info: fpga image specific information * * Return fpga_bridge struct if successful. * Return -EBUSY if someone already has a reference to the bridge. - * Return -ENODEV if @np is not a FPGA Bridge. + * Return -ENODEV if @np is not an FPGA Bridge. */ struct fpga_bridge *of_fpga_bridge_get(struct device_node *np, struct fpga_image_info *info) @@ -113,11 +113,11 @@ static int fpga_bridge_dev_match(struct device *dev, const void *data) } /** - * fpga_bridge_get - get an exclusive reference to a fpga bridge + * fpga_bridge_get - get an exclusive reference to an fpga bridge * @dev: parent device that fpga bridge was registered with * @info: fpga manager info * - * Given a device, get an exclusive reference to a fpga bridge. + * Given a device, get an exclusive reference to an fpga bridge. * * Return: fpga bridge struct or IS_ERR() condition containing error code. */ @@ -224,7 +224,7 @@ EXPORT_SYMBOL_GPL(fpga_bridges_put); /** * of_fpga_bridge_get_to_list - get a bridge, add it to a list * - * @np: node pointer of a FPGA bridge + * @np: node pointer of an FPGA bridge * @info: fpga image specific information * @bridge_list: list of FPGA bridges * @@ -373,7 +373,7 @@ error_kfree: EXPORT_SYMBOL_GPL(fpga_bridge_create); /** - * fpga_bridge_free - free a fpga bridge created by fpga_bridge_create() + * fpga_bridge_free - free an fpga bridge created by fpga_bridge_create() * @bridge: FPGA bridge struct */ void fpga_bridge_free(struct fpga_bridge *bridge) @@ -397,7 +397,7 @@ static void devm_fpga_bridge_release(struct device *dev, void *res) * @br_ops: pointer to structure of fpga bridge ops * @priv: FPGA bridge private data * - * This function is intended for use in a FPGA bridge driver's probe function. + * This function is intended for use in an FPGA bridge driver's probe function. * After the bridge driver creates the struct with devm_fpga_bridge_create(), it * should register the bridge with fpga_bridge_register(). The bridge driver's * remove function should call fpga_bridge_unregister(). The bridge struct @@ -430,7 +430,7 @@ struct fpga_bridge EXPORT_SYMBOL_GPL(devm_fpga_bridge_create); /** - * fpga_bridge_register - register a FPGA bridge + * fpga_bridge_register - register an FPGA bridge * * @bridge: FPGA bridge struct * @@ -454,11 +454,11 @@ int fpga_bridge_register(struct fpga_bridge *bridge) EXPORT_SYMBOL_GPL(fpga_bridge_register); /** - * fpga_bridge_unregister - unregister a FPGA bridge + * fpga_bridge_unregister - unregister an FPGA bridge * * @bridge: FPGA bridge struct * - * This function is intended for use in a FPGA bridge driver's remove function. + * This function is intended for use in an FPGA bridge driver's remove function. */ void fpga_bridge_unregister(struct fpga_bridge *bridge) { diff --git a/include/linux/fpga/fpga-bridge.h b/include/linux/fpga/fpga-bridge.h index 817600a32c93..6c3c28806ff1 100644 --- a/include/linux/fpga/fpga-bridge.h +++ b/include/linux/fpga/fpga-bridge.h @@ -11,7 +11,7 @@ struct fpga_bridge; /** * struct fpga_bridge_ops - ops for low level FPGA bridge drivers * @enable_show: returns the FPGA bridge's status - * @enable_set: set a FPGA bridge as enabled or disabled + * @enable_set: set an FPGA bridge as enabled or disabled * @fpga_bridge_remove: set FPGA into a specific state during driver remove * @groups: optional attribute groups. */ -- cgit v1.2.3 From 895ec9c09aa77e9f0129576995cb21191d3958f1 Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Tue, 8 Jun 2021 14:23:46 -0700 Subject: fpga-mgr: change FPGA indirect article to an Change use of 'a fpga' to 'an fpga' Signed-off-by: Tom Rix Link: https://lore.kernel.org/r/20210608212350.3029742-9-trix@redhat.com Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/fpga-mgr.c | 22 +++++++++++----------- include/linux/fpga/fpga-mgr.h | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c index b85bc47c91a9..ae21202105af 100644 --- a/drivers/fpga/fpga-mgr.c +++ b/drivers/fpga/fpga-mgr.c @@ -26,7 +26,7 @@ struct fpga_mgr_devres { }; /** - * fpga_image_info_alloc - Allocate a FPGA image info struct + * fpga_image_info_alloc - Allocate an FPGA image info struct * @dev: owning device * * Return: struct fpga_image_info or NULL @@ -50,7 +50,7 @@ struct fpga_image_info *fpga_image_info_alloc(struct device *dev) EXPORT_SYMBOL_GPL(fpga_image_info_alloc); /** - * fpga_image_info_free - Free a FPGA image info struct + * fpga_image_info_free - Free an FPGA image info struct * @info: FPGA image info struct to free */ void fpga_image_info_free(struct fpga_image_info *info) @@ -470,7 +470,7 @@ static int fpga_mgr_dev_match(struct device *dev, const void *data) } /** - * fpga_mgr_get - Given a device, get a reference to a fpga mgr. + * fpga_mgr_get - Given a device, get a reference to an fpga mgr. * @dev: parent device that fpga mgr was registered with * * Return: fpga manager struct or IS_ERR() condition containing error code. @@ -487,7 +487,7 @@ struct fpga_manager *fpga_mgr_get(struct device *dev) EXPORT_SYMBOL_GPL(fpga_mgr_get); /** - * of_fpga_mgr_get - Given a device node, get a reference to a fpga mgr. + * of_fpga_mgr_get - Given a device node, get a reference to an fpga mgr. * * @node: device node * @@ -506,7 +506,7 @@ struct fpga_manager *of_fpga_mgr_get(struct device_node *node) EXPORT_SYMBOL_GPL(of_fpga_mgr_get); /** - * fpga_mgr_put - release a reference to a fpga manager + * fpga_mgr_put - release a reference to an fpga manager * @mgr: fpga manager structure */ void fpga_mgr_put(struct fpga_manager *mgr) @@ -550,7 +550,7 @@ void fpga_mgr_unlock(struct fpga_manager *mgr) EXPORT_SYMBOL_GPL(fpga_mgr_unlock); /** - * fpga_mgr_create - create and initialize a FPGA manager struct + * fpga_mgr_create - create and initialize an FPGA manager struct * @dev: fpga manager device from pdev * @name: fpga manager name * @mops: pointer to structure of fpga manager ops @@ -617,7 +617,7 @@ error_kfree: EXPORT_SYMBOL_GPL(fpga_mgr_create); /** - * fpga_mgr_free - free a FPGA manager created with fpga_mgr_create() + * fpga_mgr_free - free an FPGA manager created with fpga_mgr_create() * @mgr: fpga manager struct */ void fpga_mgr_free(struct fpga_manager *mgr) @@ -641,7 +641,7 @@ static void devm_fpga_mgr_release(struct device *dev, void *res) * @mops: pointer to structure of fpga manager ops * @priv: fpga manager private data * - * This function is intended for use in a FPGA manager driver's probe function. + * This function is intended for use in an FPGA manager driver's probe function. * After the manager driver creates the manager struct with * devm_fpga_mgr_create(), it should register it with fpga_mgr_register(). The * manager driver's remove function should call fpga_mgr_unregister(). The @@ -674,7 +674,7 @@ struct fpga_manager *devm_fpga_mgr_create(struct device *dev, const char *name, EXPORT_SYMBOL_GPL(devm_fpga_mgr_create); /** - * fpga_mgr_register - register a FPGA manager + * fpga_mgr_register - register an FPGA manager * @mgr: fpga manager struct * * Return: 0 on success, negative error code otherwise. @@ -706,10 +706,10 @@ error_device: EXPORT_SYMBOL_GPL(fpga_mgr_register); /** - * fpga_mgr_unregister - unregister a FPGA manager + * fpga_mgr_unregister - unregister an FPGA manager * @mgr: fpga manager struct * - * This function is intended for use in a FPGA manager driver's remove function. + * This function is intended for use in an FPGA manager driver's remove function. */ void fpga_mgr_unregister(struct fpga_manager *mgr) { diff --git a/include/linux/fpga/fpga-mgr.h b/include/linux/fpga/fpga-mgr.h index 2bc3030a69e5..ec2cd8bfceb0 100644 --- a/include/linux/fpga/fpga-mgr.h +++ b/include/linux/fpga/fpga-mgr.h @@ -75,7 +75,7 @@ enum fpga_mgr_states { #define FPGA_MGR_COMPRESSED_BITSTREAM BIT(4) /** - * struct fpga_image_info - information specific to a FPGA image + * struct fpga_image_info - information specific to an FPGA image * @flags: boolean flags as defined above * @enable_timeout_us: maximum time to enable traffic through bridge (uSec) * @disable_timeout_us: maximum time to disable traffic through bridge (uSec) -- cgit v1.2.3 From fd307a4ad332ef50be5569c92490219e7cd84ce5 Mon Sep 17 00:00:00 2001 From: Jiri Prchal Date: Fri, 11 Jun 2021 11:45:58 +0200 Subject: nvmem: prepare basics for FRAM support Added enum and string for FRAM (ferroelectric RAM) to expose it as file named "fram". Added documentation of sysfs file. Signed-off-by: Jiri Prchal Link: https://lore.kernel.org/r/20210611094601.95131-2-jiri.prchal@aksignal.cz Signed-off-by: Greg Kroah-Hartman --- Documentation/ABI/testing/sysfs-class-spi-eeprom | 19 +++ Documentation/devicetree/bindings/eeprom/at25.yaml | 31 +++- drivers/misc/eeprom/Kconfig | 5 +- drivers/misc/eeprom/at25.c | 161 +++++++++++++++++---- drivers/nvmem/core.c | 4 + include/linux/nvmem-provider.h | 1 + 6 files changed, 183 insertions(+), 38 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-class-spi-eeprom (limited to 'include') diff --git a/Documentation/ABI/testing/sysfs-class-spi-eeprom b/Documentation/ABI/testing/sysfs-class-spi-eeprom new file mode 100644 index 000000000000..1ff757982079 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-spi-eeprom @@ -0,0 +1,19 @@ +What: /sys/class/spi_master/spi/spi./fram +Date: June 2021 +KernelVersion: 5.14 +Contact: Jiri Prchal +Description: + Contains the FRAM binary data. Same as EEPROM, just another file + name to indicate that it employs ferroelectric process. + It performs write operations at bus speed - no write delays. + +What: /sys/class/spi_master/spi/spi./sernum +Date: May 2021 +KernelVersion: 5.14 +Contact: Jiri Prchal +Description: + Contains the serial number of the Cypress FRAM (FM25VN) if it is + present. It will be displayed as a 8 byte hex string, as read + from the device. + + This is a read-only attribute. diff --git a/Documentation/devicetree/bindings/eeprom/at25.yaml b/Documentation/devicetree/bindings/eeprom/at25.yaml index 6a2dc8b3ed14..fbf99e346966 100644 --- a/Documentation/devicetree/bindings/eeprom/at25.yaml +++ b/Documentation/devicetree/bindings/eeprom/at25.yaml @@ -4,14 +4,16 @@ $id: "http://devicetree.org/schemas/eeprom/at25.yaml#" $schema: "http://devicetree.org/meta-schemas/core.yaml#" -title: SPI EEPROMs compatible with Atmel's AT25 +title: SPI EEPROMs or FRAMs compatible with Atmel's AT25 maintainers: - Christian Eggers properties: $nodename: - pattern: "^eeprom@[0-9a-f]{1,2}$" + anyOf: + - pattern: "^eeprom@[0-9a-f]{1,2}$" + - pattern: "^fram@[0-9a-f]{1,2}$" # There are multiple known vendors who manufacture EEPROM chips compatible # with Atmel's AT25. The compatible string requires two items where the @@ -31,6 +33,7 @@ properties: - microchip,25lc040 - st,m95m02 - st,m95256 + - cypress,fm25 - const: atmel,at25 @@ -47,7 +50,7 @@ properties: $ref: /schemas/types.yaml#/definitions/uint32 enum: [1, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072] description: - Size of the eeprom page. + Size of the eeprom page. FRAMs don't have pages. size: $ref: /schemas/types.yaml#/definitions/uint32 @@ -100,9 +103,19 @@ required: - compatible - reg - spi-max-frequency - - pagesize - - size - - address-width + +allOf: + - if: + properties: + compatible: + not: + contains: + const: cypress,fm25 + then: + required: + - pagesize + - size + - address-width additionalProperties: false @@ -125,4 +138,10 @@ examples: size = <32768>; address-width = <16>; }; + + fram@1 { + compatible = "cypress,fm25", "atmel,at25"; + reg = <1>; + spi-max-frequency = <40000000>; + }; }; diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig index 0f791bfdc1f5..f0a7531f354c 100644 --- a/drivers/misc/eeprom/Kconfig +++ b/drivers/misc/eeprom/Kconfig @@ -32,12 +32,13 @@ config EEPROM_AT24 will be called at24. config EEPROM_AT25 - tristate "SPI EEPROMs from most vendors" + tristate "SPI EEPROMs (FRAMs) from most vendors" depends on SPI && SYSFS select NVMEM select NVMEM_SYSFS help - Enable this driver to get read/write support to most SPI EEPROMs, + Enable this driver to get read/write support to most SPI EEPROMs + and Cypress FRAMs, after you configure the board init code to know about each eeprom on your target board. diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c index b76e4901b4a4..6e26de68a001 100644 --- a/drivers/misc/eeprom/at25.c +++ b/drivers/misc/eeprom/at25.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* * at25.c -- support most SPI EEPROMs, such as Atmel AT25 models + * and Cypress FRAMs FM25 models * * Copyright (C) 2006 David Brownell */ @@ -16,6 +17,9 @@ #include #include #include +#include +#include +#include /* * NOTE: this is an *EEPROM* driver. The vagaries of product naming @@ -27,6 +31,7 @@ * AT25M02, AT25128B */ +#define FM25_SN_LEN 8 /* serial number length */ struct at25_data { struct spi_device *spi; struct mutex lock; @@ -34,6 +39,7 @@ struct at25_data { unsigned addrlen; struct nvmem_config nvmem_config; struct nvmem_device *nvmem; + u8 sernum[FM25_SN_LEN]; }; #define AT25_WREN 0x06 /* latch the write enable */ @@ -42,6 +48,9 @@ struct at25_data { #define AT25_WRSR 0x01 /* write status register */ #define AT25_READ 0x03 /* read byte(s) */ #define AT25_WRITE 0x02 /* write byte(s)/sector */ +#define FM25_SLEEP 0xb9 /* enter sleep mode */ +#define FM25_RDID 0x9f /* read device ID */ +#define FM25_RDSN 0xc3 /* read S/N */ #define AT25_SR_nRDY 0x01 /* nRDY = write-in-progress */ #define AT25_SR_WEN 0x02 /* write enable (latched) */ @@ -51,6 +60,8 @@ struct at25_data { #define AT25_INSTR_BIT3 0x08 /* Additional address bit in instr */ +#define FM25_ID_LEN 9 /* ID length */ + #define EE_MAXADDRLEN 3 /* 24 bit addresses, up to 2 MBytes */ /* Specs often allow 5 msec for a page write, sometimes 20 msec; @@ -58,6 +69,9 @@ struct at25_data { */ #define EE_TIMEOUT 25 +#define IS_EEPROM 0 +#define IS_FRAM 1 + /*-------------------------------------------------------------------------*/ #define io_limit PAGE_SIZE /* bytes */ @@ -129,6 +143,51 @@ static int at25_ee_read(void *priv, unsigned int offset, return status; } +/* + * read extra registers as ID or serial number + */ +static int fm25_aux_read(struct at25_data *at25, u8 *buf, uint8_t command, + int len) +{ + int status; + struct spi_transfer t[2]; + struct spi_message m; + + spi_message_init(&m); + memset(t, 0, sizeof(t)); + + t[0].tx_buf = &command; + t[0].len = 1; + spi_message_add_tail(&t[0], &m); + + t[1].rx_buf = buf; + t[1].len = len; + spi_message_add_tail(&t[1], &m); + + mutex_lock(&at25->lock); + + status = spi_sync(at25->spi, &m); + dev_dbg(&at25->spi->dev, "read %d aux bytes --> %d\n", len, status); + + mutex_unlock(&at25->lock); + return status; +} + +static ssize_t sernum_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct at25_data *at25; + + at25 = dev_get_drvdata(dev); + return sysfs_emit(buf, "%*ph\n", sizeof(at25->sernum), at25->sernum); +} +static DEVICE_ATTR_RO(sernum); + +static struct attribute *sernum_attrs[] = { + &dev_attr_sernum.attr, + NULL, +}; +ATTRIBUTE_GROUPS(sernum); + static int at25_ee_write(void *priv, unsigned int off, void *val, size_t count) { struct at25_data *at25 = priv; @@ -303,34 +362,39 @@ static int at25_fw_to_chip(struct device *dev, struct spi_eeprom *chip) return 0; } +static const struct of_device_id at25_of_match[] = { + { .compatible = "atmel,at25", .data = (const void *)IS_EEPROM }, + { .compatible = "cypress,fm25", .data = (const void *)IS_FRAM }, + { } +}; +MODULE_DEVICE_TABLE(of, at25_of_match); + static int at25_probe(struct spi_device *spi) { struct at25_data *at25 = NULL; struct spi_eeprom chip; int err; int sr; - int addrlen; + u8 id[FM25_ID_LEN]; + u8 sernum[FM25_SN_LEN]; + int i; + const struct of_device_id *match; + int is_fram = 0; + + match = of_match_device(of_match_ptr(at25_of_match), &spi->dev); + if (match) + is_fram = (int)match->data; /* Chip description */ if (!spi->dev.platform_data) { - err = at25_fw_to_chip(&spi->dev, &chip); - if (err) - return err; + if (!is_fram) { + err = at25_fw_to_chip(&spi->dev, &chip); + if (err) + return err; + } } else chip = *(struct spi_eeprom *)spi->dev.platform_data; - /* For now we only support 8/16/24 bit addressing */ - if (chip.flags & EE_ADDR1) - addrlen = 1; - else if (chip.flags & EE_ADDR2) - addrlen = 2; - else if (chip.flags & EE_ADDR3) - addrlen = 3; - else { - dev_dbg(&spi->dev, "unsupported address type\n"); - return -EINVAL; - } - /* Ping the chip ... the status register is pretty portable, * unlike probing manufacturer IDs. We do expect that system * firmware didn't write it in the past few milliseconds! @@ -349,9 +413,51 @@ static int at25_probe(struct spi_device *spi) at25->chip = chip; at25->spi = spi; spi_set_drvdata(spi, at25); - at25->addrlen = addrlen; - at25->nvmem_config.type = NVMEM_TYPE_EEPROM; + if (is_fram) { + /* Get ID of chip */ + fm25_aux_read(at25, id, FM25_RDID, FM25_ID_LEN); + if (id[6] != 0xc2) { + dev_err(&spi->dev, + "Error: no Cypress FRAM (id %02x)\n", id[6]); + return -ENODEV; + } + /* set size found in ID */ + if (id[7] < 0x21 || id[7] > 0x26) { + dev_err(&spi->dev, "Error: unsupported size (id %02x)\n", id[7]); + return -ENODEV; + } + chip.byte_len = int_pow(2, id[7] - 0x21 + 4) * 1024; + + if (at25->chip.byte_len > 64 * 1024) + at25->chip.flags |= EE_ADDR3; + else + at25->chip.flags |= EE_ADDR2; + + if (id[8]) { + fm25_aux_read(at25, sernum, FM25_RDSN, FM25_SN_LEN); + /* swap byte order */ + for (i = 0; i < FM25_SN_LEN; i++) + at25->sernum[i] = sernum[FM25_SN_LEN - 1 - i]; + } + + at25->chip.page_size = PAGE_SIZE; + strncpy(at25->chip.name, "fm25", sizeof(at25->chip.name)); + } + + /* For now we only support 8/16/24 bit addressing */ + if (at25->chip.flags & EE_ADDR1) + at25->addrlen = 1; + else if (at25->chip.flags & EE_ADDR2) + at25->addrlen = 2; + else if (at25->chip.flags & EE_ADDR3) + at25->addrlen = 3; + else { + dev_dbg(&spi->dev, "unsupported address type\n"); + return -EINVAL; + } + + at25->nvmem_config.type = is_fram ? NVMEM_TYPE_FRAM : NVMEM_TYPE_EEPROM; at25->nvmem_config.name = dev_name(&spi->dev); at25->nvmem_config.dev = &spi->dev; at25->nvmem_config.read_only = chip.flags & EE_READONLY; @@ -370,27 +476,22 @@ static int at25_probe(struct spi_device *spi) if (IS_ERR(at25->nvmem)) return PTR_ERR(at25->nvmem); - dev_info(&spi->dev, "%d %s %s eeprom%s, pagesize %u\n", - (chip.byte_len < 1024) ? chip.byte_len : (chip.byte_len / 1024), - (chip.byte_len < 1024) ? "Byte" : "KByte", - at25->chip.name, - (chip.flags & EE_READONLY) ? " (readonly)" : "", - at25->chip.page_size); + dev_info(&spi->dev, "%d %s %s %s%s, pagesize %u\n", + (chip.byte_len < 1024) ? chip.byte_len : (chip.byte_len / 1024), + (chip.byte_len < 1024) ? "Byte" : "KByte", + at25->chip.name, is_fram ? "fram" : "eeprom", + (chip.flags & EE_READONLY) ? " (readonly)" : "", + at25->chip.page_size); return 0; } /*-------------------------------------------------------------------------*/ -static const struct of_device_id at25_of_match[] = { - { .compatible = "atmel,at25", }, - { } -}; -MODULE_DEVICE_TABLE(of, at25_of_match); - static struct spi_driver at25_driver = { .driver = { .name = "at25", .of_match_table = at25_of_match, + .dev_groups = sernum_groups, }, .probe = at25_probe, }; diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index b3c28a2d4c10..4d1c4f83b22f 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -180,6 +180,7 @@ static const char * const nvmem_type_str[] = { [NVMEM_TYPE_EEPROM] = "EEPROM", [NVMEM_TYPE_OTP] = "OTP", [NVMEM_TYPE_BATTERY_BACKED] = "Battery backed", + [NVMEM_TYPE_FRAM] = "FRAM", }; #ifdef CONFIG_DEBUG_LOCK_ALLOC @@ -359,6 +360,9 @@ static int nvmem_sysfs_setup_compat(struct nvmem_device *nvmem, if (!config->base_dev) return -EINVAL; + if (config->type == NVMEM_TYPE_FRAM) + bin_attr_nvmem_eeprom_compat.attr.name = "fram"; + nvmem->eeprom = bin_attr_nvmem_eeprom_compat; nvmem->eeprom.attr.mode = nvmem_bin_attr_get_umode(nvmem); nvmem->eeprom.size = nvmem->size; diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h index e162b757b6d5..890003565761 100644 --- a/include/linux/nvmem-provider.h +++ b/include/linux/nvmem-provider.h @@ -25,6 +25,7 @@ enum nvmem_type { NVMEM_TYPE_EEPROM, NVMEM_TYPE_OTP, NVMEM_TYPE_BATTERY_BACKED, + NVMEM_TYPE_FRAM, }; #define NVMEM_DEVID_NONE (-1) -- cgit v1.2.3 From 29a269c6f54825c643a5c35762a2829ba5be67f6 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 11 May 2021 13:21:32 +0800 Subject: soundwire: intel: move to auxiliary bus Now that the auxiliary_bus exists, there's no reason to use platform devices as children of a PCI device any longer. This patch refactors the code by extending a basic auxiliary device with Intel link-specific structures that need to be passed between controller and link levels. This refactoring is much cleaner with no need for cross-pointers between device and link structures. Note that the auxiliary bus API has separate init and add steps, which requires more attention in the error unwinding paths. The main loop needs to deal with kfree() and auxiliary_device_uninit() for the current iteration before jumping to the common label which releases everything allocated in prior iterations. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Guennadi Liakhovetski Reviewed-by: Ranjani Sridharan Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20210511052132.28150-1-yung-chuan.liao@linux.intel.com Signed-off-by: Vinod Koul --- drivers/soundwire/Kconfig | 1 + drivers/soundwire/intel.c | 56 +++++---- drivers/soundwire/intel.h | 14 ++- drivers/soundwire/intel_init.c | 232 ++++++++++++++++++++++++------------ include/linux/soundwire/sdw_intel.h | 6 +- 5 files changed, 202 insertions(+), 107 deletions(-) (limited to 'include') diff --git a/drivers/soundwire/Kconfig b/drivers/soundwire/Kconfig index 016e74230bb7..2b7795233282 100644 --- a/drivers/soundwire/Kconfig +++ b/drivers/soundwire/Kconfig @@ -25,6 +25,7 @@ config SOUNDWIRE_INTEL tristate "Intel SoundWire Master driver" select SOUNDWIRE_CADENCE select SOUNDWIRE_GENERIC_ALLOCATION + select AUXILIARY_BUS depends on ACPI && SND_SOC help SoundWire Intel Master driver. diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c index fd95f94630b1..c11e3d8cd308 100644 --- a/drivers/soundwire/intel.c +++ b/drivers/soundwire/intel.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include @@ -1327,11 +1327,14 @@ static int intel_init(struct sdw_intel *sdw) } /* - * probe and init + * probe and init (aux_dev_id argument is required by function prototype but not used) */ -static int intel_master_probe(struct platform_device *pdev) +static int intel_link_probe(struct auxiliary_device *auxdev, + const struct auxiliary_device_id *aux_dev_id) + { - struct device *dev = &pdev->dev; + struct device *dev = &auxdev->dev; + struct sdw_intel_link_dev *ldev = auxiliary_dev_to_sdw_intel_link_dev(auxdev); struct sdw_intel *sdw; struct sdw_cdns *cdns; struct sdw_bus *bus; @@ -1344,14 +1347,14 @@ static int intel_master_probe(struct platform_device *pdev) cdns = &sdw->cdns; bus = &cdns->bus; - sdw->instance = pdev->id; - sdw->link_res = dev_get_platdata(dev); + sdw->instance = auxdev->id; + sdw->link_res = &ldev->link_res; cdns->dev = dev; cdns->registers = sdw->link_res->registers; cdns->instance = sdw->instance; cdns->msg_count = 0; - bus->link_id = pdev->id; + bus->link_id = auxdev->id; sdw_cdns_probe(cdns); @@ -1384,10 +1387,10 @@ static int intel_master_probe(struct platform_device *pdev) return 0; } -int intel_master_startup(struct platform_device *pdev) +int intel_link_startup(struct auxiliary_device *auxdev) { struct sdw_cdns_stream_config config; - struct device *dev = &pdev->dev; + struct device *dev = &auxdev->dev; struct sdw_cdns *cdns = dev_get_drvdata(dev); struct sdw_intel *sdw = cdns_to_intel(cdns); struct sdw_bus *bus = &cdns->bus; @@ -1524,9 +1527,9 @@ err_init: return ret; } -static int intel_master_remove(struct platform_device *pdev) +static void intel_link_remove(struct auxiliary_device *auxdev) { - struct device *dev = &pdev->dev; + struct device *dev = &auxdev->dev; struct sdw_cdns *cdns = dev_get_drvdata(dev); struct sdw_intel *sdw = cdns_to_intel(cdns); struct sdw_bus *bus = &cdns->bus; @@ -1542,19 +1545,17 @@ static int intel_master_remove(struct platform_device *pdev) snd_soc_unregister_component(dev); } sdw_bus_master_delete(bus); - - return 0; } -int intel_master_process_wakeen_event(struct platform_device *pdev) +int intel_link_process_wakeen_event(struct auxiliary_device *auxdev) { - struct device *dev = &pdev->dev; + struct device *dev = &auxdev->dev; struct sdw_intel *sdw; struct sdw_bus *bus; void __iomem *shim; u16 wake_sts; - sdw = platform_get_drvdata(pdev); + sdw = dev_get_drvdata(dev); bus = &sdw->cdns.bus; if (bus->prop.hw_disabled) { @@ -1976,17 +1977,22 @@ static const struct dev_pm_ops intel_pm = { SET_RUNTIME_PM_OPS(intel_suspend_runtime, intel_resume_runtime, NULL) }; -static struct platform_driver sdw_intel_drv = { - .probe = intel_master_probe, - .remove = intel_master_remove, +static const struct auxiliary_device_id intel_link_id_table[] = { + { .name = "soundwire_intel.link" }, + {}, +}; +MODULE_DEVICE_TABLE(auxiliary, intel_link_id_table); + +static struct auxiliary_driver sdw_intel_drv = { + .probe = intel_link_probe, + .remove = intel_link_remove, .driver = { - .name = "intel-sdw", + /* auxiliary_driver_register() sets .name to be the modname */ .pm = &intel_pm, - } + }, + .id_table = intel_link_id_table }; - -module_platform_driver(sdw_intel_drv); +module_auxiliary_driver(sdw_intel_drv); MODULE_LICENSE("Dual BSD/GPL"); -MODULE_ALIAS("platform:intel-sdw"); -MODULE_DESCRIPTION("Intel Soundwire Master Driver"); +MODULE_DESCRIPTION("Intel Soundwire Link Driver"); diff --git a/drivers/soundwire/intel.h b/drivers/soundwire/intel.h index 06bac8ba14e9..0b47b148da3f 100644 --- a/drivers/soundwire/intel.h +++ b/drivers/soundwire/intel.h @@ -7,7 +7,6 @@ /** * struct sdw_intel_link_res - Soundwire Intel link resource structure, * typically populated by the controller driver. - * @pdev: platform_device * @mmio_base: mmio base of SoundWire registers * @registers: Link IO registers base * @shim: Audio shim pointer @@ -23,7 +22,6 @@ * @list: used to walk-through all masters exposed by the same controller */ struct sdw_intel_link_res { - struct platform_device *pdev; void __iomem *mmio_base; /* not strictly needed, useful for debug */ void __iomem *registers; void __iomem *shim; @@ -48,7 +46,15 @@ struct sdw_intel { #endif }; -int intel_master_startup(struct platform_device *pdev); -int intel_master_process_wakeen_event(struct platform_device *pdev); +int intel_link_startup(struct auxiliary_device *auxdev); +int intel_link_process_wakeen_event(struct auxiliary_device *auxdev); + +struct sdw_intel_link_dev { + struct auxiliary_device auxdev; + struct sdw_intel_link_res link_res; +}; + +#define auxiliary_dev_to_sdw_intel_link_dev(auxiliary_dev) \ + container_of(auxiliary_dev, struct sdw_intel_link_dev, auxdev) #endif /* __SDW_INTEL_LOCAL_H */ diff --git a/drivers/soundwire/intel_init.c b/drivers/soundwire/intel_init.c index 30ce95ec2d70..9e283bef53d2 100644 --- a/drivers/soundwire/intel_init.c +++ b/drivers/soundwire/intel_init.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include "cadence_master.h" @@ -24,28 +24,108 @@ #define SDW_LINK_BASE 0x30000 #define SDW_LINK_SIZE 0x10000 +static void intel_link_dev_release(struct device *dev) +{ + struct auxiliary_device *auxdev = to_auxiliary_dev(dev); + struct sdw_intel_link_dev *ldev = auxiliary_dev_to_sdw_intel_link_dev(auxdev); + + kfree(ldev); +} + +/* alloc, init and add link devices */ +static struct sdw_intel_link_dev *intel_link_dev_register(struct sdw_intel_res *res, + struct sdw_intel_ctx *ctx, + struct fwnode_handle *fwnode, + const char *name, + int link_id) +{ + struct sdw_intel_link_dev *ldev; + struct sdw_intel_link_res *link; + struct auxiliary_device *auxdev; + int ret; + + ldev = kzalloc(sizeof(*ldev), GFP_KERNEL); + if (!ldev) + return ERR_PTR(-ENOMEM); + + auxdev = &ldev->auxdev; + auxdev->name = name; + auxdev->dev.parent = res->parent; + auxdev->dev.fwnode = fwnode; + auxdev->dev.release = intel_link_dev_release; + + /* we don't use an IDA since we already have a link ID */ + auxdev->id = link_id; + + /* + * keep a handle on the allocated memory, to be used in all other functions. + * Since the same pattern is used to skip links that are not enabled, there is + * no need to check if ctx->ldev[i] is NULL later on. + */ + ctx->ldev[link_id] = ldev; + + /* Add link information used in the driver probe */ + link = &ldev->link_res; + link->mmio_base = res->mmio_base; + link->registers = res->mmio_base + SDW_LINK_BASE + + (SDW_LINK_SIZE * link_id); + link->shim = res->mmio_base + SDW_SHIM_BASE; + link->alh = res->mmio_base + SDW_ALH_BASE; + + link->ops = res->ops; + link->dev = res->dev; + + link->clock_stop_quirks = res->clock_stop_quirks; + link->shim_lock = &ctx->shim_lock; + link->shim_mask = &ctx->shim_mask; + link->link_mask = ctx->link_mask; + + /* now follow the two-step init/add sequence */ + ret = auxiliary_device_init(auxdev); + if (ret < 0) { + dev_err(res->parent, "failed to initialize link dev %s link_id %d\n", + name, link_id); + kfree(ldev); + return ERR_PTR(ret); + } + + ret = auxiliary_device_add(&ldev->auxdev); + if (ret < 0) { + dev_err(res->parent, "failed to add link dev %s link_id %d\n", + ldev->auxdev.name, link_id); + /* ldev will be freed with the put_device() and .release sequence */ + auxiliary_device_uninit(&ldev->auxdev); + return ERR_PTR(ret); + } + + return ldev; +} + +static void intel_link_dev_unregister(struct sdw_intel_link_dev *ldev) +{ + auxiliary_device_delete(&ldev->auxdev); + auxiliary_device_uninit(&ldev->auxdev); +} + static int sdw_intel_cleanup(struct sdw_intel_ctx *ctx) { - struct sdw_intel_link_res *link = ctx->links; + struct sdw_intel_link_dev *ldev; u32 link_mask; int i; - if (!link) - return 0; - link_mask = ctx->link_mask; - for (i = 0; i < ctx->count; i++, link++) { + for (i = 0; i < ctx->count; i++) { if (!(link_mask & BIT(i))) continue; - if (link->pdev) { - pm_runtime_disable(&link->pdev->dev); - platform_device_unregister(link->pdev); - } + ldev = ctx->ldev[i]; - if (!link->clock_stop_quirks) - pm_runtime_put_noidle(link->dev); + pm_runtime_disable(&ldev->auxdev.dev); + if (!ldev->link_res.clock_stop_quirks) + pm_runtime_put_noidle(ldev->link_res.dev); + + intel_link_dev_unregister(ldev); } return 0; @@ -91,9 +171,8 @@ EXPORT_SYMBOL_NS(sdw_intel_thread, SOUNDWIRE_INTEL_INIT); static struct sdw_intel_ctx *sdw_intel_probe_controller(struct sdw_intel_res *res) { - struct platform_device_info pdevinfo; - struct platform_device *pdev; struct sdw_intel_link_res *link; + struct sdw_intel_link_dev *ldev; struct sdw_intel_ctx *ctx; struct acpi_device *adev; struct sdw_slave *slave; @@ -116,67 +195,60 @@ static struct sdw_intel_ctx count = res->count; dev_dbg(&adev->dev, "Creating %d SDW Link devices\n", count); - ctx = devm_kzalloc(&adev->dev, sizeof(*ctx), GFP_KERNEL); + /* + * we need to alloc/free memory manually and can't use devm: + * this routine may be called from a workqueue, and not from + * the parent .probe. + * If devm_ was used, the memory might never be freed on errors. + */ + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) return NULL; ctx->count = count; - ctx->links = devm_kcalloc(&adev->dev, ctx->count, - sizeof(*ctx->links), GFP_KERNEL); - if (!ctx->links) + + /* + * allocate the array of pointers. The link-specific data is allocated + * as part of the first loop below and released with the auxiliary_device_uninit(). + * If some links are disabled, the link pointer will remain NULL. Given that the + * number of links is small, this is simpler than using a list to keep track of links. + */ + ctx->ldev = kcalloc(ctx->count, sizeof(*ctx->ldev), GFP_KERNEL); + if (!ctx->ldev) { + kfree(ctx); return NULL; + } - ctx->count = count; ctx->mmio_base = res->mmio_base; ctx->link_mask = res->link_mask; ctx->handle = res->handle; mutex_init(&ctx->shim_lock); - link = ctx->links; link_mask = ctx->link_mask; INIT_LIST_HEAD(&ctx->link_list); - /* Create SDW Master devices */ - for (i = 0; i < count; i++, link++) { - if (!(link_mask & BIT(i))) { - dev_dbg(&adev->dev, - "Link %d masked, will not be enabled\n", i); + for (i = 0; i < count; i++) { + if (!(link_mask & BIT(i))) continue; - } - link->mmio_base = res->mmio_base; - link->registers = res->mmio_base + SDW_LINK_BASE - + (SDW_LINK_SIZE * i); - link->shim = res->mmio_base + SDW_SHIM_BASE; - link->alh = res->mmio_base + SDW_ALH_BASE; - - link->ops = res->ops; - link->dev = res->dev; - - link->clock_stop_quirks = res->clock_stop_quirks; - link->shim_lock = &ctx->shim_lock; - link->shim_mask = &ctx->shim_mask; - link->link_mask = link_mask; - - memset(&pdevinfo, 0, sizeof(pdevinfo)); - - pdevinfo.parent = res->parent; - pdevinfo.name = "intel-sdw"; - pdevinfo.id = i; - pdevinfo.fwnode = acpi_fwnode_handle(adev); - pdevinfo.data = link; - pdevinfo.size_data = sizeof(*link); - - pdev = platform_device_register_full(&pdevinfo); - if (IS_ERR(pdev)) { - dev_err(&adev->dev, - "platform device creation failed: %ld\n", - PTR_ERR(pdev)); + /* + * init and add a device for each link + * + * The name of the device will be soundwire_intel.link.[i], + * with the "soundwire_intel" module prefix automatically added + * by the auxiliary bus core. + */ + ldev = intel_link_dev_register(res, + ctx, + acpi_fwnode_handle(adev), + "link", + i); + if (IS_ERR(ldev)) goto err; - } - link->pdev = pdev; - link->cdns = platform_get_drvdata(pdev); + + link = &ldev->link_res; + link->cdns = dev_get_drvdata(&ldev->auxdev.dev); if (!link->cdns) { dev_err(&adev->dev, "failed to get link->cdns\n"); @@ -194,8 +266,7 @@ static struct sdw_intel_ctx num_slaves++; } - ctx->ids = devm_kcalloc(&adev->dev, num_slaves, - sizeof(*ctx->ids), GFP_KERNEL); + ctx->ids = kcalloc(num_slaves, sizeof(*ctx->ids), GFP_KERNEL); if (!ctx->ids) goto err; @@ -213,8 +284,14 @@ static struct sdw_intel_ctx return ctx; err: - ctx->count = i; - sdw_intel_cleanup(ctx); + while (i--) { + if (!(link_mask & BIT(i))) + continue; + ldev = ctx->ldev[i]; + intel_link_dev_unregister(ldev); + } + kfree(ctx->ldev); + kfree(ctx); return NULL; } @@ -222,7 +299,7 @@ static int sdw_intel_startup_controller(struct sdw_intel_ctx *ctx) { struct acpi_device *adev; - struct sdw_intel_link_res *link; + struct sdw_intel_link_dev *ldev; u32 caps; u32 link_mask; int i; @@ -241,27 +318,28 @@ sdw_intel_startup_controller(struct sdw_intel_ctx *ctx) return -EINVAL; } - if (!ctx->links) + if (!ctx->ldev) return -EINVAL; - link = ctx->links; link_mask = ctx->link_mask; /* Startup SDW Master devices */ - for (i = 0; i < ctx->count; i++, link++) { + for (i = 0; i < ctx->count; i++) { if (!(link_mask & BIT(i))) continue; - intel_master_startup(link->pdev); + ldev = ctx->ldev[i]; + + intel_link_startup(&ldev->auxdev); - if (!link->clock_stop_quirks) { + if (!ldev->link_res.clock_stop_quirks) { /* * we need to prevent the parent PCI device * from entering pm_runtime suspend, so that * power rails to the SoundWire IP are not * turned off. */ - pm_runtime_get_noresume(link->dev); + pm_runtime_get_noresume(ldev->link_res.dev); } } @@ -272,8 +350,8 @@ sdw_intel_startup_controller(struct sdw_intel_ctx *ctx) * sdw_intel_probe() - SoundWire Intel probe routine * @res: resource data * - * This registers a platform device for each Master handled by the controller, - * and SoundWire Master and Slave devices will be created by the platform + * This registers an auxiliary device for each Master handled by the controller, + * and SoundWire Master and Slave devices will be created by the auxiliary * device probe. All the information necessary is stored in the context, and * the res argument pointer can be freed after this step. * This function will be called after sdw_intel_acpi_scan() by SOF probe. @@ -306,27 +384,31 @@ EXPORT_SYMBOL_NS(sdw_intel_startup, SOUNDWIRE_INTEL_INIT); void sdw_intel_exit(struct sdw_intel_ctx *ctx) { sdw_intel_cleanup(ctx); + kfree(ctx->ids); + kfree(ctx->ldev); + kfree(ctx); } EXPORT_SYMBOL_NS(sdw_intel_exit, SOUNDWIRE_INTEL_INIT); void sdw_intel_process_wakeen_event(struct sdw_intel_ctx *ctx) { - struct sdw_intel_link_res *link; + struct sdw_intel_link_dev *ldev; u32 link_mask; int i; - if (!ctx->links) + if (!ctx->ldev) return; - link = ctx->links; link_mask = ctx->link_mask; /* Startup SDW Master devices */ - for (i = 0; i < ctx->count; i++, link++) { + for (i = 0; i < ctx->count; i++) { if (!(link_mask & BIT(i))) continue; - intel_master_process_wakeen_event(link->pdev); + ldev = ctx->ldev[i]; + + intel_link_process_wakeen_event(&ldev->auxdev); } } EXPORT_SYMBOL_NS(sdw_intel_process_wakeen_event, SOUNDWIRE_INTEL_INIT); diff --git a/include/linux/soundwire/sdw_intel.h b/include/linux/soundwire/sdw_intel.h index 3a5446ac014a..1ebea7764011 100644 --- a/include/linux/soundwire/sdw_intel.h +++ b/include/linux/soundwire/sdw_intel.h @@ -58,7 +58,7 @@ struct sdw_intel_acpi_info { u32 link_mask; }; -struct sdw_intel_link_res; +struct sdw_intel_link_dev; /* Intel clock-stop/pm_runtime quirk definitions */ @@ -109,7 +109,7 @@ struct sdw_intel_slave_id { * Controller * @num_slaves: total number of devices exposed across all enabled links * @handle: ACPI parent handle - * @links: information for each link (controller-specific and kept + * @ldev: information for each link (controller-specific and kept * opaque here) * @ids: array of slave_id, representing Slaves exposed across all enabled * links @@ -123,7 +123,7 @@ struct sdw_intel_ctx { u32 link_mask; int num_slaves; acpi_handle handle; - struct sdw_intel_link_res *links; + struct sdw_intel_link_dev **ldev; struct sdw_intel_slave_id *ids; struct list_head link_list; struct mutex shim_lock; /* lock for access to shared SHIM registers */ -- cgit v1.2.3 From 307773f525eb9217090bd4b11748d880f7f99355 Mon Sep 17 00:00:00 2001 From: Aswath Govindraju Date: Mon, 10 May 2021 10:40:03 +0530 Subject: phy: core: Reword the comment specifying the units of max_link_rate to be Mbps In some subsystems (eg. CAN, SPI), the max link rate supported can be less than 1 Mbps and if the unit for max_link_rate is Mbps then it can't be used. Therefore, leave the decision of units to be used, to the producer and consumer. Signed-off-by: Aswath Govindraju Acked-by: Marc Kleine-Budde Acked-by: Kishon Vijay Abraham I Link: https://lore.kernel.org/r/20210510051006.11393-2-a-govindraju@ti.com Signed-off-by: Vinod Koul --- include/linux/phy/phy.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h index 0ed434d02196..f3286f4cd306 100644 --- a/include/linux/phy/phy.h +++ b/include/linux/phy/phy.h @@ -125,7 +125,7 @@ struct phy_ops { /** * struct phy_attrs - represents phy attributes * @bus_width: Data path width implemented by PHY - * @max_link_rate: Maximum link rate supported by PHY (in Mbps) + * @max_link_rate: Maximum link rate supported by PHY (units to be decided by producer and consumer) * @mode: PHY mode */ struct phy_attrs { -- cgit v1.2.3 From 341466b64f301dabaed791c5862d2ae5a9e72849 Mon Sep 17 00:00:00 2001 From: Russ Weight Date: Mon, 14 Jun 2021 10:09:02 -0700 Subject: fpga: altera-pr-ip: Remove function alt_pr_unregister Remove the alt_pr_unregister() function; it is no longer used. Signed-off-by: Russ Weight Reviewed-by: Xu Yilun Signed-off-by: Moritz Fischer Link: https://lore.kernel.org/r/20210614170909.232415-2-mdf@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/altera-pr-ip-core.c | 10 ---------- include/linux/fpga/altera-pr-ip-core.h | 1 - 2 files changed, 11 deletions(-) (limited to 'include') diff --git a/drivers/fpga/altera-pr-ip-core.c b/drivers/fpga/altera-pr-ip-core.c index 5b130c4d9882..dfdf21ed34c4 100644 --- a/drivers/fpga/altera-pr-ip-core.c +++ b/drivers/fpga/altera-pr-ip-core.c @@ -199,16 +199,6 @@ int alt_pr_register(struct device *dev, void __iomem *reg_base) } EXPORT_SYMBOL_GPL(alt_pr_register); -void alt_pr_unregister(struct device *dev) -{ - struct fpga_manager *mgr = dev_get_drvdata(dev); - - dev_dbg(dev, "%s\n", __func__); - - fpga_mgr_unregister(mgr); -} -EXPORT_SYMBOL_GPL(alt_pr_unregister); - MODULE_AUTHOR("Matthew Gerlach "); MODULE_DESCRIPTION("Altera Partial Reconfiguration IP Core"); MODULE_LICENSE("GPL v2"); diff --git a/include/linux/fpga/altera-pr-ip-core.h b/include/linux/fpga/altera-pr-ip-core.h index 0b08ac20ab16..a6b4c07858cc 100644 --- a/include/linux/fpga/altera-pr-ip-core.h +++ b/include/linux/fpga/altera-pr-ip-core.h @@ -13,6 +13,5 @@ #include int alt_pr_register(struct device *dev, void __iomem *reg_base); -void alt_pr_unregister(struct device *dev); #endif /* _ALT_PR_IP_CORE_H */ -- cgit v1.2.3 From 60f86b9a1c0d81507133173ba3dcfc3edd4d89a5 Mon Sep 17 00:00:00 2001 From: Huilong Deng Date: Tue, 15 Jun 2021 23:55:30 +0900 Subject: mcb: Remove trailing semicolon in macros Macros should not use a trailing semicolon. Signed-off-by: Huilong Deng Signed-off-by: Johannes Thumshirn Link: https://lore.kernel.org/r/fe520620eeddaa2ed8c669125f9b673c89d6b5a5.1623768541.git.johannes.thumshirn@wdc.com Signed-off-by: Greg Kroah-Hartman --- include/linux/mcb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/mcb.h b/include/linux/mcb.h index 71dd10a3d928..f6efb16f9d1b 100644 --- a/include/linux/mcb.h +++ b/include/linux/mcb.h @@ -120,7 +120,7 @@ extern int __must_check __mcb_register_driver(struct mcb_driver *drv, __mcb_register_driver(driver, THIS_MODULE, KBUILD_MODNAME) extern void mcb_unregister_driver(struct mcb_driver *driver); #define module_mcb_driver(__mcb_driver) \ - module_driver(__mcb_driver, mcb_register_driver, mcb_unregister_driver); + module_driver(__mcb_driver, mcb_register_driver, mcb_unregister_driver) extern void mcb_bus_add_devices(const struct mcb_bus *bus); extern int mcb_device_register(struct mcb_bus *bus, struct mcb_device *dev); extern struct mcb_bus *mcb_alloc_bus(struct device *carrier); -- cgit v1.2.3 From 8e8125f192288802267157f613c0ca654dfbde8e Mon Sep 17 00:00:00 2001 From: Yuri Nudelman Date: Tue, 25 May 2021 14:49:52 +0300 Subject: habanalabs: add debug flag to prevent failure on timeout Sometimes it is useful to allow the command to continue running despite the timeout occurred, to differentiate between really stuck or just very time consuming commands. This can be achieved by passing a new debug flag alongside the cs, HL_CS_FLAGS_SKIP_RESET_ON_TIMEOUT. Anyway, if the timeout occurred, a warning print shall be issued, however this shall not fail the submission. Signed-off-by: Yuri Nudelman Reviewed-by: Oded Gabbay Signed-off-by: Oded Gabbay --- .../misc/habanalabs/common/command_submission.c | 25 +++++++++++++++++----- drivers/misc/habanalabs/common/habanalabs.h | 5 +++++ include/uapi/misc/habanalabs.h | 1 + 3 files changed, 26 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/drivers/misc/habanalabs/common/command_submission.c b/drivers/misc/habanalabs/common/command_submission.c index ecd96fbe3150..6d51f54030c1 100644 --- a/drivers/misc/habanalabs/common/command_submission.c +++ b/drivers/misc/habanalabs/common/command_submission.c @@ -556,6 +556,13 @@ out: else if (!cs->submitted) cs->fence->error = -EBUSY; + if (unlikely(cs->skip_reset_on_timeout)) { + dev_err(hdev->dev, + "Command submission %llu completed after %llu (s)\n", + cs->sequence, + div_u64(jiffies - cs->submission_time_jiffies, HZ)); + } + if (cs->timestamp) cs->fence->timestamp = ktime_get(); complete_all(&cs->fence->completion); @@ -571,6 +578,8 @@ static void cs_timedout(struct work_struct *work) int rc; struct hl_cs *cs = container_of(work, struct hl_cs, work_tdr.work); + bool skip_reset_on_timeout = cs->skip_reset_on_timeout; + rc = cs_get_unless_zero(cs); if (!rc) return; @@ -581,7 +590,8 @@ static void cs_timedout(struct work_struct *work) } /* Mark the CS is timed out so we won't try to cancel its TDR */ - cs->timedout = true; + if (likely(!skip_reset_on_timeout)) + cs->timedout = true; hdev = cs->ctx->hdev; @@ -613,10 +623,12 @@ static void cs_timedout(struct work_struct *work) cs_put(cs); - if (hdev->reset_on_lockup) - hl_device_reset(hdev, HL_RESET_TDR); - else - hdev->needs_reset = true; + if (likely(!skip_reset_on_timeout)) { + if (hdev->reset_on_lockup) + hl_device_reset(hdev, HL_RESET_TDR); + else + hdev->needs_reset = true; + } } static int allocate_cs(struct hl_device *hdev, struct hl_ctx *ctx, @@ -650,6 +662,9 @@ static int allocate_cs(struct hl_device *hdev, struct hl_ctx *ctx, cs->type = cs_type; cs->timestamp = !!(flags & HL_CS_FLAGS_TIMESTAMP); cs->timeout_jiffies = timeout; + cs->skip_reset_on_timeout = + !!(flags & HL_CS_FLAGS_SKIP_RESET_ON_TIMEOUT); + cs->submission_time_jiffies = jiffies; INIT_LIST_HEAD(&cs->job_list); INIT_DELAYED_WORK(&cs->work_tdr, cs_timedout); kref_init(&cs->refcount); diff --git a/drivers/misc/habanalabs/common/habanalabs.h b/drivers/misc/habanalabs/common/habanalabs.h index e751868b3ed3..56d2f41f8893 100644 --- a/drivers/misc/habanalabs/common/habanalabs.h +++ b/drivers/misc/habanalabs/common/habanalabs.h @@ -1421,6 +1421,7 @@ struct hl_userptr { * @staged_sequence: the sequence of the staged submission this CS is part of, * relevant only if staged_cs is set. * @timeout_jiffies: cs timeout in jiffies. + * @submission_time_jiffies: submission time of the cs * @type: CS_TYPE_*. * @submitted: true if CS was submitted to H/W. * @completed: true if CS was completed by device. @@ -1433,6 +1434,8 @@ struct hl_userptr { * @staged_first: true if this is the first staged CS and we need to receive * timeout for this CS. * @staged_cs: true if this CS is part of a staged submission. + * @skip_reset_on_timeout: true if we shall not reset the device in case + * timeout occurs (debug scenario). */ struct hl_cs { u16 *jobs_in_queue_cnt; @@ -1450,6 +1453,7 @@ struct hl_cs { u64 sequence; u64 staged_sequence; u64 timeout_jiffies; + u64 submission_time_jiffies; enum hl_cs_type type; u8 submitted; u8 completed; @@ -1460,6 +1464,7 @@ struct hl_cs { u8 staged_last; u8 staged_first; u8 staged_cs; + u8 skip_reset_on_timeout; }; /** diff --git a/include/uapi/misc/habanalabs.h b/include/uapi/misc/habanalabs.h index 6d2d34c9f375..a47485a8d411 100644 --- a/include/uapi/misc/habanalabs.h +++ b/include/uapi/misc/habanalabs.h @@ -664,6 +664,7 @@ struct hl_cs_chunk { #define HL_CS_FLAGS_STAGED_SUBMISSION_FIRST 0x80 #define HL_CS_FLAGS_STAGED_SUBMISSION_LAST 0x100 #define HL_CS_FLAGS_CUSTOM_TIMEOUT 0x200 +#define HL_CS_FLAGS_SKIP_RESET_ON_TIMEOUT 0x400 #define HL_CS_STATUS_SUCCESS 0 -- cgit v1.2.3 From e307b302be8beb7fb59aa16621d5081b69397076 Mon Sep 17 00:00:00 2001 From: Yuri Nudelman Date: Mon, 24 May 2021 11:25:21 +0300 Subject: habanalabs: added open_stats info ioctl In a system with multiple ASICs, there is a need to provide monitoring tools with information on how long a device was opened and how many times a device was opened. Therefore, we add a new opcode to the INFO ioctl to provide that information. Signed-off-by: Yuri Nudelman Reviewed-by: Oded Gabbay Signed-off-by: Oded Gabbay --- drivers/misc/habanalabs/common/device.c | 3 +++ drivers/misc/habanalabs/common/habanalabs.h | 8 ++++++++ drivers/misc/habanalabs/common/habanalabs_drv.c | 3 +++ drivers/misc/habanalabs/common/habanalabs_ioctl.c | 21 +++++++++++++++++++++ include/uapi/misc/habanalabs.h | 12 ++++++++++++ 5 files changed, 47 insertions(+) (limited to 'include') diff --git a/drivers/misc/habanalabs/common/device.c b/drivers/misc/habanalabs/common/device.c index e56f5170e338..37ce38d9a1a7 100644 --- a/drivers/misc/habanalabs/common/device.c +++ b/drivers/misc/habanalabs/common/device.c @@ -132,6 +132,9 @@ static int hl_device_release(struct inode *inode, struct file *filp) dev_warn(hdev->dev, "Device is still in use because there are live CS and/or memory mappings\n"); + hdev->last_open_session_duration_jif = + jiffies - hdev->last_successful_open_jif; + return 0; } diff --git a/drivers/misc/habanalabs/common/habanalabs.h b/drivers/misc/habanalabs/common/habanalabs.h index 244fbf209d34..6c9a81c2cfe7 100644 --- a/drivers/misc/habanalabs/common/habanalabs.h +++ b/drivers/misc/habanalabs/common/habanalabs.h @@ -2137,6 +2137,11 @@ struct hl_mmu_funcs { * the error will be ignored by the driver during * device initialization. Mainly used to debug and * workaround firmware bugs + * @last_successful_open_jif: timestamp (jiffies) of the last successful + * device open. + * @last_open_session_duration_jif: duration (jiffies) of the last device open + * session. + * @open_counter: number of successful device open operations. * @in_reset: is device in reset flow. * @curr_pll_profile: current PLL profile. * @card_type: Various ASICs have several card types. This indicates the card @@ -2259,6 +2264,9 @@ struct hl_device { u64 max_power; u64 clock_gating_mask; u64 boot_error_status_mask; + u64 last_successful_open_jif; + u64 last_open_session_duration_jif; + u64 open_counter; atomic_t in_reset; enum hl_pll_frequency curr_pll_profile; enum cpucp_card_types card_type; diff --git a/drivers/misc/habanalabs/common/habanalabs_drv.c b/drivers/misc/habanalabs/common/habanalabs_drv.c index 4d377a39df13..4194cda2d04c 100644 --- a/drivers/misc/habanalabs/common/habanalabs_drv.c +++ b/drivers/misc/habanalabs/common/habanalabs_drv.c @@ -187,6 +187,9 @@ int hl_device_open(struct inode *inode, struct file *filp) hl_debugfs_add_file(hpriv); + hdev->open_counter++; + hdev->last_successful_open_jif = jiffies; + return 0; out_err: diff --git a/drivers/misc/habanalabs/common/habanalabs_ioctl.c b/drivers/misc/habanalabs/common/habanalabs_ioctl.c index 6604d30246e6..f4dda7b4acdd 100644 --- a/drivers/misc/habanalabs/common/habanalabs_ioctl.c +++ b/drivers/misc/habanalabs/common/habanalabs_ioctl.c @@ -460,6 +460,24 @@ static int power_info(struct hl_fpriv *hpriv, struct hl_info_args *args) min((size_t) max_size, sizeof(power_info))) ? -EFAULT : 0; } +static int open_stats_info(struct hl_fpriv *hpriv, struct hl_info_args *args) +{ + struct hl_device *hdev = hpriv->hdev; + u32 max_size = args->return_size; + struct hl_open_stats_info open_stats_info = {0}; + void __user *out = (void __user *) (uintptr_t) args->return_pointer; + + if ((!max_size) || (!out)) + return -EINVAL; + + open_stats_info.last_open_period_ms = jiffies64_to_msecs( + hdev->last_open_session_duration_jif); + open_stats_info.open_counter = hdev->open_counter; + + return copy_to_user(out, &open_stats_info, + min((size_t) max_size, sizeof(open_stats_info))) ? -EFAULT : 0; +} + static int _hl_info_ioctl(struct hl_fpriv *hpriv, void *data, struct device *dev) { @@ -543,6 +561,9 @@ static int _hl_info_ioctl(struct hl_fpriv *hpriv, void *data, case HL_INFO_POWER: return power_info(hpriv, args); + case HL_INFO_OPEN_STATS: + return open_stats_info(hpriv, args); + default: dev_err(dev, "Invalid request %d\n", args->op); rc = -ENOTTY; diff --git a/include/uapi/misc/habanalabs.h b/include/uapi/misc/habanalabs.h index a47485a8d411..a47a731e4527 100644 --- a/include/uapi/misc/habanalabs.h +++ b/include/uapi/misc/habanalabs.h @@ -313,6 +313,7 @@ enum hl_device_status { * HL_INFO_SYNC_MANAGER - Retrieve sync manager info per dcore * HL_INFO_TOTAL_ENERGY - Retrieve total energy consumption * HL_INFO_PLL_FREQUENCY - Retrieve PLL frequency + * HL_INFO_OPEN_STATS - Retrieve info regarding recent device open calls */ #define HL_INFO_HW_IP_INFO 0 #define HL_INFO_HW_EVENTS 1 @@ -331,6 +332,7 @@ enum hl_device_status { #define HL_INFO_TOTAL_ENERGY 15 #define HL_INFO_PLL_FREQUENCY 16 #define HL_INFO_POWER 17 +#define HL_INFO_OPEN_STATS 18 #define HL_INFO_VERSION_MAX_LEN 128 #define HL_INFO_CARD_NAME_MAX_LEN 16 @@ -444,6 +446,16 @@ struct hl_pll_frequency_info { __u16 output[HL_PLL_NUM_OUTPUTS]; }; +/** + * struct hl_open_stats_info - device open statistics information + * @open_counter: ever growing counter, increased on each successful dev open + * @last_open_period_ms: duration (ms) device was open last time + */ +struct hl_open_stats_info { + __u64 open_counter; + __u64 last_open_period_ms; +}; + /** * struct hl_power_info - power information * @power: power consumption -- cgit v1.2.3 From 031e668bc1ad7ccdbfb2b67b838bb6b7cc44ecf3 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Wed, 16 Jun 2021 15:59:01 +0100 Subject: soundwire: bus: Make sdw_nwrite() data pointer argument const Idiomatically, write functions should take const pointers to the data buffer, as they don't change the data. They are also likely to be called from functions that receive a const data pointer. Internally the pointer is passed to function/structs shared with the read functions, requiring a cast, but this is an implementation detail that should be hidden by the public API. Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20210616145901.29402-1-rf@opensource.cirrus.com Signed-off-by: Vinod Koul --- drivers/soundwire/bus.c | 8 ++++---- include/linux/soundwire/sdw.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index 85bcf60f9697..adcbf3969110 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -394,13 +394,13 @@ sdw_nread_no_pm(struct sdw_slave *slave, u32 addr, size_t count, u8 *val) } static int -sdw_nwrite_no_pm(struct sdw_slave *slave, u32 addr, size_t count, u8 *val) +sdw_nwrite_no_pm(struct sdw_slave *slave, u32 addr, size_t count, const u8 *val) { struct sdw_msg msg; int ret; ret = sdw_fill_msg(&msg, slave, addr, count, - slave->dev_num, SDW_MSG_FLAG_WRITE, val); + slave->dev_num, SDW_MSG_FLAG_WRITE, (u8 *)val); if (ret < 0) return ret; @@ -535,9 +535,9 @@ EXPORT_SYMBOL(sdw_nread); * @slave: SDW Slave * @addr: Register address * @count: length - * @val: Buffer for values to be read + * @val: Buffer for values to be written */ -int sdw_nwrite(struct sdw_slave *slave, u32 addr, size_t count, u8 *val) +int sdw_nwrite(struct sdw_slave *slave, u32 addr, size_t count, const u8 *val) { int ret; diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index 8ca736e92d5a..ddbeb00799e4 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -1039,7 +1039,7 @@ int sdw_write(struct sdw_slave *slave, u32 addr, u8 value); int sdw_write_no_pm(struct sdw_slave *slave, u32 addr, u8 value); int sdw_read_no_pm(struct sdw_slave *slave, u32 addr); int sdw_nread(struct sdw_slave *slave, u32 addr, size_t count, u8 *val); -int sdw_nwrite(struct sdw_slave *slave, u32 addr, size_t count, u8 *val); +int sdw_nwrite(struct sdw_slave *slave, u32 addr, size_t count, const u8 *val); int sdw_compare_devid(struct sdw_slave *slave, struct sdw_slave_id id); void sdw_extract_slave_id(struct sdw_bus *bus, u64 addr, struct sdw_slave_id *id); -- cgit v1.2.3 From d0b371e5fba0ef2b4e3f6a3f1b5fe7f8bd97897e Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 21 Jun 2021 18:12:43 +0300 Subject: stm class: Spelling fix Drop the repeated word "the" in a comment. Cc: Alexander Shishkin Cc: Andrew Morton Cc: Greg Kroah-Hartman [alexander.shishkin: fixed the commit message] Reviewed-by: Andy Shevchenko Signed-off-by: Randy Dunlap Signed-off-by: Alexander Shishkin Link: https://lore.kernel.org/r/20210621151246.31891-2-alexander.shishkin@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- include/linux/stm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/stm.h b/include/linux/stm.h index c6f577ab6f21..3b22689512be 100644 --- a/include/linux/stm.h +++ b/include/linux/stm.h @@ -57,7 +57,7 @@ struct stm_device; * * Normally, an STM device will have a range of masters available to software * and the rest being statically assigned to various hardware trace sources. - * The former is defined by the the range [@sw_start..@sw_end] of the device + * The former is defined by the range [@sw_start..@sw_end] of the device * description. That is, the lowest master that can be allocated to software * writers is @sw_start and data from this writer will appear is @sw_start * master in the STP stream. -- cgit v1.2.3