drivers/net/wwan/iosm/iosm_ipc_pm.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/wwan/iosm/iosm_ipc_pm.c
Extension
.c
Size
8442 bytes
Lines
334
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_pm->ap_state == IPC_MEM_DEV_PM_SLEEP) {
			/* Wake up the device. */
			ipc_cp_irq_sleep_control(ipc_pm->pcie,
						 IPC_MEM_DEV_PM_WAKEUP);
			ipc_pm->ap_state = IPC_MEM_DEV_PM_ACTIVE_WAIT;

			goto not_active;
		}

		if (ipc_pm->ap_state == IPC_MEM_DEV_PM_ACTIVE_WAIT)
			goto not_active;

		return true;
	}

not_active:
	/* link is not ready */
	return false;
}

bool ipc_pm_wait_for_device_active(struct iosm_pm *ipc_pm)
{
	bool ret_val = false;

	if (ipc_pm->ap_state != IPC_MEM_DEV_PM_ACTIVE) {
		/* Complete all memory stores before setting bit */
		smp_mb__before_atomic();

		/* Wait for IPC_PM_ACTIVE_TIMEOUT_MS for Device sleep state
		 * machine to enter ACTIVE state.
		 */
		set_bit(0, &ipc_pm->host_sleep_pend);

		/* Complete all memory stores after setting bit */
		smp_mb__after_atomic();

		if (!wait_for_completion_interruptible_timeout
		   (&ipc_pm->host_sleep_complete,
		    msecs_to_jiffies(IPC_PM_ACTIVE_TIMEOUT_MS))) {
			dev_err(ipc_pm->dev,
				"PM timeout. Expected State:%d. Actual: %d",
				IPC_MEM_DEV_PM_ACTIVE, ipc_pm->ap_state);
			goto  active_timeout;
		}
	}

	ret_val = true;
active_timeout:
	/* Complete all memory stores before clearing bit */
	smp_mb__before_atomic();

	/* Reset the atomic variable in any case as device sleep
	 * state machine change is no longer of interest.
	 */
	clear_bit(0, &ipc_pm->host_sleep_pend);

	/* Complete all memory stores after clearing bit */
	smp_mb__after_atomic();

	return ret_val;
}

static void ipc_pm_on_link_sleep(struct iosm_pm *ipc_pm)
{
	/* pending sleep ack and all conditions are cleared
	 * -> signal SLEEP__ACK to CP
	 */
	ipc_pm->cp_state = IPC_MEM_DEV_PM_SLEEP;
	ipc_pm->ap_state = IPC_MEM_DEV_PM_SLEEP;

	ipc_cp_irq_sleep_control(ipc_pm->pcie, IPC_MEM_DEV_PM_SLEEP);
}

static void ipc_pm_on_link_wake(struct iosm_pm *ipc_pm, bool ack)
{
	ipc_pm->ap_state = IPC_MEM_DEV_PM_ACTIVE;

	if (ack) {
		ipc_pm->cp_state = IPC_MEM_DEV_PM_ACTIVE;

		ipc_cp_irq_sleep_control(ipc_pm->pcie, IPC_MEM_DEV_PM_ACTIVE);

		/* check the consume state !!! */
		if (test_bit(CONSUME_STATE, &ipc_pm->host_sleep_pend))
			complete(&ipc_pm->host_sleep_complete);
	}

	/* Check for pending HPDA update.
	 * Pending HP update could be because of sending message was
	 * put on hold due to Device sleep state or due to TD update

Annotation

Implementation Notes