]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/net/ethernet/chelsio/cxgb4/cxgb4_cudbg.c
7dfee6adc51e4452deaba5c38f4d5dac9f2883f6
[linux.git] / drivers / net / ethernet / chelsio / cxgb4 / cxgb4_cudbg.c
1 /*
2  *  Copyright (C) 2017 Chelsio Communications.  All rights reserved.
3  *
4  *  This program is free software; you can redistribute it and/or modify it
5  *  under the terms and conditions of the GNU General Public License,
6  *  version 2, as published by the Free Software Foundation.
7  *
8  *  This program is distributed in the hope it will be useful, but WITHOUT
9  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11  *  more details.
12  *
13  *  The full GNU General Public License is included in this distribution in
14  *  the file called "COPYING".
15  *
16  */
17
18 #include "t4_regs.h"
19 #include "cxgb4.h"
20 #include "cxgb4_cudbg.h"
21 #include "cudbg_entity.h"
22
23 static const struct cxgb4_collect_entity cxgb4_collect_mem_dump[] = {
24         { CUDBG_EDC0, cudbg_collect_edc0_meminfo },
25         { CUDBG_EDC1, cudbg_collect_edc1_meminfo },
26 };
27
28 static const struct cxgb4_collect_entity cxgb4_collect_hw_dump[] = {
29         { CUDBG_MBOX_LOG, cudbg_collect_mbox_log },
30         { CUDBG_DEV_LOG, cudbg_collect_fw_devlog },
31         { CUDBG_REG_DUMP, cudbg_collect_reg_dump },
32         { CUDBG_TP_INDIRECT, cudbg_collect_tp_indirect },
33 };
34
35 static u32 cxgb4_get_entity_length(struct adapter *adap, u32 entity)
36 {
37         u32 value, n = 0, len = 0;
38
39         switch (entity) {
40         case CUDBG_REG_DUMP:
41                 switch (CHELSIO_CHIP_VERSION(adap->params.chip)) {
42                 case CHELSIO_T4:
43                         len = T4_REGMAP_SIZE;
44                         break;
45                 case CHELSIO_T5:
46                 case CHELSIO_T6:
47                         len = T5_REGMAP_SIZE;
48                         break;
49                 default:
50                         break;
51                 }
52                 break;
53         case CUDBG_DEV_LOG:
54                 len = adap->params.devlog.size;
55                 break;
56         case CUDBG_EDC0:
57                 value = t4_read_reg(adap, MA_TARGET_MEM_ENABLE_A);
58                 if (value & EDRAM0_ENABLE_F) {
59                         value = t4_read_reg(adap, MA_EDRAM0_BAR_A);
60                         len = EDRAM0_SIZE_G(value);
61                 }
62                 len = cudbg_mbytes_to_bytes(len);
63                 break;
64         case CUDBG_EDC1:
65                 value = t4_read_reg(adap, MA_TARGET_MEM_ENABLE_A);
66                 if (value & EDRAM1_ENABLE_F) {
67                         value = t4_read_reg(adap, MA_EDRAM1_BAR_A);
68                         len = EDRAM1_SIZE_G(value);
69                 }
70                 len = cudbg_mbytes_to_bytes(len);
71                 break;
72         case CUDBG_TP_INDIRECT:
73                 switch (CHELSIO_CHIP_VERSION(adap->params.chip)) {
74                 case CHELSIO_T5:
75                         n = sizeof(t5_tp_pio_array) +
76                             sizeof(t5_tp_tm_pio_array) +
77                             sizeof(t5_tp_mib_index_array);
78                         break;
79                 case CHELSIO_T6:
80                         n = sizeof(t6_tp_pio_array) +
81                             sizeof(t6_tp_tm_pio_array) +
82                             sizeof(t6_tp_mib_index_array);
83                         break;
84                 default:
85                         break;
86                 }
87                 n = n / (IREG_NUM_ELEM * sizeof(u32));
88                 len = sizeof(struct ireg_buf) * n;
89                 break;
90         case CUDBG_MBOX_LOG:
91                 len = sizeof(struct cudbg_mbox_log) * adap->mbox_log->size;
92                 break;
93         default:
94                 break;
95         }
96
97         return len;
98 }
99
100 u32 cxgb4_get_dump_length(struct adapter *adap, u32 flag)
101 {
102         u32 i, entity;
103         u32 len = 0;
104
105         if (flag & CXGB4_ETH_DUMP_HW) {
106                 for (i = 0; i < ARRAY_SIZE(cxgb4_collect_hw_dump); i++) {
107                         entity = cxgb4_collect_hw_dump[i].entity;
108                         len += cxgb4_get_entity_length(adap, entity);
109                 }
110         }
111
112         if (flag & CXGB4_ETH_DUMP_MEM) {
113                 for (i = 0; i < ARRAY_SIZE(cxgb4_collect_mem_dump); i++) {
114                         entity = cxgb4_collect_mem_dump[i].entity;
115                         len += cxgb4_get_entity_length(adap, entity);
116                 }
117         }
118
119         return len;
120 }
121
122 static void cxgb4_cudbg_collect_entity(struct cudbg_init *pdbg_init,
123                                        struct cudbg_buffer *dbg_buff,
124                                        const struct cxgb4_collect_entity *e_arr,
125                                        u32 arr_size, void *buf, u32 *tot_size)
126 {
127         struct adapter *adap = pdbg_init->adap;
128         struct cudbg_error cudbg_err = { 0 };
129         struct cudbg_entity_hdr *entity_hdr;
130         u32 entity_size, i;
131         u32 total_size = 0;
132         int ret;
133
134         for (i = 0; i < arr_size; i++) {
135                 const struct cxgb4_collect_entity *e = &e_arr[i];
136
137                 /* Skip entities that won't fit in output buffer */
138                 entity_size = cxgb4_get_entity_length(adap, e->entity);
139                 if (entity_size >
140                     pdbg_init->outbuf_size - *tot_size - total_size)
141                         continue;
142
143                 entity_hdr = cudbg_get_entity_hdr(buf, e->entity);
144                 entity_hdr->entity_type = e->entity;
145                 entity_hdr->start_offset = dbg_buff->offset;
146                 memset(&cudbg_err, 0, sizeof(struct cudbg_error));
147                 ret = e->collect_cb(pdbg_init, dbg_buff, &cudbg_err);
148                 if (ret) {
149                         entity_hdr->size = 0;
150                         dbg_buff->offset = entity_hdr->start_offset;
151                 } else {
152                         cudbg_align_debug_buffer(dbg_buff, entity_hdr);
153                 }
154
155                 /* Log error and continue with next entity */
156                 if (cudbg_err.sys_err)
157                         ret = CUDBG_SYSTEM_ERROR;
158
159                 entity_hdr->hdr_flags = ret;
160                 entity_hdr->sys_err = cudbg_err.sys_err;
161                 entity_hdr->sys_warn = cudbg_err.sys_warn;
162                 total_size += entity_hdr->size;
163         }
164
165         *tot_size += total_size;
166 }
167
168 int cxgb4_cudbg_collect(struct adapter *adap, void *buf, u32 *buf_size,
169                         u32 flag)
170 {
171         struct cudbg_init cudbg_init = { 0 };
172         struct cudbg_buffer dbg_buff = { 0 };
173         u32 size, min_size, total_size = 0;
174         struct cudbg_hdr *cudbg_hdr;
175
176         size = *buf_size;
177
178         cudbg_init.adap = adap;
179         cudbg_init.outbuf = buf;
180         cudbg_init.outbuf_size = size;
181
182         dbg_buff.data = buf;
183         dbg_buff.size = size;
184         dbg_buff.offset = 0;
185
186         cudbg_hdr = (struct cudbg_hdr *)buf;
187         cudbg_hdr->signature = CUDBG_SIGNATURE;
188         cudbg_hdr->hdr_len = sizeof(struct cudbg_hdr);
189         cudbg_hdr->major_ver = CUDBG_MAJOR_VERSION;
190         cudbg_hdr->minor_ver = CUDBG_MINOR_VERSION;
191         cudbg_hdr->max_entities = CUDBG_MAX_ENTITY;
192         cudbg_hdr->chip_ver = adap->params.chip;
193         cudbg_hdr->dump_type = CUDBG_DUMP_TYPE_MINI;
194         cudbg_hdr->compress_type = CUDBG_COMPRESSION_NONE;
195
196         min_size = sizeof(struct cudbg_hdr) +
197                    sizeof(struct cudbg_entity_hdr) *
198                    cudbg_hdr->max_entities;
199         if (size < min_size)
200                 return -ENOMEM;
201
202         dbg_buff.offset += min_size;
203         total_size = dbg_buff.offset;
204
205         if (flag & CXGB4_ETH_DUMP_HW)
206                 cxgb4_cudbg_collect_entity(&cudbg_init, &dbg_buff,
207                                            cxgb4_collect_hw_dump,
208                                            ARRAY_SIZE(cxgb4_collect_hw_dump),
209                                            buf,
210                                            &total_size);
211
212         if (flag & CXGB4_ETH_DUMP_MEM)
213                 cxgb4_cudbg_collect_entity(&cudbg_init, &dbg_buff,
214                                            cxgb4_collect_mem_dump,
215                                            ARRAY_SIZE(cxgb4_collect_mem_dump),
216                                            buf,
217                                            &total_size);
218
219         cudbg_hdr->data_len = total_size;
220         *buf_size = total_size;
221         return 0;
222 }
223
224 void cxgb4_init_ethtool_dump(struct adapter *adapter)
225 {
226         adapter->eth_dump.flag = CXGB4_ETH_DUMP_NONE;
227         adapter->eth_dump.version = adapter->params.fw_vers;
228         adapter->eth_dump.len = 0;
229 }