rpmsg: glink: Add early reset notifier

Currently when a remote subsystem goes down, remove_subdev will be
called from rproc for removing that subsystem from the list, but
this could be too late. Register for early SSR notifications for
getting notified about before shutdown, so that the glink_send calls
to the dead processor will not get blocked.

Change-Id: Ief7f90caf69f2855272579bc63140837e0efc447
Signed-off-by: Chris Lew <quic_clew@quicinc.com>
This commit is contained in:
Chris Lew 2022-08-01 22:48:22 -07:00
parent 1332236bd1
commit 1b8b9571dd
2 changed files with 28 additions and 10 deletions

View File

@ -1777,6 +1777,29 @@ static void qcom_glink_work(struct work_struct *work)
}
}
void qcom_glink_early_ssr_notify(void *data)
{
struct qcom_glink *glink = data;
struct glink_channel *channel;
unsigned long flags;
int cid;
if (!glink)
return;
atomic_inc(&glink->in_reset);
/* To wakeup any blocking writers */
wake_up_all(&glink->tx_avail_notify);
spin_lock_irqsave(&glink->idr_lock, flags);
idr_for_each_entry(&glink->lcids, channel, cid) {
wake_up(&channel->intent_req_ack);
wake_up(&channel->intent_req_comp);
}
spin_unlock_irqrestore(&glink->idr_lock, flags);
}
EXPORT_SYMBOL(qcom_glink_early_ssr_notify);
static void qcom_glink_cancel_rx_work(struct qcom_glink *glink)
{
struct glink_defer_cmd *dcmd;
@ -1895,6 +1918,7 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev,
}
scnprintf(glink->irqname, 32, "glink-native-%s", glink->name);
irq = of_irq_get(dev->of_node, 0);
ret = devm_request_irq(dev, irq,
qcom_glink_native_intr,
@ -1929,22 +1953,13 @@ static int qcom_glink_remove_device(struct device *dev, void *data)
void qcom_glink_native_remove(struct qcom_glink *glink)
{
struct glink_channel *channel;
unsigned long flags;
int cid;
int ret;
atomic_inc(&glink->in_reset);
qcom_glink_early_ssr_notify(glink);
disable_irq(glink->irq);
qcom_glink_cancel_rx_work(glink);
/* Signal all threads to cancel tx */
spin_lock_irqsave(&glink->idr_lock, flags);
idr_for_each_entry(&glink->lcids, channel, cid) {
wake_up(&channel->intent_req_ack);
wake_up(&channel->intent_req_comp);
}
spin_unlock_irqrestore(&glink->idr_lock, flags);
ret = device_for_each_child(glink->dev, NULL, qcom_glink_remove_device);
if (ret)
dev_warn(glink->dev, "Can't remove GLINK devices: %d\n", ret);

View File

@ -18,6 +18,7 @@ static inline void qcom_glink_ssr_notify(const char *ssr_name) {}
struct qcom_glink *qcom_glink_smem_register(struct device *parent,
struct device_node *node);
void qcom_glink_smem_unregister(struct qcom_glink *glink);
void qcom_glink_early_ssr_notify(void *data);
#else
@ -29,6 +30,8 @@ qcom_glink_smem_register(struct device *parent,
}
static inline void qcom_glink_smem_unregister(struct qcom_glink *glink) {}
static inline void qcom_glink_ssr_notify(const char *ssr_name) {}
static inline void qcom_glink_early_ssr_notify(void *data) {}
#endif
#endif