linux-stable/drivers/net/ipa/ipa_qmi_msg.c
Alex Elder cf412ec333 net: ipa: properly limit modem routing table use
IPA can route packets between IPA-connected entities.  The AP and
modem are currently the only such entities supported, and no routing
is required to transfer packets between them.

The number of entries in each routing table is fixed, and defined at
initialization time.  Some of these entries are designated for use
by the modem, and the rest are available for the AP to use.  The AP
sends a QMI message to the modem which describes (among other
things) information about routing table memory available for the
modem to use.

Currently the QMI initialization packet gives wrong information in
its description of routing tables.  What *should* be supplied is the
maximum index that the modem can use for the routing table memory
located at a given location.  The current code instead supplies the
total *number* of routing table entries.  Furthermore, the modem is
granted the entire table, not just the subset it's supposed to use.

This patch fixes this.  First, the ipa_mem_bounds structure is
generalized so its "end" field can be interpreted either as a final
byte offset, or a final array index.  Second, the IPv4 and IPv6
(non-hashed and hashed) table information fields in the QMI
ipa_init_modem_driver_req structure are changed to be ipa_mem_bounds
rather than ipa_mem_array structures.  Third, we set the "end" value
for each routing table to be the last index, rather than setting the
"count" to be the number of indices.  Finally, instead of allowing
the modem to use all of a routing table's memory, it is limited to
just the portion meant to be used by the modem.  In all versions of
IPA currently supported, that is IPA_ROUTE_MODEM_COUNT (8) entries.

Update a few comments for clarity.

Fixes: 530f9216a9 ("soc: qcom: ipa: AP/modem communications")
Signed-off-by: Alex Elder <elder@linaro.org>
Link: https://lore.kernel.org/r/20220913204602.1803004-1-elder@linaro.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2022-09-20 08:11:13 -07:00

723 lines
18 KiB
C

// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
* Copyright (C) 2018-2020 Linaro Ltd.
*/
#include <linux/stddef.h>
#include <linux/soc/qcom/qmi.h>
#include "ipa_qmi_msg.h"
/* QMI message structure definition for struct ipa_indication_register_req */
struct qmi_elem_info ipa_indication_register_req_ei[] = {
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_indication_register_req,
master_driver_init_complete_valid),
.tlv_type = 0x10,
.offset = offsetof(struct ipa_indication_register_req,
master_driver_init_complete_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_indication_register_req,
master_driver_init_complete),
.tlv_type = 0x10,
.offset = offsetof(struct ipa_indication_register_req,
master_driver_init_complete),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_indication_register_req,
data_usage_quota_reached_valid),
.tlv_type = 0x11,
.offset = offsetof(struct ipa_indication_register_req,
data_usage_quota_reached_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_indication_register_req,
data_usage_quota_reached),
.tlv_type = 0x11,
.offset = offsetof(struct ipa_indication_register_req,
data_usage_quota_reached),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_indication_register_req,
ipa_mhi_ready_ind_valid),
.tlv_type = 0x12,
.offset = offsetof(struct ipa_indication_register_req,
ipa_mhi_ready_ind_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_indication_register_req,
ipa_mhi_ready_ind),
.tlv_type = 0x12,
.offset = offsetof(struct ipa_indication_register_req,
ipa_mhi_ready_ind),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_indication_register_req,
endpoint_desc_ind_valid),
.tlv_type = 0x13,
.offset = offsetof(struct ipa_indication_register_req,
endpoint_desc_ind_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_indication_register_req,
endpoint_desc_ind),
.tlv_type = 0x13,
.offset = offsetof(struct ipa_indication_register_req,
endpoint_desc_ind),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_indication_register_req,
bw_change_ind_valid),
.tlv_type = 0x14,
.offset = offsetof(struct ipa_indication_register_req,
bw_change_ind_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_indication_register_req,
bw_change_ind),
.tlv_type = 0x14,
.offset = offsetof(struct ipa_indication_register_req,
bw_change_ind),
},
{
.data_type = QMI_EOTI,
},
};
/* QMI message structure definition for struct ipa_indication_register_rsp */
struct qmi_elem_info ipa_indication_register_rsp_ei[] = {
{
.data_type = QMI_STRUCT,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_indication_register_rsp,
rsp),
.tlv_type = 0x02,
.offset = offsetof(struct ipa_indication_register_rsp,
rsp),
.ei_array = qmi_response_type_v01_ei,
},
{
.data_type = QMI_EOTI,
},
};
/* QMI message structure definition for struct ipa_driver_init_complete_req */
struct qmi_elem_info ipa_driver_init_complete_req_ei[] = {
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_driver_init_complete_req,
status),
.tlv_type = 0x01,
.offset = offsetof(struct ipa_driver_init_complete_req,
status),
},
{
.data_type = QMI_EOTI,
},
};
/* QMI message structure definition for struct ipa_driver_init_complete_rsp */
struct qmi_elem_info ipa_driver_init_complete_rsp_ei[] = {
{
.data_type = QMI_STRUCT,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_driver_init_complete_rsp,
rsp),
.tlv_type = 0x02,
.offset = offsetof(struct ipa_driver_init_complete_rsp,
rsp),
.ei_array = qmi_response_type_v01_ei,
},
{
.data_type = QMI_EOTI,
},
};
/* QMI message structure definition for struct ipa_init_complete_ind */
struct qmi_elem_info ipa_init_complete_ind_ei[] = {
{
.data_type = QMI_STRUCT,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_complete_ind,
status),
.tlv_type = 0x02,
.offset = offsetof(struct ipa_init_complete_ind,
status),
.ei_array = qmi_response_type_v01_ei,
},
{
.data_type = QMI_EOTI,
},
};
/* QMI message structure definition for struct ipa_mem_bounds */
struct qmi_elem_info ipa_mem_bounds_ei[] = {
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_mem_bounds, start),
.offset = offsetof(struct ipa_mem_bounds, start),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_mem_bounds, end),
.offset = offsetof(struct ipa_mem_bounds, end),
},
{
.data_type = QMI_EOTI,
},
};
/* QMI message structure definition for struct ipa_mem_array */
struct qmi_elem_info ipa_mem_array_ei[] = {
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_mem_array, start),
.offset = offsetof(struct ipa_mem_array, start),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_mem_array, count),
.offset = offsetof(struct ipa_mem_array, count),
},
{
.data_type = QMI_EOTI,
},
};
/* QMI message structure definition for struct ipa_mem_range */
struct qmi_elem_info ipa_mem_range_ei[] = {
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_mem_range, start),
.offset = offsetof(struct ipa_mem_range, start),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_mem_range, size),
.offset = offsetof(struct ipa_mem_range, size),
},
{
.data_type = QMI_EOTI,
},
};
/* QMI message structure definition for struct ipa_init_modem_driver_req */
struct qmi_elem_info ipa_init_modem_driver_req_ei[] = {
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
platform_type_valid),
.tlv_type = 0x10,
.offset = offsetof(struct ipa_init_modem_driver_req,
platform_type_valid),
},
{
.data_type = QMI_SIGNED_4_BYTE_ENUM,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
platform_type),
.tlv_type = 0x10,
.offset = offsetof(struct ipa_init_modem_driver_req,
platform_type),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
hdr_tbl_info_valid),
.tlv_type = 0x11,
.offset = offsetof(struct ipa_init_modem_driver_req,
hdr_tbl_info_valid),
},
{
.data_type = QMI_STRUCT,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
hdr_tbl_info),
.tlv_type = 0x11,
.offset = offsetof(struct ipa_init_modem_driver_req,
hdr_tbl_info),
.ei_array = ipa_mem_bounds_ei,
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
v4_route_tbl_info_valid),
.tlv_type = 0x12,
.offset = offsetof(struct ipa_init_modem_driver_req,
v4_route_tbl_info_valid),
},
{
.data_type = QMI_STRUCT,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
v4_route_tbl_info),
.tlv_type = 0x12,
.offset = offsetof(struct ipa_init_modem_driver_req,
v4_route_tbl_info),
.ei_array = ipa_mem_bounds_ei,
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
v6_route_tbl_info_valid),
.tlv_type = 0x13,
.offset = offsetof(struct ipa_init_modem_driver_req,
v6_route_tbl_info_valid),
},
{
.data_type = QMI_STRUCT,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
v6_route_tbl_info),
.tlv_type = 0x13,
.offset = offsetof(struct ipa_init_modem_driver_req,
v6_route_tbl_info),
.ei_array = ipa_mem_bounds_ei,
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
v4_filter_tbl_start_valid),
.tlv_type = 0x14,
.offset = offsetof(struct ipa_init_modem_driver_req,
v4_filter_tbl_start_valid),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
v4_filter_tbl_start),
.tlv_type = 0x14,
.offset = offsetof(struct ipa_init_modem_driver_req,
v4_filter_tbl_start),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
v6_filter_tbl_start_valid),
.tlv_type = 0x15,
.offset = offsetof(struct ipa_init_modem_driver_req,
v6_filter_tbl_start_valid),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
v6_filter_tbl_start),
.tlv_type = 0x15,
.offset = offsetof(struct ipa_init_modem_driver_req,
v6_filter_tbl_start),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
modem_mem_info_valid),
.tlv_type = 0x16,
.offset = offsetof(struct ipa_init_modem_driver_req,
modem_mem_info_valid),
},
{
.data_type = QMI_STRUCT,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
modem_mem_info),
.tlv_type = 0x16,
.offset = offsetof(struct ipa_init_modem_driver_req,
modem_mem_info),
.ei_array = ipa_mem_range_ei,
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
ctrl_comm_dest_end_pt_valid),
.tlv_type = 0x17,
.offset = offsetof(struct ipa_init_modem_driver_req,
ctrl_comm_dest_end_pt_valid),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
ctrl_comm_dest_end_pt),
.tlv_type = 0x17,
.offset = offsetof(struct ipa_init_modem_driver_req,
ctrl_comm_dest_end_pt),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
skip_uc_load_valid),
.tlv_type = 0x18,
.offset = offsetof(struct ipa_init_modem_driver_req,
skip_uc_load_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
skip_uc_load),
.tlv_type = 0x18,
.offset = offsetof(struct ipa_init_modem_driver_req,
skip_uc_load),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
hdr_proc_ctx_tbl_info_valid),
.tlv_type = 0x19,
.offset = offsetof(struct ipa_init_modem_driver_req,
hdr_proc_ctx_tbl_info_valid),
},
{
.data_type = QMI_STRUCT,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
hdr_proc_ctx_tbl_info),
.tlv_type = 0x19,
.offset = offsetof(struct ipa_init_modem_driver_req,
hdr_proc_ctx_tbl_info),
.ei_array = ipa_mem_bounds_ei,
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
zip_tbl_info_valid),
.tlv_type = 0x1a,
.offset = offsetof(struct ipa_init_modem_driver_req,
zip_tbl_info_valid),
},
{
.data_type = QMI_STRUCT,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
zip_tbl_info),
.tlv_type = 0x1a,
.offset = offsetof(struct ipa_init_modem_driver_req,
zip_tbl_info),
.ei_array = ipa_mem_bounds_ei,
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
v4_hash_route_tbl_info_valid),
.tlv_type = 0x1b,
.offset = offsetof(struct ipa_init_modem_driver_req,
v4_hash_route_tbl_info_valid),
},
{
.data_type = QMI_STRUCT,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
v4_hash_route_tbl_info),
.tlv_type = 0x1b,
.offset = offsetof(struct ipa_init_modem_driver_req,
v4_hash_route_tbl_info),
.ei_array = ipa_mem_bounds_ei,
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
v6_hash_route_tbl_info_valid),
.tlv_type = 0x1c,
.offset = offsetof(struct ipa_init_modem_driver_req,
v6_hash_route_tbl_info_valid),
},
{
.data_type = QMI_STRUCT,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
v6_hash_route_tbl_info),
.tlv_type = 0x1c,
.offset = offsetof(struct ipa_init_modem_driver_req,
v6_hash_route_tbl_info),
.ei_array = ipa_mem_bounds_ei,
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
v4_hash_filter_tbl_start_valid),
.tlv_type = 0x1d,
.offset = offsetof(struct ipa_init_modem_driver_req,
v4_hash_filter_tbl_start_valid),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
v4_hash_filter_tbl_start),
.tlv_type = 0x1d,
.offset = offsetof(struct ipa_init_modem_driver_req,
v4_hash_filter_tbl_start),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
v6_hash_filter_tbl_start_valid),
.tlv_type = 0x1e,
.offset = offsetof(struct ipa_init_modem_driver_req,
v6_hash_filter_tbl_start_valid),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
v6_hash_filter_tbl_start),
.tlv_type = 0x1e,
.offset = offsetof(struct ipa_init_modem_driver_req,
v6_hash_filter_tbl_start),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
hw_stats_quota_base_addr_valid),
.tlv_type = 0x1f,
.offset = offsetof(struct ipa_init_modem_driver_req,
hw_stats_quota_base_addr_valid),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
hw_stats_quota_base_addr),
.tlv_type = 0x1f,
.offset = offsetof(struct ipa_init_modem_driver_req,
hw_stats_quota_base_addr),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
hw_stats_quota_size_valid),
.tlv_type = 0x20,
.offset = offsetof(struct ipa_init_modem_driver_req,
hw_stats_quota_size_valid),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
hw_stats_quota_size),
.tlv_type = 0x20,
.offset = offsetof(struct ipa_init_modem_driver_req,
hw_stats_quota_size),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
hw_stats_drop_base_addr_valid),
.tlv_type = 0x21,
.offset = offsetof(struct ipa_init_modem_driver_req,
hw_stats_drop_base_addr_valid),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
hw_stats_drop_base_addr),
.tlv_type = 0x21,
.offset = offsetof(struct ipa_init_modem_driver_req,
hw_stats_drop_base_addr),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
hw_stats_drop_size_valid),
.tlv_type = 0x22,
.offset = offsetof(struct ipa_init_modem_driver_req,
hw_stats_drop_size_valid),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_req,
hw_stats_drop_size),
.tlv_type = 0x22,
.offset = offsetof(struct ipa_init_modem_driver_req,
hw_stats_drop_size),
},
{
.data_type = QMI_EOTI,
},
};
/* QMI message structure definition for struct ipa_init_modem_driver_rsp */
struct qmi_elem_info ipa_init_modem_driver_rsp_ei[] = {
{
.data_type = QMI_STRUCT,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_rsp,
rsp),
.tlv_type = 0x02,
.offset = offsetof(struct ipa_init_modem_driver_rsp,
rsp),
.ei_array = qmi_response_type_v01_ei,
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_rsp,
ctrl_comm_dest_end_pt_valid),
.tlv_type = 0x10,
.offset = offsetof(struct ipa_init_modem_driver_rsp,
ctrl_comm_dest_end_pt_valid),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_rsp,
ctrl_comm_dest_end_pt),
.tlv_type = 0x10,
.offset = offsetof(struct ipa_init_modem_driver_rsp,
ctrl_comm_dest_end_pt),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_rsp,
default_end_pt_valid),
.tlv_type = 0x11,
.offset = offsetof(struct ipa_init_modem_driver_rsp,
default_end_pt_valid),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_rsp,
default_end_pt),
.tlv_type = 0x11,
.offset = offsetof(struct ipa_init_modem_driver_rsp,
default_end_pt),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_rsp,
modem_driver_init_pending_valid),
.tlv_type = 0x12,
.offset = offsetof(struct ipa_init_modem_driver_rsp,
modem_driver_init_pending_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size =
sizeof_field(struct ipa_init_modem_driver_rsp,
modem_driver_init_pending),
.tlv_type = 0x12,
.offset = offsetof(struct ipa_init_modem_driver_rsp,
modem_driver_init_pending),
},
{
.data_type = QMI_EOTI,
},
};