FreeBSD kernel CXGBE device code
cudbg_flash_utils.c
Go to the documentation of this file.
1/*-
2 * Copyright (c) 2017 Chelsio Communications, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD$");
29
30#include <sys/types.h>
31#include <sys/param.h>
32
33#include "common/common.h"
34#include "common/t4_regs.h"
35#include "cudbg.h"
36#include "cudbg_lib_common.h"
37
38enum {
39 SF_ATTEMPTS = 10, /* max retries for SF operations */
40
41 /* flash command opcodes */
42 SF_PROG_PAGE = 2, /* program page */
43 SF_WR_DISABLE = 4, /* disable writes */
44 SF_RD_STATUS = 5, /* read status register */
45 SF_WR_ENABLE = 6, /* enable writes */
46 SF_RD_DATA_FAST = 0xb, /* read flash */
47 SF_RD_ID = 0x9f, /* read ID */
48 SF_ERASE_SECTOR = 0xd8, /* erase sector */
49};
50
51int write_flash(struct adapter *adap, u32 start_sec, void *data, u32 size);
52int read_flash(struct adapter *adap, u32 start_sec , void *data, u32 size,
53 u32 start_address);
54
55void
57{
58 sec_info->skip_size += size;
59}
60
61static
63 int sector_nu, int avail)
64{
65 sector_nu -= CUDBG_START_SEC;
66 if (avail)
67 set_dbg_bitmap(sec_info->sec_bitmap, sector_nu);
68 else
69 reset_dbg_bitmap(sec_info->sec_bitmap, sector_nu);
70}
71
72/* This function will return empty sector available for filling */
73static int
75{
76 int i, index, bit;
77
78 for (i = CUDBG_START_SEC; i < CUDBG_SF_MAX_SECTOR; i++) {
79 index = (i - CUDBG_START_SEC) / 8;
80 bit = (i - CUDBG_START_SEC) % 8;
81 if (!(sec_info->sec_bitmap[index] & (1 << bit)))
82 return i;
83 }
84
86}
87
88/* This function will get header initially. If header is already there
89 * then it will update that header */
90static void update_headers(void *handle, struct cudbg_buffer *dbg_buff,
91 u64 timestamp, u32 cur_entity_hdr_offset,
92 u32 start_offset, u32 ext_size)
93{
94 struct cudbg_private *priv = handle;
95 struct cudbg_flash_sec_info *sec_info = &priv->sec_info;
96 void *sec_hdr;
97 struct cudbg_hdr *cudbg_hdr;
98 struct cudbg_flash_hdr *flash_hdr;
99 struct cudbg_entity_hdr *entity_hdr;
100 u32 hdr_offset;
101 u32 data_hdr_size;
102 u32 total_hdr_size;
103 u32 sec_hdr_start_addr;
104
105 data_hdr_size = CUDBG_MAX_ENTITY * sizeof(struct cudbg_entity_hdr) +
106 sizeof(struct cudbg_hdr);
107 total_hdr_size = data_hdr_size + sizeof(struct cudbg_flash_hdr);
108 sec_hdr_start_addr = CUDBG_SF_SECTOR_SIZE - total_hdr_size;
109 sec_hdr = sec_info->sec_data + sec_hdr_start_addr;
110
111 flash_hdr = (struct cudbg_flash_hdr *)(sec_hdr);
112 cudbg_hdr = (struct cudbg_hdr *)dbg_buff->data;
113
114 /* initially initialize flash hdr and copy all data headers and
115 * in next calling (else part) copy only current entity header
116 */
117 if ((start_offset - sec_info->skip_size) == data_hdr_size) {
118 flash_hdr->signature = CUDBG_FL_SIGNATURE;
122 flash_hdr->hdr_len = sizeof(struct cudbg_flash_hdr);
123 hdr_offset = sizeof(struct cudbg_flash_hdr);
124
125 memcpy((void *)((char *)sec_hdr + hdr_offset),
126 (void *)((char *)dbg_buff->data), data_hdr_size);
127 } else
128 memcpy((void *)((char *)sec_hdr +
129 sizeof(struct cudbg_flash_hdr) +
130 cur_entity_hdr_offset),
131 (void *)((char *)dbg_buff->data +
132 cur_entity_hdr_offset),
133 sizeof(struct cudbg_entity_hdr));
134
135 hdr_offset = data_hdr_size + sizeof(struct cudbg_flash_hdr);
136 flash_hdr->data_len = cudbg_hdr->data_len - sec_info->skip_size;
137 flash_hdr->timestamp = timestamp;
138
139 entity_hdr = (struct cudbg_entity_hdr *)((char *)sec_hdr +
140 sizeof(struct cudbg_flash_hdr) +
141 cur_entity_hdr_offset);
142 /* big entity like mc need to be skipped */
143 entity_hdr->start_offset -= sec_info->skip_size;
144
145 cudbg_hdr = (struct cudbg_hdr *)((char *)sec_hdr +
146 sizeof(struct cudbg_flash_hdr));
147 cudbg_hdr->data_len = flash_hdr->data_len;
148 flash_hdr->data_len += ext_size;
149}
150
151/* Write CUDBG data into serial flash */
152int cudbg_write_flash(void *handle, u64 timestamp, void *data,
153 u32 start_offset, u32 cur_entity_hdr_offset,
154 u32 cur_entity_size,
155 u32 ext_size)
156{
157 struct cudbg_private *priv = handle;
158 struct cudbg_init *cudbg_init = &priv->dbg_init;
159 struct cudbg_flash_sec_info *sec_info = &priv->sec_info;
160 struct adapter *adap = cudbg_init->adap;
161 struct cudbg_flash_hdr *flash_hdr = NULL;
162 struct cudbg_buffer *dbg_buff = (struct cudbg_buffer *)data;
163 u32 data_hdr_size;
164 u32 total_hdr_size;
165 u32 tmp_size;
166 u32 sec_data_offset;
167 u32 sec_hdr_start_addr;
168 u32 sec_data_size;
169 u32 space_left;
170 int rc = 0;
171 int sec;
172
173 data_hdr_size = CUDBG_MAX_ENTITY * sizeof(struct cudbg_entity_hdr) +
174 sizeof(struct cudbg_hdr);
175 total_hdr_size = data_hdr_size + sizeof(struct cudbg_flash_hdr);
176 sec_hdr_start_addr = CUDBG_SF_SECTOR_SIZE - total_hdr_size;
177 sec_data_size = sec_hdr_start_addr;
178
179 cudbg_init->print("\tWriting %u bytes to flash\n", cur_entity_size);
180
181 /* this function will get header if sec_info->sec_data does not
182 * have any header and
183 * will update the header if it has header
184 */
185 update_headers(handle, dbg_buff, timestamp,
186 cur_entity_hdr_offset,
187 start_offset, ext_size);
188
189 if (ext_size) {
190 cur_entity_size += sizeof(struct cudbg_entity_hdr);
191 start_offset = dbg_buff->offset - cur_entity_size;
192 }
193
194 flash_hdr = (struct cudbg_flash_hdr *)(sec_info->sec_data +
195 sec_hdr_start_addr);
196
197 if (flash_hdr->data_len > CUDBG_FLASH_SIZE) {
199 goto out;
200 }
201
202 space_left = CUDBG_FLASH_SIZE - flash_hdr->data_len;
203
204 if (cur_entity_size > space_left) {
206 goto out;
207 }
208
209 while (cur_entity_size > 0) {
210 sec = find_empty_sec(sec_info);
211 if (sec_info->par_sec) {
212 sec_data_offset = sec_info->par_sec_offset;
213 set_sector_availability(sec_info, sec_info->par_sec, 0);
214 sec_info->par_sec = 0;
215 sec_info->par_sec_offset = 0;
216
217 } else {
218 sec_info->cur_seq_no++;
219 flash_hdr->sec_seq_no = sec_info->cur_seq_no;
220 sec_data_offset = 0;
221 }
222
223 if (cur_entity_size + sec_data_offset > sec_data_size) {
224 tmp_size = sec_data_size - sec_data_offset;
225 } else {
226 tmp_size = cur_entity_size;
227 sec_info->par_sec = sec;
228 sec_info->par_sec_offset = cur_entity_size +
229 sec_data_offset;
230 }
231
232 memcpy((void *)((char *)sec_info->sec_data + sec_data_offset),
233 (void *)((char *)dbg_buff->data + start_offset),
234 tmp_size);
235
236 rc = write_flash(adap, sec, sec_info->sec_data,
238 if (rc)
239 goto out;
240
241 cur_entity_size -= tmp_size;
242 set_sector_availability(sec_info, sec, 1);
243 start_offset += tmp_size;
244 }
245out:
246 return rc;
247}
248
249int write_flash(struct adapter *adap, u32 start_sec, void *data, u32 size)
250{
251 unsigned int addr;
252 unsigned int i, n;
253 unsigned int sf_sec_size;
254 int rc = 0;
255
256 u8 *ptr = (u8 *)data;
257
258 sf_sec_size = adap->params.sf_size/adap->params.sf_nsec;
259
260 addr = start_sec * CUDBG_SF_SECTOR_SIZE;
261 i = DIV_ROUND_UP(size,/* # of sectors spanned */
262 sf_sec_size);
263
264 rc = t4_flash_erase_sectors(adap, start_sec,
265 start_sec + i - 1);
266 /*
267 * If size == 0 then we're simply erasing the FLASH sectors associated
268 * with the on-adapter OptionROM Configuration File.
269 */
270
271 if (rc || size == 0)
272 goto out;
273
274 /* this will write to the flash up to SF_PAGE_SIZE at a time */
275 for (i = 0; i < size; i += SF_PAGE_SIZE) {
276 if ((size - i) < SF_PAGE_SIZE)
277 n = size - i;
278 else
279 n = SF_PAGE_SIZE;
280 rc = t4_write_flash(adap, addr, n, ptr, 0);
281 if (rc)
282 goto out;
283
284 addr += n;
285 ptr += n;
286 }
287
288 return 0;
289out:
290 return rc;
291}
292
293int cudbg_read_flash_details(void *handle, struct cudbg_flash_hdr *data)
294{
295 int rc;
296 rc = cudbg_read_flash(handle, (void *)data,
297 sizeof(struct cudbg_flash_hdr), 0);
298
299 return rc;
300}
301
302int cudbg_read_flash_data(void *handle, void *buf, u32 buf_size)
303{
304 int rc;
305 u32 total_hdr_size, data_header_size;
306 void *payload = NULL;
307 u32 payload_size = 0;
308
309 data_header_size = CUDBG_MAX_ENTITY * sizeof(struct cudbg_entity_hdr) +
310 sizeof(struct cudbg_hdr);
311 total_hdr_size = data_header_size + sizeof(struct cudbg_flash_hdr);
312
313 /* Copy flash header to buffer */
314 rc = cudbg_read_flash(handle, buf, total_hdr_size, 0);
315 if (rc != 0)
316 goto out;
317 payload = (char *)buf + total_hdr_size;
318 payload_size = buf_size - total_hdr_size;
319
320 /* Reading flash data to buf */
321 rc = cudbg_read_flash(handle, payload, payload_size, 1);
322 if (rc != 0)
323 goto out;
324
325out:
326 return rc;
327}
328
329int cudbg_read_flash(void *handle, void *data, u32 size, int data_flag)
330{
331 struct cudbg_private *priv = handle;
332 struct cudbg_init *cudbg_init = &priv->dbg_init;
333 struct cudbg_flash_sec_info *sec_info = &priv->sec_info;
334 struct adapter *adap = cudbg_init->adap;
335 struct cudbg_flash_hdr flash_hdr;
336 u32 total_hdr_size;
337 u32 data_hdr_size;
338 u32 sec_hdr_start_addr;
339 u32 tmp_size;
340 u32 data_offset = 0;
341 u32 i, j;
342 int rc;
343
344 rc = t4_get_flash_params(adap);
345 if (rc) {
346 cudbg_init->print("\nGet flash params failed."
347 "Try Again...readflash\n\n");
348 return rc;
349 }
350
351 data_hdr_size = CUDBG_MAX_ENTITY * sizeof(struct cudbg_entity_hdr) +
352 sizeof(struct cudbg_hdr);
353 total_hdr_size = data_hdr_size + sizeof(struct cudbg_flash_hdr);
354 sec_hdr_start_addr = CUDBG_SF_SECTOR_SIZE - total_hdr_size;
355
356 if (!data_flag) {
357 /* fill header */
358 if (!sec_info->max_timestamp) {
359 /* finding max time stamp because it may
360 * have older filled sector also
361 */
362 memset(&flash_hdr, 0, sizeof(struct cudbg_flash_hdr));
363 rc = read_flash(adap, CUDBG_START_SEC, &flash_hdr,
364 sizeof(struct cudbg_flash_hdr),
365 sec_hdr_start_addr);
366
367 if (flash_hdr.signature == CUDBG_FL_SIGNATURE) {
368 sec_info->max_timestamp = flash_hdr.timestamp;
369 } else {
370 rc = read_flash(adap, CUDBG_START_SEC + 1,
371 &flash_hdr,
372 sizeof(struct cudbg_flash_hdr),
373 sec_hdr_start_addr);
374
375 if (flash_hdr.signature == CUDBG_FL_SIGNATURE)
376 sec_info->max_timestamp =
377 flash_hdr.timestamp;
378 else {
379 cudbg_init->print("\n\tNo cudbg dump "\
380 "found in flash\n\n");
382 }
383
384 }
385
386 /* finding max sequence number because max sequenced
387 * sector has updated header
388 */
389 for (i = CUDBG_START_SEC; i <
390 CUDBG_SF_MAX_SECTOR; i++) {
391 memset(&flash_hdr, 0,
392 sizeof(struct cudbg_flash_hdr));
393 rc = read_flash(adap, i, &flash_hdr,
394 sizeof(struct cudbg_flash_hdr),
395 sec_hdr_start_addr);
396
397 if (flash_hdr.signature == CUDBG_FL_SIGNATURE &&
398 sec_info->max_timestamp ==
399 flash_hdr.timestamp &&
400 sec_info->max_seq_no <=
401 flash_hdr.sec_seq_no) {
402 if (sec_info->max_seq_no ==
403 flash_hdr.sec_seq_no) {
404 if (sec_info->hdr_data_len <
405 flash_hdr.data_len)
406 sec_info->max_seq_sec = i;
407 } else {
408 sec_info->max_seq_sec = i;
409 sec_info->hdr_data_len =
410 flash_hdr.data_len;
411 }
412 sec_info->max_seq_no = flash_hdr.sec_seq_no;
413 }
414 }
415 }
416 rc = read_flash(adap, sec_info->max_seq_sec,
417 (struct cudbg_flash_hdr *)data,
418 size, sec_hdr_start_addr);
419
420 if (rc)
421 cudbg_init->print("Read flash header failed, rc %d\n",
422 rc);
423
424 return rc;
425 }
426
427 /* finding sector sequence sorted */
428 for (i = 1; i <= sec_info->max_seq_no; i++) {
429 for (j = CUDBG_START_SEC; j < CUDBG_SF_MAX_SECTOR; j++) {
430 memset(&flash_hdr, 0, sizeof(struct cudbg_flash_hdr));
431 rc = read_flash(adap, j, &flash_hdr,
432 sizeof(struct cudbg_flash_hdr),
433 sec_hdr_start_addr);
434
435 if (flash_hdr.signature ==
437 sec_info->max_timestamp ==
438 flash_hdr.timestamp &&
439 flash_hdr.sec_seq_no == i) {
440 if (size + total_hdr_size >
442 tmp_size = CUDBG_SF_SECTOR_SIZE -
443 total_hdr_size;
444 else
445 tmp_size = size;
446
447 if ((i != sec_info->max_seq_no) ||
448 (i == sec_info->max_seq_no &&
449 j == sec_info->max_seq_sec)){
450 /* filling data buffer with sector data
451 * except sector header
452 */
453 rc = read_flash(adap, j,
454 (void *)((char *)data +
455 data_offset),
456 tmp_size, 0);
457 data_offset += (tmp_size);
458 size -= (tmp_size);
459 break;
460 }
461 }
462 }
463 }
464
465 return rc;
466}
467
468int read_flash(struct adapter *adap, u32 start_sec , void *data, u32 size,
469 u32 start_address)
470{
471 unsigned int addr, i, n;
472 int rc;
473 u32 *ptr = (u32 *)data;
474 addr = start_sec * CUDBG_SF_SECTOR_SIZE + start_address;
475 size = size / 4;
476 for (i = 0; i < size; i += SF_PAGE_SIZE) {
477 if ((size - i) < SF_PAGE_SIZE)
478 n = size - i;
479 else
480 n = SF_PAGE_SIZE;
481 rc = t4_read_flash(adap, addr, n, ptr, 0);
482 if (rc)
483 goto out;
484
485 addr = addr + (n*4);
486 ptr += n;
487 }
488
489 return 0;
490out:
491 return rc;
492}
int t4_get_flash_params(struct adapter *adapter)
Definition: t4_hw.c:9118
int t4_write_flash(struct adapter *adapter, unsigned int addr, unsigned int n, const u8 *data, int byte_oriented)
Definition: t4_hw.c:3237
int t4_flash_erase_sectors(struct adapter *adapter, int start, int end)
Definition: t4_hw.c:3494
int t4_read_flash(struct adapter *adapter, unsigned int addr, unsigned int nwords, u32 *data, int byte_oriented)
Definition: t4_hw.c:3198
static void set_dbg_bitmap(u8 *bitmap, enum CUDBG_DBG_ENTITY_TYPE type)
Definition: cudbg.h:395
static void reset_dbg_bitmap(u8 *bitmap, enum CUDBG_DBG_ENTITY_TYPE type)
Definition: cudbg.h:403
@ CUDBG_MAX_ENTITY
Definition: cudbg.h:217
#define CUDBG_STATUS_FLASH_FULL
Definition: cudbg.h:89
#define CUDBG_STATUS_NO_SIGNATURE
Definition: cudbg.h:67
static void update_headers(void *handle, struct cudbg_buffer *dbg_buff, u64 timestamp, u32 cur_entity_hdr_offset, u32 start_offset, u32 ext_size)
int cudbg_read_flash_data(void *handle, void *buf, u32 buf_size)
int cudbg_write_flash(void *handle, u64 timestamp, void *data, u32 start_offset, u32 cur_entity_hdr_offset, u32 cur_entity_size, u32 ext_size)
static int find_empty_sec(struct cudbg_flash_sec_info *sec_info)
void update_skip_size(struct cudbg_flash_sec_info *sec_info, u32 size)
__FBSDID("$FreeBSD$")
@ SF_WR_ENABLE
@ SF_PROG_PAGE
@ SF_RD_DATA_FAST
@ SF_RD_STATUS
@ SF_ATTEMPTS
@ SF_RD_ID
@ SF_WR_DISABLE
@ SF_ERASE_SECTOR
static void set_sector_availability(struct cudbg_flash_sec_info *sec_info, int sector_nu, int avail)
int cudbg_read_flash(void *handle, void *data, u32 size, int data_flag)
int write_flash(struct adapter *adap, u32 start_sec, void *data, u32 size)
int cudbg_read_flash_details(void *handle, struct cudbg_flash_hdr *data)
int read_flash(struct adapter *adap, u32 start_sec, void *data, u32 size, u32 start_address)
#define CUDBG_FL_SIGNATURE
#define CUDBG_SF_MAX_SECTOR
#define CUDBG_FL_BUILD_VERSION
#define CUDBG_FL_MAJOR_VERSION
#define CUDBG_SF_SECTOR_SIZE
#define CUDBG_FLASH_SIZE
#define CUDBG_FL_MINOR_VERSION
#define CUDBG_START_SEC
uint64_t u64
Definition: osdep.h:62
uint8_t u8
Definition: osdep.h:59
uint32_t u32
Definition: osdep.h:61
#define DIV_ROUND_UP(x, y)
Definition: osdep.h:92
unsigned int sf_size
Definition: common.h:368
unsigned int sf_nsec
Definition: common.h:369
struct adapter_params params
Definition: adapter.h:958
u64 timestamp
Definition: cudbg.h:326
u32 data_len
Definition: cudbg.h:329
u32 signature
Definition: cudbg.h:321
u32 sec_seq_no
Definition: cudbg.h:331
char sec_data[CUDBG_SF_SECTOR_SIZE]
struct adapter * adap
Definition: cudbg.h:373
cudbg_print_cb print
Definition: cudbg.h:375
struct cudbg_flash_sec_info sec_info
struct cudbg_init dbg_init
@ SF_PAGE_SIZE
Definition: t4_hw.h:81