Loading drivers/rpmsg/qcom_glink_native.c +63 −17 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <linux/kthread.h> #include <linux/mailbox_client.h> #include <linux/ipc_logging.h> #include <soc/qcom/subsystem_notif.h> #include "rpmsg_internal.h" #include "qcom_glink_native.h" Loading Loading @@ -284,13 +285,22 @@ static void qcom_glink_channel_release(struct kref *ref) { struct glink_channel *channel = container_of(ref, struct glink_channel, refcount); struct glink_core_rx_intent *tmp; unsigned long flags; int iid; CH_INFO(channel, "\n"); wake_up(&channel->intent_req_event); spin_lock_irqsave(&channel->intent_lock, flags); idr_for_each_entry(&channel->liids, tmp, iid) { kfree(tmp->data); kfree(tmp); } idr_destroy(&channel->liids); idr_for_each_entry(&channel->riids, tmp, iid) kfree(tmp); idr_destroy(&channel->riids); spin_unlock_irqrestore(&channel->intent_lock, flags); Loading Loading @@ -813,9 +823,11 @@ static void qcom_glink_handle_rx_done(struct qcom_glink *glink, static void qcom_glink_handle_intent_req(struct qcom_glink *glink, u32 cid, size_t size) { struct glink_core_rx_intent *intent; struct glink_core_rx_intent *intent = NULL; struct glink_core_rx_intent *tmp; struct glink_channel *channel; unsigned long flags; int iid; spin_lock_irqsave(&glink->idr_lock, flags); channel = idr_find(&glink->rcids, cid); Loading @@ -826,6 +838,19 @@ static void qcom_glink_handle_intent_req(struct qcom_glink *glink, return; } spin_lock_irqsave(&channel->intent_lock, flags); idr_for_each_entry(&channel->liids, tmp, iid) { if (tmp->size >= size && tmp->reuse) { intent = tmp; break; } } spin_unlock_irqrestore(&channel->intent_lock, flags); if (intent) { qcom_glink_send_intent_req_ack(glink, channel, !!intent); return; } intent = qcom_glink_alloc_intent(glink, channel, size, false); if (intent) qcom_glink_advertise_intent(glink, channel, intent); Loading Loading @@ -1614,7 +1639,7 @@ static int qcom_glink_rx_open(struct qcom_glink *glink, unsigned int rcid, ret = rpmsg_register_device(rpdev); if (ret) goto free_rpdev; goto rcid_remove; channel->rpdev = rpdev; } Loading @@ -1622,9 +1647,6 @@ static int qcom_glink_rx_open(struct qcom_glink *glink, unsigned int rcid, return 0; free_rpdev: CH_INFO(channel, "free_rpdev\n"); kfree(rpdev); rcid_remove: CH_INFO(channel, "rcid_remove\n"); spin_lock_irqsave(&glink->idr_lock, flags); Loading Loading @@ -1816,6 +1838,23 @@ static void qcom_glink_set_affinity(struct qcom_glink *glink, u32 *arr, dev_err(glink->dev, "failed to set task affinity\n"); } static void qcom_glink_notif_reset(void *data) { struct qcom_glink *glink = data; struct glink_channel *channel; unsigned long flags; int cid; if (!glink) return; atomic_inc(&glink->in_reset); spin_lock_irqsave(&glink->idr_lock, flags); idr_for_each_entry(&glink->lcids, channel, cid) { wake_up(&channel->intent_req_event); } spin_unlock_irqrestore(&glink->idr_lock, flags); } struct qcom_glink *qcom_glink_native_probe(struct device *dev, unsigned long features, Loading Loading @@ -1874,6 +1913,13 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev, return ERR_CAST(glink->task); } ret = subsys_register_early_notifier(glink->name, XPORT_LAYER_NOTIF, qcom_glink_notif_reset, glink); if (ret) { dev_err(dev, "failed to register early notif %d\n", ret); return ERR_PTR(ret); } irq = of_irq_get(dev->of_node, 0); ret = devm_request_irq(dev, irq, qcom_glink_native_intr, Loading @@ -1881,7 +1927,7 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev, "glink-native", glink); if (ret) { dev_err(dev, "failed to request IRQ\n"); return ERR_PTR(ret); goto unregister; } glink->irq = irq; Loading @@ -1889,8 +1935,10 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev, size = of_property_count_u32_elems(dev->of_node, "cpu-affinity"); if (size > 0) { arr = kmalloc_array(size, sizeof(u32), GFP_KERNEL); if (!arr) return ERR_PTR(-ENOMEM); if (!arr) { ret = -ENOMEM; goto unregister; } ret = of_property_read_u32_array(dev->of_node, "cpu-affinity", arr, size); if (!ret) Loading @@ -1901,7 +1949,7 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev, ret = qcom_glink_send_version(glink); if (ret) { dev_err(dev, "failed to send version %d\n", ret); return ERR_PTR(ret); goto unregister; } ret = qcom_glink_create_chrdev(glink); Loading @@ -1911,6 +1959,10 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev, glink->ilc = ipc_log_context_create(GLINK_LOG_PAGE_CNT, glink->name, 0); return glink; unregister: subsys_unregister_early_notifier(glink->name, XPORT_LAYER_NOTIF); return ERR_PTR(ret); } EXPORT_SYMBOL_GPL(qcom_glink_native_probe); Loading @@ -1928,17 +1980,11 @@ void qcom_glink_native_remove(struct qcom_glink *glink) int ret; unsigned long flags; atomic_inc(&glink->in_reset); subsys_unregister_early_notifier(glink->name, XPORT_LAYER_NOTIF); qcom_glink_notif_reset(glink); disable_irq(glink->irq); cancel_work_sync(&glink->rx_work); /* 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_event); } 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); Loading Loading
drivers/rpmsg/qcom_glink_native.c +63 −17 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <linux/kthread.h> #include <linux/mailbox_client.h> #include <linux/ipc_logging.h> #include <soc/qcom/subsystem_notif.h> #include "rpmsg_internal.h" #include "qcom_glink_native.h" Loading Loading @@ -284,13 +285,22 @@ static void qcom_glink_channel_release(struct kref *ref) { struct glink_channel *channel = container_of(ref, struct glink_channel, refcount); struct glink_core_rx_intent *tmp; unsigned long flags; int iid; CH_INFO(channel, "\n"); wake_up(&channel->intent_req_event); spin_lock_irqsave(&channel->intent_lock, flags); idr_for_each_entry(&channel->liids, tmp, iid) { kfree(tmp->data); kfree(tmp); } idr_destroy(&channel->liids); idr_for_each_entry(&channel->riids, tmp, iid) kfree(tmp); idr_destroy(&channel->riids); spin_unlock_irqrestore(&channel->intent_lock, flags); Loading Loading @@ -813,9 +823,11 @@ static void qcom_glink_handle_rx_done(struct qcom_glink *glink, static void qcom_glink_handle_intent_req(struct qcom_glink *glink, u32 cid, size_t size) { struct glink_core_rx_intent *intent; struct glink_core_rx_intent *intent = NULL; struct glink_core_rx_intent *tmp; struct glink_channel *channel; unsigned long flags; int iid; spin_lock_irqsave(&glink->idr_lock, flags); channel = idr_find(&glink->rcids, cid); Loading @@ -826,6 +838,19 @@ static void qcom_glink_handle_intent_req(struct qcom_glink *glink, return; } spin_lock_irqsave(&channel->intent_lock, flags); idr_for_each_entry(&channel->liids, tmp, iid) { if (tmp->size >= size && tmp->reuse) { intent = tmp; break; } } spin_unlock_irqrestore(&channel->intent_lock, flags); if (intent) { qcom_glink_send_intent_req_ack(glink, channel, !!intent); return; } intent = qcom_glink_alloc_intent(glink, channel, size, false); if (intent) qcom_glink_advertise_intent(glink, channel, intent); Loading Loading @@ -1614,7 +1639,7 @@ static int qcom_glink_rx_open(struct qcom_glink *glink, unsigned int rcid, ret = rpmsg_register_device(rpdev); if (ret) goto free_rpdev; goto rcid_remove; channel->rpdev = rpdev; } Loading @@ -1622,9 +1647,6 @@ static int qcom_glink_rx_open(struct qcom_glink *glink, unsigned int rcid, return 0; free_rpdev: CH_INFO(channel, "free_rpdev\n"); kfree(rpdev); rcid_remove: CH_INFO(channel, "rcid_remove\n"); spin_lock_irqsave(&glink->idr_lock, flags); Loading Loading @@ -1816,6 +1838,23 @@ static void qcom_glink_set_affinity(struct qcom_glink *glink, u32 *arr, dev_err(glink->dev, "failed to set task affinity\n"); } static void qcom_glink_notif_reset(void *data) { struct qcom_glink *glink = data; struct glink_channel *channel; unsigned long flags; int cid; if (!glink) return; atomic_inc(&glink->in_reset); spin_lock_irqsave(&glink->idr_lock, flags); idr_for_each_entry(&glink->lcids, channel, cid) { wake_up(&channel->intent_req_event); } spin_unlock_irqrestore(&glink->idr_lock, flags); } struct qcom_glink *qcom_glink_native_probe(struct device *dev, unsigned long features, Loading Loading @@ -1874,6 +1913,13 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev, return ERR_CAST(glink->task); } ret = subsys_register_early_notifier(glink->name, XPORT_LAYER_NOTIF, qcom_glink_notif_reset, glink); if (ret) { dev_err(dev, "failed to register early notif %d\n", ret); return ERR_PTR(ret); } irq = of_irq_get(dev->of_node, 0); ret = devm_request_irq(dev, irq, qcom_glink_native_intr, Loading @@ -1881,7 +1927,7 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev, "glink-native", glink); if (ret) { dev_err(dev, "failed to request IRQ\n"); return ERR_PTR(ret); goto unregister; } glink->irq = irq; Loading @@ -1889,8 +1935,10 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev, size = of_property_count_u32_elems(dev->of_node, "cpu-affinity"); if (size > 0) { arr = kmalloc_array(size, sizeof(u32), GFP_KERNEL); if (!arr) return ERR_PTR(-ENOMEM); if (!arr) { ret = -ENOMEM; goto unregister; } ret = of_property_read_u32_array(dev->of_node, "cpu-affinity", arr, size); if (!ret) Loading @@ -1901,7 +1949,7 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev, ret = qcom_glink_send_version(glink); if (ret) { dev_err(dev, "failed to send version %d\n", ret); return ERR_PTR(ret); goto unregister; } ret = qcom_glink_create_chrdev(glink); Loading @@ -1911,6 +1959,10 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev, glink->ilc = ipc_log_context_create(GLINK_LOG_PAGE_CNT, glink->name, 0); return glink; unregister: subsys_unregister_early_notifier(glink->name, XPORT_LAYER_NOTIF); return ERR_PTR(ret); } EXPORT_SYMBOL_GPL(qcom_glink_native_probe); Loading @@ -1928,17 +1980,11 @@ void qcom_glink_native_remove(struct qcom_glink *glink) int ret; unsigned long flags; atomic_inc(&glink->in_reset); subsys_unregister_early_notifier(glink->name, XPORT_LAYER_NOTIF); qcom_glink_notif_reset(glink); disable_irq(glink->irq); cancel_work_sync(&glink->rx_work); /* 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_event); } 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); Loading