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

Commit be9e06a7 authored by Chris Lew's avatar Chris Lew
Browse files

rpmsg: glink: spi: Rework glink spi bus voting logic



The spi suspend callback should be used when a driver would like to
suspend the bus, it does not act as a voting mechanism. Instead of the
suspend callback, GLINK should respond to the SUSPEND_EVENT with EBUSY
if there are transactions in flight. Change the activity flag to a
counter to keep track of the different active threads.

Before sending any data on the spi bus, GLINK should call the resume
callback. Increment the activity count on each thread before command
processing.

Change-Id: Iefbbac78bdd9d171bdfd2fdb3a339f040eb4347a
Signed-off-by: default avatarChris Lew <clew@codeaurora.org>
parent dcf44293
Loading
Loading
Loading
Loading
+19 −43
Original line number Original line Diff line number Diff line
@@ -200,8 +200,7 @@ struct glink_spi {


	struct wcd_spi_ops spi_ops;
	struct wcd_spi_ops spi_ops;
	struct glink_cmpnt cmpnt;
	struct glink_cmpnt cmpnt;
	u32 activity_flag;
	atomic_t activity_cnt;
	spinlock_t activity_lock;
	atomic_t in_reset;
	atomic_t in_reset;


	void *ilc;
	void *ilc;
@@ -297,21 +296,6 @@ static const struct rpmsg_endpoint_ops glink_endpoint_ops;
static void glink_spi_rx_done_work(struct work_struct *work);
static void glink_spi_rx_done_work(struct work_struct *work);
static void glink_spi_remove(struct glink_spi *glink);
static void glink_spi_remove(struct glink_spi *glink);


/**
 * spi_suspend() - Vote for the spi device suspend
 * @cmpnt:	Component to identify the spi device.
 *
 * Return: 0 on success, standard Linux error codes on failure.
 */
static int spi_suspend(struct glink_cmpnt *cmpnt)
{
	if (!cmpnt || !cmpnt->master_dev || !cmpnt->master_ops ||
	    !cmpnt->master_ops->suspend)
		return 0;

	return cmpnt->master_ops->suspend(cmpnt->master_dev);
}

/**
/**
 * spi_resume() - Vote for the spi device resume
 * spi_resume() - Vote for the spi device resume
 * @cmpnt:	Component to identify the spi device.
 * @cmpnt:	Component to identify the spi device.
@@ -337,12 +321,7 @@ static int spi_resume(struct glink_cmpnt *cmpnt)
 */
 */
static void glink_spi_xprt_set_poll_mode(struct glink_spi *glink)
static void glink_spi_xprt_set_poll_mode(struct glink_spi *glink)
{
{
	unsigned long flags;
	atomic_inc(&glink->activity_cnt);

	spin_lock_irqsave(&glink->activity_lock, flags);
	glink->activity_flag |= ACTIVE_RX;
	spin_unlock_irqrestore(&glink->activity_lock, flags);

	spi_resume(&glink->cmpnt);
	spi_resume(&glink->cmpnt);
}
}


@@ -355,13 +334,7 @@ static void glink_spi_xprt_set_poll_mode(struct glink_spi *glink)
 */
 */
static void glink_spi_xprt_set_irq_mode(struct glink_spi *glink)
static void glink_spi_xprt_set_irq_mode(struct glink_spi *glink)
{
{
	unsigned long flags;
	atomic_dec(&glink->activity_cnt);

	spin_lock_irqsave(&glink->activity_lock, flags);
	glink->activity_flag &= ~ACTIVE_RX;
	spin_unlock_irqrestore(&glink->activity_lock, flags);

	spi_suspend(&glink->cmpnt);
}
}


static struct glink_channel *glink_spi_alloc_channel(struct glink_spi *glink,
static struct glink_channel *glink_spi_alloc_channel(struct glink_spi *glink,
@@ -1259,11 +1232,8 @@ static int __glink_spi_send(struct glink_channel *channel,


	CH_INFO(channel, "size:%d, wait:%d\n", len, wait);
	CH_INFO(channel, "size:%d, wait:%d\n", len, wait);


	spin_lock_irqsave(&glink->activity_lock, flags);
	atomic_inc(&glink->activity_cnt);
	glink->activity_flag |= ACTIVE_TX;
	spi_resume(&glink->cmpnt);
	spin_unlock_irqrestore(&glink->activity_lock, flags);

	kref_get(&channel->refcount);
	while (!intent) {
	while (!intent) {
		spin_lock_irqsave(&channel->intent_lock, flags);
		spin_lock_irqsave(&channel->intent_lock, flags);
		idr_for_each_entry(&channel->riids, tmp, iid) {
		idr_for_each_entry(&channel->riids, tmp, iid) {
@@ -1315,11 +1285,8 @@ static int __glink_spi_send(struct glink_channel *channel,
	/* Mark intent available if we failed */
	/* Mark intent available if we failed */
	if (ret && intent)
	if (ret && intent)
		intent->in_use = false;
		intent->in_use = false;
	kref_put(&channel->refcount, glink_spi_channel_release);


	spin_lock_irqsave(&glink->activity_lock, flags);
	atomic_dec(&glink->activity_cnt);
	glink->activity_flag &= ~ACTIVE_TX;
	spin_unlock_irqrestore(&glink->activity_lock, flags);


	return ret;
	return ret;
}
}
@@ -1402,6 +1369,9 @@ static void glink_spi_rx_done_work(struct work_struct *work)
	struct glink_core_rx_intent *intent, *tmp;
	struct glink_core_rx_intent *intent, *tmp;
	unsigned long flags;
	unsigned long flags;


	atomic_inc(&glink->activity_cnt);
	spi_resume(&glink->cmpnt);

	spin_lock_irqsave(&channel->intent_lock, flags);
	spin_lock_irqsave(&channel->intent_lock, flags);
	list_for_each_entry_safe(intent, tmp, &channel->done_intents, node) {
	list_for_each_entry_safe(intent, tmp, &channel->done_intents, node) {
		list_del(&intent->node);
		list_del(&intent->node);
@@ -1412,6 +1382,8 @@ static void glink_spi_rx_done_work(struct work_struct *work)
		spin_lock_irqsave(&channel->intent_lock, flags);
		spin_lock_irqsave(&channel->intent_lock, flags);
	}
	}
	spin_unlock_irqrestore(&channel->intent_lock, flags);
	spin_unlock_irqrestore(&channel->intent_lock, flags);

	atomic_dec(&glink->activity_cnt);
}
}


static void glink_spi_rx_done(struct glink_spi *glink,
static void glink_spi_rx_done(struct glink_spi *glink,
@@ -2053,6 +2025,8 @@ static void glink_spi_defer_work(struct work_struct *work)
	unsigned int param4;
	unsigned int param4;
	unsigned int cmd;
	unsigned int cmd;


	atomic_inc(&glink->activity_cnt);
	spi_resume(&glink->cmpnt);
	for (;;) {
	for (;;) {
		spin_lock_irqsave(&glink->rx_lock, flags);
		spin_lock_irqsave(&glink->rx_lock, flags);
		if (list_empty(&glink->rx_queue)) {
		if (list_empty(&glink->rx_queue)) {
@@ -2088,6 +2062,7 @@ static void glink_spi_defer_work(struct work_struct *work)


		kfree(dcmd);
		kfree(dcmd);
	}
	}
	atomic_dec(&glink->activity_cnt);
}
}


static int glink_spi_rx_defer(struct glink_spi *glink,
static int glink_spi_rx_defer(struct glink_spi *glink,
@@ -2267,7 +2242,7 @@ static int glink_spi_cmpnt_event_handler(struct device *dev, void *priv,
{
{
	struct glink_spi *glink = dev_get_drvdata(dev);
	struct glink_spi *glink = dev_get_drvdata(dev);
	struct glink_cmpnt *cmpnt = &glink->cmpnt;
	struct glink_cmpnt *cmpnt = &glink->cmpnt;
	int ret;
	int ret = 0;


	switch (event) {
	switch (event) {
	case WDSP_EVENT_PRE_BOOTUP:
	case WDSP_EVENT_PRE_BOOTUP:
@@ -2296,13 +2271,15 @@ static int glink_spi_cmpnt_event_handler(struct device *dev, void *priv,
	case WDSP_EVENT_RESUME:
	case WDSP_EVENT_RESUME:
		break;
		break;
	case WDSP_EVENT_SUSPEND:
	case WDSP_EVENT_SUSPEND:
		if (atomic_read(&glink->activity_cnt))
			ret = -EBUSY;
		break;
		break;
	default:
	default:
		GLINK_INFO(glink, "unhandled event %d", event);
		GLINK_INFO(glink, "unhandled event %d", event);
		break;
		break;
	}
	}


	return 0;
	return ret;
}
}


/* glink_spi_cmpnt_ops - Callback operations registered wtih wdsp framework */
/* glink_spi_cmpnt_ops - Callback operations registered wtih wdsp framework */
@@ -2424,8 +2401,7 @@ struct glink_spi *qcom_glink_spi_register(struct device *parent,
	idr_init(&glink->rcids);
	idr_init(&glink->rcids);


	atomic_set(&glink->in_reset, 1);
	atomic_set(&glink->in_reset, 1);
	glink->activity_flag = 0;
	atomic_set(&glink->activity_cnt, 0);
	spin_lock_init(&glink->activity_lock);


	ret = glink_spi_init_pipe("tx-descriptors", node, &glink->tx_pipe);
	ret = glink_spi_init_pipe("tx-descriptors", node, &glink->tx_pipe);
	if (ret)
	if (ret)