aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRon Mercer <ron.mercer@qlogic.com>2010-01-15 08:31:32 -0500
committerDavid S. Miller <davem@davemloft.net>2010-01-16 04:01:54 -0500
commita48c86fdb1253f36167bab1fc30a51211d49a901 (patch)
tree553e9a55d9a57d89b91541e7f2012885259a5983
parent24bb55b480f16f4cd8d64c2d46e28f0c82df0409 (diff)
qlge: Add serdes reg blocks dump to firmware dump.
Signed-off-by: Ron Mercer <ron.mercer@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/qlge/qlge_dbg.c417
1 files changed, 417 insertions, 0 deletions
diff --git a/drivers/net/qlge/qlge_dbg.c b/drivers/net/qlge/qlge_dbg.c
index 181281390129..87e50d9c3350 100644
--- a/drivers/net/qlge/qlge_dbg.c
+++ b/drivers/net/qlge/qlge_dbg.c
@@ -19,6 +19,318 @@ static u32 ql_read_other_func_reg(struct ql_adapter *qdev,
19 return reg_val; 19 return reg_val;
20} 20}
21 21
22/* Write a NIC register from the alternate function. */
23static int ql_write_other_func_reg(struct ql_adapter *qdev,
24 u32 reg, u32 reg_val)
25{
26 u32 register_to_read;
27 int status = 0;
28
29 register_to_read = MPI_NIC_REG_BLOCK
30 | MPI_NIC_READ
31 | (qdev->alt_func << MPI_NIC_FUNCTION_SHIFT)
32 | reg;
33 status = ql_write_mpi_reg(qdev, register_to_read, reg_val);
34
35 return status;
36}
37
38static int ql_wait_other_func_reg_rdy(struct ql_adapter *qdev, u32 reg,
39 u32 bit, u32 err_bit)
40{
41 u32 temp;
42 int count = 10;
43
44 while (count) {
45 temp = ql_read_other_func_reg(qdev, reg);
46
47 /* check for errors */
48 if (temp & err_bit)
49 return -1;
50 else if (temp & bit)
51 return 0;
52 mdelay(10);
53 count--;
54 }
55 return -1;
56}
57
58static int ql_read_other_func_serdes_reg(struct ql_adapter *qdev, u32 reg,
59 u32 *data)
60{
61 int status;
62
63 /* wait for reg to come ready */
64 status = ql_wait_other_func_reg_rdy(qdev, XG_SERDES_ADDR / 4,
65 XG_SERDES_ADDR_RDY, 0);
66 if (status)
67 goto exit;
68
69 /* set up for reg read */
70 ql_write_other_func_reg(qdev, XG_SERDES_ADDR/4, reg | PROC_ADDR_R);
71
72 /* wait for reg to come ready */
73 status = ql_wait_other_func_reg_rdy(qdev, XG_SERDES_ADDR / 4,
74 XG_SERDES_ADDR_RDY, 0);
75 if (status)
76 goto exit;
77
78 /* get the data */
79 *data = ql_read_other_func_reg(qdev, (XG_SERDES_DATA / 4));
80exit:
81 return status;
82}
83
84/* Read out the SERDES registers */
85static int ql_read_serdes_reg(struct ql_adapter *qdev, u32 reg, u32 * data)
86{
87 int status;
88
89 /* wait for reg to come ready */
90 status = ql_wait_reg_rdy(qdev, XG_SERDES_ADDR, XG_SERDES_ADDR_RDY, 0);
91 if (status)
92 goto exit;
93
94 /* set up for reg read */
95 ql_write32(qdev, XG_SERDES_ADDR, reg | PROC_ADDR_R);
96
97 /* wait for reg to come ready */
98 status = ql_wait_reg_rdy(qdev, XG_SERDES_ADDR, XG_SERDES_ADDR_RDY, 0);
99 if (status)
100 goto exit;
101
102 /* get the data */
103 *data = ql_read32(qdev, XG_SERDES_DATA);
104exit:
105 return status;
106}
107
108static void ql_get_both_serdes(struct ql_adapter *qdev, u32 addr,
109 u32 *direct_ptr, u32 *indirect_ptr,
110 unsigned int direct_valid, unsigned int indirect_valid)
111{
112 unsigned int status;
113
114 status = 1;
115 if (direct_valid)
116 status = ql_read_serdes_reg(qdev, addr, direct_ptr);
117 /* Dead fill any failures or invalids. */
118 if (status)
119 *direct_ptr = 0xDEADBEEF;
120
121 status = 1;
122 if (indirect_valid)
123 status = ql_read_other_func_serdes_reg(
124 qdev, addr, indirect_ptr);
125 /* Dead fill any failures or invalids. */
126 if (status)
127 *indirect_ptr = 0xDEADBEEF;
128}
129
130static int ql_get_serdes_regs(struct ql_adapter *qdev,
131 struct ql_mpi_coredump *mpi_coredump)
132{
133 int status;
134 unsigned int xfi_direct_valid, xfi_indirect_valid, xaui_direct_valid;
135 unsigned int xaui_indirect_valid, i;
136 u32 *direct_ptr, temp;
137 u32 *indirect_ptr;
138
139 xfi_direct_valid = xfi_indirect_valid = 0;
140 xaui_direct_valid = xaui_indirect_valid = 1;
141
142 /* The XAUI needs to be read out per port */
143 if (qdev->func & 1) {
144 /* We are NIC 2 */
145 status = ql_read_other_func_serdes_reg(qdev,
146 XG_SERDES_XAUI_HSS_PCS_START, &temp);
147 if (status)
148 temp = XG_SERDES_ADDR_XAUI_PWR_DOWN;
149 if ((temp & XG_SERDES_ADDR_XAUI_PWR_DOWN) ==
150 XG_SERDES_ADDR_XAUI_PWR_DOWN)
151 xaui_indirect_valid = 0;
152
153 status = ql_read_serdes_reg(qdev,
154 XG_SERDES_XAUI_HSS_PCS_START, &temp);
155 if (status)
156 temp = XG_SERDES_ADDR_XAUI_PWR_DOWN;
157
158 if ((temp & XG_SERDES_ADDR_XAUI_PWR_DOWN) ==
159 XG_SERDES_ADDR_XAUI_PWR_DOWN)
160 xaui_direct_valid = 0;
161 } else {
162 /* We are NIC 1 */
163 status = ql_read_other_func_serdes_reg(qdev,
164 XG_SERDES_XAUI_HSS_PCS_START, &temp);
165 if (status)
166 temp = XG_SERDES_ADDR_XAUI_PWR_DOWN;
167 if ((temp & XG_SERDES_ADDR_XAUI_PWR_DOWN) ==
168 XG_SERDES_ADDR_XAUI_PWR_DOWN)
169 xaui_indirect_valid = 0;
170
171 status = ql_read_serdes_reg(qdev,
172 XG_SERDES_XAUI_HSS_PCS_START, &temp);
173 if (status)
174 temp = XG_SERDES_ADDR_XAUI_PWR_DOWN;
175 if ((temp & XG_SERDES_ADDR_XAUI_PWR_DOWN) ==
176 XG_SERDES_ADDR_XAUI_PWR_DOWN)
177 xaui_direct_valid = 0;
178 }
179
180 /*
181 * XFI register is shared so only need to read one
182 * functions and then check the bits.
183 */
184 status = ql_read_serdes_reg(qdev, XG_SERDES_ADDR_STS, &temp);
185 if (status)
186 temp = 0;
187
188 if ((temp & XG_SERDES_ADDR_XFI1_PWR_UP) ==
189 XG_SERDES_ADDR_XFI1_PWR_UP) {
190 /* now see if i'm NIC 1 or NIC 2 */
191 if (qdev->func & 1)
192 /* I'm NIC 2, so the indirect (NIC1) xfi is up. */
193 xfi_indirect_valid = 1;
194 else
195 xfi_direct_valid = 1;
196 }
197 if ((temp & XG_SERDES_ADDR_XFI2_PWR_UP) ==
198 XG_SERDES_ADDR_XFI2_PWR_UP) {
199 /* now see if i'm NIC 1 or NIC 2 */
200 if (qdev->func & 1)
201 /* I'm NIC 2, so the indirect (NIC1) xfi is up. */
202 xfi_direct_valid = 1;
203 else
204 xfi_indirect_valid = 1;
205 }
206
207 /* Get XAUI_AN register block. */
208 if (qdev->func & 1) {
209 /* Function 2 is direct */
210 direct_ptr = mpi_coredump->serdes2_xaui_an;
211 indirect_ptr = mpi_coredump->serdes_xaui_an;
212 } else {
213 /* Function 1 is direct */
214 direct_ptr = mpi_coredump->serdes_xaui_an;
215 indirect_ptr = mpi_coredump->serdes2_xaui_an;
216 }
217
218 for (i = 0; i <= 0x000000034; i += 4, direct_ptr++, indirect_ptr++)
219 ql_get_both_serdes(qdev, i, direct_ptr, indirect_ptr,
220 xaui_direct_valid, xaui_indirect_valid);
221
222 /* Get XAUI_HSS_PCS register block. */
223 if (qdev->func & 1) {
224 direct_ptr =
225 mpi_coredump->serdes2_xaui_hss_pcs;
226 indirect_ptr =
227 mpi_coredump->serdes_xaui_hss_pcs;
228 } else {
229 direct_ptr =
230 mpi_coredump->serdes_xaui_hss_pcs;
231 indirect_ptr =
232 mpi_coredump->serdes2_xaui_hss_pcs;
233 }
234
235 for (i = 0x800; i <= 0x880; i += 4, direct_ptr++, indirect_ptr++)
236 ql_get_both_serdes(qdev, i, direct_ptr, indirect_ptr,
237 xaui_direct_valid, xaui_indirect_valid);
238
239 /* Get XAUI_XFI_AN register block. */
240 if (qdev->func & 1) {
241 direct_ptr = mpi_coredump->serdes2_xfi_an;
242 indirect_ptr = mpi_coredump->serdes_xfi_an;
243 } else {
244 direct_ptr = mpi_coredump->serdes_xfi_an;
245 indirect_ptr = mpi_coredump->serdes2_xfi_an;
246 }
247
248 for (i = 0x1000; i <= 0x1034; i += 4, direct_ptr++, indirect_ptr++)
249 ql_get_both_serdes(qdev, i, direct_ptr, indirect_ptr,
250 xfi_direct_valid, xfi_indirect_valid);
251
252 /* Get XAUI_XFI_TRAIN register block. */
253 if (qdev->func & 1) {
254 direct_ptr = mpi_coredump->serdes2_xfi_train;
255 indirect_ptr =
256 mpi_coredump->serdes_xfi_train;
257 } else {
258 direct_ptr = mpi_coredump->serdes_xfi_train;
259 indirect_ptr =
260 mpi_coredump->serdes2_xfi_train;
261 }
262
263 for (i = 0x1050; i <= 0x107c; i += 4, direct_ptr++, indirect_ptr++)
264 ql_get_both_serdes(qdev, i, direct_ptr, indirect_ptr,
265 xfi_direct_valid, xfi_indirect_valid);
266
267 /* Get XAUI_XFI_HSS_PCS register block. */
268 if (qdev->func & 1) {
269 direct_ptr =
270 mpi_coredump->serdes2_xfi_hss_pcs;
271 indirect_ptr =
272 mpi_coredump->serdes_xfi_hss_pcs;
273 } else {
274 direct_ptr =
275 mpi_coredump->serdes_xfi_hss_pcs;
276 indirect_ptr =
277 mpi_coredump->serdes2_xfi_hss_pcs;
278 }
279
280 for (i = 0x1800; i <= 0x1838; i += 4, direct_ptr++, indirect_ptr++)
281 ql_get_both_serdes(qdev, i, direct_ptr, indirect_ptr,
282 xfi_direct_valid, xfi_indirect_valid);
283
284 /* Get XAUI_XFI_HSS_TX register block. */
285 if (qdev->func & 1) {
286 direct_ptr =
287 mpi_coredump->serdes2_xfi_hss_tx;
288 indirect_ptr =
289 mpi_coredump->serdes_xfi_hss_tx;
290 } else {
291 direct_ptr = mpi_coredump->serdes_xfi_hss_tx;
292 indirect_ptr =
293 mpi_coredump->serdes2_xfi_hss_tx;
294 }
295 for (i = 0x1c00; i <= 0x1c1f; i++, direct_ptr++, indirect_ptr++)
296 ql_get_both_serdes(qdev, i, direct_ptr, indirect_ptr,
297 xfi_direct_valid, xfi_indirect_valid);
298
299 /* Get XAUI_XFI_HSS_RX register block. */
300 if (qdev->func & 1) {
301 direct_ptr =
302 mpi_coredump->serdes2_xfi_hss_rx;
303 indirect_ptr =
304 mpi_coredump->serdes_xfi_hss_rx;
305 } else {
306 direct_ptr = mpi_coredump->serdes_xfi_hss_rx;
307 indirect_ptr =
308 mpi_coredump->serdes2_xfi_hss_rx;
309 }
310
311 for (i = 0x1c40; i <= 0x1c5f; i++, direct_ptr++, indirect_ptr++)
312 ql_get_both_serdes(qdev, i, direct_ptr, indirect_ptr,
313 xfi_direct_valid, xfi_indirect_valid);
314
315
316 /* Get XAUI_XFI_HSS_PLL register block. */
317 if (qdev->func & 1) {
318 direct_ptr =
319 mpi_coredump->serdes2_xfi_hss_pll;
320 indirect_ptr =
321 mpi_coredump->serdes_xfi_hss_pll;
322 } else {
323 direct_ptr =
324 mpi_coredump->serdes_xfi_hss_pll;
325 indirect_ptr =
326 mpi_coredump->serdes2_xfi_hss_pll;
327 }
328 for (i = 0x1e00; i <= 0x1e1f; i++, direct_ptr++, indirect_ptr++)
329 ql_get_both_serdes(qdev, i, direct_ptr, indirect_ptr,
330 xfi_direct_valid, xfi_indirect_valid);
331 return 0;
332}
333
22static int ql_get_ets_regs(struct ql_adapter *qdev, u32 * buf) 334static int ql_get_ets_regs(struct ql_adapter *qdev, u32 * buf)
23{ 335{
24 int status = 0; 336 int status = 0;
@@ -413,6 +725,111 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
413 ql_read_other_func_reg(qdev, (i * sizeof(u32)) / 4); 725 ql_read_other_func_reg(qdev, (i * sizeof(u32)) / 4);
414 } 726 }
415 727
728 /* Rev C. Step 20a */
729 ql_build_coredump_seg_header(&mpi_coredump->xaui_an_hdr,
730 XAUI_AN_SEG_NUM,
731 sizeof(struct mpi_coredump_segment_header) +
732 sizeof(mpi_coredump->serdes_xaui_an),
733 "XAUI AN Registers");
734
735 /* Rev C. Step 20b */
736 ql_build_coredump_seg_header(&mpi_coredump->xaui_hss_pcs_hdr,
737 XAUI_HSS_PCS_SEG_NUM,
738 sizeof(struct mpi_coredump_segment_header) +
739 sizeof(mpi_coredump->serdes_xaui_hss_pcs),
740 "XAUI HSS PCS Registers");
741
742 ql_build_coredump_seg_header(&mpi_coredump->xfi_an_hdr, XFI_AN_SEG_NUM,
743 sizeof(struct mpi_coredump_segment_header) +
744 sizeof(mpi_coredump->serdes_xfi_an),
745 "XFI AN Registers");
746
747 ql_build_coredump_seg_header(&mpi_coredump->xfi_train_hdr,
748 XFI_TRAIN_SEG_NUM,
749 sizeof(struct mpi_coredump_segment_header) +
750 sizeof(mpi_coredump->serdes_xfi_train),
751 "XFI TRAIN Registers");
752
753 ql_build_coredump_seg_header(&mpi_coredump->xfi_hss_pcs_hdr,
754 XFI_HSS_PCS_SEG_NUM,
755 sizeof(struct mpi_coredump_segment_header) +
756 sizeof(mpi_coredump->serdes_xfi_hss_pcs),
757 "XFI HSS PCS Registers");
758
759 ql_build_coredump_seg_header(&mpi_coredump->xfi_hss_tx_hdr,
760 XFI_HSS_TX_SEG_NUM,
761 sizeof(struct mpi_coredump_segment_header) +
762 sizeof(mpi_coredump->serdes_xfi_hss_tx),
763 "XFI HSS TX Registers");
764
765 ql_build_coredump_seg_header(&mpi_coredump->xfi_hss_rx_hdr,
766 XFI_HSS_RX_SEG_NUM,
767 sizeof(struct mpi_coredump_segment_header) +
768 sizeof(mpi_coredump->serdes_xfi_hss_rx),
769 "XFI HSS RX Registers");
770
771 ql_build_coredump_seg_header(&mpi_coredump->xfi_hss_pll_hdr,
772 XFI_HSS_PLL_SEG_NUM,
773 sizeof(struct mpi_coredump_segment_header) +
774 sizeof(mpi_coredump->serdes_xfi_hss_pll),
775 "XFI HSS PLL Registers");
776
777 ql_build_coredump_seg_header(&mpi_coredump->xaui2_an_hdr,
778 XAUI2_AN_SEG_NUM,
779 sizeof(struct mpi_coredump_segment_header) +
780 sizeof(mpi_coredump->serdes2_xaui_an),
781 "XAUI2 AN Registers");
782
783 ql_build_coredump_seg_header(&mpi_coredump->xaui2_hss_pcs_hdr,
784 XAUI2_HSS_PCS_SEG_NUM,
785 sizeof(struct mpi_coredump_segment_header) +
786 sizeof(mpi_coredump->serdes2_xaui_hss_pcs),
787 "XAUI2 HSS PCS Registers");
788
789 ql_build_coredump_seg_header(&mpi_coredump->xfi2_an_hdr,
790 XFI2_AN_SEG_NUM,
791 sizeof(struct mpi_coredump_segment_header) +
792 sizeof(mpi_coredump->serdes2_xfi_an),
793 "XFI2 AN Registers");
794
795 ql_build_coredump_seg_header(&mpi_coredump->xfi2_train_hdr,
796 XFI2_TRAIN_SEG_NUM,
797 sizeof(struct mpi_coredump_segment_header) +
798 sizeof(mpi_coredump->serdes2_xfi_train),
799 "XFI2 TRAIN Registers");
800
801 ql_build_coredump_seg_header(&mpi_coredump->xfi2_hss_pcs_hdr,
802 XFI2_HSS_PCS_SEG_NUM,
803 sizeof(struct mpi_coredump_segment_header) +
804 sizeof(mpi_coredump->serdes2_xfi_hss_pcs),
805 "XFI2 HSS PCS Registers");
806
807 ql_build_coredump_seg_header(&mpi_coredump->xfi2_hss_tx_hdr,
808 XFI2_HSS_TX_SEG_NUM,
809 sizeof(struct mpi_coredump_segment_header) +
810 sizeof(mpi_coredump->serdes2_xfi_hss_tx),
811 "XFI2 HSS TX Registers");
812
813 ql_build_coredump_seg_header(&mpi_coredump->xfi2_hss_rx_hdr,
814 XFI2_HSS_RX_SEG_NUM,
815 sizeof(struct mpi_coredump_segment_header) +
816 sizeof(mpi_coredump->serdes2_xfi_hss_rx),
817 "XFI2 HSS RX Registers");
818
819 ql_build_coredump_seg_header(&mpi_coredump->xfi2_hss_pll_hdr,
820 XFI2_HSS_PLL_SEG_NUM,
821 sizeof(struct mpi_coredump_segment_header) +
822 sizeof(mpi_coredump->serdes2_xfi_hss_pll),
823 "XFI2 HSS PLL Registers");
824
825 status = ql_get_serdes_regs(qdev, mpi_coredump);
826 if (status) {
827 QPRINTK(qdev, DRV, ERR,
828 "Failed Dump of Serdes Registers. Status = 0x%.08x\n",
829 status);
830 goto err;
831 }
832
416 ql_build_coredump_seg_header(&mpi_coredump->core_regs_seg_hdr, 833 ql_build_coredump_seg_header(&mpi_coredump->core_regs_seg_hdr,
417 CORE_SEG_NUM, 834 CORE_SEG_NUM,
418 sizeof(mpi_coredump->core_regs_seg_hdr) + 835 sizeof(mpi_coredump->core_regs_seg_hdr) +