Merge "rpmsg: glink: Move intent work to private workqueue"

This commit is contained in:
qctecmdr Service 2018-08-24 12:24:03 -07:00 committed by Gerrit - the friendly Code Review server
commit fcb93c3e29

View File

@ -27,6 +27,7 @@
#include <linux/sizes.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/kthread.h>
#include <linux/mailbox_client.h>
#include <linux/ipc_logging.h>
@ -114,6 +115,8 @@ struct glink_core_rx_intent {
* @rx_pipe: pipe object for receive FIFO
* @tx_pipe: pipe object for transmit FIFO
* @irq: IRQ for signaling incoming events
* @kworker: kworker to handle rx_done work
* @task: kthread running @kworker
* @rx_work: worker for handling received control messages
* @rx_lock: protects the @rx_queue
* @rx_queue: queue of received control messages to be processed in @rx_work
@ -136,6 +139,9 @@ struct qcom_glink {
int irq;
struct kthread_worker kworker;
struct task_struct *task;
struct work_struct rx_work;
spinlock_t rx_lock;
struct list_head rx_queue;
@ -200,7 +206,7 @@ struct glink_channel {
spinlock_t intent_lock;
struct idr liids;
struct idr riids;
struct work_struct intent_work;
struct kthread_work intent_work;
struct list_head done_intents;
struct glink_core_rx_intent *buf;
@ -240,7 +246,7 @@ static const struct rpmsg_endpoint_ops glink_endpoint_ops;
#define GLINK_FEATURE_INTENTLESS BIT(1)
static void qcom_glink_rx_done_work(struct work_struct *work);
static void qcom_glink_rx_done_work(struct kthread_work *work);
static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink,
const char *name)
@ -264,7 +270,7 @@ static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink,
init_completion(&channel->intent_req_comp);
INIT_LIST_HEAD(&channel->done_intents);
INIT_WORK(&channel->intent_work, qcom_glink_rx_done_work);
kthread_init_work(&channel->intent_work, qcom_glink_rx_done_work);
idr_init(&channel->liids);
idr_init(&channel->riids);
@ -280,6 +286,8 @@ static void qcom_glink_channel_release(struct kref *ref)
unsigned long flags;
CH_INFO(channel, "\n");
kthread_cancel_work_sync(&channel->intent_work);
spin_lock_irqsave(&channel->intent_lock, flags);
idr_destroy(&channel->liids);
idr_destroy(&channel->riids);
@ -504,7 +512,7 @@ static void qcom_glink_send_close_ack(struct qcom_glink *glink,
qcom_glink_tx(glink, &req, sizeof(req), NULL, 0, true);
}
static void qcom_glink_rx_done_work(struct work_struct *work)
static void qcom_glink_rx_done_work(struct kthread_work *work)
{
struct glink_channel *channel = container_of(work, struct glink_channel,
intent_work);
@ -566,7 +574,7 @@ static void qcom_glink_rx_done(struct qcom_glink *glink,
list_add_tail(&intent->node, &channel->done_intents);
spin_unlock(&channel->intent_lock);
schedule_work(&channel->intent_work);
kthread_queue_work(&glink->kworker, &channel->intent_work);
}
/**
@ -1610,7 +1618,7 @@ static void qcom_glink_rx_close(struct qcom_glink *glink, unsigned int rcid)
CH_INFO(channel, "\n");
/* cancel pending rx_done work */
cancel_work_sync(&channel->intent_work);
kthread_cancel_work_sync(&channel->intent_work);
if (channel->rpdev) {
strlcpy(chinfo.name, channel->name, sizeof(chinfo.name));
@ -1800,6 +1808,15 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev,
return ERR_CAST(glink->mbox_chan);
}
kthread_init_worker(&glink->kworker);
glink->task = kthread_run(kthread_worker_fn, &glink->kworker,
"glink_%s", glink->name);
if (IS_ERR(glink->task)) {
dev_err(dev, "failed to spawn intent kthread %d\n",
PTR_ERR(glink->task));
return ERR_CAST(glink->task);
}
irq = of_irq_get(dev->of_node, 0);
ret = devm_request_irq(dev, irq,
qcom_glink_native_intr,
@ -1864,6 +1881,8 @@ void qcom_glink_native_remove(struct qcom_glink *glink)
idr_destroy(&glink->rcids);
spin_unlock_irqrestore(&glink->idr_lock, flags);
kthread_flush_worker(&glink->kworker);
kthread_stop(glink->task);
qcom_glink_pipe_reset(glink);
mbox_free_channel(glink->mbox_chan);
}