Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

wusb: add debug files for ASL, PZL and DI to the whci-hcd driver

Add asl, pzl and di debugfs files to uwb/uwbN/wusbhc for WHCI host
controller. These dump the current ASL, PZL and DI buffer.

Signed-off-by: David Vrabel <david.vrabel@csr.com>

+223 -123
+1
drivers/usb/host/whci/Kbuild
··· 2 2 3 3 whci-hcd-y := \ 4 4 asl.o \ 5 + debug.o \ 5 6 hcd.o \ 6 7 hw.o \ 7 8 init.o \
-25
drivers/usb/host/whci/asl.c
··· 19 19 #include <linux/dma-mapping.h> 20 20 #include <linux/uwb/umc.h> 21 21 #include <linux/usb.h> 22 - #define D_LOCAL 0 23 - #include <linux/uwb/debug.h> 24 22 25 23 #include "../../wusbcore/wusbhc.h" 26 24 27 25 #include "whcd.h" 28 - 29 - #if D_LOCAL >= 4 30 - static void dump_asl(struct whc *whc, const char *tag) 31 - { 32 - struct device *dev = &whc->umc->dev; 33 - struct whc_qset *qset; 34 - 35 - d_printf(4, dev, "ASL %s\n", tag); 36 - 37 - list_for_each_entry(qset, &whc->async_list, list_node) { 38 - dump_qset(qset, dev); 39 - } 40 - } 41 - #else 42 - static inline void dump_asl(struct whc *whc, const char *tag) 43 - { 44 - } 45 - #endif 46 - 47 26 48 27 static void qset_get_next_prev(struct whc *whc, struct whc_qset *qset, 49 28 struct whc_qset **next, struct whc_qset **prev) ··· 196 217 197 218 spin_lock_irq(&whc->lock); 198 219 199 - dump_asl(whc, "before processing"); 200 - 201 220 /* 202 221 * Transerve the software list backwards so new qsets can be 203 222 * safely inserted into the ASL without making it non-circular. ··· 208 231 209 232 update |= process_qset(whc, qset); 210 233 } 211 - 212 - dump_asl(whc, "after processing"); 213 234 214 235 spin_unlock_irq(&whc->lock); 215 236
+189
drivers/usb/host/whci/debug.c
··· 1 + /* 2 + * Wireless Host Controller (WHC) debug. 3 + * 4 + * Copyright (C) 2008 Cambridge Silicon Radio Ltd. 5 + * 6 + * This program is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU General Public License version 8 + * 2 as published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope that it will be useful, 11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 + * GNU General Public License for more details. 14 + * 15 + * You should have received a copy of the GNU General Public License 16 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 + */ 18 + #include <linux/kernel.h> 19 + #include <linux/debugfs.h> 20 + #include <linux/seq_file.h> 21 + 22 + #include "../../wusbcore/wusbhc.h" 23 + 24 + #include "whcd.h" 25 + 26 + struct whc_dbg { 27 + struct dentry *di_f; 28 + struct dentry *asl_f; 29 + struct dentry *pzl_f; 30 + }; 31 + 32 + void qset_print(struct seq_file *s, struct whc_qset *qset) 33 + { 34 + struct whc_std *std; 35 + struct urb *urb = NULL; 36 + int i; 37 + 38 + seq_printf(s, "qset %08x\n", (u32)qset->qset_dma); 39 + seq_printf(s, " -> %08x\n", (u32)qset->qh.link); 40 + seq_printf(s, " info: %08x %08x %08x\n", 41 + qset->qh.info1, qset->qh.info2, qset->qh.info3); 42 + seq_printf(s, " sts: %04x errs: %d\n", qset->qh.status, qset->qh.err_count); 43 + seq_printf(s, " TD: sts: %08x opts: %08x\n", 44 + qset->qh.overlay.qtd.status, qset->qh.overlay.qtd.options); 45 + 46 + for (i = 0; i < WHCI_QSET_TD_MAX; i++) { 47 + seq_printf(s, " %c%c TD[%d]: sts: %08x opts: %08x ptr: %08x\n", 48 + i == qset->td_start ? 'S' : ' ', 49 + i == qset->td_end ? 'E' : ' ', 50 + i, qset->qtd[i].status, qset->qtd[i].options, 51 + (u32)qset->qtd[i].page_list_ptr); 52 + } 53 + seq_printf(s, " ntds: %d\n", qset->ntds); 54 + list_for_each_entry(std, &qset->stds, list_node) { 55 + if (urb != std->urb) { 56 + urb = std->urb; 57 + seq_printf(s, " urb %p transferred: %d bytes\n", urb, 58 + urb->actual_length); 59 + } 60 + if (std->qtd) 61 + seq_printf(s, " sTD[%td]: %zu bytes @ %08x\n", 62 + std->qtd - &qset->qtd[0], 63 + std->len, std->num_pointers ? 64 + (u32)(std->pl_virt[0].buf_ptr) : (u32)std->dma_addr); 65 + else 66 + seq_printf(s, " sTD[-]: %zd bytes @ %08x\n", 67 + std->len, std->num_pointers ? 68 + (u32)(std->pl_virt[0].buf_ptr) : (u32)std->dma_addr); 69 + } 70 + } 71 + 72 + static int di_print(struct seq_file *s, void *p) 73 + { 74 + struct whc *whc = s->private; 75 + char buf[72]; 76 + int d; 77 + 78 + for (d = 0; d < whc->n_devices; d++) { 79 + struct di_buf_entry *di = &whc->di_buf[d]; 80 + 81 + bitmap_scnprintf(buf, sizeof(buf), 82 + (unsigned long *)di->availability_info, UWB_NUM_MAS); 83 + 84 + seq_printf(s, "DI[%d]\n", d); 85 + seq_printf(s, " availability: %s\n", buf); 86 + seq_printf(s, " %c%c key idx: %d dev addr: %d\n", 87 + (di->addr_sec_info & WHC_DI_SECURE) ? 'S' : ' ', 88 + (di->addr_sec_info & WHC_DI_DISABLE) ? 'D' : ' ', 89 + (di->addr_sec_info & WHC_DI_KEY_IDX_MASK) >> 8, 90 + (di->addr_sec_info & WHC_DI_DEV_ADDR_MASK)); 91 + } 92 + return 0; 93 + } 94 + 95 + static int asl_print(struct seq_file *s, void *p) 96 + { 97 + struct whc *whc = s->private; 98 + struct whc_qset *qset; 99 + 100 + list_for_each_entry(qset, &whc->async_list, list_node) { 101 + qset_print(s, qset); 102 + } 103 + 104 + return 0; 105 + } 106 + 107 + static int pzl_print(struct seq_file *s, void *p) 108 + { 109 + struct whc *whc = s->private; 110 + struct whc_qset *qset; 111 + int period; 112 + 113 + for (period = 0; period < 5; period++) { 114 + seq_printf(s, "Period %d\n", period); 115 + list_for_each_entry(qset, &whc->periodic_list[period], list_node) { 116 + qset_print(s, qset); 117 + } 118 + } 119 + return 0; 120 + } 121 + 122 + static int di_open(struct inode *inode, struct file *file) 123 + { 124 + return single_open(file, di_print, inode->i_private); 125 + } 126 + 127 + static int asl_open(struct inode *inode, struct file *file) 128 + { 129 + return single_open(file, asl_print, inode->i_private); 130 + } 131 + 132 + static int pzl_open(struct inode *inode, struct file *file) 133 + { 134 + return single_open(file, pzl_print, inode->i_private); 135 + } 136 + 137 + static struct file_operations di_fops = { 138 + .open = di_open, 139 + .read = seq_read, 140 + .llseek = seq_lseek, 141 + .release = single_release, 142 + .owner = THIS_MODULE, 143 + }; 144 + 145 + static struct file_operations asl_fops = { 146 + .open = asl_open, 147 + .read = seq_read, 148 + .llseek = seq_lseek, 149 + .release = single_release, 150 + .owner = THIS_MODULE, 151 + }; 152 + 153 + static struct file_operations pzl_fops = { 154 + .open = pzl_open, 155 + .read = seq_read, 156 + .llseek = seq_lseek, 157 + .release = single_release, 158 + .owner = THIS_MODULE, 159 + }; 160 + 161 + void whc_dbg_init(struct whc *whc) 162 + { 163 + if (whc->wusbhc.pal.debugfs_dir == NULL) 164 + return; 165 + 166 + whc->dbg = kzalloc(sizeof(struct whc_dbg), GFP_KERNEL); 167 + if (whc->dbg == NULL) 168 + return; 169 + 170 + whc->dbg->di_f = debugfs_create_file("di", 0444, 171 + whc->wusbhc.pal.debugfs_dir, whc, 172 + &di_fops); 173 + whc->dbg->asl_f = debugfs_create_file("asl", 0444, 174 + whc->wusbhc.pal.debugfs_dir, whc, 175 + &asl_fops); 176 + whc->dbg->pzl_f = debugfs_create_file("pzl", 0444, 177 + whc->wusbhc.pal.debugfs_dir, whc, 178 + &pzl_fops); 179 + } 180 + 181 + void whc_dbg_clean_up(struct whc *whc) 182 + { 183 + if (whc->dbg) { 184 + debugfs_remove(whc->dbg->pzl_f); 185 + debugfs_remove(whc->dbg->asl_f); 186 + debugfs_remove(whc->dbg->di_f); 187 + kfree(whc->dbg); 188 + } 189 + }
+3
drivers/usb/host/whci/hcd.c
··· 273 273 goto error_wusbhc_b_create; 274 274 } 275 275 276 + whc_dbg_init(whc); 277 + 276 278 return 0; 277 279 278 280 error_wusbhc_b_create: ··· 298 296 struct whc *whc = wusbhc_to_whc(wusbhc); 299 297 300 298 if (usb_hcd) { 299 + whc_dbg_clean_up(whc); 301 300 wusbhc_b_destroy(wusbhc); 302 301 usb_remove_hcd(usb_hcd); 303 302 wusbhc_destroy(wusbhc);
-28
drivers/usb/host/whci/pzl.c
··· 19 19 #include <linux/dma-mapping.h> 20 20 #include <linux/uwb/umc.h> 21 21 #include <linux/usb.h> 22 - #define D_LOCAL 0 23 - #include <linux/uwb/debug.h> 24 22 25 23 #include "../../wusbcore/wusbhc.h" 26 24 27 25 #include "whcd.h" 28 - 29 - #if D_LOCAL >= 4 30 - static void dump_pzl(struct whc *whc, const char *tag) 31 - { 32 - struct device *dev = &whc->umc->dev; 33 - struct whc_qset *qset; 34 - int period = 0; 35 - 36 - d_printf(4, dev, "PZL %s\n", tag); 37 - 38 - for (period = 0; period < 5; period++) { 39 - d_printf(4, dev, "Period %d\n", period); 40 - list_for_each_entry(qset, &whc->periodic_list[period], list_node) { 41 - dump_qset(qset, dev); 42 - } 43 - } 44 - } 45 - #else 46 - static inline void dump_pzl(struct whc *whc, const char *tag) 47 - { 48 - } 49 - #endif 50 26 51 27 static void update_pzl_pointers(struct whc *whc, int period, u64 addr) 52 28 { ··· 226 250 227 251 spin_lock_irq(&whc->lock); 228 252 229 - dump_pzl(whc, "before processing"); 230 - 231 253 for (period = 4; period >= 0; period--) { 232 254 list_for_each_entry_safe(qset, t, &whc->periodic_list[period], list_node) { 233 255 if (!qset->in_hw_list) ··· 236 262 237 263 if (update & (WHC_UPDATE_ADDED | WHC_UPDATE_REMOVED)) 238 264 update_pzl_hw_view(whc); 239 - 240 - dump_pzl(whc, "after processing"); 241 265 242 266 spin_unlock_irq(&whc->lock); 243 267
-40
drivers/usb/host/whci/qset.c
··· 24 24 25 25 #include "whcd.h" 26 26 27 - void dump_qset(struct whc_qset *qset, struct device *dev) 28 - { 29 - struct whc_std *std; 30 - struct urb *urb = NULL; 31 - int i; 32 - 33 - dev_dbg(dev, "qset %08x\n", (u32)qset->qset_dma); 34 - dev_dbg(dev, " -> %08x\n", (u32)qset->qh.link); 35 - dev_dbg(dev, " info: %08x %08x %08x\n", 36 - qset->qh.info1, qset->qh.info2, qset->qh.info3); 37 - dev_dbg(dev, " sts: %04x errs: %d\n", qset->qh.status, qset->qh.err_count); 38 - dev_dbg(dev, " TD: sts: %08x opts: %08x\n", 39 - qset->qh.overlay.qtd.status, qset->qh.overlay.qtd.options); 40 - 41 - for (i = 0; i < WHCI_QSET_TD_MAX; i++) { 42 - dev_dbg(dev, " %c%c TD[%d]: sts: %08x opts: %08x ptr: %08x\n", 43 - i == qset->td_start ? 'S' : ' ', 44 - i == qset->td_end ? 'E' : ' ', 45 - i, qset->qtd[i].status, qset->qtd[i].options, 46 - (u32)qset->qtd[i].page_list_ptr); 47 - } 48 - dev_dbg(dev, " ntds: %d\n", qset->ntds); 49 - list_for_each_entry(std, &qset->stds, list_node) { 50 - if (urb != std->urb) { 51 - urb = std->urb; 52 - dev_dbg(dev, " urb %p transferred: %d bytes\n", urb, 53 - urb->actual_length); 54 - } 55 - if (std->qtd) 56 - dev_dbg(dev, " sTD[%td]: %zu bytes @ %08x\n", 57 - std->qtd - &qset->qtd[0], 58 - std->len, std->num_pointers ? 59 - (u32)(std->pl_virt[0].buf_ptr) : (u32)std->dma_addr); 60 - else 61 - dev_dbg(dev, " sTD[-]: %zd bytes @ %08x\n", 62 - std->len, std->num_pointers ? 63 - (u32)(std->pl_virt[0].buf_ptr) : (u32)std->dma_addr); 64 - } 65 - } 66 - 67 27 struct whc_qset *qset_alloc(struct whc *whc, gfp_t mem_flags) 68 28 { 69 29 struct whc_qset *qset;
+8 -1
drivers/usb/host/whci/whcd.h
··· 21 21 #define __WHCD_H 22 22 23 23 #include <linux/uwb/whci.h> 24 + #include <linux/uwb/umc.h> 24 25 #include <linux/workqueue.h> 25 26 26 27 #include "whci-hc.h" ··· 29 28 /* Generic command timeout. */ 30 29 #define WHC_GENCMD_TIMEOUT_MS 100 31 30 31 + struct whc_dbg; 32 32 33 33 struct whc { 34 34 struct wusbhc wusbhc; ··· 71 69 struct list_head periodic_removed_list; 72 70 wait_queue_head_t periodic_list_wq; 73 71 struct work_struct periodic_work; 72 + 73 + struct whc_dbg *dbg; 74 74 }; 75 75 76 76 #define wusbhc_to_whc(w) (container_of((w), struct whc, wusbhc)) ··· 194 190 struct whc_qtd *qtd); 195 191 enum whc_update qset_add_qtds(struct whc *whc, struct whc_qset *qset); 196 192 void qset_remove_complete(struct whc *whc, struct whc_qset *qset); 197 - void dump_qset(struct whc_qset *qset, struct device *dev); 198 193 void pzl_update(struct whc *whc, uint32_t wusbcmd); 199 194 void asl_update(struct whc *whc, uint32_t wusbcmd); 195 + 196 + /* debug.c */ 197 + void whc_dbg_init(struct whc *whc); 198 + void whc_dbg_clean_up(struct whc *whc); 200 199 201 200 #endif /* #ifndef __WHCD_H */
-27
drivers/usb/host/whci/wusb.c
··· 18 18 #include <linux/kernel.h> 19 19 #include <linux/init.h> 20 20 #include <linux/uwb/umc.h> 21 - #define D_LOCAL 1 22 - #include <linux/uwb/debug.h> 23 21 24 22 #include "../../wusbcore/wusbhc.h" 25 23 26 24 #include "whcd.h" 27 25 28 - #if D_LOCAL >= 1 29 - static void dump_di(struct whc *whc, int idx) 30 - { 31 - struct di_buf_entry *di = &whc->di_buf[idx]; 32 - struct device *dev = &whc->umc->dev; 33 - char buf[128]; 34 - 35 - bitmap_scnprintf(buf, sizeof(buf), (unsigned long *)di->availability_info, UWB_NUM_MAS); 36 - 37 - d_printf(1, dev, "DI[%d]\n", idx); 38 - d_printf(1, dev, " availability: %s\n", buf); 39 - d_printf(1, dev, " %c%c key idx: %d dev addr: %d\n", 40 - (di->addr_sec_info & WHC_DI_SECURE) ? 'S' : ' ', 41 - (di->addr_sec_info & WHC_DI_DISABLE) ? 'D' : ' ', 42 - (di->addr_sec_info & WHC_DI_KEY_IDX_MASK) >> 8, 43 - (di->addr_sec_info & WHC_DI_DEV_ADDR_MASK)); 44 - } 45 - #else 46 - static inline void dump_di(struct whc *whc, int idx) 47 - { 48 - } 49 - #endif 50 - 51 26 static int whc_update_di(struct whc *whc, int idx) 52 27 { 53 28 int offset = idx / 32; 54 29 u32 bit = 1 << (idx % 32); 55 - 56 - dump_di(whc, idx); 57 30 58 31 le_writel(bit, whc->base + WUSBDIBUPDATED + offset); 59 32
+5
drivers/uwb/pal.c
··· 16 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 17 */ 18 18 #include <linux/kernel.h> 19 + #include <linux/debugfs.h> 19 20 #include <linux/uwb.h> 20 21 21 22 #include "uwb-internal.h" ··· 55 54 } 56 55 } 57 56 57 + pal->debugfs_dir = uwb_dbg_create_pal_dir(pal); 58 + 58 59 mutex_lock(&rc->uwb_dev.mutex); 59 60 list_add(&pal->node, &rc->pals); 60 61 mutex_unlock(&rc->uwb_dev.mutex); ··· 78 75 mutex_lock(&rc->uwb_dev.mutex); 79 76 list_del(&pal->node); 80 77 mutex_unlock(&rc->uwb_dev.mutex); 78 + 79 + debugfs_remove(pal->debugfs_dir); 81 80 82 81 if (pal->device) { 83 82 sysfs_remove_link(&rc->uwb_dev.dev.kobj, pal->name);
+13
drivers/uwb/uwb-debug.c
··· 407 407 { 408 408 debugfs_remove(root_dir); 409 409 } 410 + 411 + /** 412 + * uwb_dbg_create_pal_dir - create a debugfs directory for a PAL 413 + * @pal: The PAL. 414 + */ 415 + struct dentry *uwb_dbg_create_pal_dir(struct uwb_pal *pal) 416 + { 417 + struct uwb_rc *rc = pal->rc; 418 + 419 + if (root_dir && rc->dbg && rc->dbg->root_d && pal->name) 420 + return debugfs_create_dir(pal->name, rc->dbg->root_d); 421 + return NULL; 422 + }
+1 -2
drivers/uwb/uwb-internal.h
··· 284 284 void uwb_dbg_exit(void); 285 285 void uwb_dbg_add_rc(struct uwb_rc *rc); 286 286 void uwb_dbg_del_rc(struct uwb_rc *rc); 287 - 288 - /* Workarounds for version specific stuff */ 287 + struct dentry *uwb_dbg_create_pal_dir(struct uwb_pal *pal); 289 288 290 289 static inline void uwb_dev_lock(struct uwb_dev *uwb_dev) 291 290 {
+3
include/linux/uwb.h
··· 394 394 * @channel: channel being used by the PAL; 0 if the PAL isn't using 395 395 * the radio; -1 if the PAL wishes to use the radio but 396 396 * cannot. 397 + * @debugfs_dir: a debugfs directory which the PAL can use for its own 398 + * debugfs files. 397 399 * 398 400 * A Protocol Adaptation Layer (PAL) is a user of the WiMedia UWB 399 401 * radio platform (e.g., WUSB, WLP or Bluetooth UWB AMP). ··· 420 418 void (*new_rsv)(struct uwb_pal *pal, struct uwb_rsv *rsv); 421 419 422 420 int channel; 421 + struct dentry *debugfs_dir; 423 422 }; 424 423 425 424 void uwb_pal_init(struct uwb_pal *pal);