diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_debugfs.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_debugfs.c | 159 |
1 files changed, 158 insertions, 1 deletions
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index dc7b858b95fa..f334761d04df 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c | |||
@@ -101,14 +101,20 @@ MODULE_PARM_DESC(lpfc_debugfs_mask_disc_trc, | |||
101 | #define LPFC_NODELIST_SIZE 8192 | 101 | #define LPFC_NODELIST_SIZE 8192 |
102 | #define LPFC_NODELIST_ENTRY_SIZE 120 | 102 | #define LPFC_NODELIST_ENTRY_SIZE 120 |
103 | 103 | ||
104 | /* dump_slim output buffer size */ | 104 | /* dumpslim output buffer size */ |
105 | #define LPFC_DUMPSLIM_SIZE 4096 | 105 | #define LPFC_DUMPSLIM_SIZE 4096 |
106 | 106 | ||
107 | /* hbqinfo output buffer size */ | ||
108 | #define LPFC_HBQINFO_SIZE 8192 | ||
109 | |||
107 | struct lpfc_debug { | 110 | struct lpfc_debug { |
108 | char *buffer; | 111 | char *buffer; |
109 | int len; | 112 | int len; |
110 | }; | 113 | }; |
111 | 114 | ||
115 | extern struct lpfc_hbq_init *lpfc_hbq_defs[]; | ||
116 | extern int lpfc_sli_hbq_count(void); | ||
117 | |||
112 | atomic_t lpfc_debugfs_seq_trc_cnt = ATOMIC_INIT(0); | 118 | atomic_t lpfc_debugfs_seq_trc_cnt = ATOMIC_INIT(0); |
113 | unsigned long lpfc_debugfs_start_time = 0L; | 119 | unsigned long lpfc_debugfs_start_time = 0L; |
114 | 120 | ||
@@ -196,6 +202,105 @@ lpfc_debugfs_slow_ring_trc_data(struct lpfc_hba *phba, char *buf, int size) | |||
196 | return len; | 202 | return len; |
197 | } | 203 | } |
198 | 204 | ||
205 | int lpfc_debugfs_last_hbq = -1; | ||
206 | |||
207 | static int | ||
208 | lpfc_debugfs_hbqinfo_data(struct lpfc_hba *phba, char *buf, int size) | ||
209 | { | ||
210 | int len = 0; | ||
211 | int cnt, i, j, found, posted, low; | ||
212 | uint32_t phys, raw_index, getidx; | ||
213 | struct lpfc_hbq_init *hip; | ||
214 | struct hbq_s *hbqs; | ||
215 | struct lpfc_hbq_entry *hbqe; | ||
216 | struct lpfc_dmabuf *d_buf; | ||
217 | struct hbq_dmabuf *hbq_buf; | ||
218 | |||
219 | cnt = LPFC_HBQINFO_SIZE; | ||
220 | spin_lock_irq(&phba->hbalock); | ||
221 | |||
222 | /* toggle between multiple hbqs, if any */ | ||
223 | i = lpfc_sli_hbq_count(); | ||
224 | if (i > 1) { | ||
225 | lpfc_debugfs_last_hbq++; | ||
226 | if (lpfc_debugfs_last_hbq >= i) | ||
227 | lpfc_debugfs_last_hbq = 0; | ||
228 | } | ||
229 | else | ||
230 | lpfc_debugfs_last_hbq = 0; | ||
231 | |||
232 | i = lpfc_debugfs_last_hbq; | ||
233 | |||
234 | len += snprintf(buf+len, size-len, "HBQ %d Info\n", i); | ||
235 | |||
236 | posted = 0; | ||
237 | list_for_each_entry(d_buf, &phba->hbq_buffer_list, list) | ||
238 | posted++; | ||
239 | |||
240 | hip = lpfc_hbq_defs[i]; | ||
241 | len += snprintf(buf+len, size-len, | ||
242 | "idx:%d prof:%d rn:%d bufcnt:%d icnt:%d acnt:%d posted %d\n", | ||
243 | hip->hbq_index, hip->profile, hip->rn, | ||
244 | hip->buffer_count, hip->init_count, hip->add_count, posted); | ||
245 | |||
246 | hbqs = &phba->hbqs[i]; | ||
247 | raw_index = phba->hbq_get[i]; | ||
248 | getidx = le32_to_cpu(raw_index); | ||
249 | len += snprintf(buf+len, size-len, | ||
250 | "entrys:%d Put:%d nPut:%d localGet:%d hbaGet:%d\n", | ||
251 | hbqs->entry_count, hbqs->hbqPutIdx, hbqs->next_hbqPutIdx, | ||
252 | hbqs->local_hbqGetIdx, getidx); | ||
253 | |||
254 | hbqe = (struct lpfc_hbq_entry *) phba->hbqslimp.virt; | ||
255 | for (j=0; j<hbqs->entry_count; j++) { | ||
256 | len += snprintf(buf+len, size-len, | ||
257 | "%03d: %08x %04x %05x ", j, | ||
258 | hbqe->bde.addrLow, hbqe->bde.tus.w, hbqe->buffer_tag); | ||
259 | |||
260 | i = 0; | ||
261 | found = 0; | ||
262 | |||
263 | /* First calculate if slot has an associated posted buffer */ | ||
264 | low = hbqs->hbqPutIdx - posted; | ||
265 | if (low >= 0) { | ||
266 | if ((j >= hbqs->hbqPutIdx) || (j < low)) { | ||
267 | len += snprintf(buf+len, size-len, "Unused\n"); | ||
268 | goto skipit; | ||
269 | } | ||
270 | } | ||
271 | else { | ||
272 | if ((j >= hbqs->hbqPutIdx) && | ||
273 | (j < (hbqs->entry_count+low))) { | ||
274 | len += snprintf(buf+len, size-len, "Unused\n"); | ||
275 | goto skipit; | ||
276 | } | ||
277 | } | ||
278 | |||
279 | /* Get the Buffer info for the posted buffer */ | ||
280 | list_for_each_entry(d_buf, &phba->hbq_buffer_list, list) { | ||
281 | hbq_buf = container_of(d_buf, struct hbq_dmabuf, dbuf); | ||
282 | phys = ((uint64_t)hbq_buf->dbuf.phys & 0xffffffff); | ||
283 | if (phys == hbqe->bde.addrLow) { | ||
284 | len += snprintf(buf+len, size-len, | ||
285 | "Buf%d: %p %06x\n", i, | ||
286 | hbq_buf->dbuf.virt, hbq_buf->tag); | ||
287 | found = 1; | ||
288 | break; | ||
289 | } | ||
290 | i++; | ||
291 | } | ||
292 | if (!found) { | ||
293 | len += snprintf(buf+len, size-len, "No DMAinfo?\n"); | ||
294 | } | ||
295 | skipit: | ||
296 | hbqe++; | ||
297 | if (len > LPFC_HBQINFO_SIZE - 54) | ||
298 | break; | ||
299 | } | ||
300 | spin_unlock_irq(&phba->hbalock); | ||
301 | return len; | ||
302 | } | ||
303 | |||
199 | static int | 304 | static int |
200 | lpfc_debugfs_dumpslim_data(struct lpfc_hba *phba, char *buf, int size) | 305 | lpfc_debugfs_dumpslim_data(struct lpfc_hba *phba, char *buf, int size) |
201 | { | 306 | { |
@@ -492,6 +597,33 @@ out: | |||
492 | } | 597 | } |
493 | 598 | ||
494 | static int | 599 | static int |
600 | lpfc_debugfs_hbqinfo_open(struct inode *inode, struct file *file) | ||
601 | { | ||
602 | struct lpfc_hba *phba = inode->i_private; | ||
603 | struct lpfc_debug *debug; | ||
604 | int rc = -ENOMEM; | ||
605 | |||
606 | debug = kmalloc(sizeof(*debug), GFP_KERNEL); | ||
607 | if (!debug) | ||
608 | goto out; | ||
609 | |||
610 | /* Round to page boundry */ | ||
611 | debug->buffer = kmalloc(LPFC_HBQINFO_SIZE, GFP_KERNEL); | ||
612 | if (!debug->buffer) { | ||
613 | kfree(debug); | ||
614 | goto out; | ||
615 | } | ||
616 | |||
617 | debug->len = lpfc_debugfs_hbqinfo_data(phba, debug->buffer, | ||
618 | LPFC_HBQINFO_SIZE); | ||
619 | file->private_data = debug; | ||
620 | |||
621 | rc = 0; | ||
622 | out: | ||
623 | return rc; | ||
624 | } | ||
625 | |||
626 | static int | ||
495 | lpfc_debugfs_dumpslim_open(struct inode *inode, struct file *file) | 627 | lpfc_debugfs_dumpslim_open(struct inode *inode, struct file *file) |
496 | { | 628 | { |
497 | struct lpfc_hba *phba = inode->i_private; | 629 | struct lpfc_hba *phba = inode->i_private; |
@@ -604,6 +736,15 @@ static struct file_operations lpfc_debugfs_op_nodelist = { | |||
604 | .release = lpfc_debugfs_release, | 736 | .release = lpfc_debugfs_release, |
605 | }; | 737 | }; |
606 | 738 | ||
739 | #undef lpfc_debugfs_op_hbqinfo | ||
740 | static struct file_operations lpfc_debugfs_op_hbqinfo = { | ||
741 | .owner = THIS_MODULE, | ||
742 | .open = lpfc_debugfs_hbqinfo_open, | ||
743 | .llseek = lpfc_debugfs_lseek, | ||
744 | .read = lpfc_debugfs_read, | ||
745 | .release = lpfc_debugfs_release, | ||
746 | }; | ||
747 | |||
607 | #undef lpfc_debugfs_op_dumpslim | 748 | #undef lpfc_debugfs_op_dumpslim |
608 | static struct file_operations lpfc_debugfs_op_dumpslim = { | 749 | static struct file_operations lpfc_debugfs_op_dumpslim = { |
609 | .owner = THIS_MODULE, | 750 | .owner = THIS_MODULE, |
@@ -663,6 +804,18 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport) | |||
663 | atomic_inc(&lpfc_debugfs_hba_count); | 804 | atomic_inc(&lpfc_debugfs_hba_count); |
664 | atomic_set(&phba->debugfs_vport_count, 0); | 805 | atomic_set(&phba->debugfs_vport_count, 0); |
665 | 806 | ||
807 | /* Setup hbqinfo */ | ||
808 | snprintf(name, sizeof(name), "hbqinfo"); | ||
809 | phba->debug_hbqinfo = | ||
810 | debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, | ||
811 | phba->hba_debugfs_root, | ||
812 | phba, &lpfc_debugfs_op_hbqinfo); | ||
813 | if (!phba->debug_hbqinfo) { | ||
814 | lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, | ||
815 | "0409 Cannot create debugfs hbqinfo\n"); | ||
816 | goto debug_failed; | ||
817 | } | ||
818 | |||
666 | /* Setup dumpslim */ | 819 | /* Setup dumpslim */ |
667 | snprintf(name, sizeof(name), "dumpslim"); | 820 | snprintf(name, sizeof(name), "dumpslim"); |
668 | phba->debug_dumpslim = | 821 | phba->debug_dumpslim = |
@@ -819,6 +972,10 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport) | |||
819 | } | 972 | } |
820 | if (atomic_read(&phba->debugfs_vport_count) == 0) { | 973 | if (atomic_read(&phba->debugfs_vport_count) == 0) { |
821 | 974 | ||
975 | if (phba->debug_hbqinfo) { | ||
976 | debugfs_remove(phba->debug_hbqinfo); /* hbqinfo */ | ||
977 | phba->debug_hbqinfo = NULL; | ||
978 | } | ||
822 | if (phba->debug_dumpslim) { | 979 | if (phba->debug_dumpslim) { |
823 | debugfs_remove(phba->debug_dumpslim); /* dumpslim */ | 980 | debugfs_remove(phba->debug_dumpslim); /* dumpslim */ |
824 | phba->debug_dumpslim = NULL; | 981 | phba->debug_dumpslim = NULL; |