[PATCH 33/50] wifi: ath12k: add mhi.c

Jeff Johnson quic_jjohnson at quicinc.com
Thu Aug 18 15:25:49 PDT 2022


On 8/12/2022 9:09 AM, Kalle Valo wrote:
> From: Kalle Valo <quic_kvalo at quicinc.com>
> 
> (Patches split into one patch per file for easier review, but the final
> commit will be one big patch. See the cover letter for more info.)
> 
> Signed-off-by: Kalle Valo <quic_kvalo at quicinc.com>
> ---
>   drivers/net/wireless/ath/ath12k/mhi.c | 615 ++++++++++++++++++++++++++++++++++
>   1 file changed, 615 insertions(+)
> 
> diff --git a/drivers/net/wireless/ath/ath12k/mhi.c b/drivers/net/wireless/ath/ath12k/mhi.c
> new file mode 100644
> index 000000000000..f77634994d97
> --- /dev/null
> +++ b/drivers/net/wireless/ath/ath12k/mhi.c
> @@ -0,0 +1,615 @@
> +// SPDX-License-Identifier: BSD-3-Clause-Clear
> +/*
> + * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved.
> + * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
> + */
> +
> +#include <linux/msi.h>
> +#include <linux/pci.h>
> +
> +#include "core.h"
> +#include "debug.h"
> +#include "mhi.h"
> +#include "pci.h"
> +
> +#define MHI_TIMEOUT_DEFAULT_MS	90000
> +
> +static struct mhi_channel_config ath12k_mhi_channels_qcn9274[] = {

should this be const?
in struct mhi_controller_config:
	const struct mhi_channel_config *ch_cfg;

> +	{
> +		.num = 0,
> +		.name = "LOOPBACK",
> +		.num_elements = 32,
> +		.event_ring = 1,
> +		.dir = DMA_TO_DEVICE,
> +		.ee_mask = 0x4,
> +		.pollcfg = 0,
> +		.doorbell = MHI_DB_BRST_DISABLE,
> +		.lpm_notify = false,
> +		.offload_channel = false,
> +		.doorbell_mode_switch = false,
> +		.auto_queue = false,
> +	},
> +	{
> +		.num = 1,
> +		.name = "LOOPBACK",
> +		.num_elements = 32,
> +		.event_ring = 1,
> +		.dir = DMA_FROM_DEVICE,
> +		.ee_mask = 0x4,
> +		.pollcfg = 0,
> +		.doorbell = MHI_DB_BRST_DISABLE,
> +		.lpm_notify = false,
> +		.offload_channel = false,
> +		.doorbell_mode_switch = false,
> +		.auto_queue = false,
> +	},
> +	{
> +		.num = 20,
> +		.name = "IPCR",
> +		.num_elements = 32,
> +		.event_ring = 1,
> +		.dir = DMA_TO_DEVICE,
> +		.ee_mask = 0x4,
> +		.pollcfg = 0,
> +		.doorbell = MHI_DB_BRST_DISABLE,
> +		.lpm_notify = false,
> +		.offload_channel = false,
> +		.doorbell_mode_switch = false,
> +		.auto_queue = false,
> +	},
> +	{
> +		.num = 21,
> +		.name = "IPCR",
> +		.num_elements = 32,
> +		.event_ring = 1,
> +		.dir = DMA_FROM_DEVICE,
> +		.ee_mask = 0x4,
> +		.pollcfg = 0,
> +		.doorbell = MHI_DB_BRST_DISABLE,
> +		.lpm_notify = false,
> +		.offload_channel = false,
> +		.doorbell_mode_switch = false,
> +		.auto_queue = true,
> +	},
> +};
> +
> +static struct mhi_event_config ath12k_mhi_events_qcn9274[] = {

seems this should be const
but for some reason struct mhi_controller_config has:
	struct mhi_event_config *event_cfg;

(not const) so this can't be const :(

perhaps someone can propose a MHI interface change?
especially since internally to MHI in parse_ev_cfg() we have:
	const struct mhi_event_config *event_cfg;
	[...]
	for (i = 0; i < num; i++) {
		event_cfg = &config->event_cfg[i];

so it is treated as const

> +	{
> +		.num_elements = 32,
> +		.irq_moderation_ms = 0,
> +		.irq = 1,
> +		.data_type = MHI_ER_CTRL,
> +		.mode = MHI_DB_BRST_DISABLE,
> +		.hardware_event = false,
> +		.client_managed = false,
> +		.offload_channel = false,
> +	},
> +	{
> +		.num_elements = 256,
> +		.irq_moderation_ms = 1,
> +		.irq = 2,
> +		.mode = MHI_DB_BRST_DISABLE,
> +		.priority = 1,
> +		.hardware_event = false,
> +		.client_managed = false,
> +		.offload_channel = false,
> +	},
> +};
> +
> +struct mhi_controller_config ath12k_mhi_config_qcn9274 = {
> +	.max_channels = 30,
> +	.timeout_ms = 10000,
> +	.use_bounce_buf = false,
> +	.buf_len = 0,
> +	.num_channels = ARRAY_SIZE(ath12k_mhi_channels_qcn9274),
> +	.ch_cfg = ath12k_mhi_channels_qcn9274,
> +	.num_events = ARRAY_SIZE(ath12k_mhi_events_qcn9274),
> +	.event_cfg = ath12k_mhi_events_qcn9274,
> +};
> +
> +static struct mhi_channel_config ath12k_mhi_channels_wcn7850[] = {

const

> +	{
> +		.num = 0,
> +		.name = "LOOPBACK",
> +		.num_elements = 32,
> +		.event_ring = 0,
> +		.dir = DMA_TO_DEVICE,
> +		.ee_mask = 0x4,
> +		.pollcfg = 0,
> +		.doorbell = MHI_DB_BRST_DISABLE,
> +		.lpm_notify = false,
> +		.offload_channel = false,
> +		.doorbell_mode_switch = false,
> +		.auto_queue = false,
> +	},
> +	{
> +		.num = 1,
> +		.name = "LOOPBACK",
> +		.num_elements = 32,
> +		.event_ring = 0,
> +		.dir = DMA_FROM_DEVICE,
> +		.ee_mask = 0x4,
> +		.pollcfg = 0,
> +		.doorbell = MHI_DB_BRST_DISABLE,
> +		.lpm_notify = false,
> +		.offload_channel = false,
> +		.doorbell_mode_switch = false,
> +		.auto_queue = false,
> +	},
> +	{
> +		.num = 20,
> +		.name = "IPCR",
> +		.num_elements = 64,
> +		.event_ring = 1,
> +		.dir = DMA_TO_DEVICE,
> +		.ee_mask = 0x4,
> +		.pollcfg = 0,
> +		.doorbell = MHI_DB_BRST_DISABLE,
> +		.lpm_notify = false,
> +		.offload_channel = false,
> +		.doorbell_mode_switch = false,
> +		.auto_queue = false,
> +	},
> +	{
> +		.num = 21,
> +		.name = "IPCR",
> +		.num_elements = 64,
> +		.event_ring = 1,
> +		.dir = DMA_FROM_DEVICE,
> +		.ee_mask = 0x4,
> +		.pollcfg = 0,
> +		.doorbell = MHI_DB_BRST_DISABLE,
> +		.lpm_notify = false,
> +		.offload_channel = false,
> +		.doorbell_mode_switch = false,
> +		.auto_queue = true,
> +	},
> +};
> +
> +static struct mhi_event_config ath12k_mhi_events_wcn7850[] = {

keep not const (for now) :(

> +	{
> +		.num_elements = 32,
> +		.irq_moderation_ms = 0,
> +		.irq = 1,
> +		.mode = MHI_DB_BRST_DISABLE,
> +		.data_type = MHI_ER_CTRL,
> +		.hardware_event = false,
> +		.client_managed = false,
> +		.offload_channel = false,
> +	},
> +	{
> +		.num_elements = 256,
> +		.irq_moderation_ms = 1,
> +		.irq = 2,
> +		.mode = MHI_DB_BRST_DISABLE,
> +		.priority = 1,
> +		.hardware_event = false,
> +		.client_managed = false,
> +		.offload_channel = false,
> +	},
> +};
> +
> +struct mhi_controller_config ath12k_mhi_config_wcn7850 = {

and this one should be const since it is registered via:

int mhi_register_controller(struct mhi_controller *mhi_cntrl,
			const struct mhi_controller_config *config);

> +	.max_channels = 128,
> +	.timeout_ms = 2000,
> +	.use_bounce_buf = false,
> +	.buf_len = 0,
> +	.num_channels = ARRAY_SIZE(ath12k_mhi_channels_wcn7850),
> +	.ch_cfg = ath12k_mhi_channels_wcn7850,
> +	.num_events = ARRAY_SIZE(ath12k_mhi_events_wcn7850),
> +	.event_cfg = ath12k_mhi_events_wcn7850,
> +};
> +

snip

> +static int ath12k_mhi_get_msi(struct ath12k_pci *ab_pci)
> +{
> +	struct ath12k_base *ab = ab_pci->ab;
> +	u32 user_base_data, base_vector;
> +	int ret, num_vectors, i;
> +	int *irq;
> +
> +	ret = ath12k_pci_get_user_msi_assignment(ab,
> +						 "MHI", &num_vectors,
> +						 &user_base_data, &base_vector);
> +	if (ret)
> +		return ret;
> +
> +	ath12k_dbg(ab, ATH12K_DBG_PCI, "Number of assigned MSI for MHI is %d, base vector is %d\n",
> +		   num_vectors, base_vector);
> +
> +	irq = kcalloc(num_vectors, sizeof(int), GFP_KERNEL);

prefer sizeof(*irq)?

> +	if (!irq)
> +		return -ENOMEM;
> +
> +	for (i = 0; i < num_vectors; i++)
> +		irq[i] = ath12k_pci_get_msi_irq(ab->dev,
> +						base_vector + i);
> +
> +	ab_pci->mhi_ctrl->irq = irq;
> +	ab_pci->mhi_ctrl->nr_irqs = num_vectors;
> +
> +	return 0;
> +}
> +

snip

> +void ath12k_mhi_unregister(struct ath12k_pci *ab_pci)
> +{
> +	struct mhi_controller *mhi_ctrl = ab_pci->mhi_ctrl;
> +
> +	mhi_unregister_controller(mhi_ctrl);
> +	kfree(mhi_ctrl->irq);
> +	mhi_free_controller(mhi_ctrl);

consider setting ab_pci->mhi_ctrl = NULL to avoid dangling pointer?

> +}

rest snipped



More information about the ath12k mailing list