[PATCH v3 04/12] firmware: tegra: Add IVC library

Jon Hunter jonathanh at nvidia.com
Wed Aug 24 08:13:03 PDT 2016


On 19/08/16 18:32, Thierry Reding wrote:
> From: Thierry Reding <treding at nvidia.com>
> 
> The Inter-VM communication (IVC) is a communication protocol which is
> designed for interprocessor communication (IPC) or the communication
> between the hypervisor and the virtual machine with a guest OS.
> 
> Message channels are used to communicate between processors. They are
> backed by DRAM or SRAM, so care must be taken to maintain coherence of
> data.
> 
> The IVC library maintains memory-based descriptors for the transmission
> and reception channels as well as the data coherence of the counter and
> payload. Clients, such as the driver for the BPMP firmware, can use the
> library to exchange messages with remote processors.
> 
> Based on work by Peter Newman <pnewman at nvidia.com> and Joseph Lo
> <josephl at nvidia.com>.
> 
> Signed-off-by: Thierry Reding <treding at nvidia.com>
> ---
> Changes in v3:
> - use a more object oriented design
> 
>  drivers/firmware/Kconfig        |   1 +
>  drivers/firmware/Makefile       |   1 +
>  drivers/firmware/tegra/Kconfig  |  13 +
>  drivers/firmware/tegra/Makefile |   1 +
>  drivers/firmware/tegra/ivc.c    | 683 ++++++++++++++++++++++++++++++++++++++++
>  include/soc/tegra/ivc.h         | 109 +++++++
>  6 files changed, 808 insertions(+)
>  create mode 100644 drivers/firmware/tegra/Kconfig
>  create mode 100644 drivers/firmware/tegra/Makefile
>  create mode 100644 drivers/firmware/tegra/ivc.c
>  create mode 100644 include/soc/tegra/ivc.h

[snip]

> +static int check_ivc_params(unsigned long base1, unsigned long base2,
> +			    unsigned int num_frames, size_t frame_size)
> +{
> +	BUG_ON(offsetof(struct tegra_ivc_header, tx.count) & (TEGRA_IVC_ALIGN - 1));
> +	BUG_ON(offsetof(struct tegra_ivc_header, rx.count) & (TEGRA_IVC_ALIGN - 1));
> +	BUG_ON(sizeof(struct tegra_ivc_header) & (TEGRA_IVC_ALIGN - 1));
> +
> +	if ((uint64_t)num_frames * (uint64_t)frame_size >= 0x100000000) {
> +		pr_err("num_frames * frame_size overflows\n");
> +		return -EINVAL;
> +	}

This generates the following sparse warning ...

drivers/firmware/tegra/ivc.c:574:60: warning: constant 0x100000000 is so
big it is long

I think we need to append a UL.

> +
> +	/*
> +	 * The headers must at least be aligned enough for counters
> +	 * to be accessed atomically.
> +	 */
> +	if (base1 & (TEGRA_IVC_ALIGN - 1)) {
> +		pr_err("IVC channel start not aligned: %lx\n", base1);
> +		return -EINVAL;
> +	}
> +
> +	if (base2 & (TEGRA_IVC_ALIGN - 1)) {
> +		pr_err("IVC channel start not aligned: %lx\n", base2);
> +		return -EINVAL;
> +	}
> +
> +	if (frame_size & (TEGRA_IVC_ALIGN - 1)) {
> +		pr_err("frame size not adequately aligned: %zu\n", frame_size);
> +		return -EINVAL;
> +	}
> +
> +	if (base1 < base2) {
> +		if (base1 + frame_size * num_frames > base2) {
> +			pr_err("queue regions overlap: %lx + %zx, %zx\n",
> +			       base1, frame_size, frame_size * num_frames);
> +			return -EINVAL;
> +		}
> +	} else {
> +		if (base2 + frame_size * num_frames > base1) {
> +			pr_err("queue regions overlap: %lx + %zx, %zx\n",
> +			       base2, frame_size, frame_size * num_frames);
> +			return -EINVAL;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +int tegra_ivc_init(struct tegra_ivc *ivc, struct device *peer,
> +		   void __iomem *rx_virt, dma_addr_t rx_phys,
> +		   void __iomem *tx_virt, dma_addr_t tx_phys,
> +		   unsigned int num_frames, size_t frame_size,
> +		   void (*notify)(struct tegra_ivc *ivc, void *data),
> +		   void *data)
> +{
> +	size_t queue_size;
> +	int err;
> +
> +	err = check_ivc_params((unsigned long)rx_virt, (unsigned long)tx_virt,
> +			       num_frames, frame_size);
> +	if (err < 0)
> +		return err;
> +
> +	BUG_ON(!ivc);
> +	BUG_ON(!notify);
> +
> +	queue_size = tegra_ivc_total_queue_size(num_frames * frame_size);
> +
> +	/*
> +	 * All sizes that can be returned by communication functions should
> +	 * fit in an int.
> +	 */
> +	if (frame_size > INT_MAX)
> +		return -E2BIG;
> +
> +	ivc->rx.channel = (struct tegra_ivc_header *)rx_virt;
> +	ivc->tx.channel = (struct tegra_ivc_header *)tx_virt;

And these generate the sparse warnings ...

drivers/firmware/tegra/ivc.c:642:28: warning: cast removes address space
of expression
drivers/firmware/tegra/ivc.c:643:28: warning: cast removes address space
of expression

Cheers
Jon

-- 
nvpublic



More information about the linux-arm-kernel mailing list