sound/soc/intel/atom/sst/sst_ipc.c

Source file repositories/reference/linux-study-clean/sound/soc/intel/atom/sst/sst_ipc.c

File Facts

System
Linux kernel
Corpus path
sound/soc/intel/atom/sst/sst_ipc.c
Extension
.c
Size
11123 bytes
Lines
376
Domain
Driver Families
Bucket
sound/soc
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 (block->msg_id == ipc && block->drv_id == drv_id) {
			dev_dbg(ctx->dev, "free up the block\n");
			block->ret_code = result;
			block->data = data;
			block->size = size;
			block->condition = true;
			spin_unlock_bh(&ctx->block_lock);
			wake_up(&ctx->wait_queue);
			return 0;
		}
	}
	spin_unlock_bh(&ctx->block_lock);
	dev_dbg(ctx->dev,
		"Block not found or a response received for a short msg for ipc %d, drv_id %d\n",
		ipc, drv_id);
	return -EINVAL;
}

int sst_free_block(struct intel_sst_drv *ctx, struct sst_block *freed)
{
	struct sst_block *block, *__block;

	dev_dbg(ctx->dev, "Enter\n");
	spin_lock_bh(&ctx->block_lock);
	list_for_each_entry_safe(block, __block, &ctx->block_list, node) {
		if (block == freed) {
			pr_debug("pvt_id freed --> %d\n", freed->drv_id);
			/* toggle the index position of pvt_id */
			list_del(&freed->node);
			spin_unlock_bh(&ctx->block_lock);
			kfree(freed->data);
			freed->data = NULL;
			kfree(freed);
			return 0;
		}
	}
	spin_unlock_bh(&ctx->block_lock);
	dev_err(ctx->dev, "block is already freed!!!\n");
	return -EINVAL;
}

int sst_post_message_mrfld(struct intel_sst_drv *sst_drv_ctx,
		struct ipc_post *ipc_msg, bool sync)
{
	struct ipc_post *msg = ipc_msg;
	union ipc_header_mrfld header;
	unsigned int loop_count = 0;
	int retval = 0;
	unsigned long irq_flags;

	dev_dbg(sst_drv_ctx->dev, "Enter: sync: %d\n", sync);
	spin_lock_irqsave(&sst_drv_ctx->ipc_spin_lock, irq_flags);
	header.full = sst_shim_read64(sst_drv_ctx->shim, SST_IPCX);
	if (sync) {
		while (header.p.header_high.part.busy) {
			if (loop_count > 25) {
				dev_err(sst_drv_ctx->dev,
					"sst: Busy wait failed, can't send this msg\n");
				retval = -EBUSY;
				goto out;
			}
			cpu_relax();
			loop_count++;
			header.full = sst_shim_read64(sst_drv_ctx->shim, SST_IPCX);
		}
	} else {
		if (list_empty(&sst_drv_ctx->ipc_dispatch_list)) {
			/* queue is empty, nothing to send */
			spin_unlock_irqrestore(&sst_drv_ctx->ipc_spin_lock, irq_flags);
			dev_dbg(sst_drv_ctx->dev,
					"Empty msg queue... NO Action\n");
			return 0;
		}

		if (header.p.header_high.part.busy) {
			spin_unlock_irqrestore(&sst_drv_ctx->ipc_spin_lock, irq_flags);
			dev_dbg(sst_drv_ctx->dev, "Busy not free... post later\n");
			return 0;
		}

		/* copy msg from list */
		msg = list_entry(sst_drv_ctx->ipc_dispatch_list.next,
				struct ipc_post, node);
		list_del(&msg->node);
	}
	dev_dbg(sst_drv_ctx->dev, "sst: Post message: header = %x\n",
				msg->mrfld_header.p.header_high.full);
	dev_dbg(sst_drv_ctx->dev, "sst: size = 0x%x\n",
			msg->mrfld_header.p.header_low_payload);

Annotation

Implementation Notes