drivers/net/wwan/iosm/iosm_ipc_protocol.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/wwan/iosm/iosm_ipc_protocol.c
Extension
.c
Size
7975 bytes
Lines
283
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

msecs_to_jiffies(exec_timeout))) {
	case 0:
		/* Timeout, there was no response from the device.
		 * Remove the reference to the local response completion
		 * object as we are no longer interested in the response.
		 */
		ipc_task_queue_send_task(ipc_protocol->imem,
					 ipc_protocol_tq_msg_remove, index,
					 NULL, 0, true);
		dev_err(ipc_protocol->dev, "msg timeout");
		ipc_uevent_send(ipc_protocol->pcie->dev, UEVENT_MDM_TIMEOUT);
		break;
	default:
		/* We got a response in time; check completion status: */
		if (response.status != IPC_MEM_MSG_CS_SUCCESS) {
			dev_err(ipc_protocol->dev,
				"msg completion status error %d",
				response.status);
			return -EIO;
		}
	}

	return 0;
}

static int ipc_protocol_msg_send_host_sleep(struct iosm_protocol *ipc_protocol,
					    u32 state)
{
	union ipc_msg_prep_args prep_args = {
		.sleep.target = 0,
		.sleep.state = state,
	};

	return ipc_protocol_msg_send(ipc_protocol, IPC_MSG_PREP_SLEEP,
				     &prep_args);
}

void ipc_protocol_doorbell_trigger(struct iosm_protocol *ipc_protocol,
				   u32 identifier)
{
	ipc_pm_signal_hpda_doorbell(&ipc_protocol->pm, identifier, true);
}

bool ipc_protocol_pm_dev_sleep_handle(struct iosm_protocol *ipc_protocol)
{
	u32 ipc_status = ipc_protocol_get_ipc_status(ipc_protocol);
	u32 requested;

	if (ipc_status != IPC_MEM_DEVICE_IPC_RUNNING) {
		dev_err(ipc_protocol->dev,
			"irq ignored, CP IPC state is %d, should be RUNNING",
			ipc_status);

		/* Stop further processing. */
		return false;
	}

	/* Get a copy of the requested PM state by the device and the local
	 * device PM state.
	 */
	requested = ipc_protocol_pm_dev_get_sleep_notification(ipc_protocol);

	return ipc_pm_dev_slp_notification(&ipc_protocol->pm, requested);
}

static int ipc_protocol_tq_wakeup_dev_slp(struct iosm_imem *ipc_imem, int arg,
					  void *msg, size_t size)
{
	struct iosm_pm *ipc_pm = &ipc_imem->ipc_protocol->pm;

	/* Wakeup from device sleep if it is not ACTIVE */
	ipc_pm_trigger(ipc_pm, IPC_PM_UNIT_HS, true);

	ipc_pm_trigger(ipc_pm, IPC_PM_UNIT_HS, false);

	return 0;
}

void ipc_protocol_s2idle_sleep(struct iosm_protocol *ipc_protocol, bool sleep)
{
	ipc_pm_set_s2idle_sleep(&ipc_protocol->pm, sleep);
}

bool ipc_protocol_suspend(struct iosm_protocol *ipc_protocol)
{
	if (!ipc_pm_prepare_host_sleep(&ipc_protocol->pm))
		goto err;

	ipc_task_queue_send_task(ipc_protocol->imem,
				 ipc_protocol_tq_wakeup_dev_slp, 0, NULL, 0,

Annotation

Implementation Notes