drivers/net/wwan/iosm/iosm_ipc_mux.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/wwan/iosm/iosm_ipc_mux.c
Extension
.c
Size
13308 bytes
Lines
490
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 (ipc_mux->state != MUX_S_ACTIVE) {
			ret = ipc_mux->channel_id; /* Missing the MUX channel */
			goto out;
		}

		/* Disable the TD update timer and open the first IP session. */
		ipc_imem_td_update_timer_suspend(ipc_mux->imem, true);
		ipc_mux->event = MUX_E_MUX_SESSION_OPEN;
		success = ipc_mux_session_open(ipc_mux, &msg->session_open);

		ipc_imem_td_update_timer_suspend(ipc_mux->imem, false);
		if (success)
			ret = ipc_mux->channel_id;
		goto out;

	case MUX_S_ACTIVE:
		switch (order) {
		case MUX_E_MUX_SESSION_OPEN:
			/* Disable the TD update timer and open a session */
			ipc_imem_td_update_timer_suspend(ipc_mux->imem, true);
			ipc_mux->event = MUX_E_MUX_SESSION_OPEN;
			success = ipc_mux_session_open(ipc_mux,
						       &msg->session_open);
			ipc_imem_td_update_timer_suspend(ipc_mux->imem, false);
			if (success)
				ret = ipc_mux->channel_id;
			goto out;

		case MUX_E_MUX_SESSION_CLOSE:
			/* Release an IP session. */
			ipc_mux->event = MUX_E_MUX_SESSION_CLOSE;
			ipc_mux_session_close(ipc_mux, &msg->session_close);
			if (!ipc_mux->nr_sessions) {
				ipc_mux->event = MUX_E_MUX_CHANNEL_CLOSE;
				ipc_mux_channel_close(ipc_mux,
						      &msg->channel_close);
			}
			ret = ipc_mux->channel_id;
			goto out;

		case MUX_E_MUX_CHANNEL_CLOSE:
			/* Close the MUX channel pipes. */
			ipc_mux->event = MUX_E_MUX_CHANNEL_CLOSE;
			ipc_mux_channel_close(ipc_mux, &msg->channel_close);
			ret = ipc_mux->channel_id;
			goto out;

		default:
			/* Invalid order. */
			goto out;
		}

	default:
		dev_err(ipc_mux->dev,
			"unexpected MUX transition: state=%d, event=%d",
			ipc_mux->state, ipc_mux->event);
	}
out:
	return ret;
}

struct iosm_mux *ipc_mux_init(struct ipc_mux_config *mux_cfg,
			      struct iosm_imem *imem)
{
	struct iosm_mux *ipc_mux = kzalloc_obj(*ipc_mux);
	int i, j, ul_tds, ul_td_size;
	struct sk_buff_head *free_list;
	struct sk_buff *skb;
	int qlt_size;

	if (!ipc_mux)
		return NULL;

	ipc_mux->protocol = mux_cfg->protocol;
	ipc_mux->ul_flow = mux_cfg->ul_flow;
	ipc_mux->instance_id = mux_cfg->instance_id;
	ipc_mux->wwan_q_offset = 0;

	ipc_mux->pcie = imem->pcie;
	ipc_mux->imem = imem;
	ipc_mux->ipc_protocol = imem->ipc_protocol;
	ipc_mux->dev = imem->dev;
	ipc_mux->wwan = imem->wwan;

	/* Get the reference to the UL ADB list. */
	free_list = &ipc_mux->ul_adb.free_list;

	/* Initialize the list with free ADB. */
	skb_queue_head_init(free_list);

Annotation

Implementation Notes