drivers/mailbox/mailbox.c

Source file repositories/reference/linux-study-clean/drivers/mailbox/mailbox.c

File Facts

System
Linux kernel
Corpus path
drivers/mailbox/mailbox.c
Extension
.c
Size
17261 bytes
Lines
635
Domain
Driver Families
Bucket
drivers/mailbox
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 (!err) {
			chan->active_req = data;
			chan->msg_count--;
		}
	}

	if (!err && (chan->txdone_method & MBOX_TXDONE_BY_POLL)) {
		/* kick start the timer immediately to avoid delays */
		scoped_guard(spinlock_irqsave, &chan->mbox->poll_hrt_lock)
			hrtimer_start(&chan->mbox->poll_hrt, 0, HRTIMER_MODE_REL);
	}
}

static void tx_tick(struct mbox_chan *chan, int r)
{
	void *mssg;

	scoped_guard(spinlock_irqsave, &chan->lock) {
		mssg = chan->active_req;
		chan->active_req = MBOX_NO_MSG;
	}

	/* Submit next message */
	msg_submit(chan);

	if (mssg == MBOX_NO_MSG)
		return;

	/* Notify the client */
	if (chan->cl->tx_done)
		chan->cl->tx_done(chan->cl, mssg, r);

	if (r != -ETIME && chan->cl->tx_block)
		complete(&chan->tx_complete);
}

static enum hrtimer_restart txdone_hrtimer(struct hrtimer *hrtimer)
{
	struct mbox_controller *mbox =
		container_of(hrtimer, struct mbox_controller, poll_hrt);
	bool txdone, resched = false;
	int i;

	for (i = 0; i < mbox->num_chans; i++) {
		struct mbox_chan *chan = &mbox->chans[i];

		if (chan->active_req != MBOX_NO_MSG && chan->cl) {
			txdone = chan->mbox->ops->last_tx_done(chan);
			if (txdone)
				tx_tick(chan, 0);
			else
				resched = true;
		}
	}

	if (resched) {
		scoped_guard(spinlock_irqsave, &mbox->poll_hrt_lock) {
			if (!hrtimer_is_queued(hrtimer))
				hrtimer_forward_now(hrtimer, ms_to_ktime(mbox->txpoll_period));
		}

		return HRTIMER_RESTART;
	}
	return HRTIMER_NORESTART;
}

/**
 * mbox_chan_received_data - A way for controller driver to push data
 *				received from remote to the upper layer.
 * @chan: Pointer to the mailbox channel on which RX happened.
 * @mssg: Client specific message typecasted as void *
 *
 * After startup and before shutdown any data received on the chan
 * is passed on to the API via atomic mbox_chan_received_data().
 * The controller should ACK the RX only after this call returns.
 */
void mbox_chan_received_data(struct mbox_chan *chan, void *mssg)
{
	/* No buffering the received data */
	if (chan->cl->rx_callback)
		chan->cl->rx_callback(chan->cl, mssg);
}
EXPORT_SYMBOL_GPL(mbox_chan_received_data);

/**
 * mbox_chan_txdone - A way for controller driver to notify the
 *			framework that the last TX has completed.
 * @chan: Pointer to the mailbox chan on which TX happened.
 * @r: Status of last TX - OK or ERROR
 *

Annotation

Implementation Notes