Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 43adfd14 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge changes Ib15db652,Ia66031dc,I6b6e81f5,Idf4290d3 into msm-next

* changes:
  drivers: mailbox: add controller debug
  drivers: mailbox: retry on -EAGAIN
  drivers: mailbox: Write data to the controller without sending
  drivers: mailbox: query controller idle status
parents 41bd774c 8a09f746
Loading
Loading
Loading
Loading
+59 −0
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ static void msg_submit(struct mbox_chan *chan)
	void *data;
	int err = -EBUSY;

again:
	spin_lock_irqsave(&chan->lock, flags);

	if (!chan->msg_count || chan->active_req)
@@ -85,6 +86,16 @@ static void msg_submit(struct mbox_chan *chan)
exit:
	spin_unlock_irqrestore(&chan->lock, flags);

	/*
	 * If the controller returns -EAGAIN, then it means, our spinlock
	 * here is preventing the controller from receiving its interrupt,
	 * that would help clear the controller channels that are currently
	 * blocked waiting on the interrupt response.
	 * Unlock and retry again.
	 */
	if (err == -EAGAIN)
		goto again;

	if (!err && (chan->txdone_method & TXDONE_BY_POLL))
		/* kick start the timer immediately to avoid delays */
		hrtimer_start(&chan->mbox->poll_hrt, 0, HRTIMER_MODE_REL);
@@ -283,6 +294,54 @@ int mbox_send_message(struct mbox_chan *chan, void *mssg)
}
EXPORT_SYMBOL_GPL(mbox_send_message);

/**
 * mbox_send_controller_data-	For client to submit a message to be
 *				sent only to the controller.
 * @chan: Mailbox channel assigned to this client.
 * @mssg: Client specific message typecasted.
 *
 * For client to submit data to the controller. There is no ACK expected
 * from the controller. This request is not buffered in the mailbox framework.
 *
 * Return: Non-negative integer for successful submission (non-blocking mode)
 *	or transmission over chan (blocking mode).
 *	Negative value denotes failure.
 */
int mbox_send_controller_data(struct mbox_chan *chan, void *mssg)
{
	unsigned long flags;
	int err;

	if (!chan || !chan->cl)
		return -EINVAL;

	spin_lock_irqsave(&chan->lock, flags);
	err = chan->mbox->ops->send_controller_data(chan, mssg);
	spin_unlock_irqrestore(&chan->lock, flags);

	return err;
}
EXPORT_SYMBOL(mbox_send_controller_data);

bool mbox_controller_is_idle(struct mbox_chan *chan)
{
	if (!chan || !chan->cl || !chan->mbox->is_idle)
		return false;

	return chan->mbox->is_idle(chan->mbox);
}
EXPORT_SYMBOL(mbox_controller_is_idle);


void mbox_chan_debug(struct mbox_chan *chan)
{
	if (!chan || !chan->cl || !chan->mbox->debug)
		return;

	return chan->mbox->debug(chan);
}
EXPORT_SYMBOL(mbox_chan_debug);

/**
 * mbox_request_channel - Request a mailbox channel.
 * @cl: Identity of the client requesting the channel.
+3 −0
Original line number Diff line number Diff line
@@ -44,8 +44,11 @@ struct mbox_chan *mbox_request_channel_byname(struct mbox_client *cl,
					      const char *name);
struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index);
int mbox_send_message(struct mbox_chan *chan, void *mssg);
int mbox_send_controller_data(struct mbox_chan *chan, void *mssg);
void mbox_client_txdone(struct mbox_chan *chan, int r); /* atomic */
bool mbox_client_peek_data(struct mbox_chan *chan); /* atomic */
void mbox_free_channel(struct mbox_chan *chan); /* may sleep */
bool mbox_controller_is_idle(struct mbox_chan *chan); /* atomic */
void mbox_chan_debug(struct mbox_chan *chan);

#endif /* __MAILBOX_CLIENT_H */
+12 −0
Original line number Diff line number Diff line
@@ -24,6 +24,12 @@ struct mbox_chan;
 *		transmission of data is reported by the controller via
 *		mbox_chan_txdone (if it has some TX ACK irq). It must not
 *		sleep.
 * @send_controller_data:
 *		Send data for the controller driver. This could be data to
 *		configure the controller or data that may be cached in the
 *		controller and not transmitted immediately. There is no ACK
 *		for this request and the request is not buffered in the
 *		controller. Must not sleep.
 * @startup:	Called when a client requests the chan. The controller
 *		could ask clients for additional parameters of communication
 *		to be provided via client's chan_data. This call may
@@ -43,9 +49,12 @@ struct mbox_chan;
 *		  Used only if txdone_poll:=true && txdone_irq:=false
 * @peek_data: Atomic check for any received data. Return true if controller
 *		  has some data to push to the client. False otherwise.
 * @debug:	Allow chan to be debugged when the client detects a channel is
 *		locked up.
 */
struct mbox_chan_ops {
	int (*send_data)(struct mbox_chan *chan, void *data);
	int (*send_controller_data)(struct mbox_chan *chan, void *data);
	int (*startup)(struct mbox_chan *chan);
	void (*shutdown)(struct mbox_chan *chan);
	bool (*last_tx_done)(struct mbox_chan *chan);
@@ -67,6 +76,7 @@ struct mbox_chan_ops {
 * @txpoll_period:	If 'txdone_poll' is in effect, the API polls for
 *			last TX's status after these many millisecs
 * @of_xlate:		Controller driver specific mapping of channel via DT
 * @is_idle:		Is the controller idle?
 * @poll_hrt:		API private. hrtimer used to poll for TXDONE on all
 *			channels.
 * @node:		API private. To hook into list of controllers.
@@ -81,6 +91,8 @@ struct mbox_controller {
	unsigned txpoll_period;
	struct mbox_chan *(*of_xlate)(struct mbox_controller *mbox,
				      const struct of_phandle_args *sp);
	bool (*is_idle)(struct mbox_controller *mbox);
	void (*debug)(struct mbox_chan *chan);
	/* Internal to API */
	struct hrtimer poll_hrt;
	struct list_head node;