aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorAndrew Vasquez <andrew.vasquez@qlogic.com>2008-01-17 12:02:17 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-01-23 12:29:32 -0500
commitdf613b96077cee826b14089ae6e75eeabf71faa3 (patch)
tree262f0b96f1dc94da58f837e5446b02da52d80471 /drivers/scsi
parent00b6bd25166e2a4bad23c614c10c55993bb2489e (diff)
[SCSI] qla2xxx: Add Fibre Channel Event (FCE) tracing support.
FCE support enables the firmware to record FC extended link services and basic link services frames which have been transmitted and received by the ISP. This allows for a limited view of the FC traffic through the ISP without using a FC analyzer. This can be useful in situations where a physical connection to the FC bus is not possible. The driver exports this information in two ways -- first, via a debugfs node exported for all supported ISPs under: <debugfs_mount_point>/qla2xxx/qla2xxx_<host_no>/fce where a read of the 'fce' file will provide a snapshot of the firmware's FCE buffer; and finally, the FCE buffer will be extracted during a firmware-dump scenario. Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/qla2xxx/Makefile2
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.c22
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.h19
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h10
-rw-r--r--drivers/scsi/qla2xxx/qla_dfs.c175
-rw-r--r--drivers/scsi/qla2xxx/qla_fw.h7
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h13
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c73
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c87
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c11
10 files changed, 405 insertions, 14 deletions
diff --git a/drivers/scsi/qla2xxx/Makefile b/drivers/scsi/qla2xxx/Makefile
index 71ddb5db4944..c51fd1f86639 100644
--- a/drivers/scsi/qla2xxx/Makefile
+++ b/drivers/scsi/qla2xxx/Makefile
@@ -1,4 +1,4 @@
1qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \ 1qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \
2 qla_dbg.o qla_sup.o qla_attr.o qla_mid.o 2 qla_dbg.o qla_sup.o qla_attr.o qla_mid.o qla_dfs.o
3 3
4obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o 4obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index 796c4ce87831..d88e98c476b0 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -1051,6 +1051,7 @@ qla25xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
1051 struct qla25xx_fw_dump *fw; 1051 struct qla25xx_fw_dump *fw;
1052 uint32_t ext_mem_cnt; 1052 uint32_t ext_mem_cnt;
1053 void *nxt; 1053 void *nxt;
1054 struct qla2xxx_fce_chain *fcec;
1054 1055
1055 risc_address = ext_mem_cnt = 0; 1056 risc_address = ext_mem_cnt = 0;
1056 flags = 0; 1057 flags = 0;
@@ -1321,10 +1322,31 @@ qla25xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
1321 if (rval != QLA_SUCCESS) 1322 if (rval != QLA_SUCCESS)
1322 goto qla25xx_fw_dump_failed_0; 1323 goto qla25xx_fw_dump_failed_0;
1323 1324
1325 /* Fibre Channel Trace Buffer. */
1324 nxt = qla2xxx_copy_queues(ha, nxt); 1326 nxt = qla2xxx_copy_queues(ha, nxt);
1325 if (ha->eft) 1327 if (ha->eft)
1326 memcpy(nxt, ha->eft, ntohl(ha->fw_dump->eft_size)); 1328 memcpy(nxt, ha->eft, ntohl(ha->fw_dump->eft_size));
1327 1329
1330 /* Fibre Channel Event Buffer. */
1331 if (!ha->fce)
1332 goto qla25xx_fw_dump_failed_0;
1333
1334 ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT);
1335
1336 fcec = nxt + ntohl(ha->fw_dump->eft_size);
1337 fcec->type = __constant_htonl(DUMP_CHAIN_FCE | DUMP_CHAIN_LAST);
1338 fcec->chain_size = htonl(sizeof(struct qla2xxx_fce_chain) +
1339 fce_calc_size(ha->fce_bufs));
1340 fcec->size = htonl(fce_calc_size(ha->fce_bufs));
1341 fcec->addr_l = htonl(LSD(ha->fce_dma));
1342 fcec->addr_h = htonl(MSD(ha->fce_dma));
1343
1344 iter_reg = fcec->eregs;
1345 for (cnt = 0; cnt < 8; cnt++)
1346 *iter_reg++ = htonl(ha->fce_mb[cnt]);
1347
1348 memcpy(iter_reg, ha->fce, ntohl(fcec->size));
1349
1328qla25xx_fw_dump_failed_0: 1350qla25xx_fw_dump_failed_0:
1329 if (rval != QLA_SUCCESS) { 1351 if (rval != QLA_SUCCESS) {
1330 qla_printk(KERN_WARNING, ha, 1352 qla_printk(KERN_WARNING, ha,
diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h
index a50ecf0b7c84..524598afc81c 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.h
+++ b/drivers/scsi/qla2xxx/qla_dbg.h
@@ -256,6 +256,25 @@ struct qla25xx_fw_dump {
256#define EFT_BYTES_PER_BUFFER 0x4000 256#define EFT_BYTES_PER_BUFFER 0x4000
257#define EFT_SIZE ((EFT_BYTES_PER_BUFFER) * (EFT_NUM_BUFFERS)) 257#define EFT_SIZE ((EFT_BYTES_PER_BUFFER) * (EFT_NUM_BUFFERS))
258 258
259#define FCE_NUM_BUFFERS 64
260#define FCE_BYTES_PER_BUFFER 0x400
261#define FCE_SIZE ((FCE_BYTES_PER_BUFFER) * (FCE_NUM_BUFFERS))
262#define fce_calc_size(b) ((FCE_BYTES_PER_BUFFER) * (b))
263
264struct qla2xxx_fce_chain {
265 uint32_t type;
266 uint32_t chain_size;
267
268 uint32_t size;
269 uint32_t addr_l;
270 uint32_t addr_h;
271 uint32_t eregs[8];
272};
273
274#define DUMP_CHAIN_VARIANT 0x80000000
275#define DUMP_CHAIN_FCE 0x7FFFFAF0
276#define DUMP_CHAIN_LAST 0x80000000
277
259struct qla2xxx_fw_dump { 278struct qla2xxx_fw_dump {
260 uint8_t signature[4]; 279 uint8_t signature[4];
261 uint32_t version; 280 uint32_t version;
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 3f934bdce6ae..6f129da37589 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2156,6 +2156,7 @@ typedef struct scsi_qla_host {
2156 uint32_t gpsc_supported :1; 2156 uint32_t gpsc_supported :1;
2157 uint32_t vsan_enabled :1; 2157 uint32_t vsan_enabled :1;
2158 uint32_t npiv_supported :1; 2158 uint32_t npiv_supported :1;
2159 uint32_t fce_enabled :1;
2159 } flags; 2160 } flags;
2160 2161
2161 atomic_t loop_state; 2162 atomic_t loop_state;
@@ -2449,6 +2450,15 @@ typedef struct scsi_qla_host {
2449 dma_addr_t eft_dma; 2450 dma_addr_t eft_dma;
2450 void *eft; 2451 void *eft;
2451 2452
2453 struct dentry *dfs_dir;
2454 struct dentry *dfs_fce;
2455 dma_addr_t fce_dma;
2456 void *fce;
2457 uint32_t fce_bufs;
2458 uint16_t fce_mb[8];
2459 uint64_t fce_wr, fce_rd;
2460 struct mutex fce_mutex;
2461
2452 uint8_t host_str[16]; 2462 uint8_t host_str[16];
2453 uint32_t pci_attr; 2463 uint32_t pci_attr;
2454 uint16_t chip_revision; 2464 uint16_t chip_revision;
diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c
new file mode 100644
index 000000000000..1479c60441c8
--- /dev/null
+++ b/drivers/scsi/qla2xxx/qla_dfs.c
@@ -0,0 +1,175 @@
1/*
2 * QLogic Fibre Channel HBA Driver
3 * Copyright (c) 2003-2005 QLogic Corporation
4 *
5 * See LICENSE.qla2xxx for copyright and licensing details.
6 */
7#include "qla_def.h"
8
9#include <linux/debugfs.h>
10#include <linux/seq_file.h>
11
12static struct dentry *qla2x00_dfs_root;
13static atomic_t qla2x00_dfs_root_count;
14
15static int
16qla2x00_dfs_fce_show(struct seq_file *s, void *unused)
17{
18 scsi_qla_host_t *ha = s->private;
19 uint32_t cnt;
20 uint32_t *fce;
21 uint64_t fce_start;
22
23 mutex_lock(&ha->fce_mutex);
24
25 seq_printf(s, "FCE Trace Buffer\n");
26 seq_printf(s, "In Pointer = %llx\n\n", ha->fce_wr);
27 seq_printf(s, "Base = %llx\n\n", (unsigned long long) ha->fce_dma);
28 seq_printf(s, "FCE Enable Registers\n");
29 seq_printf(s, "%08x %08x %08x %08x %08x %08x\n",
30 ha->fce_mb[0], ha->fce_mb[2], ha->fce_mb[3], ha->fce_mb[4],
31 ha->fce_mb[5], ha->fce_mb[6]);
32
33 fce = (uint32_t *) ha->fce;
34 fce_start = (unsigned long long) ha->fce_dma;
35 for (cnt = 0; cnt < fce_calc_size(ha->fce_bufs) / 4; cnt++) {
36 if (cnt % 8 == 0)
37 seq_printf(s, "\n%llx: ",
38 (unsigned long long)((cnt * 4) + fce_start));
39 else
40 seq_printf(s, " ");
41 seq_printf(s, "%08x", *fce++);
42 }
43
44 seq_printf(s, "\nEnd\n");
45
46 mutex_unlock(&ha->fce_mutex);
47
48 return 0;
49}
50
51static int
52qla2x00_dfs_fce_open(struct inode *inode, struct file *file)
53{
54 scsi_qla_host_t *ha = inode->i_private;
55 int rval;
56
57 if (!ha->flags.fce_enabled)
58 goto out;
59
60 mutex_lock(&ha->fce_mutex);
61
62 /* Pause tracing to flush FCE buffers. */
63 rval = qla2x00_disable_fce_trace(ha, &ha->fce_wr, &ha->fce_rd);
64 if (rval)
65 qla_printk(KERN_WARNING, ha,
66 "DebugFS: Unable to disable FCE (%d).\n", rval);
67
68 ha->flags.fce_enabled = 0;
69
70 mutex_unlock(&ha->fce_mutex);
71out:
72 return single_open(file, qla2x00_dfs_fce_show, ha);
73}
74
75static int
76qla2x00_dfs_fce_release(struct inode *inode, struct file *file)
77{
78 scsi_qla_host_t *ha = inode->i_private;
79 int rval;
80
81 if (ha->flags.fce_enabled)
82 goto out;
83
84 mutex_lock(&ha->fce_mutex);
85
86 /* Re-enable FCE tracing. */
87 ha->flags.fce_enabled = 1;
88 memset(ha->fce, 0, fce_calc_size(ha->fce_bufs));
89 rval = qla2x00_enable_fce_trace(ha, ha->fce_dma, ha->fce_bufs,
90 ha->fce_mb, &ha->fce_bufs);
91 if (rval) {
92 qla_printk(KERN_WARNING, ha,
93 "DebugFS: Unable to reinitialize FCE (%d).\n", rval);
94 ha->flags.fce_enabled = 0;
95 }
96
97 mutex_unlock(&ha->fce_mutex);
98out:
99 return single_release(inode, file);
100}
101
102static const struct file_operations dfs_fce_ops = {
103 .open = qla2x00_dfs_fce_open,
104 .read = seq_read,
105 .llseek = seq_lseek,
106 .release = qla2x00_dfs_fce_release,
107};
108
109int
110qla2x00_dfs_setup(scsi_qla_host_t *ha)
111{
112 if (!IS_QLA25XX(ha))
113 goto out;
114 if (!ha->fce)
115 goto out;
116
117 if (qla2x00_dfs_root)
118 goto create_dir;
119
120 atomic_set(&qla2x00_dfs_root_count, 0);
121 qla2x00_dfs_root = debugfs_create_dir(QLA2XXX_DRIVER_NAME, NULL);
122 if (!qla2x00_dfs_root) {
123 qla_printk(KERN_NOTICE, ha,
124 "DebugFS: Unable to create root directory.\n");
125 goto out;
126 }
127
128create_dir:
129 if (ha->dfs_dir)
130 goto create_nodes;
131
132 mutex_init(&ha->fce_mutex);
133 ha->dfs_dir = debugfs_create_dir(ha->host_str, qla2x00_dfs_root);
134 if (!ha->dfs_dir) {
135 qla_printk(KERN_NOTICE, ha,
136 "DebugFS: Unable to create ha directory.\n");
137 goto out;
138 }
139
140 atomic_inc(&qla2x00_dfs_root_count);
141
142create_nodes:
143 ha->dfs_fce = debugfs_create_file("fce", S_IRUSR, ha->dfs_dir, ha,
144 &dfs_fce_ops);
145 if (!ha->dfs_fce) {
146 qla_printk(KERN_NOTICE, ha,
147 "DebugFS: Unable to fce node.\n");
148 goto out;
149 }
150out:
151 return 0;
152}
153
154int
155qla2x00_dfs_remove(scsi_qla_host_t *ha)
156{
157 if (ha->dfs_fce) {
158 debugfs_remove(ha->dfs_fce);
159 ha->dfs_fce = NULL;
160 }
161
162 if (ha->dfs_dir) {
163 debugfs_remove(ha->dfs_dir);
164 ha->dfs_dir = NULL;
165 atomic_dec(&qla2x00_dfs_root_count);
166 }
167
168 if (atomic_read(&qla2x00_dfs_root_count) == 0 &&
169 qla2x00_dfs_root) {
170 debugfs_remove(qla2x00_dfs_root);
171 qla2x00_dfs_root = NULL;
172 }
173
174 return 0;
175}
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index ef14bcde712a..9337e138ed63 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -959,6 +959,13 @@ struct device_reg_24xx {
959#define TC_EFT_ENABLE 4 959#define TC_EFT_ENABLE 4
960#define TC_EFT_DISABLE 5 960#define TC_EFT_DISABLE 5
961 961
962#define TC_FCE_ENABLE 8
963#define TC_FCE_OPTIONS 0
964#define TC_FCE_DEFAULT_RX_SIZE 2112
965#define TC_FCE_DEFAULT_TX_SIZE 2112
966#define TC_FCE_DISABLE 9
967#define TC_FCE_DISABLE_TRACE BIT_0
968
962/* MID Support ***************************************************************/ 969/* MID Support ***************************************************************/
963 970
964#define MIN_MULTI_ID_FABRIC 64 /* Must be power-of-2. */ 971#define MIN_MULTI_ID_FABRIC 64 /* Must be power-of-2. */
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 2fd31fdafcc9..ba35fc26ce6b 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -233,6 +233,13 @@ extern int
233qla2x00_disable_eft_trace(scsi_qla_host_t *); 233qla2x00_disable_eft_trace(scsi_qla_host_t *);
234 234
235extern int 235extern int
236qla2x00_enable_fce_trace(scsi_qla_host_t *, dma_addr_t, uint16_t , uint16_t *,
237 uint32_t *);
238
239extern int
240qla2x00_disable_fce_trace(scsi_qla_host_t *, uint64_t *, uint64_t *);
241
242extern int
236qla2x00_read_sfp(scsi_qla_host_t *, dma_addr_t, uint16_t, uint16_t, uint16_t); 243qla2x00_read_sfp(scsi_qla_host_t *, dma_addr_t, uint16_t, uint16_t, uint16_t);
237 244
238extern int 245extern int
@@ -334,4 +341,10 @@ extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *);
334extern void qla2x00_init_host_attr(scsi_qla_host_t *); 341extern void qla2x00_init_host_attr(scsi_qla_host_t *);
335extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *); 342extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *);
336extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *); 343extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *);
344
345/*
346 * Global Function Prototypes in qla_dfs.c source file.
347 */
348extern int qla2x00_dfs_setup(scsi_qla_host_t *);
349extern int qla2x00_dfs_remove(scsi_qla_host_t *);
337#endif /* _QLA_GBL_H */ 350#endif /* _QLA_GBL_H */
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index da2cce011520..cacfd2509387 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -732,9 +732,9 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *ha)
732{ 732{
733 int rval; 733 int rval;
734 uint32_t dump_size, fixed_size, mem_size, req_q_size, rsp_q_size, 734 uint32_t dump_size, fixed_size, mem_size, req_q_size, rsp_q_size,
735 eft_size; 735 eft_size, fce_size;
736 dma_addr_t eft_dma; 736 dma_addr_t tc_dma;
737 void *eft; 737 void *tc;
738 738
739 if (ha->fw_dump) { 739 if (ha->fw_dump) {
740 qla_printk(KERN_WARNING, ha, 740 qla_printk(KERN_WARNING, ha,
@@ -743,7 +743,7 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *ha)
743 } 743 }
744 744
745 ha->fw_dumped = 0; 745 ha->fw_dumped = 0;
746 fixed_size = mem_size = eft_size = 0; 746 fixed_size = mem_size = eft_size = fce_size = 0;
747 if (IS_QLA2100(ha) || IS_QLA2200(ha)) { 747 if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
748 fixed_size = sizeof(struct qla2100_fw_dump); 748 fixed_size = sizeof(struct qla2100_fw_dump);
749 } else if (IS_QLA23XX(ha)) { 749 } else if (IS_QLA23XX(ha)) {
@@ -758,20 +758,20 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *ha)
758 sizeof(uint32_t); 758 sizeof(uint32_t);
759 759
760 /* Allocate memory for Extended Trace Buffer. */ 760 /* Allocate memory for Extended Trace Buffer. */
761 eft = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &eft_dma, 761 tc = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma,
762 GFP_KERNEL); 762 GFP_KERNEL);
763 if (!eft) { 763 if (!tc) {
764 qla_printk(KERN_WARNING, ha, "Unable to allocate " 764 qla_printk(KERN_WARNING, ha, "Unable to allocate "
765 "(%d KB) for EFT.\n", EFT_SIZE / 1024); 765 "(%d KB) for EFT.\n", EFT_SIZE / 1024);
766 goto cont_alloc; 766 goto cont_alloc;
767 } 767 }
768 768
769 rval = qla2x00_enable_eft_trace(ha, eft_dma, EFT_NUM_BUFFERS); 769 rval = qla2x00_enable_eft_trace(ha, tc_dma, EFT_NUM_BUFFERS);
770 if (rval) { 770 if (rval) {
771 qla_printk(KERN_WARNING, ha, "Unable to initialize " 771 qla_printk(KERN_WARNING, ha, "Unable to initialize "
772 "EFT (%d).\n", rval); 772 "EFT (%d).\n", rval);
773 dma_free_coherent(&ha->pdev->dev, EFT_SIZE, eft, 773 dma_free_coherent(&ha->pdev->dev, EFT_SIZE, tc,
774 eft_dma); 774 tc_dma);
775 goto cont_alloc; 775 goto cont_alloc;
776 } 776 }
777 777
@@ -779,9 +779,41 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *ha)
779 EFT_SIZE / 1024); 779 EFT_SIZE / 1024);
780 780
781 eft_size = EFT_SIZE; 781 eft_size = EFT_SIZE;
782 memset(eft, 0, eft_size); 782 memset(tc, 0, eft_size);
783 ha->eft_dma = eft_dma; 783 ha->eft_dma = tc_dma;
784 ha->eft = eft; 784 ha->eft = tc;
785
786 /* Allocate memory for Fibre Channel Event Buffer. */
787 if (!IS_QLA25XX(ha))
788 goto cont_alloc;
789
790 tc = dma_alloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma,
791 GFP_KERNEL);
792 if (!tc) {
793 qla_printk(KERN_WARNING, ha, "Unable to allocate "
794 "(%d KB) for FCE.\n", FCE_SIZE / 1024);
795 goto cont_alloc;
796 }
797
798 memset(tc, 0, FCE_SIZE);
799 rval = qla2x00_enable_fce_trace(ha, tc_dma, FCE_NUM_BUFFERS,
800 ha->fce_mb, &ha->fce_bufs);
801 if (rval) {
802 qla_printk(KERN_WARNING, ha, "Unable to initialize "
803 "FCE (%d).\n", rval);
804 dma_free_coherent(&ha->pdev->dev, FCE_SIZE, tc,
805 tc_dma);
806 ha->flags.fce_enabled = 0;
807 goto cont_alloc;
808 }
809
810 qla_printk(KERN_INFO, ha, "Allocated (%d KB) for FCE...\n",
811 FCE_SIZE / 1024);
812
813 fce_size = sizeof(struct qla2xxx_fce_chain) + EFT_SIZE;
814 ha->flags.fce_enabled = 1;
815 ha->fce_dma = tc_dma;
816 ha->fce = tc;
785 } 817 }
786cont_alloc: 818cont_alloc:
787 req_q_size = ha->request_q_length * sizeof(request_t); 819 req_q_size = ha->request_q_length * sizeof(request_t);
@@ -789,7 +821,7 @@ cont_alloc:
789 821
790 dump_size = offsetof(struct qla2xxx_fw_dump, isp); 822 dump_size = offsetof(struct qla2xxx_fw_dump, isp);
791 dump_size += fixed_size + mem_size + req_q_size + rsp_q_size + 823 dump_size += fixed_size + mem_size + req_q_size + rsp_q_size +
792 eft_size; 824 eft_size + fce_size;
793 825
794 ha->fw_dump = vmalloc(dump_size); 826 ha->fw_dump = vmalloc(dump_size);
795 if (!ha->fw_dump) { 827 if (!ha->fw_dump) {
@@ -3247,6 +3279,21 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
3247 "(%d).\n", rval); 3279 "(%d).\n", rval);
3248 } 3280 }
3249 } 3281 }
3282
3283 if (ha->fce) {
3284 ha->flags.fce_enabled = 1;
3285 memset(ha->fce, 0,
3286 fce_calc_size(ha->fce_bufs));
3287 rval = qla2x00_enable_fce_trace(ha,
3288 ha->fce_dma, ha->fce_bufs, ha->fce_mb,
3289 &ha->fce_bufs);
3290 if (rval) {
3291 qla_printk(KERN_WARNING, ha,
3292 "Unable to reinitialize FCE "
3293 "(%d).\n", rval);
3294 ha->flags.fce_enabled = 0;
3295 }
3296 }
3250 } else { /* failed the ISP abort */ 3297 } else { /* failed the ISP abort */
3251 ha->flags.online = 1; 3298 ha->flags.online = 1;
3252 if (test_bit(ISP_ABORT_RETRY, &ha->dpc_flags)) { 3299 if (test_bit(ISP_ABORT_RETRY, &ha->dpc_flags)) {
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 7c6aa4ec8f4f..99d29fff836d 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -2415,6 +2415,93 @@ qla2x00_disable_eft_trace(scsi_qla_host_t *ha)
2415} 2415}
2416 2416
2417int 2417int
2418qla2x00_enable_fce_trace(scsi_qla_host_t *ha, dma_addr_t fce_dma,
2419 uint16_t buffers, uint16_t *mb, uint32_t *dwords)
2420{
2421 int rval;
2422 mbx_cmd_t mc;
2423 mbx_cmd_t *mcp = &mc;
2424
2425 if (!IS_QLA25XX(ha))
2426 return QLA_FUNCTION_FAILED;
2427
2428 DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
2429
2430 mcp->mb[0] = MBC_TRACE_CONTROL;
2431 mcp->mb[1] = TC_FCE_ENABLE;
2432 mcp->mb[2] = LSW(fce_dma);
2433 mcp->mb[3] = MSW(fce_dma);
2434 mcp->mb[4] = LSW(MSD(fce_dma));
2435 mcp->mb[5] = MSW(MSD(fce_dma));
2436 mcp->mb[6] = buffers;
2437 mcp->mb[7] = TC_AEN_DISABLE;
2438 mcp->mb[8] = 0;
2439 mcp->mb[9] = TC_FCE_DEFAULT_RX_SIZE;
2440 mcp->mb[10] = TC_FCE_DEFAULT_TX_SIZE;
2441 mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|
2442 MBX_1|MBX_0;
2443 mcp->in_mb = MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
2444 mcp->tov = 30;
2445 mcp->flags = 0;
2446 rval = qla2x00_mailbox_command(ha, mcp);
2447 if (rval != QLA_SUCCESS) {
2448 DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x.\n",
2449 __func__, ha->host_no, rval, mcp->mb[0], mcp->mb[1]));
2450 } else {
2451 DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
2452
2453 if (mb)
2454 memcpy(mb, mcp->mb, 8 * sizeof(*mb));
2455 if (dwords)
2456 *dwords = mcp->mb[6];
2457 }
2458
2459 return rval;
2460}
2461
2462int
2463qla2x00_disable_fce_trace(scsi_qla_host_t *ha, uint64_t *wr, uint64_t *rd)
2464{
2465 int rval;
2466 mbx_cmd_t mc;
2467 mbx_cmd_t *mcp = &mc;
2468
2469 if (!IS_FWI2_CAPABLE(ha))
2470 return QLA_FUNCTION_FAILED;
2471
2472 DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
2473
2474 mcp->mb[0] = MBC_TRACE_CONTROL;
2475 mcp->mb[1] = TC_FCE_DISABLE;
2476 mcp->mb[2] = TC_FCE_DISABLE_TRACE;
2477 mcp->out_mb = MBX_2|MBX_1|MBX_0;
2478 mcp->in_mb = MBX_9|MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|
2479 MBX_1|MBX_0;
2480 mcp->tov = 30;
2481 mcp->flags = 0;
2482 rval = qla2x00_mailbox_command(ha, mcp);
2483 if (rval != QLA_SUCCESS) {
2484 DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x.\n",
2485 __func__, ha->host_no, rval, mcp->mb[0], mcp->mb[1]));
2486 } else {
2487 DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
2488
2489 if (wr)
2490 *wr = (uint64_t) mcp->mb[5] << 48 |
2491 (uint64_t) mcp->mb[4] << 32 |
2492 (uint64_t) mcp->mb[3] << 16 |
2493 (uint64_t) mcp->mb[2];
2494 if (rd)
2495 *rd = (uint64_t) mcp->mb[9] << 48 |
2496 (uint64_t) mcp->mb[8] << 32 |
2497 (uint64_t) mcp->mb[7] << 16 |
2498 (uint64_t) mcp->mb[6];
2499 }
2500
2501 return rval;
2502}
2503
2504int
2418qla2x00_read_sfp(scsi_qla_host_t *ha, dma_addr_t sfp_dma, uint16_t addr, 2505qla2x00_read_sfp(scsi_qla_host_t *ha, dma_addr_t sfp_dma, uint16_t addr,
2419 uint16_t off, uint16_t count) 2506 uint16_t off, uint16_t count)
2420{ 2507{
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 63938d74a571..8d1408e18efd 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1791,6 +1791,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
1791 1791
1792 qla2x00_init_host_attr(ha); 1792 qla2x00_init_host_attr(ha);
1793 1793
1794 qla2x00_dfs_setup(ha);
1795
1794 qla_printk(KERN_INFO, ha, "\n" 1796 qla_printk(KERN_INFO, ha, "\n"
1795 " QLogic Fibre Channel HBA Driver: %s\n" 1797 " QLogic Fibre Channel HBA Driver: %s\n"
1796 " QLogic %s - %s\n" 1798 " QLogic %s - %s\n"
@@ -1822,6 +1824,8 @@ qla2x00_remove_one(struct pci_dev *pdev)
1822 1824
1823 ha = pci_get_drvdata(pdev); 1825 ha = pci_get_drvdata(pdev);
1824 1826
1827 qla2x00_dfs_remove(ha);
1828
1825 qla2x00_free_sysfs_attr(ha); 1829 qla2x00_free_sysfs_attr(ha);
1826 1830
1827 fc_remove_host(ha->host); 1831 fc_remove_host(ha->host);
@@ -1855,6 +1859,9 @@ qla2x00_free_device(scsi_qla_host_t *ha)
1855 kthread_stop(t); 1859 kthread_stop(t);
1856 } 1860 }
1857 1861
1862 if (ha->flags.fce_enabled)
1863 qla2x00_disable_fce_trace(ha, NULL, NULL);
1864
1858 if (ha->eft) 1865 if (ha->eft)
1859 qla2x00_disable_eft_trace(ha); 1866 qla2x00_disable_eft_trace(ha);
1860 1867
@@ -2212,6 +2219,10 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
2212 /* free sp pool */ 2219 /* free sp pool */
2213 qla2x00_free_sp_pool(ha); 2220 qla2x00_free_sp_pool(ha);
2214 2221
2222 if (ha->fce)
2223 dma_free_coherent(&ha->pdev->dev, FCE_SIZE, ha->fce,
2224 ha->fce_dma);
2225
2215 if (ha->fw_dump) { 2226 if (ha->fw_dump) {
2216 if (ha->eft) 2227 if (ha->eft)
2217 dma_free_coherent(&ha->pdev->dev, 2228 dma_free_coherent(&ha->pdev->dev,