aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHiral Patel <hiralpat@cisco.com>2013-02-12 20:01:02 -0500
committerJames Bottomley <JBottomley@Parallels.com>2013-02-22 12:32:07 -0500
commit4d7007b49d523d8f954ae047118d82c130f673ce (patch)
tree16ce6d74b77020b444a554bc5d63c1c2718df701
parent14eb5d905d16ecd33e5e3113eb44cfa2bb47e7d7 (diff)
[SCSI] fnic: Fnic Trace Utility
Fnic Trace utility is a tracing functionality built directly into fnic driver to trace events. The benefit that trace buffer brings to fnic driver is the ability to see what it happening inside the fnic driver. It also provides the capability to trace every IO event inside fnic driver to debug panics, hangs and potentially IO corruption issues. This feature makes it easy to find problems in fnic driver and it also helps in tracking down strange bugs in a more manageable way. Trace buffer is shared across all fnic instances for this implementation. Signed-off-by: Hiral Patel <hiralpat@cisco.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-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