drivers/net/wwan/iosm/iosm_ipc_mux_codec.c

Source file repositories/reference/linux-study-clean/drivers/net/wwan/iosm/iosm_ipc_mux_codec.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wwan/iosm/iosm_ipc_mux_codec.c
Extension
.c
Size
43276 bytes
Lines
1554
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (if_id >= IPC_MEM_MUX_IP_SESSION_ENTRIES) {
			dev_err(ipc_mux->dev, "if_id [%d] not valid",
				if_id);
			return -EINVAL; /* No session interface id. */
		}

		session = &ipc_mux->session[if_id];
		adb_timer = &ipc_mux->imem->adb_timer;

		if (param->flow_ctl.mask == cpu_to_le32(0xFFFFFFFF)) {
			/* Backward Compatibility */
			if (cmd_len == cpu_to_le16(size))
				session->flow_ctl_mask =
					le32_to_cpu(param->flow_ctl.mask);
			else
				session->flow_ctl_mask = ~0;
			/* if CP asks for FLOW CTRL Enable
			 * then set our internal flow control Tx flag
			 * to limit uplink session queueing
			 */
			session->net_tx_stop = true;

			/* We have to call Finish ADB here.
			 * Otherwise any already queued data
			 * will be sent to CP when ADB is full
			 * for some other sessions.
			 */
			if (ipc_mux->protocol == MUX_AGGREGATION) {
				ipc_mux_ul_adb_finish(ipc_mux);
				ipc_imem_hrtimer_stop(adb_timer);
			}
			/* Update the stats */
			session->flow_ctl_en_cnt++;
		} else if (param->flow_ctl.mask == 0) {
			/* Just reset the Flow control mask and let
			 * mux_flow_ctrl_low_thre_b take control on
			 * our internal Tx flag and enabling kernel
			 * flow control
			 */
			dev_dbg(ipc_mux->dev, "if_id[%u] flow_ctl mask 0x%08X",
				if_id, le32_to_cpu(param->flow_ctl.mask));
			/* Backward Compatibility */
			if (cmd_len == cpu_to_le16(size))
				session->flow_ctl_mask =
					le32_to_cpu(param->flow_ctl.mask);
			else
				session->flow_ctl_mask = 0;
			/* Update the stats */
			session->flow_ctl_dis_cnt++;
		} else {
			break;
		}

		ipc_mux->acc_adb_size = 0;
		ipc_mux->acc_payload_size = 0;

		dev_dbg(ipc_mux->dev, "if_id[%u] FLOW CTRL 0x%08X", if_id,
			le32_to_cpu(param->flow_ctl.mask));
		break;

	case MUX_LITE_CMD_LINK_STATUS_REPORT:
		break;

	default:
		return -EINVAL;
	}
	return 0;
}

/* Decode and Send appropriate response to a command block. */
static void ipc_mux_dl_cmd_decode(struct iosm_mux *ipc_mux, struct sk_buff *skb)
{
	struct mux_lite_cmdh *cmdh = (struct mux_lite_cmdh *)skb->data;
	__le32 trans_id = cmdh->transaction_id;
	int size;

	if (ipc_mux_dl_cmdresps_decode_process(ipc_mux, cmdh->param,
					       cmdh->command_type, cmdh->if_id,
					       cmdh->transaction_id)) {
		/* Unable to decode command response indicates the cmd_type
		 * may be a command instead of response. So try to decoding it.
		 */
		size = offsetof(struct mux_lite_cmdh, param) +
				sizeof(cmdh->param.flow_ctl);
		if (!ipc_mux_dl_cmds_decode_process(ipc_mux, &cmdh->param,
						    cmdh->command_type,
						    cmdh->if_id,
						    cmdh->cmd_len, size)) {
			/* Decoded command may need a response. Give the
			 * response according to the command type.

Annotation

Implementation Notes