struct virtqueue *vq[2];
int base_vq_id;
int num_of_vqs;
- u32 vproc_id;
- struct notifier_block nb;
+ struct imx_rpmsg_vproc *rpdev;
};
struct imx_rpmsg_vproc {
u32 out_idx;
u32 core_id;
u32 mub_partition;
- struct notifier_block *pnotifier;
+ struct notifier_block proc_nb;
spinlock_t mu_lock;
struct platform_device *pdev;
};
struct imx_rpmsg_vproc *rpdev;
};
-static int imx_rpmsg_partion_notify0(struct notifier_block *nb,
- unsigned long event, void *group);
-static int imx_rpmsg_partion_notify1(struct notifier_block *nb,
- unsigned long event, void *group);
-
-static struct imx_rpmsg_vproc imx_rpmsg_vprocs[];
-
static u64 imx_rpmsg_get_features(struct virtio_device *vdev)
{
/* VIRTIO_RPMSG_F_NS has been made private */
return true;
}
-static int imx_mu_rpmsg_callback(struct notifier_block *this,
- unsigned long index, void *data)
-{
- u32 mu_msg = (phys_addr_t) data;
- struct imx_virdev *virdev;
-
- virdev = container_of(this, struct imx_virdev, nb);
-
- pr_debug("%s mu_msg: 0x%x\n", __func__, mu_msg);
- /* ignore vq indices which are clearly not for us */
- mu_msg = mu_msg >> 16;
- if (mu_msg < virdev->base_vq_id || mu_msg > virdev->base_vq_id + 1) {
- pr_debug("mu_msg: 0x%x is invalid\n", mu_msg);
- return NOTIFY_DONE;
- }
-
- mu_msg -= virdev->base_vq_id;
-
- /*
- * Currently both PENDING_MSG and explicit-virtqueue-index
- * messaging are supported.
- * Whatever approach is taken, at this point 'mu_msg' contains
- * the index of the vring which was just triggered.
- */
- if (mu_msg < virdev->num_of_vqs)
- vring_interrupt(mu_msg, virdev->vq[mu_msg]);
-
- return NOTIFY_DONE;
-}
-
-static int imx_mu_rpmsg_register_nb(struct imx_rpmsg_vproc *rpdev,
- struct notifier_block *nb)
-{
- if ((rpdev == NULL) || (nb == NULL))
- return -EINVAL;
-
- blocking_notifier_chain_register(&(rpdev->notifier), nb);
-
- return 0;
-}
-
-static int imx_mu_rpmsg_unregister_nb(struct imx_rpmsg_vproc *rpdev,
- struct notifier_block *nb)
-{
- if ((rpdev == NULL) || (nb == NULL))
- return -EINVAL;
-
- blocking_notifier_chain_unregister(&(rpdev->notifier), nb);
-
- return 0;
-}
-
static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
unsigned int index,
void (*callback)(struct virtqueue *vq),
bool ctx)
{
struct imx_virdev *virdev = to_imx_virdev(vdev);
- int id = virdev->vproc_id;
- struct imx_rpmsg_vproc *rpdev = &imx_rpmsg_vprocs[id];
+ struct imx_rpmsg_vproc *rpdev = virdev->rpdev;
struct imx_rpmsg_vq_info *rpvq;
struct virtqueue *vq;
int err;
static void imx_rpmsg_del_vqs(struct virtio_device *vdev)
{
struct virtqueue *vq, *n;
- struct imx_virdev *virdev = to_imx_virdev(vdev);
- int id = virdev->vproc_id;
- struct imx_rpmsg_vproc *rpdev = &imx_rpmsg_vprocs[id];
list_for_each_entry_safe(vq, n, &vdev->vqs, list) {
struct imx_rpmsg_vq_info *rpvq = vq->priv;
vring_del_virtqueue(vq);
kfree(rpvq);
}
-
- if (&virdev->nb)
- imx_mu_rpmsg_unregister_nb(rpdev, &virdev->nb);
}
static int imx_rpmsg_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
struct irq_affinity *desc)
{
struct imx_virdev *virdev = to_imx_virdev(vdev);
- int id = virdev->vproc_id;
- struct imx_rpmsg_vproc *rpdev = &imx_rpmsg_vprocs[id];
int i, err;
/* we maintain two virtqueues per remote processor (for RX and TX) */
}
virdev->num_of_vqs = nvqs;
-
- virdev->nb.notifier_call = imx_mu_rpmsg_callback;
- imx_mu_rpmsg_register_nb(rpdev, &virdev->nb);
-
return 0;
error:
.get_status = imx_rpmsg_get_status,
};
-static struct notifier_block imx_rpmsg_partion_notifier[] = {
- {
- .notifier_call = imx_rpmsg_partion_notify0,
- },
- {
- .notifier_call = imx_rpmsg_partion_notify1,
- },
-};
-
-static struct imx_rpmsg_vproc imx_rpmsg_vprocs[] = {
- {
- .rproc_name = "m4",
- .pnotifier = &imx_rpmsg_partion_notifier[0],
- },
- {
- .rproc_name = "m4",
- .pnotifier = &imx_rpmsg_partion_notifier[1],
- },
-};
-
static const struct of_device_id imx_rpmsg_dt_ids[] = {
{ .compatible = "fsl,imx6sx-rpmsg", .data = (void *)IMX6SX, },
{ .compatible = "fsl,imx7d-rpmsg", .data = (void *)IMX7D, },
{
u32 message;
unsigned long flags;
+ struct imx_virdev *virdev;
struct delayed_work *dwork = to_delayed_work(work);
struct imx_rpmsg_vproc *rpdev = container_of(dwork,
struct imx_rpmsg_vproc, rpmsg_work);
message = rpdev->m4_message[rpdev->out_idx % MAX_NUM];
spin_unlock_irqrestore(&rpdev->mu_lock, flags);
- blocking_notifier_call_chain(&(rpdev->notifier), 4,
- (void *)(phys_addr_t)message);
+ virdev = rpdev->ivdev[(message >> 16) / 2];
+
+ pr_debug("%s msg: 0x%x\n", __func__, message);
+ message = message >> 16;
+ message -= virdev->base_vq_id;
+
+ /*
+ * Currently both PENDING_MSG and explicit-virtqueue-index
+ * messaging are supported.
+ * Whatever approach is taken, at this point message contains
+ * the index of the vring which was just triggered.
+ */
+ if (message < virdev->num_of_vqs)
+ vring_interrupt(message, virdev->vq[message]);
spin_lock_irqsave(&rpdev->mu_lock, flags);
rpdev->m4_message[rpdev->out_idx % MAX_NUM] = 0;
rpdev->ivdev[i]->vdev.dev.parent = &rpdev->pdev->dev;
rpdev->ivdev[i]->vdev.dev.release = imx_rpmsg_vproc_release;
rpdev->ivdev[i]->base_vq_id = i * 2;
- rpdev->ivdev[i]->vproc_id = rpdev->core_id;
+ rpdev->ivdev[i]->rpdev = rpdev;
if (register_virtio_device(&rpdev->ivdev[i]->vdev))
pr_err("%s failed to register rpdev.\n", __func__);
}
}
-static int imx_rpmsg_partion_notify0(struct notifier_block *nb,
+static int imx_rpmsg_partion_notify(struct notifier_block *nb,
unsigned long event, void *group)
{
#ifdef CONFIG_HAVE_IMX_SC
- struct imx_rpmsg_vproc *rpdev = &imx_rpmsg_vprocs[0];
-
- /* Ignore other irqs */
- if (!((event & BIT(rpdev->mub_partition)) &&
- (*(sc_irq_group_t *)group == SC_IRQ_GROUP_REBOOTED)))
- return 0;
-
- imx_rpmsg_restore(rpdev);
- pr_info("Patition%d reset!\n", rpdev->mub_partition);
-#endif
- return 0;
-}
+ struct imx_rpmsg_vproc *rpdev;
-static int imx_rpmsg_partion_notify1(struct notifier_block *nb,
- unsigned long event, void *group)
-{
-#ifdef CONFIG_HAVE_IMX_SC
- struct imx_rpmsg_vproc *rpdev = &imx_rpmsg_vprocs[1];
+ rpdev = container_of(nb, struct imx_rpmsg_vproc, proc_nb);
/* Ignore other irqs */
if (!((event & BIT(rpdev->mub_partition)) &&
struct device_node *np = pdev->dev.of_node;
struct imx_rpmsg_vproc *rpdev;
+ rpdev = devm_kzalloc(dev, sizeof(*rpdev), GFP_KERNEL);
+ if (!rpdev)
+ return -ENOMEM;
+ rpdev->none_suspend = 1;
+ rpdev->rproc_name = "m4";
+ rpdev->proc_nb.notifier_call = imx_rpmsg_partion_notify;
+
if (of_property_read_u32(np, "multi-core-id", &core_id))
core_id = 0;
- rpdev = &imx_rpmsg_vprocs[core_id];
rpdev->core_id = core_id;
rpdev->variant = (enum imx_rpmsg_variants)of_device_get_match_data(dev);
rpdev->ivdev[j]->vdev.dev.parent = &pdev->dev;
rpdev->ivdev[j]->vdev.dev.release = imx_rpmsg_vproc_release;
rpdev->ivdev[j]->base_vq_id = j * 2;
- rpdev->ivdev[j]->vproc_id = rpdev->core_id;
+ rpdev->ivdev[j]->rpdev = rpdev;
ret = register_virtio_device(&rpdev->ivdev[j]->vdev);
if (ret) {
if (sciErr)
pr_info("Cannot request partition reset interrupt\n");
- return register_scu_notifier(rpdev->pnotifier);
+ return register_scu_notifier(&rpdev->proc_nb);
}
#endif