b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame^] | 1 | // SPDX-License-Identifier: GPL-2.0-only |
| 2 | /* |
| 3 | * Intel MIC Platform Software Stack (MPSS) |
| 4 | * |
| 5 | * Copyright(c) 2016 Intel Corporation. |
| 6 | * |
| 7 | * Intel Virtio Over PCIe (VOP) driver. |
| 8 | */ |
| 9 | #include <linux/debugfs.h> |
| 10 | #include <linux/seq_file.h> |
| 11 | |
| 12 | #include "vop_main.h" |
| 13 | |
| 14 | static int vop_dp_show(struct seq_file *s, void *pos) |
| 15 | { |
| 16 | struct mic_device_desc *d; |
| 17 | struct mic_device_ctrl *dc; |
| 18 | struct mic_vqconfig *vqconfig; |
| 19 | __u32 *features; |
| 20 | __u8 *config; |
| 21 | struct vop_info *vi = s->private; |
| 22 | struct vop_device *vpdev = vi->vpdev; |
| 23 | struct mic_bootparam *bootparam = vpdev->hw_ops->get_dp(vpdev); |
| 24 | int j, k; |
| 25 | |
| 26 | seq_printf(s, "Bootparam: magic 0x%x\n", |
| 27 | bootparam->magic); |
| 28 | seq_printf(s, "Bootparam: h2c_config_db %d\n", |
| 29 | bootparam->h2c_config_db); |
| 30 | seq_printf(s, "Bootparam: node_id %d\n", |
| 31 | bootparam->node_id); |
| 32 | seq_printf(s, "Bootparam: c2h_scif_db %d\n", |
| 33 | bootparam->c2h_scif_db); |
| 34 | seq_printf(s, "Bootparam: h2c_scif_db %d\n", |
| 35 | bootparam->h2c_scif_db); |
| 36 | seq_printf(s, "Bootparam: scif_host_dma_addr 0x%llx\n", |
| 37 | bootparam->scif_host_dma_addr); |
| 38 | seq_printf(s, "Bootparam: scif_card_dma_addr 0x%llx\n", |
| 39 | bootparam->scif_card_dma_addr); |
| 40 | |
| 41 | for (j = sizeof(*bootparam); |
| 42 | j < MIC_DP_SIZE; j += mic_total_desc_size(d)) { |
| 43 | d = (void *)bootparam + j; |
| 44 | dc = (void *)d + mic_aligned_desc_size(d); |
| 45 | |
| 46 | /* end of list */ |
| 47 | if (d->type == 0) |
| 48 | break; |
| 49 | |
| 50 | if (d->type == -1) |
| 51 | continue; |
| 52 | |
| 53 | seq_printf(s, "Type %d ", d->type); |
| 54 | seq_printf(s, "Num VQ %d ", d->num_vq); |
| 55 | seq_printf(s, "Feature Len %d\n", d->feature_len); |
| 56 | seq_printf(s, "Config Len %d ", d->config_len); |
| 57 | seq_printf(s, "Shutdown Status %d\n", d->status); |
| 58 | |
| 59 | for (k = 0; k < d->num_vq; k++) { |
| 60 | vqconfig = mic_vq_config(d) + k; |
| 61 | seq_printf(s, "vqconfig[%d]: ", k); |
| 62 | seq_printf(s, "address 0x%llx ", |
| 63 | vqconfig->address); |
| 64 | seq_printf(s, "num %d ", vqconfig->num); |
| 65 | seq_printf(s, "used address 0x%llx\n", |
| 66 | vqconfig->used_address); |
| 67 | } |
| 68 | |
| 69 | features = (__u32 *)mic_vq_features(d); |
| 70 | seq_printf(s, "Features: Host 0x%x ", features[0]); |
| 71 | seq_printf(s, "Guest 0x%x\n", features[1]); |
| 72 | |
| 73 | config = mic_vq_configspace(d); |
| 74 | for (k = 0; k < d->config_len; k++) |
| 75 | seq_printf(s, "config[%d]=%d\n", k, config[k]); |
| 76 | |
| 77 | seq_puts(s, "Device control:\n"); |
| 78 | seq_printf(s, "Config Change %d ", dc->config_change); |
| 79 | seq_printf(s, "Vdev reset %d\n", dc->vdev_reset); |
| 80 | seq_printf(s, "Guest Ack %d ", dc->guest_ack); |
| 81 | seq_printf(s, "Host ack %d\n", dc->host_ack); |
| 82 | seq_printf(s, "Used address updated %d ", |
| 83 | dc->used_address_updated); |
| 84 | seq_printf(s, "Vdev 0x%llx\n", dc->vdev); |
| 85 | seq_printf(s, "c2h doorbell %d ", dc->c2h_vdev_db); |
| 86 | seq_printf(s, "h2c doorbell %d\n", dc->h2c_vdev_db); |
| 87 | } |
| 88 | schedule_work(&vi->hotplug_work); |
| 89 | return 0; |
| 90 | } |
| 91 | |
| 92 | DEFINE_SHOW_ATTRIBUTE(vop_dp); |
| 93 | |
| 94 | static int vop_vdev_info_show(struct seq_file *s, void *unused) |
| 95 | { |
| 96 | struct vop_info *vi = s->private; |
| 97 | struct list_head *pos, *tmp; |
| 98 | struct vop_vdev *vdev; |
| 99 | int i, j; |
| 100 | |
| 101 | mutex_lock(&vi->vop_mutex); |
| 102 | list_for_each_safe(pos, tmp, &vi->vdev_list) { |
| 103 | vdev = list_entry(pos, struct vop_vdev, list); |
| 104 | seq_printf(s, "VDEV type %d state %s in %ld out %ld in_dma %ld out_dma %ld\n", |
| 105 | vdev->virtio_id, |
| 106 | vop_vdevup(vdev) ? "UP" : "DOWN", |
| 107 | vdev->in_bytes, |
| 108 | vdev->out_bytes, |
| 109 | vdev->in_bytes_dma, |
| 110 | vdev->out_bytes_dma); |
| 111 | for (i = 0; i < MIC_MAX_VRINGS; i++) { |
| 112 | struct vring_desc *desc; |
| 113 | struct vring_avail *avail; |
| 114 | struct vring_used *used; |
| 115 | struct vop_vringh *vvr = &vdev->vvr[i]; |
| 116 | struct vringh *vrh = &vvr->vrh; |
| 117 | int num = vrh->vring.num; |
| 118 | |
| 119 | if (!num) |
| 120 | continue; |
| 121 | desc = vrh->vring.desc; |
| 122 | seq_printf(s, "vring i %d avail_idx %d", |
| 123 | i, vvr->vring.info->avail_idx & (num - 1)); |
| 124 | seq_printf(s, " vring i %d avail_idx %d\n", |
| 125 | i, vvr->vring.info->avail_idx); |
| 126 | seq_printf(s, "vrh i %d weak_barriers %d", |
| 127 | i, vrh->weak_barriers); |
| 128 | seq_printf(s, " last_avail_idx %d last_used_idx %d", |
| 129 | vrh->last_avail_idx, vrh->last_used_idx); |
| 130 | seq_printf(s, " completed %d\n", vrh->completed); |
| 131 | for (j = 0; j < num; j++) { |
| 132 | seq_printf(s, "desc[%d] addr 0x%llx len %d", |
| 133 | j, desc->addr, desc->len); |
| 134 | seq_printf(s, " flags 0x%x next %d\n", |
| 135 | desc->flags, desc->next); |
| 136 | desc++; |
| 137 | } |
| 138 | avail = vrh->vring.avail; |
| 139 | seq_printf(s, "avail flags 0x%x idx %d\n", |
| 140 | vringh16_to_cpu(vrh, avail->flags), |
| 141 | vringh16_to_cpu(vrh, |
| 142 | avail->idx) & (num - 1)); |
| 143 | seq_printf(s, "avail flags 0x%x idx %d\n", |
| 144 | vringh16_to_cpu(vrh, avail->flags), |
| 145 | vringh16_to_cpu(vrh, avail->idx)); |
| 146 | for (j = 0; j < num; j++) |
| 147 | seq_printf(s, "avail ring[%d] %d\n", |
| 148 | j, avail->ring[j]); |
| 149 | used = vrh->vring.used; |
| 150 | seq_printf(s, "used flags 0x%x idx %d\n", |
| 151 | vringh16_to_cpu(vrh, used->flags), |
| 152 | vringh16_to_cpu(vrh, used->idx) & (num - 1)); |
| 153 | seq_printf(s, "used flags 0x%x idx %d\n", |
| 154 | vringh16_to_cpu(vrh, used->flags), |
| 155 | vringh16_to_cpu(vrh, used->idx)); |
| 156 | for (j = 0; j < num; j++) |
| 157 | seq_printf(s, "used ring[%d] id %d len %d\n", |
| 158 | j, vringh32_to_cpu(vrh, |
| 159 | used->ring[j].id), |
| 160 | vringh32_to_cpu(vrh, |
| 161 | used->ring[j].len)); |
| 162 | } |
| 163 | } |
| 164 | mutex_unlock(&vi->vop_mutex); |
| 165 | |
| 166 | return 0; |
| 167 | } |
| 168 | |
| 169 | DEFINE_SHOW_ATTRIBUTE(vop_vdev_info); |
| 170 | |
| 171 | void vop_init_debugfs(struct vop_info *vi) |
| 172 | { |
| 173 | char name[16]; |
| 174 | |
| 175 | snprintf(name, sizeof(name), "%s%d", KBUILD_MODNAME, vi->vpdev->dnode); |
| 176 | vi->dbg = debugfs_create_dir(name, NULL); |
| 177 | debugfs_create_file("dp", 0444, vi->dbg, vi, &vop_dp_fops); |
| 178 | debugfs_create_file("vdev_info", 0444, vi->dbg, vi, &vop_vdev_info_fops); |
| 179 | } |
| 180 | |
| 181 | void vop_exit_debugfs(struct vop_info *vi) |
| 182 | { |
| 183 | debugfs_remove_recursive(vi->dbg); |
| 184 | } |