Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2da5335 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: ipa: Validate USB teth protocol switches"

parents 09f1a0f6 614728df
Loading
Loading
Loading
Loading
+73 −0
Original line number Original line Diff line number Diff line
@@ -175,6 +175,23 @@ struct ipa3_usb_smmu_reg_map {
	phys_addr_t addr;
	phys_addr_t addr;
};
};


/*
 * Relevant for IPA4.5 on sdx55v1 and Kona.
 */
static const bool teth_type_switch_tbl_ipa45
	[IPA_USB_MAX_TETH_PROT_SIZE][IPA_USB_MAX_TETH_PROT_SIZE] = {
		[IPA_USB_RNDIS] = {true, false, false, false, false},
		[IPA_USB_ECM] = {false, true, false, false, false},
		[IPA_USB_RMNET] = {true, false, true, false, false},
		[IPA_USB_MBIM] = {true, true, true, true, false},
		[IPA_USB_DIAG] = {false, false, false, false, true},
	};

struct ipa3_usb_teth_type_switch {
	bool valid;
	enum ipa_usb_teth_prot teth;
};

struct ipa3_usb_context {
struct ipa3_usb_context {
	struct ipa3_usb_teth_prot_context
	struct ipa3_usb_teth_prot_context
		teth_prot_ctx[IPA_USB_MAX_TETH_PROT_SIZE];
		teth_prot_ctx[IPA_USB_MAX_TETH_PROT_SIZE];
@@ -191,6 +208,7 @@ struct ipa3_usb_context {
	struct dentry *dfile_state_info;
	struct dentry *dfile_state_info;
	struct dentry *dent;
	struct dentry *dent;
	struct ipa3_usb_smmu_reg_map smmu_reg_map;
	struct ipa3_usb_smmu_reg_map smmu_reg_map;
	struct ipa3_usb_teth_type_switch prev_teth;
};
};


enum ipa3_usb_op {
enum ipa3_usb_op {
@@ -861,6 +879,56 @@ static int ipa3_usb_create_rm_resources(enum ipa3_usb_transport_type ttype)
	return result;
	return result;
}
}


static bool ipa3_usb_is_teth_switch_valid(enum ipa_usb_teth_prot new_teth)
{
	enum ipa_usb_teth_prot old_teth;
	u32 ipa_r_rev;

	IPA_USB_DBG("Start new_teth=%s\n",
		ipa3_usb_teth_prot_to_string(new_teth));

	if (IPA3_USB_IS_TTYPE_DPL(IPA3_USB_GET_TTYPE(new_teth)))
		return true;

	if (ipa3_ctx->ipa_hw_type != IPA_HW_v4_5)
		return true;

	ipa_r_rev = ipa3_get_r_rev_version();
	IPA_USB_DBG("ipa_r_rev=%u\n", ipa_r_rev);

	/* issue relevant for IPA4.5v1 */
	if (ipa_r_rev != 10 && ipa_r_rev != 13)
		return true;

	if (ipa3_usb_ctx == NULL) {
		IPA_USB_ERR("Invalid context");
		return false;
	}

	if (new_teth < 0 || new_teth >= IPA_USB_MAX_TETH_PROT_SIZE) {
		IPA_USB_ERR("Invalid new_teth %d\n", new_teth);
		return false;
	}

	if (!ipa3_usb_ctx->prev_teth.valid) {
		ipa3_usb_ctx->prev_teth.teth = new_teth;
		ipa3_usb_ctx->prev_teth.valid = true;
		return true;
	}

	old_teth = ipa3_usb_ctx->prev_teth.teth;
	if (teth_type_switch_tbl_ipa45[old_teth][new_teth]) {
		ipa3_usb_ctx->prev_teth.teth = new_teth;
		return true;
	}

	IPA_USB_DBG("Invalid teth switch %s -> %s\n",
		ipa3_usb_teth_prot_to_string(old_teth),
		ipa3_usb_teth_prot_to_string(new_teth));
	return false;
}


int ipa_usb_init_teth_prot(enum ipa_usb_teth_prot teth_prot,
int ipa_usb_init_teth_prot(enum ipa_usb_teth_prot teth_prot,
			   struct ipa_usb_teth_params *teth_params,
			   struct ipa_usb_teth_params *teth_params,
			   int (*ipa_usb_notify_cb)(enum ipa_usb_notify_event,
			   int (*ipa_usb_notify_cb)(enum ipa_usb_notify_event,
@@ -2192,6 +2260,11 @@ int ipa_usb_xdci_connect(struct ipa_usb_xdci_chan_params *ul_chan_params,
		goto bad_params;
		goto bad_params;
	}
	}


	if (!ipa3_usb_is_teth_switch_valid(connect_params->teth_prot)) {
		IPA_USB_ERR("Invalid teth type switch\n");
		goto bad_params;
	}

	if (connect_params->teth_prot != IPA_USB_DIAG) {
	if (connect_params->teth_prot != IPA_USB_DIAG) {
		result = ipa3_usb_request_xdci_channel(ul_chan_params,
		result = ipa3_usb_request_xdci_channel(ul_chan_params,
			IPA_USB_DIR_UL, ul_out_params);
			IPA_USB_DIR_UL, ul_out_params);
+1 −0
Original line number Original line Diff line number Diff line
@@ -2735,6 +2735,7 @@ int ipa3_get_transport_info(
	unsigned long *size_ptr);
	unsigned long *size_ptr);
irq_handler_t ipa3_get_isr(void);
irq_handler_t ipa3_get_isr(void);
void ipa_pc_qmp_enable(void);
void ipa_pc_qmp_enable(void);
u32 ipa3_get_r_rev_version(void);
#if defined(CONFIG_IPA3_REGDUMP)
#if defined(CONFIG_IPA3_REGDUMP)
int ipa_reg_save_init(u32 value);
int ipa_reg_save_init(u32 value);
void ipa_save_registers(void);
void ipa_save_registers(void);
+14 −0
Original line number Original line Diff line number Diff line
@@ -8120,3 +8120,17 @@ void ipa3_init_imm_cmd_desc(struct ipa3_desc *desc,
	desc->len = cmd_pyld->len;
	desc->len = cmd_pyld->len;
	desc->type = IPA_IMM_CMD_DESC;
	desc->type = IPA_IMM_CMD_DESC;
}
}

u32 ipa3_get_r_rev_version(void)
{
	static u32 r_rev;

	if (r_rev != 0)
		return r_rev;

	IPA_ACTIVE_CLIENTS_INC_SIMPLE();
	r_rev = ipahal_read_reg(IPA_VERSION);
	IPA_ACTIVE_CLIENTS_DEC_SIMPLE();

	return r_rev;
}