drivers/firmware/arm_scmi/shmem.c

Source file repositories/reference/linux-study-clean/drivers/firmware/arm_scmi/shmem.c

File Facts

System
Linux kernel
Corpus path
drivers/firmware/arm_scmi/shmem.c
Extension
.c
Size
7396 bytes
Lines
267
Domain
Driver Families
Bucket
drivers/firmware
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

struct scmi_shared_mem {
	__le32 reserved;
	__le32 channel_status;
#define SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR	BIT(1)
#define SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE	BIT(0)
	__le32 reserved1[2];
	__le32 flags;
#define SCMI_SHMEM_FLAG_INTR_ENABLED	BIT(0)
	__le32 length;
	__le32 msg_header;
	u8 msg_payload[];
};

static inline void shmem_memcpy_fromio32(void *to,
					 const void __iomem *from,
					 size_t count)
{
	WARN_ON(!IS_ALIGNED((unsigned long)from, 4) ||
		!IS_ALIGNED((unsigned long)to, 4) ||
		count % 4);

	__ioread32_copy(to, from, count / 4);
}

static inline void shmem_memcpy_toio32(void __iomem *to,
				       const void *from,
				       size_t count)
{
	WARN_ON(!IS_ALIGNED((unsigned long)to, 4) ||
		!IS_ALIGNED((unsigned long)from, 4) ||
		count % 4);

	__iowrite32_copy(to, from, count / 4);
}

static struct scmi_shmem_io_ops shmem_io_ops32 = {
	.fromio	= shmem_memcpy_fromio32,
	.toio	= shmem_memcpy_toio32,
};

/* Wrappers are needed for proper memcpy_{from,to}_io expansion by the
 * pre-processor.
 */
static inline void shmem_memcpy_fromio(void *to,
				       const void __iomem *from,
				       size_t count)
{
	memcpy_fromio(to, from, count);
}

static inline void shmem_memcpy_toio(void __iomem *to,
				     const void *from,
				     size_t count)
{
	memcpy_toio(to, from, count);
}

static struct scmi_shmem_io_ops shmem_io_ops_default = {
	.fromio = shmem_memcpy_fromio,
	.toio	= shmem_memcpy_toio,
};

static void shmem_tx_prepare(struct scmi_shared_mem __iomem *shmem,
			     struct scmi_xfer *xfer,
			     struct scmi_chan_info *cinfo,
			     shmem_copy_toio_t copy_toio)
{
	ktime_t stop;

	/*
	 * Ideally channel must be free by now unless OS timeout last
	 * request and platform continued to process the same, wait
	 * until it releases the shared memory, otherwise we may endup
	 * overwriting its response with new message payload or vice-versa.
	 * Giving up anyway after twice the expected channel timeout so as
	 * not to bail-out on intermittent issues where the platform is
	 * occasionally a bit slower to answer.
	 *
	 * Note that after a timeout is detected we bail-out and carry on but
	 * the transport functionality is probably permanently compromised:
	 * this is just to ease debugging and avoid complete hangs on boot
	 * due to a misbehaving SCMI firmware.
	 */
	stop = ktime_add_ms(ktime_get(), 2 * cinfo->rx_timeout_ms);
	spin_until_cond((ioread32(&shmem->channel_status) &
			 SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE) ||
			 ktime_after(ktime_get(), stop));
	if (!(ioread32(&shmem->channel_status) &
	      SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE)) {
		WARN_ON_ONCE(1);

Annotation

Implementation Notes