The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/cxgbe/cudbg/cudbg_flash_utils.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 
   38 enum {
   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 
   51 int write_flash(struct adapter *adap, u32 start_sec, void *data, u32 size);
   52 int read_flash(struct adapter *adap, u32 start_sec , void *data, u32 size,
   53                 u32 start_address);
   54 
   55 void
   56 update_skip_size(struct cudbg_flash_sec_info *sec_info, u32 size)
   57 {
   58         sec_info->skip_size += size;
   59 }
   60 
   61 static
   62 void set_sector_availability(struct cudbg_flash_sec_info *sec_info,
   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 */
   73 static int
   74 find_empty_sec(struct cudbg_flash_sec_info *sec_info)
   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 
   85         return CUDBG_STATUS_FLASH_FULL;
   86 }
   87 
   88 /* This function will get header initially. If header is already there
   89  * then it will update that header */
   90 static 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;
  119                 flash_hdr->major_ver = CUDBG_FL_MAJOR_VERSION;
  120                 flash_hdr->minor_ver = CUDBG_FL_MINOR_VERSION;
  121                 flash_hdr->build_ver = CUDBG_FL_BUILD_VERSION;
  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 */
  152 int 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) {
  198                 rc = CUDBG_STATUS_FLASH_FULL;
  199                 goto out;
  200         }
  201 
  202         space_left = CUDBG_FLASH_SIZE - flash_hdr->data_len;
  203 
  204         if (cur_entity_size > space_left) {
  205                 rc = CUDBG_STATUS_FLASH_FULL;
  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,
  237                                 CUDBG_SF_SECTOR_SIZE);
  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         }
  245 out:
  246         return rc;
  247 }
  248 
  249 int 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;
  289 out:
  290         return rc;
  291 }
  292 
  293 int 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 
  302 int 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 
  325 out:
  326         return rc;
  327 }
  328 
  329 int 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");
  381                                         return CUDBG_STATUS_NO_SIGNATURE;
  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 ==
  436                                         CUDBG_FL_SIGNATURE &&
  437                                         sec_info->max_timestamp ==
  438                                         flash_hdr.timestamp &&
  439                                         flash_hdr.sec_seq_no == i) {
  440                                 if (size + total_hdr_size >
  441                                                 CUDBG_SF_SECTOR_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 
  468 int 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;
  490 out:
  491         return rc;
  492 }

Cache object: 47856b43d2305506c1b4741dd99c647b


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.