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