aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/fnic/Makefile2
-rw-r--r--drivers/scsi/fnic/fnic.h1
-rw-r--r--drivers/scsi/fnic/fnic_debugfs.c314
-rw-r--r--drivers/scsi/fnic/fnic_main.c14
-rw-r--r--drivers/scsi/fnic/fnic_scsi.c120
-rw-r--r--drivers/scsi/fnic/fnic_trace.c273
-rw-r--r--drivers/scsi/fnic/fnic_trace.h90
7 files changed, 803 insertions, 11 deletions
diff --git a/drivers/scsi/fnic/Makefile b/drivers/scsi/fnic/Makefile
index 37c3440bc17c..383598fadf04 100644
--- a/drivers/scsi/fnic/Makefile
+++ b/drivers/scsi/fnic/Makefile
@@ -7,6 +7,8 @@ fnic-y := \
7 fnic_res.o \ 7 fnic_res.o \
8 fnic_fcs.o \ 8 fnic_fcs.o \
9 fnic_scsi.o \ 9 fnic_scsi.o \
10 fnic_trace.o \
11 fnic_debugfs.o \
10 vnic_cq.o \ 12 vnic_cq.o \
11 vnic_dev.o \ 13 vnic_dev.o \
12 vnic_intr.o \ 14 vnic_intr.o \
diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h
index 9c95a1ad56b9..98436c363035 100644
--- a/drivers/scsi/fnic/fnic.h
+++ b/drivers/scsi/fnic/fnic.h
@@ -26,6 +26,7 @@
26#include <scsi/libfcoe.h> 26#include <scsi/libfcoe.h>
27#include "fnic_io.h" 27#include "fnic_io.h"
28#include "fnic_res.h" 28#include "fnic_res.h"
29#include "fnic_trace.h"
29#include "vnic_dev.h" 30#include "vnic_dev.h"
30#include "vnic_wq.h" 31#include "vnic_wq.h"
31#include "vnic_rq.h" 32#include "vnic_rq.h"
diff --git a/drivers/scsi/fnic/fnic_debugfs.c b/drivers/scsi/fnic/fnic_debugfs.c
new file mode 100644
index 000000000000..adc1f7f471f5
--- /dev/null
+++ b/drivers/scsi/fnic/fnic_debugfs.c
@@ -0,0 +1,314 @@
1/*
2 * Copyright 2012 Cisco Systems, Inc. All rights reserved.
3 *
4 * This program is free software; you may redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
9 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
10 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
11 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
12 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
13 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
14 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
15 * SOFTWARE.
16 */
17
18#include <linux/module.h>
19#include <linux/errno.h>
20#include <linux/debugfs.h>
21#include "fnic.h"
22
23static struct dentry *fnic_trace_debugfs_root;
24static struct dentry *fnic_trace_debugfs_file;
25static struct dentry *fnic_trace_enable;
26
27/*
28 * fnic_trace_ctrl_open - Open the trace_enable file
29 * @inode: The inode pointer.
30 * @file: The file pointer to attach the trace enable/disable flag.
31 *
32 * Description:
33 * This routine opens a debugsfs file trace_enable.
34 *
35 * Returns:
36 * This function returns zero if successful.
37 */
38static int fnic_trace_ctrl_open(struct inode *inode, struct file *filp)
39{
40 filp->private_data = inode->i_private;
41 return 0;
42}
43
44/*
45 * fnic_trace_ctrl_read - Read a trace_enable debugfs file
46 * @filp: The file pointer to read from.
47 * @ubuf: The buffer to copy the data to.
48 * @cnt: The number of bytes to read.
49 * @ppos: The position in the file to start reading from.
50 *
51 * Description:
52 * This routine reads value of variable fnic_tracing_enabled
53 * and stores into local @buf. It will start reading file at @ppos and
54 * copy up to @cnt of data to @ubuf from @buf.
55 *
56 * Returns:
57 * This function returns the amount of data that was read.
58 */
59static ssize_t fnic_trace_ctrl_read(struct file *filp,
60 char __user *ubuf,
61 size_t cnt, loff_t *ppos)
62{
63 char buf[64];
64 int len;
65 len = sprintf(buf, "%u\n", fnic_tracing_enabled);
66
67 return simple_read_from_buffer(ubuf, cnt, ppos, buf, len);
68}
69
70/*
71 * fnic_trace_ctrl_write - Write to trace_enable debugfs file
72 * @filp: The file pointer to write from.
73 * @ubuf: The buffer to copy the data from.
74 * @cnt: The number of bytes to write.
75 * @ppos: The position in the file to start writing to.
76 *
77 * Description:
78 * This routine writes data from user buffer @ubuf to buffer @buf and
79 * sets fnic_tracing_enabled value as per user input.
80 *
81 * Returns:
82 * This function returns the amount of data that was written.
83 */
84static ssize_t fnic_trace_ctrl_write(struct file *filp,
85 const char __user *ubuf,
86 size_t cnt, loff_t *ppos)
87{
88 char buf[64];
89 unsigned long val;
90 int ret;
91
92 if (cnt >= sizeof(buf))
93 return -EINVAL;
94
95 if (copy_from_user(&buf, ubuf, cnt))
96 return -EFAULT;
97
98 buf[cnt] = 0;
99
100 ret = kstrtoul(buf, 10, &val);
101 if (ret < 0)
102 return ret;
103
104 fnic_tracing_enabled = val;
105 (*ppos)++;
106
107 return cnt;
108}
109
110/*
111 * fnic_trace_debugfs_open - Open the fnic trace log
112 * @inode: The inode pointer
113 * @file: The file pointer to attach the log output
114 *
115 * Description:
116 * This routine is the entry point for the debugfs open file operation.
117 * It allocates the necessary buffer for the log, fills the buffer from
118 * the in-memory log and then returns a pointer to that log in
119 * the private_data field in @file.
120 *
121 * Returns:
122 * This function returns zero if successful. On error it will return
123 * a negative error value.
124 */
125static int fnic_trace_debugfs_open(struct inode *inode,
126 struct file *file)
127{
128 fnic_dbgfs_t *fnic_dbg_prt;
129 fnic_dbg_prt = kzalloc(sizeof(fnic_dbgfs_t), GFP_KERNEL);
130 if (!fnic_dbg_prt)
131 return -ENOMEM;
132
133 fnic_dbg_prt->buffer = vmalloc((3*(trace_max_pages * PAGE_SIZE)));
134 if (!fnic_dbg_prt->buffer) {
135 kfree(fnic_dbg_prt);
136 return -ENOMEM;
137 }
138 memset((void *)fnic_dbg_prt->buffer, 0,
139 (3*(trace_max_pages * PAGE_SIZE)));
140 fnic_dbg_prt->buffer_len = fnic_get_trace_data(fnic_dbg_prt);
141 file->private_data = fnic_dbg_prt;
142 return 0;
143}
144
145/*
146 * fnic_trace_debugfs_lseek - Seek through a debugfs file
147 * @file: The file pointer to seek through.
148 * @offset: The offset to seek to or the amount to seek by.
149 * @howto: Indicates how to seek.
150 *
151 * Description:
152 * This routine is the entry point for the debugfs lseek file operation.
153 * The @howto parameter indicates whether @offset is the offset to directly
154 * seek to, or if it is a value to seek forward or reverse by. This function
155 * figures out what the new offset of the debugfs file will be and assigns
156 * that value to the f_pos field of @file.
157 *
158 * Returns:
159 * This function returns the new offset if successful and returns a negative
160 * error if unable to process the seek.
161 */
162static loff_t fnic_trace_debugfs_lseek(struct file *file,
163 loff_t offset,
164 int howto)
165{
166 fnic_dbgfs_t *fnic_dbg_prt = file->private_data;
167 loff_t pos = -1;
168
169 switch (howto) {
170 case 0:
171 pos = offset;
172 break;
173 case 1:
174 pos = file->f_pos + offset;
175 break;
176 case 2:
177 pos = fnic_dbg_prt->buffer_len - offset;
178 }
179 return (pos < 0 || pos > fnic_dbg_prt->buffer_len) ?
180 -EINVAL : (file->f_pos = pos);
181}
182
183/*
184 * fnic_trace_debugfs_read - Read a debugfs file
185 * @file: The file pointer to read from.
186 * @ubuf: The buffer to copy the data to.
187 * @nbytes: The number of bytes to read.
188 * @pos: The position in the file to start reading from.
189 *
190 * Description:
191 * This routine reads data from the buffer indicated in the private_data
192 * field of @file. It will start reading at @pos and copy up to @nbytes of
193 * data to @ubuf.
194 *
195 * Returns:
196 * This function returns the amount of data that was read (this could be
197 * less than @nbytes if the end of the file was reached).
198 */
199static ssize_t fnic_trace_debugfs_read(struct file *file,
200 char __user *ubuf,
201 size_t nbytes,
202 loff_t *pos)
203{
204 fnic_dbgfs_t *fnic_dbg_prt = file->private_data;
205 int rc = 0;
206 rc = simple_read_from_buffer(ubuf, nbytes, pos,
207 fnic_dbg_prt->buffer,
208 fnic_dbg_prt->buffer_len);
209 return rc;
210}
211
212/*
213 * fnic_trace_debugfs_release - Release the buffer used to store
214 * debugfs file data
215 * @inode: The inode pointer
216 * @file: The file pointer that contains the buffer to release
217 *
218 * Description:
219 * This routine frees the buffer that was allocated when the debugfs
220 * file was opened.
221 *
222 * Returns:
223 * This function returns zero.
224 */
225static int fnic_trace_debugfs_release(struct inode *inode,
226 struct file *file)
227{
228 fnic_dbgfs_t *fnic_dbg_prt = file->private_data;
229
230 vfree(fnic_dbg_prt->buffer);
231 kfree(fnic_dbg_prt);
232 return 0;
233}
234
235static const struct file_operations fnic_trace_ctrl_fops = {
236 .owner = THIS_MODULE,
237 .open = fnic_trace_ctrl_open,
238 .read = fnic_trace_ctrl_read,
239 .write = fnic_trace_ctrl_write,
240};
241
242static const struct file_operations fnic_trace_debugfs_fops = {
243 .owner = THIS_MODULE,
244 .open = fnic_trace_debugfs_open,
245 .llseek = fnic_trace_debugfs_lseek,
246 .read = fnic_trace_debugfs_read,
247 .release = fnic_trace_debugfs_release,
248};
249
250/*
251 * fnic_trace_debugfs_init - Initialize debugfs for fnic trace logging
252 *
253 * Description:
254 * When Debugfs is configured this routine sets up the fnic debugfs
255 * file system. If not already created, this routine will create the
256 * fnic directory. It will create file trace to log fnic trace buffer
257 * output into debugfs and it will also create file trace_enable to
258 * control enable/disable of trace logging into trace buffer.
259 */
260int fnic_trace_debugfs_init(void)
261{
262 int rc = -1;
263 fnic_trace_debugfs_root = debugfs_create_dir("fnic", NULL);
264 if (!fnic_trace_debugfs_root) {
265 printk(KERN_DEBUG "Cannot create debugfs root\n");
266 return rc;
267 }
268 fnic_trace_enable = debugfs_create_file("tracing_enable",
269 S_IFREG|S_IRUGO|S_IWUSR,
270 fnic_trace_debugfs_root,
271 NULL, &fnic_trace_ctrl_fops);
272
273 if (!fnic_trace_enable) {
274 printk(KERN_DEBUG "Cannot create trace_enable file"
275 " under debugfs");
276 return rc;
277 }
278
279 fnic_trace_debugfs_file = debugfs_create_file("trace",
280 S_IFREG|S_IRUGO|S_IWUSR,
281 fnic_trace_debugfs_root,
282 NULL,
283 &fnic_trace_debugfs_fops);
284
285 if (!fnic_trace_debugfs_file) {
286 printk(KERN_DEBUG "Cannot create trace file under debugfs");
287 return rc;
288 }
289 rc = 0;
290 return rc;
291}
292
293/*
294 * fnic_trace_debugfs_terminate - Tear down debugfs infrastructure
295 *
296 * Description:
297 * When Debugfs is configured this routine removes debugfs file system
298 * elements that are specific to fnic trace logging.
299 */
300void fnic_trace_debugfs_terminate(void)
301{
302 if (fnic_trace_debugfs_file) {
303 debugfs_remove(fnic_trace_debugfs_file);
304 fnic_trace_debugfs_file = NULL;
305 }
306 if (fnic_trace_enable) {
307 debugfs_remove(fnic_trace_enable);
308 fnic_trace_enable = NULL;
309 }
310 if (fnic_trace_debugfs_root) {
311 debugfs_remove(fnic_trace_debugfs_root);
312 fnic_trace_debugfs_root = NULL;
313 }
314}
diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c
index fcecbb7281aa..d601ac543c52 100644
--- a/drivers/scsi/fnic/fnic_main.c
+++ b/drivers/scsi/fnic/fnic_main.c
@@ -68,6 +68,10 @@ unsigned int fnic_log_level;
68module_param(fnic_log_level, int, S_IRUGO|S_IWUSR); 68module_param(fnic_log_level, int, S_IRUGO|S_IWUSR);
69MODULE_PARM_DESC(fnic_log_level, "bit mask of fnic logging levels"); 69MODULE_PARM_DESC(fnic_log_level, "bit mask of fnic logging levels");
70 70
71unsigned int fnic_trace_max_pages = 16;
72module_param(fnic_trace_max_pages, uint, S_IRUGO|S_IWUSR);
73MODULE_PARM_DESC(fnic_trace_max_pages, "Total allocated memory pages "
74 "for fnic trace buffer");
71 75
72static struct libfc_function_template fnic_transport_template = { 76static struct libfc_function_template fnic_transport_template = {
73 .frame_send = fnic_send, 77 .frame_send = fnic_send,
@@ -861,6 +865,14 @@ static int __init fnic_init_module(void)
861 865
862 printk(KERN_INFO PFX "%s, ver %s\n", DRV_DESCRIPTION, DRV_VERSION); 866 printk(KERN_INFO PFX "%s, ver %s\n", DRV_DESCRIPTION, DRV_VERSION);
863 867
868 /* Allocate memory for trace buffer */
869 err = fnic_trace_buf_init();
870 if (err < 0) {
871 printk(KERN_ERR PFX "Trace buffer initialization Failed "
872 "Fnic Tracing utility is disabled\n");
873 fnic_trace_free();
874 }
875
864 /* Create a cache for allocation of default size sgls */ 876 /* Create a cache for allocation of default size sgls */
865 len = sizeof(struct fnic_dflt_sgl_list); 877 len = sizeof(struct fnic_dflt_sgl_list);
866 fnic_sgl_cache[FNIC_SGL_CACHE_DFLT] = kmem_cache_create 878 fnic_sgl_cache[FNIC_SGL_CACHE_DFLT] = kmem_cache_create
@@ -931,6 +943,7 @@ err_create_fnic_ioreq_slab:
931err_create_fnic_sgl_slab_max: 943err_create_fnic_sgl_slab_max:
932 kmem_cache_destroy(fnic_sgl_cache[FNIC_SGL_CACHE_DFLT]); 944 kmem_cache_destroy(fnic_sgl_cache[FNIC_SGL_CACHE_DFLT]);
933err_create_fnic_sgl_slab_dflt: 945err_create_fnic_sgl_slab_dflt:
946 fnic_trace_free();
934 return err; 947 return err;
935} 948}
936 949
@@ -942,6 +955,7 @@ static void __exit fnic_cleanup_module(void)
942 kmem_cache_destroy(fnic_sgl_cache[FNIC_SGL_CACHE_DFLT]); 955 kmem_cache_destroy(fnic_sgl_cache[FNIC_SGL_CACHE_DFLT]);
943 kmem_cache_destroy(fnic_io_req_cache); 956 kmem_cache_destroy(fnic_io_req_cache);
944 fc_release_transport(fnic_fc_transport); 957 fc_release_transport(fnic_fc_transport);
958 fnic_trace_free();
945} 959}
946 960
947module_init(fnic_init_module); 961module_init(fnic_init_module);
diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c
index 7cb653309125..be99e7549d89 100644
--- a/drivers/scsi/fnic/fnic_scsi.c
+++ b/drivers/scsi/fnic/fnic_scsi.c
@@ -393,11 +393,12 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
393{ 393{
394 struct fc_lport *lp = shost_priv(sc->device->host); 394 struct fc_lport *lp = shost_priv(sc->device->host);
395 struct fc_rport *rport; 395 struct fc_rport *rport;
396 struct fnic_io_req *io_req; 396 struct fnic_io_req *io_req = NULL;
397 struct fnic *fnic = lport_priv(lp); 397 struct fnic *fnic = lport_priv(lp);
398 struct vnic_wq_copy *wq; 398 struct vnic_wq_copy *wq;
399 int ret; 399 int ret;
400 int sg_count; 400 u64 cmd_trace;
401 int sg_count = 0;
401 unsigned long flags; 402 unsigned long flags;
402 unsigned long ptr; 403 unsigned long ptr;
403 404
@@ -437,6 +438,9 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
437 /* Map the data buffer */ 438 /* Map the data buffer */
438 sg_count = scsi_dma_map(sc); 439 sg_count = scsi_dma_map(sc);
439 if (sg_count < 0) { 440 if (sg_count < 0) {
441 FNIC_TRACE(fnic_queuecommand, sc->device->host->host_no,
442 sc->request->tag, sc, 0, sc->cmnd[0],
443 sg_count, CMD_STATE(sc));
440 mempool_free(io_req, fnic->io_req_pool); 444 mempool_free(io_req, fnic->io_req_pool);
441 goto out; 445 goto out;
442 } 446 }
@@ -486,7 +490,9 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
486 * refetch the pointer under the lock. 490 * refetch the pointer under the lock.
487 */ 491 */
488 spinlock_t *io_lock = fnic_io_lock_hash(fnic, sc); 492 spinlock_t *io_lock = fnic_io_lock_hash(fnic, sc);
489 493 FNIC_TRACE(fnic_queuecommand, sc->device->host->host_no,
494 sc->request->tag, sc, 0, 0, 0,
495 (((u64)CMD_FLAGS(sc) << 32) | CMD_STATE(sc)));
490 spin_lock_irqsave(io_lock, flags); 496 spin_lock_irqsave(io_lock, flags);
491 io_req = (struct fnic_io_req *)CMD_SP(sc); 497 io_req = (struct fnic_io_req *)CMD_SP(sc);
492 CMD_SP(sc) = NULL; 498 CMD_SP(sc) = NULL;
@@ -501,6 +507,15 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
501 CMD_FLAGS(sc) |= FNIC_IO_ISSUED; 507 CMD_FLAGS(sc) |= FNIC_IO_ISSUED;
502 } 508 }
503out: 509out:
510 cmd_trace = ((u64)sc->cmnd[0] << 56 | (u64)sc->cmnd[7] << 40 |
511 (u64)sc->cmnd[8] << 32 | (u64)sc->cmnd[2] << 24 |
512 (u64)sc->cmnd[3] << 16 | (u64)sc->cmnd[4] << 8 |
513 sc->cmnd[5]);
514
515 FNIC_TRACE(fnic_queuecommand, sc->device->host->host_no,
516 sc->request->tag, sc, io_req,
517 sg_count, cmd_trace,
518 (((u64)CMD_FLAGS(sc) >> 32) | CMD_STATE(sc)));
504 atomic_dec(&fnic->in_flight); 519 atomic_dec(&fnic->in_flight);
505 /* acquire host lock before returning to SCSI */ 520 /* acquire host lock before returning to SCSI */
506 spin_lock(lp->host->host_lock); 521 spin_lock(lp->host->host_lock);
@@ -674,6 +689,7 @@ static inline void fnic_fcpio_ack_handler(struct fnic *fnic,
674 struct vnic_wq_copy *wq; 689 struct vnic_wq_copy *wq;
675 u16 request_out = desc->u.ack.request_out; 690 u16 request_out = desc->u.ack.request_out;
676 unsigned long flags; 691 unsigned long flags;
692 u64 *ox_id_tag = (u64 *)(void *)desc;
677 693
678 /* mark the ack state */ 694 /* mark the ack state */
679 wq = &fnic->wq_copy[cq_index - fnic->raw_wq_count - fnic->rq_count]; 695 wq = &fnic->wq_copy[cq_index - fnic->raw_wq_count - fnic->rq_count];
@@ -684,6 +700,9 @@ static inline void fnic_fcpio_ack_handler(struct fnic *fnic,
684 fnic->fw_ack_recd[0] = 1; 700 fnic->fw_ack_recd[0] = 1;
685 } 701 }
686 spin_unlock_irqrestore(&fnic->wq_copy_lock[0], flags); 702 spin_unlock_irqrestore(&fnic->wq_copy_lock[0], flags);
703 FNIC_TRACE(fnic_fcpio_ack_handler,
704 fnic->lport->host->host_no, 0, 0, ox_id_tag[2], ox_id_tag[3],
705 ox_id_tag[4], ox_id_tag[5]);
687} 706}
688 707
689/* 708/*
@@ -703,6 +722,7 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic,
703 struct scsi_cmnd *sc; 722 struct scsi_cmnd *sc;
704 unsigned long flags; 723 unsigned long flags;
705 spinlock_t *io_lock; 724 spinlock_t *io_lock;
725 u64 cmd_trace;
706 unsigned long start_time; 726 unsigned long start_time;
707 727
708 /* Decode the cmpl description to get the io_req id */ 728 /* Decode the cmpl description to get the io_req id */
@@ -724,6 +744,14 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic,
724 "icmnd_cmpl sc is null - " 744 "icmnd_cmpl sc is null - "
725 "hdr status = %s tag = 0x%x desc = 0x%p\n", 745 "hdr status = %s tag = 0x%x desc = 0x%p\n",
726 fnic_fcpio_status_to_str(hdr_status), id, desc); 746 fnic_fcpio_status_to_str(hdr_status), id, desc);
747 FNIC_TRACE(fnic_fcpio_icmnd_cmpl_handler,
748 fnic->lport->host->host_no, id,
749 ((u64)icmnd_cmpl->_resvd0[1] << 16 |
750 (u64)icmnd_cmpl->_resvd0[0]),
751 ((u64)hdr_status << 16 |
752 (u64)icmnd_cmpl->scsi_status << 8 |
753 (u64)icmnd_cmpl->flags), desc,
754 (u64)icmnd_cmpl->residual, 0);
727 return; 755 return;
728 } 756 }
729 757
@@ -864,6 +892,20 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic,
864 892
865 mempool_free(io_req, fnic->io_req_pool); 893 mempool_free(io_req, fnic->io_req_pool);
866 894
895 cmd_trace = ((u64)hdr_status << 56) |
896 (u64)icmnd_cmpl->scsi_status << 48 |
897 (u64)icmnd_cmpl->flags << 40 | (u64)sc->cmnd[0] << 32 |
898 (u64)sc->cmnd[2] << 24 | (u64)sc->cmnd[3] << 16 |
899 (u64)sc->cmnd[4] << 8 | sc->cmnd[5];
900
901 FNIC_TRACE(fnic_fcpio_icmnd_cmpl_handler,
902 sc->device->host->host_no, id, sc,
903 ((u64)icmnd_cmpl->_resvd0[1] << 56 |
904 (u64)icmnd_cmpl->_resvd0[0] << 48 |
905 jiffies_to_msecs(jiffies - start_time)),
906 desc, cmd_trace,
907 (((u64)CMD_FLAGS(sc) << 32) | CMD_STATE(sc)));
908
867 if (sc->sc_data_direction == DMA_FROM_DEVICE) { 909 if (sc->sc_data_direction == DMA_FROM_DEVICE) {
868 fnic->lport->host_stats.fcp_input_requests++; 910 fnic->lport->host_stats.fcp_input_requests++;
869 fnic->fcp_input_bytes += xfer_len; 911 fnic->fcp_input_bytes += xfer_len;
@@ -876,7 +918,6 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic,
876 /* Call SCSI completion function to complete the IO */ 918 /* Call SCSI completion function to complete the IO */
877 if (sc->scsi_done) 919 if (sc->scsi_done)
878 sc->scsi_done(sc); 920 sc->scsi_done(sc);
879
880} 921}
881 922
882/* fnic_fcpio_itmf_cmpl_handler 923/* fnic_fcpio_itmf_cmpl_handler
@@ -974,8 +1015,21 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic,
974 1015
975 fnic_release_ioreq_buf(fnic, io_req, sc); 1016 fnic_release_ioreq_buf(fnic, io_req, sc);
976 mempool_free(io_req, fnic->io_req_pool); 1017 mempool_free(io_req, fnic->io_req_pool);
977 if (sc->scsi_done) 1018 if (sc->scsi_done) {
1019 FNIC_TRACE(fnic_fcpio_itmf_cmpl_handler,
1020 sc->device->host->host_no, id,
1021 sc,
1022 jiffies_to_msecs(jiffies - start_time),
1023 desc,
1024 (((u64)hdr_status << 40) |
1025 (u64)sc->cmnd[0] << 32 |
1026 (u64)sc->cmnd[2] << 24 |
1027 (u64)sc->cmnd[3] << 16 |
1028 (u64)sc->cmnd[4] << 8 | sc->cmnd[5]),
1029 (((u64)CMD_FLAGS(sc) << 32) |
1030 CMD_STATE(sc)));
978 sc->scsi_done(sc); 1031 sc->scsi_done(sc);
1032 }
979 } 1033 }
980 1034
981 } else if (id & FNIC_TAG_DEV_RST) { 1035 } else if (id & FNIC_TAG_DEV_RST) {
@@ -984,6 +1038,11 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic,
984 if (CMD_STATE(sc) == FNIC_IOREQ_ABTS_PENDING) { 1038 if (CMD_STATE(sc) == FNIC_IOREQ_ABTS_PENDING) {
985 spin_unlock_irqrestore(io_lock, flags); 1039 spin_unlock_irqrestore(io_lock, flags);
986 CMD_FLAGS(sc) |= FNIC_DEV_RST_ABTS_PENDING; 1040 CMD_FLAGS(sc) |= FNIC_DEV_RST_ABTS_PENDING;
1041 FNIC_TRACE(fnic_fcpio_itmf_cmpl_handler,
1042 sc->device->host->host_no, id, sc,
1043 jiffies_to_msecs(jiffies - start_time),
1044 desc, 0,
1045 (((u64)CMD_FLAGS(sc) << 32) | CMD_STATE(sc)));
987 FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, 1046 FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
988 "Terminate pending " 1047 "Terminate pending "
989 "dev reset cmpl recd. id %d status %s\n", 1048 "dev reset cmpl recd. id %d status %s\n",
@@ -994,6 +1053,11 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic,
994 if (CMD_FLAGS(sc) & FNIC_DEV_RST_TIMED_OUT) { 1053 if (CMD_FLAGS(sc) & FNIC_DEV_RST_TIMED_OUT) {
995 /* Need to wait for terminate completion */ 1054 /* Need to wait for terminate completion */
996 spin_unlock_irqrestore(io_lock, flags); 1055 spin_unlock_irqrestore(io_lock, flags);
1056 FNIC_TRACE(fnic_fcpio_itmf_cmpl_handler,
1057 sc->device->host->host_no, id, sc,
1058 jiffies_to_msecs(jiffies - start_time),
1059 desc, 0,
1060 (((u64)CMD_FLAGS(sc) << 32) | CMD_STATE(sc)));
997 FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, 1061 FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
998 "dev reset cmpl recd after time out. " 1062 "dev reset cmpl recd after time out. "
999 "id %d status %s\n", 1063 "id %d status %s\n",
@@ -1142,8 +1206,18 @@ cleanup_scsi_cmd:
1142 " DID_TRANSPORT_DISRUPTED\n"); 1206 " DID_TRANSPORT_DISRUPTED\n");
1143 1207
1144 /* Complete the command to SCSI */ 1208 /* Complete the command to SCSI */
1145 if (sc->scsi_done) 1209 if (sc->scsi_done) {
1210 FNIC_TRACE(fnic_cleanup_io,
1211 sc->device->host->host_no, i, sc,
1212 jiffies_to_msecs(jiffies - start_time),
1213 0, ((u64)sc->cmnd[0] << 32 |
1214 (u64)sc->cmnd[2] << 24 |
1215 (u64)sc->cmnd[3] << 16 |
1216 (u64)sc->cmnd[4] << 8 | sc->cmnd[5]),
1217 (((u64)CMD_FLAGS(sc) << 32) | CMD_STATE(sc)));
1218
1146 sc->scsi_done(sc); 1219 sc->scsi_done(sc);
1220 }
1147 } 1221 }
1148} 1222}
1149 1223
@@ -1195,8 +1269,17 @@ wq_copy_cleanup_scsi_cmd:
1195 FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, "wq_copy_cleanup_handler:" 1269 FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, "wq_copy_cleanup_handler:"
1196 " DID_NO_CONNECT\n"); 1270 " DID_NO_CONNECT\n");
1197 1271
1198 if (sc->scsi_done) 1272 if (sc->scsi_done) {
1273 FNIC_TRACE(fnic_wq_copy_cleanup_handler,
1274 sc->device->host->host_no, id, sc,
1275 jiffies_to_msecs(jiffies - start_time),
1276 0, ((u64)sc->cmnd[0] << 32 |
1277 (u64)sc->cmnd[2] << 24 | (u64)sc->cmnd[3] << 16 |
1278 (u64)sc->cmnd[4] << 8 | sc->cmnd[5]),
1279 (((u64)CMD_FLAGS(sc) << 32) | CMD_STATE(sc)));
1280
1199 sc->scsi_done(sc); 1281 sc->scsi_done(sc);
1282 }
1200} 1283}
1201 1284
1202static inline int fnic_queue_abort_io_req(struct fnic *fnic, int tag, 1285static inline int fnic_queue_abort_io_req(struct fnic *fnic, int tag,
@@ -1476,7 +1559,7 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
1476{ 1559{
1477 struct fc_lport *lp; 1560 struct fc_lport *lp;
1478 struct fnic *fnic; 1561 struct fnic *fnic;
1479 struct fnic_io_req *io_req; 1562 struct fnic_io_req *io_req = NULL;
1480 struct fc_rport *rport; 1563 struct fc_rport *rport;
1481 spinlock_t *io_lock; 1564 spinlock_t *io_lock;
1482 unsigned long flags; 1565 unsigned long flags;
@@ -1503,7 +1586,6 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
1503 1586
1504 CMD_FLAGS(sc) = FNIC_NO_FLAGS; 1587 CMD_FLAGS(sc) = FNIC_NO_FLAGS;
1505 1588
1506
1507 if (lp->state != LPORT_ST_READY || !(lp->link_up)) { 1589 if (lp->state != LPORT_ST_READY || !(lp->link_up)) {
1508 ret = FAILED; 1590 ret = FAILED;
1509 goto fnic_abort_cmd_end; 1591 goto fnic_abort_cmd_end;
@@ -1621,6 +1703,14 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
1621 mempool_free(io_req, fnic->io_req_pool); 1703 mempool_free(io_req, fnic->io_req_pool);
1622 1704
1623fnic_abort_cmd_end: 1705fnic_abort_cmd_end:
1706 FNIC_TRACE(fnic_abort_cmd, sc->device->host->host_no,
1707 sc->request->tag, sc,
1708 jiffies_to_msecs(jiffies - start_time),
1709 0, ((u64)sc->cmnd[0] << 32 |
1710 (u64)sc->cmnd[2] << 24 | (u64)sc->cmnd[3] << 16 |
1711 (u64)sc->cmnd[4] << 8 | sc->cmnd[5]),
1712 (((u64)CMD_FLAGS(sc) << 32) | CMD_STATE(sc)));
1713
1624 FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, 1714 FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
1625 "Returning from abort cmd type %x %s\n", task_req, 1715 "Returning from abort cmd type %x %s\n", task_req,
1626 (ret == SUCCESS) ? 1716 (ret == SUCCESS) ?
@@ -1891,7 +1981,7 @@ int fnic_device_reset(struct scsi_cmnd *sc)
1891{ 1981{
1892 struct fc_lport *lp; 1982 struct fc_lport *lp;
1893 struct fnic *fnic; 1983 struct fnic *fnic;
1894 struct fnic_io_req *io_req; 1984 struct fnic_io_req *io_req = NULL;
1895 struct fc_rport *rport; 1985 struct fc_rport *rport;
1896 int status; 1986 int status;
1897 int ret = FAILED; 1987 int ret = FAILED;
@@ -1899,7 +1989,7 @@ int fnic_device_reset(struct scsi_cmnd *sc)
1899 unsigned long flags; 1989 unsigned long flags;
1900 unsigned long start_time = 0; 1990 unsigned long start_time = 0;
1901 struct scsi_lun fc_lun; 1991 struct scsi_lun fc_lun;
1902 int tag; 1992 int tag = 0;
1903 DECLARE_COMPLETION_ONSTACK(tm_done); 1993 DECLARE_COMPLETION_ONSTACK(tm_done);
1904 int tag_gen_flag = 0; /*to track tags allocated by fnic driver*/ 1994 int tag_gen_flag = 0; /*to track tags allocated by fnic driver*/
1905 1995
@@ -2094,6 +2184,14 @@ fnic_device_reset_clean:
2094 } 2184 }
2095 2185
2096fnic_device_reset_end: 2186fnic_device_reset_end:
2187 FNIC_TRACE(fnic_device_reset, sc->device->host->host_no,
2188 sc->request->tag, sc,
2189 jiffies_to_msecs(jiffies - start_time),
2190 0, ((u64)sc->cmnd[0] << 32 |
2191 (u64)sc->cmnd[2] << 24 | (u64)sc->cmnd[3] << 16 |
2192 (u64)sc->cmnd[4] << 8 | sc->cmnd[5]),
2193 (((u64)CMD_FLAGS(sc) << 32) | CMD_STATE(sc)));
2194
2097 /* free tag if it is allocated */ 2195 /* free tag if it is allocated */
2098 if (unlikely(tag_gen_flag)) 2196 if (unlikely(tag_gen_flag))
2099 fnic_scsi_host_end_tag(fnic, sc); 2197 fnic_scsi_host_end_tag(fnic, sc);
diff --git a/drivers/scsi/fnic/fnic_trace.c b/drivers/scsi/fnic/fnic_trace.c
new file mode 100644
index 000000000000..23a60e3d8527
--- /dev/null
+++ b/drivers/scsi/fnic/fnic_trace.c
@@ -0,0 +1,273 @@
1/*
2 * Copyright 2012 Cisco Systems, Inc. All rights reserved.
3 *
4 * This program is free software; you may redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
9 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
10 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
11 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
12 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
13 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
14 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
15 * SOFTWARE.
16 */
17
18#include <linux/module.h>
19#include <linux/mempool.h>
20#include <linux/errno.h>
21#include <linux/spinlock.h>
22#include <linux/kallsyms.h>
23#include "fnic_io.h"
24#include "fnic.h"
25
26unsigned int trace_max_pages;
27static int fnic_max_trace_entries;
28
29static unsigned long fnic_trace_buf_p;
30static DEFINE_SPINLOCK(fnic_trace_lock);
31
32static fnic_trace_dbg_t fnic_trace_entries;
33int fnic_tracing_enabled = 1;
34
35/*
36 * fnic_trace_get_buf - Give buffer pointer to user to fill up trace information
37 *
38 * Description:
39 * This routine gets next available trace buffer entry location @wr_idx
40 * from allocated trace buffer pages and give that memory location
41 * to user to store the trace information.
42 *
43 * Return Value:
44 * This routine returns pointer to next available trace entry
45 * @fnic_buf_head for user to fill trace information.
46 */
47fnic_trace_data_t *fnic_trace_get_buf(void)
48{
49 unsigned long fnic_buf_head;
50 unsigned long flags;
51
52 spin_lock_irqsave(&fnic_trace_lock, flags);
53
54 /*
55 * Get next available memory location for writing trace information
56 * at @wr_idx and increment @wr_idx
57 */
58 fnic_buf_head =
59 fnic_trace_entries.page_offset[fnic_trace_entries.wr_idx];
60 fnic_trace_entries.wr_idx++;
61
62 /*
63 * Verify if trace buffer is full then change wd_idx to
64 * start from zero
65 */
66 if (fnic_trace_entries.wr_idx >= fnic_max_trace_entries)
67 fnic_trace_entries.wr_idx = 0;
68
69 /*
70 * Verify if write index @wr_idx and read index @rd_idx are same then
71 * increment @rd_idx to move to next entry in trace buffer
72 */
73 if (fnic_trace_entries.wr_idx == fnic_trace_entries.rd_idx) {
74 fnic_trace_entries.rd_idx++;
75 if (fnic_trace_entries.rd_idx >= fnic_max_trace_entries)
76 fnic_trace_entries.rd_idx = 0;
77 }
78 spin_unlock_irqrestore(&fnic_trace_lock, flags);
79 return (fnic_trace_data_t *)fnic_buf_head;
80}
81
82/*
83 * fnic_get_trace_data - Copy trace buffer to a memory file
84 * @fnic_dbgfs_t: pointer to debugfs trace buffer
85 *
86 * Description:
87 * This routine gathers the fnic trace debugfs data from the fnic_trace_data_t
88 * buffer and dumps it to fnic_dbgfs_t. It will start at the rd_idx entry in
89 * the log and process the log until the end of the buffer. Then it will gather
90 * from the beginning of the log and process until the current entry @wr_idx.
91 *
92 * Return Value:
93 * This routine returns the amount of bytes that were dumped into fnic_dbgfs_t
94 */
95int fnic_get_trace_data(fnic_dbgfs_t *fnic_dbgfs_prt)
96{
97 int rd_idx;
98 int wr_idx;
99 int len = 0;
100 unsigned long flags;
101 char str[KSYM_SYMBOL_LEN];
102 struct timespec val;
103 fnic_trace_data_t *tbp;
104
105 spin_lock_irqsave(&fnic_trace_lock, flags);
106 rd_idx = fnic_trace_entries.rd_idx;
107 wr_idx = fnic_trace_entries.wr_idx;
108 if (wr_idx < rd_idx) {
109 while (1) {
110 /* Start from read index @rd_idx */
111 tbp = (fnic_trace_data_t *)
112 fnic_trace_entries.page_offset[rd_idx];
113 if (!tbp) {
114 spin_unlock_irqrestore(&fnic_trace_lock, flags);
115 return 0;
116 }
117 /* Convert function pointer to function name */
118 if (sizeof(unsigned long) < 8) {
119 sprint_symbol(str, tbp->fnaddr.low);
120 jiffies_to_timespec(tbp->timestamp.low, &val);
121 } else {
122 sprint_symbol(str, tbp->fnaddr.val);
123 jiffies_to_timespec(tbp->timestamp.val, &val);
124 }
125 /*
126 * Dump trace buffer entry to memory file
127 * and increment read index @rd_idx
128 */
129 len += snprintf(fnic_dbgfs_prt->buffer + len,
130 (trace_max_pages * PAGE_SIZE * 3) - len,
131 "%16lu.%16lu %-50s %8x %8x %16llx %16llx "
132 "%16llx %16llx %16llx\n", val.tv_sec,
133 val.tv_nsec, str, tbp->host_no, tbp->tag,
134 tbp->data[0], tbp->data[1], tbp->data[2],
135 tbp->data[3], tbp->data[4]);
136 rd_idx++;
137 /*
138 * If rd_idx is reached to maximum trace entries
139 * then move rd_idx to zero
140 */
141 if (rd_idx > (fnic_max_trace_entries-1))
142 rd_idx = 0;
143 /*
144 * Continure dumpping trace buffer entries into
145 * memory file till rd_idx reaches write index
146 */
147 if (rd_idx == wr_idx)
148 break;
149 }
150 } else if (wr_idx > rd_idx) {
151 while (1) {
152 /* Start from read index @rd_idx */
153 tbp = (fnic_trace_data_t *)
154 fnic_trace_entries.page_offset[rd_idx];
155 if (!tbp) {
156 spin_unlock_irqrestore(&fnic_trace_lock, flags);
157 return 0;
158 }
159 /* Convert function pointer to function name */
160 if (sizeof(unsigned long) < 8) {
161 sprint_symbol(str, tbp->fnaddr.low);
162 jiffies_to_timespec(tbp->timestamp.low, &val);
163 } else {
164 sprint_symbol(str, tbp->fnaddr.val);
165 jiffies_to_timespec(tbp->timestamp.val, &val);
166 }
167 /*
168 * Dump trace buffer entry to memory file
169 * and increment read index @rd_idx
170 */
171 len += snprintf(fnic_dbgfs_prt->buffer + len,
172 (trace_max_pages * PAGE_SIZE * 3) - len,
173 "%16lu.%16lu %-50s %8x %8x %16llx %16llx "
174 "%16llx %16llx %16llx\n", val.tv_sec,
175 val.tv_nsec, str, tbp->host_no, tbp->tag,
176 tbp->data[0], tbp->data[1], tbp->data[2],
177 tbp->data[3], tbp->data[4]);
178 rd_idx++;
179 /*
180 * Continue dumpping trace buffer entries into
181 * memory file till rd_idx reaches write index
182 */
183 if (rd_idx == wr_idx)
184 break;
185 }
186 }
187 spin_unlock_irqrestore(&fnic_trace_lock, flags);
188 return len;
189}
190
191/*
192 * fnic_trace_buf_init - Initialize fnic trace buffer logging facility
193 *
194 * Description:
195 * Initialize trace buffer data structure by allocating required memory and
196 * setting page_offset information for every trace entry by adding trace entry
197 * length to previous page_offset value.
198 */
199int fnic_trace_buf_init(void)
200{
201 unsigned long fnic_buf_head;
202 int i;
203 int err = 0;
204
205 trace_max_pages = fnic_trace_max_pages;
206 fnic_max_trace_entries = (trace_max_pages * PAGE_SIZE)/
207 FNIC_ENTRY_SIZE_BYTES;
208
209 fnic_trace_buf_p = (unsigned long)vmalloc((trace_max_pages * PAGE_SIZE));
210 if (!fnic_trace_buf_p) {
211 printk(KERN_ERR PFX "Failed to allocate memory "
212 "for fnic_trace_buf_p\n");
213 err = -ENOMEM;
214 goto err_fnic_trace_buf_init;
215 }
216 memset((void *)fnic_trace_buf_p, 0, (trace_max_pages * PAGE_SIZE));
217
218 fnic_trace_entries.page_offset = vmalloc(fnic_max_trace_entries *
219 sizeof(unsigned long));
220 if (!fnic_trace_entries.page_offset) {
221 printk(KERN_ERR PFX "Failed to allocate memory for"
222 " page_offset\n");
223 if (fnic_trace_buf_p) {
224 vfree((void *)fnic_trace_buf_p);
225 fnic_trace_buf_p = 0;
226 }
227 err = -ENOMEM;
228 goto err_fnic_trace_buf_init;
229 }
230 memset((void *)fnic_trace_entries.page_offset, 0,
231 (fnic_max_trace_entries * sizeof(unsigned long)));
232 fnic_trace_entries.wr_idx = fnic_trace_entries.rd_idx = 0;
233 fnic_buf_head = fnic_trace_buf_p;
234
235 /*
236 * Set page_offset field of fnic_trace_entries struct by
237 * calculating memory location for every trace entry using
238 * length of each trace entry
239 */
240 for (i = 0; i < fnic_max_trace_entries; i++) {
241 fnic_trace_entries.page_offset[i] = fnic_buf_head;
242 fnic_buf_head += FNIC_ENTRY_SIZE_BYTES;
243 }
244 err = fnic_trace_debugfs_init();
245 if (err < 0) {
246 printk(KERN_ERR PFX "Failed to initialize debugfs for tracing\n");
247 goto err_fnic_trace_debugfs_init;
248 }
249 printk(KERN_INFO PFX "Successfully Initialized Trace Buffer\n");
250 return err;
251err_fnic_trace_debugfs_init:
252 fnic_trace_free();
253err_fnic_trace_buf_init:
254 return err;
255}
256
257/*
258 * fnic_trace_free - Free memory of fnic trace data structures.
259 */
260void fnic_trace_free(void)
261{
262 fnic_tracing_enabled = 0;
263 fnic_trace_debugfs_terminate();
264 if (fnic_trace_entries.page_offset) {
265 vfree((void *)fnic_trace_entries.page_offset);
266 fnic_trace_entries.page_offset = NULL;
267 }
268 if (fnic_trace_buf_p) {
269 vfree((void *)fnic_trace_buf_p);
270 fnic_trace_buf_p = 0;
271 }
272 printk(KERN_INFO PFX "Successfully Freed Trace Buffer\n");
273}
diff --git a/drivers/scsi/fnic/fnic_trace.h b/drivers/scsi/fnic/fnic_trace.h
new file mode 100644
index 000000000000..cef42b4c4d6c
--- /dev/null
+++ b/drivers/scsi/fnic/fnic_trace.h
@@ -0,0 +1,90 @@
1/*
2 * Copyright 2012 Cisco Systems, Inc. All rights reserved.
3 *
4 * This program is free software; you may redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
9 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
10 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
11 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
12 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
13 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
14 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
15 * SOFTWARE.
16 */
17
18#ifndef __FNIC_TRACE_H__
19#define __FNIC_TRACE_H__
20
21#define FNIC_ENTRY_SIZE_BYTES 64
22
23extern ssize_t simple_read_from_buffer(void __user *to,
24 size_t count,
25 loff_t *ppos,
26 const void *from,
27 size_t available);
28
29extern unsigned int fnic_trace_max_pages;
30extern int fnic_tracing_enabled;
31extern unsigned int trace_max_pages;
32
33typedef struct fnic_trace_dbg {
34 int wr_idx;
35 int rd_idx;
36 unsigned long *page_offset;
37} fnic_trace_dbg_t;
38
39typedef struct fnic_dbgfs {
40 int buffer_len;
41 char *buffer;
42} fnic_dbgfs_t;
43
44struct fnic_trace_data {
45 union {
46 struct {
47 u32 low;
48 u32 high;
49 };
50 u64 val;
51 } timestamp, fnaddr;
52 u32 host_no;
53 u32 tag;
54 u64 data[5];
55} __attribute__((__packed__));
56
57typedef struct fnic_trace_data fnic_trace_data_t;
58
59#define FNIC_TRACE_ENTRY_SIZE \
60 (FNIC_ENTRY_SIZE_BYTES - sizeof(fnic_trace_data_t))
61
62#define FNIC_TRACE(_fn, _hn, _t, _a, _b, _c, _d, _e) \
63 if (unlikely(fnic_tracing_enabled)) { \
64 fnic_trace_data_t *trace_buf = fnic_trace_get_buf(); \
65 if (trace_buf) { \
66 if (sizeof(unsigned long) < 8) { \
67 trace_buf->timestamp.low = jiffies; \
68 trace_buf->fnaddr.low = (u32)(unsigned long)_fn; \
69 } else { \
70 trace_buf->timestamp.val = jiffies; \
71 trace_buf->fnaddr.val = (u64)(unsigned long)_fn; \
72 } \
73 trace_buf->host_no = _hn; \
74 trace_buf->tag = _t; \
75 trace_buf->data[0] = (u64)(unsigned long)_a; \
76 trace_buf->data[1] = (u64)(unsigned long)_b; \
77 trace_buf->data[2] = (u64)(unsigned long)_c; \
78 trace_buf->data[3] = (u64)(unsigned long)_d; \
79 trace_buf->data[4] = (u64)(unsigned long)_e; \
80 } \
81 }
82
83fnic_trace_data_t *fnic_trace_get_buf(void);
84int fnic_get_trace_data(fnic_dbgfs_t *);
85int fnic_trace_buf_init(void);
86void fnic_trace_free(void);
87int fnic_trace_debugfs_init(void);
88void fnic_trace_debugfs_terminate(void);
89
90#endif