1 /* Intel(R) Ethernet Switch Host Interface Driver 2 * Copyright(c) 2013 - 2016 Intel Corporation. 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms and conditions of the GNU General Public License, 6 * version 2, as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 * more details. 12 * 13 * The full GNU General Public License is included in this distribution in 14 * the file called "COPYING". 15 * 16 * Contact Information: 17 * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> 18 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 19 */ 20 21 #include "fm10k.h" 22 23 #include <linux/debugfs.h> 24 #include <linux/seq_file.h> 25 26 static struct dentry *dbg_root; 27 28 /* Descriptor Seq Functions */ 29 30 static void *fm10k_dbg_desc_seq_start(struct seq_file *s, loff_t *pos) 31 { 32 struct fm10k_ring *ring = s->private; 33 34 return (*pos < ring->count) ? pos : NULL; 35 } 36 37 static void *fm10k_dbg_desc_seq_next(struct seq_file *s, 38 void __always_unused *v, 39 loff_t *pos) 40 { 41 struct fm10k_ring *ring = s->private; 42 43 return (++(*pos) < ring->count) ? pos : NULL; 44 } 45 46 static void fm10k_dbg_desc_seq_stop(struct seq_file __always_unused *s, 47 void __always_unused *v) 48 { 49 /* Do nothing. */ 50 } 51 52 static void fm10k_dbg_desc_break(struct seq_file *s, int i) 53 { 54 while (i--) 55 seq_puts(s, "-"); 56 57 seq_puts(s, "\n"); 58 } 59 60 static int fm10k_dbg_tx_desc_seq_show(struct seq_file *s, void *v) 61 { 62 struct fm10k_ring *ring = s->private; 63 int i = *(loff_t *)v; 64 static const char tx_desc_hdr[] = 65 "DES BUFFER_ADDRESS LENGTH VLAN MSS HDRLEN FLAGS\n"; 66 67 /* Generate header */ 68 if (!i) { 69 seq_printf(s, tx_desc_hdr); 70 fm10k_dbg_desc_break(s, sizeof(tx_desc_hdr) - 1); 71 } 72 73 /* Validate descriptor allocation */ 74 if (!ring->desc) { 75 seq_printf(s, "%03X Descriptor ring not allocated.\n", i); 76 } else { 77 struct fm10k_tx_desc *txd = FM10K_TX_DESC(ring, i); 78 79 seq_printf(s, "%03X %#018llx %#06x %#06x %#06x %#06x %#04x\n", 80 i, txd->buffer_addr, txd->buflen, txd->vlan, 81 txd->mss, txd->hdrlen, txd->flags); 82 } 83 84 return 0; 85 } 86 87 static int fm10k_dbg_rx_desc_seq_show(struct seq_file *s, void *v) 88 { 89 struct fm10k_ring *ring = s->private; 90 int i = *(loff_t *)v; 91 static const char rx_desc_hdr[] = 92 "DES DATA RSS STATERR LENGTH VLAN DGLORT SGLORT TIMESTAMP\n"; 93 94 /* Generate header */ 95 if (!i) { 96 seq_printf(s, rx_desc_hdr); 97 fm10k_dbg_desc_break(s, sizeof(rx_desc_hdr) - 1); 98 } 99 100 /* Validate descriptor allocation */ 101 if (!ring->desc) { 102 seq_printf(s, "%03X Descriptor ring not allocated.\n", i); 103 } else { 104 union fm10k_rx_desc *rxd = FM10K_RX_DESC(ring, i); 105 106 seq_printf(s, 107 "%03X %#010x %#010x %#010x %#06x %#06x %#06x %#06x %#018llx\n", 108 i, rxd->d.data, rxd->d.rss, rxd->d.staterr, 109 rxd->w.length, rxd->w.vlan, rxd->w.dglort, 110 rxd->w.sglort, rxd->q.timestamp); 111 } 112 113 return 0; 114 } 115 116 static const struct seq_operations fm10k_dbg_tx_desc_seq_ops = { 117 .start = fm10k_dbg_desc_seq_start, 118 .next = fm10k_dbg_desc_seq_next, 119 .stop = fm10k_dbg_desc_seq_stop, 120 .show = fm10k_dbg_tx_desc_seq_show, 121 }; 122 123 static const struct seq_operations fm10k_dbg_rx_desc_seq_ops = { 124 .start = fm10k_dbg_desc_seq_start, 125 .next = fm10k_dbg_desc_seq_next, 126 .stop = fm10k_dbg_desc_seq_stop, 127 .show = fm10k_dbg_rx_desc_seq_show, 128 }; 129 130 static int fm10k_dbg_desc_open(struct inode *inode, struct file *filep) 131 { 132 struct fm10k_ring *ring = inode->i_private; 133 struct fm10k_q_vector *q_vector = ring->q_vector; 134 const struct seq_operations *desc_seq_ops; 135 int err; 136 137 if (ring < q_vector->rx.ring) 138 desc_seq_ops = &fm10k_dbg_tx_desc_seq_ops; 139 else 140 desc_seq_ops = &fm10k_dbg_rx_desc_seq_ops; 141 142 err = seq_open(filep, desc_seq_ops); 143 if (err) 144 return err; 145 146 ((struct seq_file *)filep->private_data)->private = ring; 147 148 return 0; 149 } 150 151 static const struct file_operations fm10k_dbg_desc_fops = { 152 .owner = THIS_MODULE, 153 .open = fm10k_dbg_desc_open, 154 .read = seq_read, 155 .llseek = seq_lseek, 156 .release = seq_release, 157 }; 158 159 /** 160 * fm10k_dbg_q_vector_init - setup debugfs for the q_vectors 161 * @q_vector: q_vector to allocate directories for 162 * 163 * A folder is created for each q_vector found. In each q_vector 164 * folder, a debugfs file is created for each tx and rx ring 165 * allocated to the q_vector. 166 **/ 167 void fm10k_dbg_q_vector_init(struct fm10k_q_vector *q_vector) 168 { 169 struct fm10k_intfc *interface = q_vector->interface; 170 char name[16]; 171 int i; 172 173 if (!interface->dbg_intfc) 174 return; 175 176 /* Generate a folder for each q_vector */ 177 snprintf(name, sizeof(name), "q_vector.%03d", q_vector->v_idx); 178 179 q_vector->dbg_q_vector = debugfs_create_dir(name, interface->dbg_intfc); 180 if (!q_vector->dbg_q_vector) 181 return; 182 183 /* Generate a file for each rx ring in the q_vector */ 184 for (i = 0; i < q_vector->tx.count; i++) { 185 struct fm10k_ring *ring = &q_vector->tx.ring[i]; 186 187 snprintf(name, sizeof(name), "tx_ring.%03d", ring->queue_index); 188 189 debugfs_create_file(name, 0600, 190 q_vector->dbg_q_vector, ring, 191 &fm10k_dbg_desc_fops); 192 } 193 194 /* Generate a file for each rx ring in the q_vector */ 195 for (i = 0; i < q_vector->rx.count; i++) { 196 struct fm10k_ring *ring = &q_vector->rx.ring[i]; 197 198 snprintf(name, sizeof(name), "rx_ring.%03d", ring->queue_index); 199 200 debugfs_create_file(name, 0600, 201 q_vector->dbg_q_vector, ring, 202 &fm10k_dbg_desc_fops); 203 } 204 } 205 206 /** 207 * fm10k_dbg_free_q_vector_dir - setup debugfs for the q_vectors 208 * @q_vector: q_vector to allocate directories for 209 **/ 210 void fm10k_dbg_q_vector_exit(struct fm10k_q_vector *q_vector) 211 { 212 struct fm10k_intfc *interface = q_vector->interface; 213 214 if (interface->dbg_intfc) 215 debugfs_remove_recursive(q_vector->dbg_q_vector); 216 q_vector->dbg_q_vector = NULL; 217 } 218 219 /** 220 * fm10k_dbg_intfc_init - setup the debugfs directory for the intferface 221 * @interface: the interface that is starting up 222 **/ 223 224 void fm10k_dbg_intfc_init(struct fm10k_intfc *interface) 225 { 226 const char *name = pci_name(interface->pdev); 227 228 if (dbg_root) 229 interface->dbg_intfc = debugfs_create_dir(name, dbg_root); 230 } 231 232 /** 233 * fm10k_dbg_intfc_exit - clean out the interface's debugfs entries 234 * @interface: the interface that is stopping 235 **/ 236 void fm10k_dbg_intfc_exit(struct fm10k_intfc *interface) 237 { 238 if (dbg_root) 239 debugfs_remove_recursive(interface->dbg_intfc); 240 interface->dbg_intfc = NULL; 241 } 242 243 /** 244 * fm10k_dbg_init - start up debugfs for the driver 245 **/ 246 void fm10k_dbg_init(void) 247 { 248 dbg_root = debugfs_create_dir(fm10k_driver_name, NULL); 249 } 250 251 /** 252 * fm10k_dbg_exit - clean out the driver's debugfs entries 253 **/ 254 void fm10k_dbg_exit(void) 255 { 256 debugfs_remove_recursive(dbg_root); 257 dbg_root = NULL; 258 } 259