/**************************************************************************** * drivers/rptun/rptun_dump.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. The * ASF licenses this file to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. * ****************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include #include #include #include #include "rptun.h" /**************************************************************************** * Private Functions ****************************************************************************/ static void rptun_dump_addr(FAR struct rpmsg_device *rdev, FAR void *addr, bool rx) { FAR struct rpmsg_hdr *hdr = addr; FAR struct rpmsg_endpoint *ept; ept = rpmsg_get_ept_from_addr(rdev, rx ? hdr->dst : hdr->src); if (ept) { metal_log(METAL_LOG_EMERGENCY, " %s buffer %p hold by %s\n", rx ? "RX" : "TX", hdr, ept->name); } } static void rptun_dump_buffer(FAR struct rpmsg_virtio_device *rvdev, bool rx) { FAR struct virtqueue *vq = rx ? rvdev->rvq : rvdev->svq; FAR void *addr; int desc_idx; int num; int i; num = rptun_buffer_nused(rvdev, rx); metal_log(METAL_LOG_EMERGENCY, " %s buffer, total %d, pending %d\n", rx ? "RX" : "TX", vq->vq_nentries, num); for (i = 0; i < num; i++) { if ((rpmsg_virtio_get_role(rvdev) == RPMSG_HOST) ^ rx) { desc_idx = (vq->vq_ring.used->idx + i) & (vq->vq_nentries - 1); desc_idx = vq->vq_ring.avail->ring[desc_idx]; } else { desc_idx = (vq->vq_ring.avail->idx + i) & (vq->vq_nentries - 1); desc_idx = vq->vq_ring.used->ring[desc_idx].id; } addr = metal_io_phys_to_virt(vq->shm_io, vq->vq_ring.desc[desc_idx].addr); if (addr) { rptun_dump_addr(&rvdev->rdev, addr, rx); } } } /**************************************************************************** * Public Functions ****************************************************************************/ void rptun_dump(FAR struct rpmsg_virtio_device *rvdev) { FAR struct rpmsg_device *rdev = &rvdev->rdev; FAR struct rpmsg_endpoint *ept; FAR struct metal_list *node; bool needlock = true; if (!rvdev->vdev) { return; } if (up_interrupt_context() || sched_idletask() || nxmutex_is_hold(&rdev->lock)) { needlock = false; } if (needlock) { metal_mutex_acquire(&rdev->lock); } metal_log(METAL_LOG_EMERGENCY, "Dump rpmsg info between cpu (master: %s)%s <==> %s:\n", rpmsg_virtio_get_role(rvdev) == RPMSG_HOST ? "yes" : "no", CONFIG_RPMSG_LOCAL_CPUNAME, rpmsg_get_cpuname(rdev)); metal_log(METAL_LOG_EMERGENCY, "rpmsg vq RX:\n"); virtqueue_dump(rvdev->rvq); metal_log(METAL_LOG_EMERGENCY, "rpmsg vq TX:\n"); virtqueue_dump(rvdev->svq); metal_log(METAL_LOG_EMERGENCY, " rpmsg ept list:\n"); metal_list_for_each(&rdev->endpoints, node) { ept = metal_container_of(node, struct rpmsg_endpoint, node); metal_log(METAL_LOG_EMERGENCY, " ept %s\n", ept->name); } metal_log(METAL_LOG_EMERGENCY, " rpmsg buffer list:\n"); rptun_dump_buffer(rvdev, true); rptun_dump_buffer(rvdev, false); if (needlock) { metal_mutex_release(&rdev->lock); } }