LCOV - code coverage report
Current view: top level - drivers/net/fm10k/base - fm10k_tlv.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 275 0.0 %
Date: 2024-12-01 18:57:19 Functions: 0 19 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 241 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2013 - 2015 Intel Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #include "fm10k_tlv.h"
       6                 :            : 
       7                 :            : /**
       8                 :            :  *  fm10k_tlv_msg_init - Initialize message block for TLV data storage
       9                 :            :  *  @msg: Pointer to message block
      10                 :            :  *  @msg_id: Message ID indicating message type
      11                 :            :  *
      12                 :            :  *  This function return success if provided with a valid message pointer
      13                 :            :  **/
      14                 :          0 : s32 fm10k_tlv_msg_init(u32 *msg, u16 msg_id)
      15                 :            : {
      16                 :          0 :         DEBUGFUNC("fm10k_tlv_msg_init");
      17                 :            : 
      18                 :            :         /* verify pointer is not NULL */
      19         [ #  # ]:          0 :         if (!msg)
      20                 :            :                 return FM10K_ERR_PARAM;
      21                 :            : 
      22                 :          0 :         *msg = (FM10K_TLV_FLAGS_MSG << FM10K_TLV_FLAGS_SHIFT) | msg_id;
      23                 :            : 
      24                 :          0 :         return FM10K_SUCCESS;
      25                 :            : }
      26                 :            : 
      27                 :            : /**
      28                 :            :  *  fm10k_tlv_attr_put_null_string - Place null terminated string on message
      29                 :            :  *  @msg: Pointer to message block
      30                 :            :  *  @attr_id: Attribute ID
      31                 :            :  *  @string: Pointer to string to be stored in attribute
      32                 :            :  *
      33                 :            :  *  This function will reorder a string to be CPU endian and store it in
      34                 :            :  *  the attribute buffer.  It will return success if provided with a valid
      35                 :            :  *  pointers.
      36                 :            :  **/
      37                 :          0 : static s32 fm10k_tlv_attr_put_null_string(u32 *msg, u16 attr_id,
      38                 :            :                                           const unsigned char *string)
      39                 :            : {
      40                 :            :         u32 attr_data = 0, len = 0;
      41                 :            :         u32 *attr;
      42                 :            : 
      43                 :          0 :         DEBUGFUNC("fm10k_tlv_attr_put_null_string");
      44                 :            : 
      45                 :            :         /* verify pointers are not NULL */
      46         [ #  # ]:          0 :         if (!string || !msg)
      47                 :            :                 return FM10K_ERR_PARAM;
      48                 :            : 
      49                 :          0 :         attr = &msg[FM10K_TLV_DWORD_LEN(*msg)];
      50                 :            : 
      51                 :            :         /* copy string into local variable and then write to msg */
      52                 :            :         do {
      53                 :            :                 /* write data to message */
      54   [ #  #  #  # ]:          0 :                 if (len && !(len % 4)) {
      55                 :          0 :                         attr[len / 4] = attr_data;
      56                 :            :                         attr_data = 0;
      57                 :            :                 }
      58                 :            : 
      59                 :            :                 /* record character to offset location */
      60                 :          0 :                 attr_data |= (u32)(*string) << (8 * (len % 4));
      61                 :          0 :                 len++;
      62                 :            : 
      63                 :            :                 /* test for NULL and then increment */
      64         [ #  # ]:          0 :         } while (*(string++));
      65                 :            : 
      66                 :            :         /* write last piece of data to message */
      67                 :          0 :         attr[(len + 3) / 4] = attr_data;
      68                 :            : 
      69                 :            :         /* record attribute header, update message length */
      70                 :          0 :         len <<= FM10K_TLV_LEN_SHIFT;
      71                 :          0 :         attr[0] = len | attr_id;
      72                 :            : 
      73                 :            :         /* add header length to length */
      74                 :            :         len += FM10K_TLV_HDR_LEN << FM10K_TLV_LEN_SHIFT;
      75                 :          0 :         *msg += FM10K_TLV_LEN_ALIGN(len);
      76                 :            : 
      77                 :          0 :         return FM10K_SUCCESS;
      78                 :            : }
      79                 :            : 
      80                 :            : /**
      81                 :            :  *  fm10k_tlv_attr_get_null_string - Get null terminated string from attribute
      82                 :            :  *  @attr: Pointer to attribute
      83                 :            :  *  @string: Pointer to location of destination string
      84                 :            :  *
      85                 :            :  *  This function pulls the string back out of the attribute and will place
      86                 :            :  *  it in the array pointed by by string.  It will return success if provided
      87                 :            :  *  with a valid pointers.
      88                 :            :  **/
      89                 :          0 : static s32 fm10k_tlv_attr_get_null_string(u32 *attr, unsigned char *string)
      90                 :            : {
      91                 :            :         u32 len;
      92                 :            : 
      93                 :          0 :         DEBUGFUNC("fm10k_tlv_attr_get_null_string");
      94                 :            : 
      95                 :            :         /* verify pointers are not NULL */
      96         [ #  # ]:          0 :         if (!string || !attr)
      97                 :            :                 return FM10K_ERR_PARAM;
      98                 :            : 
      99                 :          0 :         len = *attr >> FM10K_TLV_LEN_SHIFT;
     100                 :            :         attr++;
     101                 :            : 
     102         [ #  # ]:          0 :         while (len--)
     103                 :          0 :                 string[len] = (u8)(attr[len / 4] >> (8 * (len % 4)));
     104                 :            : 
     105                 :            :         return FM10K_SUCCESS;
     106                 :            : }
     107                 :            : 
     108                 :            : /**
     109                 :            :  *  fm10k_tlv_attr_put_mac_vlan - Store MAC/VLAN attribute in message
     110                 :            :  *  @msg: Pointer to message block
     111                 :            :  *  @attr_id: Attribute ID
     112                 :            :  *  @mac_addr: MAC address to be stored
     113                 :            :  *
     114                 :            :  *  This function will reorder a MAC address to be CPU endian and store it
     115                 :            :  *  in the attribute buffer.  It will return success if provided with a
     116                 :            :  *  valid pointers.
     117                 :            :  **/
     118                 :          0 : s32 fm10k_tlv_attr_put_mac_vlan(u32 *msg, u16 attr_id,
     119                 :            :                                 const u8 *mac_addr, u16 vlan)
     120                 :            : {
     121                 :            :         u32 len = ETH_ALEN << FM10K_TLV_LEN_SHIFT;
     122                 :            :         u32 *attr;
     123                 :            : 
     124                 :          0 :         DEBUGFUNC("fm10k_tlv_attr_put_mac_vlan");
     125                 :            : 
     126                 :            :         /* verify pointers are not NULL */
     127         [ #  # ]:          0 :         if (!msg || !mac_addr)
     128                 :            :                 return FM10K_ERR_PARAM;
     129                 :            : 
     130                 :          0 :         attr = &msg[FM10K_TLV_DWORD_LEN(*msg)];
     131                 :            : 
     132                 :            :         /* record attribute header, update message length */
     133                 :          0 :         attr[0] = len | attr_id;
     134                 :            : 
     135                 :            :         /* copy value into local variable and then write to msg */
     136                 :          0 :         attr[1] = FM10K_LE32_TO_CPU(*(const __le32 *)&mac_addr[0]);
     137                 :          0 :         attr[2] = FM10K_LE16_TO_CPU(*(const __le16 *)&mac_addr[4]);
     138                 :          0 :         attr[2] |= (u32)vlan << 16;
     139                 :            : 
     140                 :            :         /* add header length to length */
     141                 :            :         len += FM10K_TLV_HDR_LEN << FM10K_TLV_LEN_SHIFT;
     142                 :          0 :         *msg += FM10K_TLV_LEN_ALIGN(len);
     143                 :            : 
     144                 :          0 :         return FM10K_SUCCESS;
     145                 :            : }
     146                 :            : 
     147                 :            : /**
     148                 :            :  *  fm10k_tlv_attr_get_mac_vlan - Get MAC/VLAN stored in attribute
     149                 :            :  *  @attr: Pointer to attribute
     150                 :            :  *  @attr_id: Attribute ID
     151                 :            :  *  @mac_addr: location of buffer to store MAC address
     152                 :            :  *
     153                 :            :  *  This function pulls the MAC address back out of the attribute and will
     154                 :            :  *  place it in the array pointed by by mac_addr.  It will return success
     155                 :            :  *  if provided with a valid pointers.
     156                 :            :  **/
     157                 :          0 : s32 fm10k_tlv_attr_get_mac_vlan(u32 *attr, u8 *mac_addr, u16 *vlan)
     158                 :            : {
     159                 :          0 :         DEBUGFUNC("fm10k_tlv_attr_get_mac_vlan");
     160                 :            : 
     161                 :            :         /* verify pointers are not NULL */
     162         [ #  # ]:          0 :         if (!mac_addr || !attr)
     163                 :            :                 return FM10K_ERR_PARAM;
     164                 :            : 
     165                 :          0 :         *(__le32 *)&mac_addr[0] = FM10K_CPU_TO_LE32(attr[1]);
     166                 :          0 :         *(__le16 *)&mac_addr[4] = FM10K_CPU_TO_LE16((u16)(attr[2]));
     167                 :          0 :         *vlan = (u16)(attr[2] >> 16);
     168                 :            : 
     169                 :          0 :         return FM10K_SUCCESS;
     170                 :            : }
     171                 :            : 
     172                 :            : /**
     173                 :            :  *  fm10k_tlv_attr_put_bool - Add header indicating value "true"
     174                 :            :  *  @msg: Pointer to message block
     175                 :            :  *  @attr_id: Attribute ID
     176                 :            :  *
     177                 :            :  *  This function will simply add an attribute header, the fact
     178                 :            :  *  that the header is here means the attribute value is true, else
     179                 :            :  *  it is false.  The function will return success if provided with a
     180                 :            :  *  valid pointers.
     181                 :            :  **/
     182                 :          0 : s32 fm10k_tlv_attr_put_bool(u32 *msg, u16 attr_id)
     183                 :            : {
     184                 :          0 :         DEBUGFUNC("fm10k_tlv_attr_put_bool");
     185                 :            : 
     186                 :            :         /* verify pointers are not NULL */
     187         [ #  # ]:          0 :         if (!msg)
     188                 :            :                 return FM10K_ERR_PARAM;
     189                 :            : 
     190                 :            :         /* record attribute header */
     191                 :          0 :         msg[FM10K_TLV_DWORD_LEN(*msg)] = attr_id;
     192                 :            : 
     193                 :            :         /* add header length to length */
     194                 :          0 :         *msg += FM10K_TLV_HDR_LEN << FM10K_TLV_LEN_SHIFT;
     195                 :            : 
     196                 :          0 :         return FM10K_SUCCESS;
     197                 :            : }
     198                 :            : 
     199                 :            : /**
     200                 :            :  *  fm10k_tlv_attr_put_value - Store integer value attribute in message
     201                 :            :  *  @msg: Pointer to message block
     202                 :            :  *  @attr_id: Attribute ID
     203                 :            :  *  @value: Value to be written
     204                 :            :  *  @len: Size of value
     205                 :            :  *
     206                 :            :  *  This function will place an integer value of up to 8 bytes in size
     207                 :            :  *  in a message attribute.  The function will return success provided
     208                 :            :  *  that msg is a valid pointer, and len is 1, 2, 4, or 8.
     209                 :            :  **/
     210                 :          0 : s32 fm10k_tlv_attr_put_value(u32 *msg, u16 attr_id, s64 value, u32 len)
     211                 :            : {
     212                 :            :         u32 *attr;
     213                 :            : 
     214                 :          0 :         DEBUGFUNC("fm10k_tlv_attr_put_value");
     215                 :            : 
     216                 :            :         /* verify non-null msg and len is 1, 2, 4, or 8 */
     217   [ #  #  #  #  :          0 :         if (!msg || !len || len > 8 || (len & (len - 1)))
                   #  # ]
     218                 :            :                 return FM10K_ERR_PARAM;
     219                 :            : 
     220                 :          0 :         attr = &msg[FM10K_TLV_DWORD_LEN(*msg)];
     221                 :            : 
     222         [ #  # ]:          0 :         if (len < 4) {
     223                 :          0 :                 attr[1] = (u32)value & (BIT(8 * len) - 1);
     224                 :            :         } else {
     225                 :          0 :                 attr[1] = (u32)value;
     226         [ #  # ]:          0 :                 if (len > 4)
     227                 :          0 :                         attr[2] = (u32)(value >> 32);
     228                 :            :         }
     229                 :            : 
     230                 :            :         /* record attribute header, update message length */
     231                 :          0 :         len <<= FM10K_TLV_LEN_SHIFT;
     232                 :          0 :         attr[0] = len | attr_id;
     233                 :            : 
     234                 :            :         /* add header length to length */
     235                 :            :         len += FM10K_TLV_HDR_LEN << FM10K_TLV_LEN_SHIFT;
     236                 :          0 :         *msg += FM10K_TLV_LEN_ALIGN(len);
     237                 :            : 
     238                 :          0 :         return FM10K_SUCCESS;
     239                 :            : }
     240                 :            : 
     241                 :            : /**
     242                 :            :  *  fm10k_tlv_attr_get_value - Get integer value stored in attribute
     243                 :            :  *  @attr: Pointer to attribute
     244                 :            :  *  @value: Pointer to destination buffer
     245                 :            :  *  @len: Size of value
     246                 :            :  *
     247                 :            :  *  This function will place an integer value of up to 8 bytes in size
     248                 :            :  *  in the offset pointed to by value.  The function will return success
     249                 :            :  *  provided that pointers are valid and the len value matches the
     250                 :            :  *  attribute length.
     251                 :            :  **/
     252                 :          0 : s32 fm10k_tlv_attr_get_value(u32 *attr, void *value, u32 len)
     253                 :            : {
     254                 :          0 :         DEBUGFUNC("fm10k_tlv_attr_get_value");
     255                 :            : 
     256                 :            :         /* verify pointers are not NULL */
     257         [ #  # ]:          0 :         if (!attr || !value)
     258                 :            :                 return FM10K_ERR_PARAM;
     259                 :            : 
     260         [ #  # ]:          0 :         if ((*attr >> FM10K_TLV_LEN_SHIFT) != len)
     261                 :            :                 return FM10K_ERR_PARAM;
     262                 :            : 
     263         [ #  # ]:          0 :         if (len == 8)
     264                 :          0 :                 *(u64 *)value = ((u64)attr[2] << 32) | attr[1];
     265         [ #  # ]:          0 :         else if (len == 4)
     266                 :          0 :                 *(u32 *)value = attr[1];
     267         [ #  # ]:          0 :         else if (len == 2)
     268                 :          0 :                 *(u16 *)value = (u16)attr[1];
     269                 :            :         else
     270                 :          0 :                 *(u8 *)value = (u8)attr[1];
     271                 :            : 
     272                 :            :         return FM10K_SUCCESS;
     273                 :            : }
     274                 :            : 
     275                 :            : /**
     276                 :            :  *  fm10k_tlv_attr_put_le_struct - Store little endian structure in message
     277                 :            :  *  @msg: Pointer to message block
     278                 :            :  *  @attr_id: Attribute ID
     279                 :            :  *  @le_struct: Pointer to structure to be written
     280                 :            :  *  @len: Size of le_struct
     281                 :            :  *
     282                 :            :  *  This function will place a little endian structure value in a message
     283                 :            :  *  attribute.  The function will return success provided that all pointers
     284                 :            :  *  are valid and length is a non-zero multiple of 4.
     285                 :            :  **/
     286                 :          0 : s32 fm10k_tlv_attr_put_le_struct(u32 *msg, u16 attr_id,
     287                 :            :                                  const void *le_struct, u32 len)
     288                 :            : {
     289                 :            :         const __le32 *le32_ptr = (const __le32 *)le_struct;
     290                 :            :         u32 *attr;
     291                 :            :         u32 i;
     292                 :            : 
     293                 :          0 :         DEBUGFUNC("fm10k_tlv_attr_put_le_struct");
     294                 :            : 
     295                 :            :         /* verify non-null msg and len is in 32 bit words */
     296   [ #  #  #  # ]:          0 :         if (!msg || !len || (len % 4))
     297                 :            :                 return FM10K_ERR_PARAM;
     298                 :            : 
     299                 :          0 :         attr = &msg[FM10K_TLV_DWORD_LEN(*msg)];
     300                 :            : 
     301                 :            :         /* copy le32 structure into host byte order at 32b boundaries */
     302         [ #  # ]:          0 :         for (i = 0; i < (len / 4); i++)
     303                 :          0 :                 attr[i + 1] = FM10K_LE32_TO_CPU(le32_ptr[i]);
     304                 :            : 
     305                 :            :         /* record attribute header, update message length */
     306                 :          0 :         len <<= FM10K_TLV_LEN_SHIFT;
     307                 :          0 :         attr[0] = len | attr_id;
     308                 :            : 
     309                 :            :         /* add header length to length */
     310                 :            :         len += FM10K_TLV_HDR_LEN << FM10K_TLV_LEN_SHIFT;
     311                 :          0 :         *msg += FM10K_TLV_LEN_ALIGN(len);
     312                 :            : 
     313                 :          0 :         return FM10K_SUCCESS;
     314                 :            : }
     315                 :            : 
     316                 :            : /**
     317                 :            :  *  fm10k_tlv_attr_get_le_struct - Get little endian struct form attribute
     318                 :            :  *  @attr: Pointer to attribute
     319                 :            :  *  @le_struct: Pointer to structure to be written
     320                 :            :  *  @len: Size of structure
     321                 :            :  *
     322                 :            :  *  This function will place a little endian structure in the buffer
     323                 :            :  *  pointed to by le_struct.  The function will return success
     324                 :            :  *  provided that pointers are valid and the len value matches the
     325                 :            :  *  attribute length.
     326                 :            :  **/
     327                 :          0 : s32 fm10k_tlv_attr_get_le_struct(u32 *attr, void *le_struct, u32 len)
     328                 :            : {
     329                 :            :         __le32 *le32_ptr = (__le32 *)le_struct;
     330                 :            :         u32 i;
     331                 :            : 
     332                 :          0 :         DEBUGFUNC("fm10k_tlv_attr_get_le_struct");
     333                 :            : 
     334                 :            :         /* verify pointers are not NULL */
     335         [ #  # ]:          0 :         if (!le_struct || !attr)
     336                 :            :                 return FM10K_ERR_PARAM;
     337                 :            : 
     338         [ #  # ]:          0 :         if ((*attr >> FM10K_TLV_LEN_SHIFT) != len)
     339                 :            :                 return FM10K_ERR_PARAM;
     340                 :            : 
     341                 :            :         attr++;
     342                 :            : 
     343         [ #  # ]:          0 :         for (i = 0; len; i++, len -= 4)
     344                 :          0 :                 le32_ptr[i] = FM10K_CPU_TO_LE32(attr[i]);
     345                 :            : 
     346                 :            :         return FM10K_SUCCESS;
     347                 :            : }
     348                 :            : 
     349                 :            : /**
     350                 :            :  *  fm10k_tlv_attr_nest_start - Start a set of nested attributes
     351                 :            :  *  @msg: Pointer to message block
     352                 :            :  *  @attr_id: Attribute ID
     353                 :            :  *
     354                 :            :  *  This function will mark off a new nested region for encapsulating
     355                 :            :  *  a given set of attributes.  The idea is if you wish to place a secondary
     356                 :            :  *  structure within the message this mechanism allows for that.  The
     357                 :            :  *  function will return NULL on failure, and a pointer to the start
     358                 :            :  *  of the nested attributes on success.
     359                 :            :  **/
     360                 :          0 : static u32 *fm10k_tlv_attr_nest_start(u32 *msg, u16 attr_id)
     361                 :            : {
     362                 :            :         u32 *attr;
     363                 :            : 
     364                 :          0 :         DEBUGFUNC("fm10k_tlv_attr_nest_start");
     365                 :            : 
     366                 :            :         /* verify pointer is not NULL */
     367         [ #  # ]:          0 :         if (!msg)
     368                 :            :                 return NULL;
     369                 :            : 
     370                 :          0 :         attr = &msg[FM10K_TLV_DWORD_LEN(*msg)];
     371                 :            : 
     372                 :          0 :         attr[0] = attr_id;
     373                 :            : 
     374                 :            :         /* return pointer to nest header */
     375                 :          0 :         return attr;
     376                 :            : }
     377                 :            : 
     378                 :            : /**
     379                 :            :  *  fm10k_tlv_attr_nest_stop - Stop a set of nested attributes
     380                 :            :  *  @msg: Pointer to message block
     381                 :            :  *
     382                 :            :  *  This function closes off an existing set of nested attributes.  The
     383                 :            :  *  message pointer should be pointing to the parent of the nest.  So in
     384                 :            :  *  the case of a nest within the nest this would be the outer nest pointer.
     385                 :            :  *  This function will return success provided all pointers are valid.
     386                 :            :  **/
     387                 :          0 : static s32 fm10k_tlv_attr_nest_stop(u32 *msg)
     388                 :            : {
     389                 :            :         u32 *attr;
     390                 :            :         u32 len;
     391                 :            : 
     392                 :          0 :         DEBUGFUNC("fm10k_tlv_attr_nest_stop");
     393                 :            : 
     394                 :            :         /* verify pointer is not NULL */
     395         [ #  # ]:          0 :         if (!msg)
     396                 :            :                 return FM10K_ERR_PARAM;
     397                 :            : 
     398                 :            :         /* locate the nested header and retrieve its length */
     399                 :          0 :         attr = &msg[FM10K_TLV_DWORD_LEN(*msg)];
     400                 :          0 :         len = (attr[0] >> FM10K_TLV_LEN_SHIFT) << FM10K_TLV_LEN_SHIFT;
     401                 :            : 
     402                 :            :         /* only include nest if data was added to it */
     403         [ #  # ]:          0 :         if (len) {
     404                 :          0 :                 len += FM10K_TLV_HDR_LEN << FM10K_TLV_LEN_SHIFT;
     405                 :          0 :                 *msg += len;
     406                 :            :         }
     407                 :            : 
     408                 :            :         return FM10K_SUCCESS;
     409                 :            : }
     410                 :            : 
     411                 :            : /**
     412                 :            :  *  fm10k_tlv_attr_validate - Validate attribute metadata
     413                 :            :  *  @attr: Pointer to attribute
     414                 :            :  *  @tlv_attr: Type and length info for attribute
     415                 :            :  *
     416                 :            :  *  This function does some basic validation of the input TLV.  It
     417                 :            :  *  verifies the length, and in the case of null terminated strings
     418                 :            :  *  it verifies that the last byte is null.  The function will
     419                 :            :  *  return FM10K_ERR_PARAM if any attribute is malformed, otherwise
     420                 :            :  *  it returns 0.
     421                 :            :  **/
     422                 :          0 : STATIC s32 fm10k_tlv_attr_validate(u32 *attr,
     423                 :            :                                    const struct fm10k_tlv_attr *tlv_attr)
     424                 :            : {
     425                 :          0 :         u32 attr_id = *attr & FM10K_TLV_ID_MASK;
     426                 :          0 :         u16 len = *attr >> FM10K_TLV_LEN_SHIFT;
     427                 :            : 
     428                 :          0 :         DEBUGFUNC("fm10k_tlv_attr_validate");
     429                 :            : 
     430                 :            :         /* verify this is an attribute and not a message */
     431         [ #  # ]:          0 :         if (*attr & (FM10K_TLV_FLAGS_MSG << FM10K_TLV_FLAGS_SHIFT))
     432                 :            :                 return FM10K_ERR_PARAM;
     433                 :            : 
     434                 :            :         /* search through the list of attributes to find a matching ID */
     435         [ #  # ]:          0 :         while (tlv_attr->id < attr_id)
     436                 :          0 :                 tlv_attr++;
     437                 :            : 
     438                 :            :         /* if didn't find a match then we should exit */
     439         [ #  # ]:          0 :         if (tlv_attr->id != attr_id)
     440                 :            :                 return FM10K_NOT_IMPLEMENTED;
     441                 :            : 
     442                 :            :         /* move to start of attribute data */
     443                 :            :         attr++;
     444                 :            : 
     445   [ #  #  #  #  :          0 :         switch (tlv_attr->type) {
                #  #  # ]
     446                 :          0 :         case FM10K_TLV_NULL_STRING:
     447         [ #  # ]:          0 :                 if (!len ||
     448         [ #  # ]:          0 :                     (attr[(len - 1) / 4] & (0xFF << (8 * ((len - 1) % 4)))))
     449                 :            :                         return FM10K_ERR_PARAM;
     450         [ #  # ]:          0 :                 if (len > tlv_attr->len)
     451                 :          0 :                         return FM10K_ERR_PARAM;
     452                 :            :                 break;
     453                 :          0 :         case FM10K_TLV_MAC_ADDR:
     454         [ #  # ]:          0 :                 if (len != ETH_ALEN)
     455                 :          0 :                         return FM10K_ERR_PARAM;
     456                 :            :                 break;
     457                 :          0 :         case FM10K_TLV_BOOL:
     458         [ #  # ]:          0 :                 if (len)
     459                 :          0 :                         return FM10K_ERR_PARAM;
     460                 :            :                 break;
     461                 :          0 :         case FM10K_TLV_UNSIGNED:
     462                 :            :         case FM10K_TLV_SIGNED:
     463         [ #  # ]:          0 :                 if (len != tlv_attr->len)
     464                 :          0 :                         return FM10K_ERR_PARAM;
     465                 :            :                 break;
     466                 :          0 :         case FM10K_TLV_LE_STRUCT:
     467                 :            :                 /* struct must be 4 byte aligned */
     468   [ #  #  #  # ]:          0 :                 if ((len % 4) || len != tlv_attr->len)
     469                 :          0 :                         return FM10K_ERR_PARAM;
     470                 :            :                 break;
     471                 :          0 :         case FM10K_TLV_NESTED:
     472                 :            :                 /* nested attributes must be 4 byte aligned */
     473         [ #  # ]:          0 :                 if (len % 4)
     474                 :          0 :                         return FM10K_ERR_PARAM;
     475                 :            :                 break;
     476                 :            :         default:
     477                 :            :                 /* attribute id is mapped to bad value */
     478                 :            :                 return FM10K_ERR_PARAM;
     479                 :            :         }
     480                 :            : 
     481                 :            :         return FM10K_SUCCESS;
     482                 :            : }
     483                 :            : 
     484                 :            : /**
     485                 :            :  *  fm10k_tlv_attr_parse - Parses stream of attribute data
     486                 :            :  *  @attr: Pointer to attribute list
     487                 :            :  *  @results: Pointer array to store pointers to attributes
     488                 :            :  *  @tlv_attr: Type and length info for attributes
     489                 :            :  *
     490                 :            :  *  This function validates a stream of attributes and parses them
     491                 :            :  *  up into an array of pointers stored in results.  The function will
     492                 :            :  *  return FM10K_ERR_PARAM on any input or message error,
     493                 :            :  *  FM10K_NOT_IMPLEMENTED for any attribute that is outside of the array
     494                 :            :  *  and 0 on success. Any attributes not found in tlv_attr will be silently
     495                 :            :  *  ignored.
     496                 :            :  **/
     497                 :          0 : static s32 fm10k_tlv_attr_parse(u32 *attr, u32 **results,
     498                 :            :                                 const struct fm10k_tlv_attr *tlv_attr)
     499                 :            : {
     500                 :            :         u32 i, attr_id, offset = 0;
     501                 :            :         s32 err = 0;
     502                 :            :         u16 len;
     503                 :            : 
     504                 :          0 :         DEBUGFUNC("fm10k_tlv_attr_parse");
     505                 :            : 
     506                 :            :         /* verify pointers are not NULL */
     507         [ #  # ]:          0 :         if (!attr || !results)
     508                 :            :                 return FM10K_ERR_PARAM;
     509                 :            : 
     510                 :            :         /* initialize results to NULL */
     511         [ #  # ]:          0 :         for (i = 0; i < FM10K_TLV_RESULTS_MAX; i++)
     512                 :          0 :                 results[i] = NULL;
     513                 :            : 
     514                 :            :         /* pull length from the message header */
     515                 :          0 :         len = *attr >> FM10K_TLV_LEN_SHIFT;
     516                 :            : 
     517                 :            :         /* no attributes to parse if there is no length */
     518         [ #  # ]:          0 :         if (!len)
     519                 :            :                 return FM10K_SUCCESS;
     520                 :            : 
     521                 :            :         /* no attributes to parse, just raw data, message becomes attribute */
     522         [ #  # ]:          0 :         if (!tlv_attr) {
     523                 :          0 :                 results[0] = attr;
     524                 :          0 :                 return FM10K_SUCCESS;
     525                 :            :         }
     526                 :            : 
     527                 :            :         /* move to start of attribute data */
     528                 :          0 :         attr++;
     529                 :            : 
     530                 :            :         /* run through list parsing all attributes */
     531         [ #  # ]:          0 :         while (offset < len) {
     532                 :          0 :                 attr_id = *attr & FM10K_TLV_ID_MASK;
     533                 :            : 
     534         [ #  # ]:          0 :                 if (attr_id >= FM10K_TLV_RESULTS_MAX)
     535                 :            :                         return FM10K_NOT_IMPLEMENTED;
     536                 :            : 
     537                 :          0 :                 err = fm10k_tlv_attr_validate(attr, tlv_attr);
     538         [ #  # ]:          0 :                 if (err == FM10K_NOT_IMPLEMENTED)
     539                 :            :                         ; /* silently ignore non-implemented attributes */
     540         [ #  # ]:          0 :                 else if (err)
     541                 :          0 :                         return err;
     542                 :            :                 else
     543                 :          0 :                         results[attr_id] = attr;
     544                 :            : 
     545                 :            :                 /* update offset */
     546                 :          0 :                 offset += FM10K_TLV_DWORD_LEN(*attr) * 4;
     547                 :            : 
     548                 :            :                 /* move to next attribute */
     549                 :          0 :                 attr = &attr[FM10K_TLV_DWORD_LEN(*attr)];
     550                 :            :         }
     551                 :            : 
     552                 :            :         /* we should find ourselves at the end of the list */
     553         [ #  # ]:          0 :         if (offset != len)
     554                 :          0 :                 return FM10K_ERR_PARAM;
     555                 :            : 
     556                 :            :         return FM10K_SUCCESS;
     557                 :            : }
     558                 :            : 
     559                 :            : /**
     560                 :            :  *  fm10k_tlv_msg_parse - Parses message header and calls function handler
     561                 :            :  *  @hw: Pointer to hardware structure
     562                 :            :  *  @msg: Pointer to message
     563                 :            :  *  @mbx: Pointer to mailbox information structure
     564                 :            :  *  @func: Function array containing list of message handling functions
     565                 :            :  *
     566                 :            :  *  This function should be the first function called upon receiving a
     567                 :            :  *  message.  The handler will identify the message type and call the correct
     568                 :            :  *  handler for the given message.  It will return the value from the function
     569                 :            :  *  call on a recognized message type, otherwise it will return
     570                 :            :  *  FM10K_NOT_IMPLEMENTED on an unrecognized type.
     571                 :            :  **/
     572                 :          0 : s32 fm10k_tlv_msg_parse(struct fm10k_hw *hw, u32 *msg,
     573                 :            :                         struct fm10k_mbx_info *mbx,
     574                 :            :                         const struct fm10k_msg_data *data)
     575                 :            : {
     576                 :            :         u32 *results[FM10K_TLV_RESULTS_MAX];
     577                 :            :         u32 msg_id;
     578                 :            :         s32 err;
     579                 :            : 
     580                 :          0 :         DEBUGFUNC("fm10k_tlv_msg_parse");
     581                 :            : 
     582                 :            :         /* verify pointer is not NULL */
     583         [ #  # ]:          0 :         if (!msg || !data)
     584                 :            :                 return FM10K_ERR_PARAM;
     585                 :            : 
     586                 :            :         /* verify this is a message and not an attribute */
     587         [ #  # ]:          0 :         if (!(*msg & (FM10K_TLV_FLAGS_MSG << FM10K_TLV_FLAGS_SHIFT)))
     588                 :            :                 return FM10K_ERR_PARAM;
     589                 :            : 
     590                 :            :         /* grab message ID */
     591                 :          0 :         msg_id = *msg & FM10K_TLV_ID_MASK;
     592                 :            : 
     593         [ #  # ]:          0 :         while (data->id < msg_id)
     594                 :          0 :                 data++;
     595                 :            : 
     596                 :            :         /* if we didn't find it then pass it up as an error */
     597         [ #  # ]:          0 :         if (data->id != msg_id) {
     598         [ #  # ]:          0 :                 while (data->id != FM10K_TLV_ERROR)
     599                 :          0 :                         data++;
     600                 :            :         }
     601                 :            : 
     602                 :            :         /* parse the attributes into the results list */
     603                 :          0 :         err = fm10k_tlv_attr_parse(msg, results, data->attr);
     604         [ #  # ]:          0 :         if (err < 0)
     605                 :            :                 return err;
     606                 :            : 
     607                 :          0 :         return data->func(hw, results, mbx);
     608                 :            : }
     609                 :            : 
     610                 :            : /**
     611                 :            :  *  fm10k_tlv_msg_error - Default handler for unrecognized TLV message IDs
     612                 :            :  *  @hw: Pointer to hardware structure
     613                 :            :  *  @results: Pointer array to message, results[0] is pointer to message
     614                 :            :  *  @mbx: Unused mailbox pointer
     615                 :            :  *
     616                 :            :  *  This function is a default handler for unrecognized messages.  At a
     617                 :            :  *  a minimum it just indicates that the message requested was
     618                 :            :  *  unimplemented.
     619                 :            :  **/
     620                 :          0 : s32 fm10k_tlv_msg_error(struct fm10k_hw *hw, u32 **results,
     621                 :            :                         struct fm10k_mbx_info *mbx)
     622                 :            : {
     623                 :            :         UNREFERENCED_3PARAMETER(hw, results, mbx);
     624                 :          0 :         DEBUGOUT1("Unknown message ID %u\n", **results & FM10K_TLV_ID_MASK);
     625                 :          0 :         return FM10K_NOT_IMPLEMENTED;
     626                 :            : }
     627                 :            : 
     628                 :            : STATIC const unsigned char test_str[] = "fm10k";
     629                 :            : STATIC const unsigned char test_mac[ETH_ALEN] = { 0x12, 0x34, 0x56,
     630                 :            :                                                   0x78, 0x9a, 0xbc };
     631                 :            : STATIC const u16 test_vlan = 0x0FED;
     632                 :            : STATIC const u64 test_u64 = 0xfedcba9876543210ull;
     633                 :            : STATIC const u32 test_u32 = 0x87654321;
     634                 :            : STATIC const u16 test_u16 = 0x8765;
     635                 :            : STATIC const u8  test_u8  = 0x87;
     636                 :            : STATIC const s64 test_s64 = -0x123456789abcdef0ll;
     637                 :            : STATIC const s32 test_s32 = -0x1235678;
     638                 :            : STATIC const s16 test_s16 = -0x1234;
     639                 :            : STATIC const s8  test_s8  = -0x12;
     640                 :            : STATIC const __le32 test_le[2] = { FM10K_CPU_TO_LE32(0x12345678),
     641                 :            :                                    FM10K_CPU_TO_LE32(0x9abcdef0)};
     642                 :            : 
     643                 :            : /* The message below is meant to be used as a test message to demonstrate
     644                 :            :  * how to use the TLV interface and to test the types.  Normally this code
     645                 :            :  * be compiled out by stripping the code wrapped in FM10K_TLV_TEST_MSG
     646                 :            :  */
     647                 :            : const struct fm10k_tlv_attr fm10k_tlv_msg_test_attr[] = {
     648                 :            :         FM10K_TLV_ATTR_NULL_STRING(FM10K_TEST_MSG_STRING, 80),
     649                 :            :         FM10K_TLV_ATTR_MAC_ADDR(FM10K_TEST_MSG_MAC_ADDR),
     650                 :            :         FM10K_TLV_ATTR_U8(FM10K_TEST_MSG_U8),
     651                 :            :         FM10K_TLV_ATTR_U16(FM10K_TEST_MSG_U16),
     652                 :            :         FM10K_TLV_ATTR_U32(FM10K_TEST_MSG_U32),
     653                 :            :         FM10K_TLV_ATTR_U64(FM10K_TEST_MSG_U64),
     654                 :            :         FM10K_TLV_ATTR_S8(FM10K_TEST_MSG_S8),
     655                 :            :         FM10K_TLV_ATTR_S16(FM10K_TEST_MSG_S16),
     656                 :            :         FM10K_TLV_ATTR_S32(FM10K_TEST_MSG_S32),
     657                 :            :         FM10K_TLV_ATTR_S64(FM10K_TEST_MSG_S64),
     658                 :            :         FM10K_TLV_ATTR_LE_STRUCT(FM10K_TEST_MSG_LE_STRUCT, 8),
     659                 :            :         FM10K_TLV_ATTR_NESTED(FM10K_TEST_MSG_NESTED),
     660                 :            :         FM10K_TLV_ATTR_S32(FM10K_TEST_MSG_RESULT),
     661                 :            :         FM10K_TLV_ATTR_LAST
     662                 :            : };
     663                 :            : 
     664                 :            : /**
     665                 :            :  *  fm10k_tlv_msg_test_generate_data - Stuff message with data
     666                 :            :  *  @msg: Pointer to message
     667                 :            :  *  @attr_flags: List of flags indicating what attributes to add
     668                 :            :  *
     669                 :            :  *  This function is meant to load a message buffer with attribute data
     670                 :            :  **/
     671                 :          0 : STATIC void fm10k_tlv_msg_test_generate_data(u32 *msg, u32 attr_flags)
     672                 :            : {
     673                 :          0 :         DEBUGFUNC("fm10k_tlv_msg_test_generate_data");
     674                 :            : 
     675         [ #  # ]:          0 :         if (attr_flags & BIT(FM10K_TEST_MSG_STRING))
     676                 :          0 :                 fm10k_tlv_attr_put_null_string(msg, FM10K_TEST_MSG_STRING,
     677                 :            :                                                test_str);
     678         [ #  # ]:          0 :         if (attr_flags & BIT(FM10K_TEST_MSG_MAC_ADDR))
     679                 :          0 :                 fm10k_tlv_attr_put_mac_vlan(msg, FM10K_TEST_MSG_MAC_ADDR,
     680                 :            :                                             test_mac, test_vlan);
     681         [ #  # ]:          0 :         if (attr_flags & BIT(FM10K_TEST_MSG_U8))
     682                 :          0 :                 fm10k_tlv_attr_put_u8(msg, FM10K_TEST_MSG_U8,  test_u8);
     683         [ #  # ]:          0 :         if (attr_flags & BIT(FM10K_TEST_MSG_U16))
     684                 :          0 :                 fm10k_tlv_attr_put_u16(msg, FM10K_TEST_MSG_U16, test_u16);
     685         [ #  # ]:          0 :         if (attr_flags & BIT(FM10K_TEST_MSG_U32))
     686                 :          0 :                 fm10k_tlv_attr_put_u32(msg, FM10K_TEST_MSG_U32, test_u32);
     687         [ #  # ]:          0 :         if (attr_flags & BIT(FM10K_TEST_MSG_U64))
     688                 :          0 :                 fm10k_tlv_attr_put_u64(msg, FM10K_TEST_MSG_U64, test_u64);
     689         [ #  # ]:          0 :         if (attr_flags & BIT(FM10K_TEST_MSG_S8))
     690                 :          0 :                 fm10k_tlv_attr_put_s8(msg, FM10K_TEST_MSG_S8,  test_s8);
     691         [ #  # ]:          0 :         if (attr_flags & BIT(FM10K_TEST_MSG_S16))
     692                 :          0 :                 fm10k_tlv_attr_put_s16(msg, FM10K_TEST_MSG_S16, test_s16);
     693         [ #  # ]:          0 :         if (attr_flags & BIT(FM10K_TEST_MSG_S32))
     694                 :          0 :                 fm10k_tlv_attr_put_s32(msg, FM10K_TEST_MSG_S32, test_s32);
     695         [ #  # ]:          0 :         if (attr_flags & BIT(FM10K_TEST_MSG_S64))
     696                 :          0 :                 fm10k_tlv_attr_put_s64(msg, FM10K_TEST_MSG_S64, test_s64);
     697         [ #  # ]:          0 :         if (attr_flags & BIT(FM10K_TEST_MSG_LE_STRUCT))
     698                 :          0 :                 fm10k_tlv_attr_put_le_struct(msg, FM10K_TEST_MSG_LE_STRUCT,
     699                 :            :                                              test_le, 8);
     700                 :          0 : }
     701                 :            : 
     702                 :            : /**
     703                 :            :  *  fm10k_tlv_msg_test_create - Create a test message testing all attributes
     704                 :            :  *  @msg: Pointer to message
     705                 :            :  *  @attr_flags: List of flags indicating what attributes to add
     706                 :            :  *
     707                 :            :  *  This function is meant to load a message buffer with all attribute types
     708                 :            :  *  including a nested attribute.
     709                 :            :  **/
     710                 :          0 : void fm10k_tlv_msg_test_create(u32 *msg, u32 attr_flags)
     711                 :            : {
     712                 :            :         u32 *nest = NULL;
     713                 :            : 
     714                 :          0 :         DEBUGFUNC("fm10k_tlv_msg_test_create");
     715                 :            : 
     716                 :          0 :         fm10k_tlv_msg_init(msg, FM10K_TLV_MSG_ID_TEST);
     717                 :            : 
     718                 :          0 :         fm10k_tlv_msg_test_generate_data(msg, attr_flags);
     719                 :            : 
     720                 :            :         /* check for nested attributes */
     721                 :          0 :         attr_flags >>= FM10K_TEST_MSG_NESTED;
     722                 :            : 
     723         [ #  # ]:          0 :         if (attr_flags) {
     724                 :          0 :                 nest = fm10k_tlv_attr_nest_start(msg, FM10K_TEST_MSG_NESTED);
     725                 :            : 
     726                 :          0 :                 fm10k_tlv_msg_test_generate_data(nest, attr_flags);
     727                 :            : 
     728                 :          0 :                 fm10k_tlv_attr_nest_stop(msg);
     729                 :            :         }
     730                 :          0 : }
     731                 :            : 
     732                 :            : /**
     733                 :            :  *  fm10k_tlv_msg_test - Validate all results on test message receive
     734                 :            :  *  @hw: Pointer to hardware structure
     735                 :            :  *  @results: Pointer array to attributes in the message
     736                 :            :  *  @mbx: Pointer to mailbox information structure
     737                 :            :  *
     738                 :            :  *  This function does a check to verify all attributes match what the test
     739                 :            :  *  message placed in the message buffer.  It is the default handler
     740                 :            :  *  for TLV test messages.
     741                 :            :  **/
     742                 :          0 : s32 fm10k_tlv_msg_test(struct fm10k_hw *hw, u32 **results,
     743                 :            :                        struct fm10k_mbx_info *mbx)
     744                 :            : {
     745                 :            :         u32 *nest_results[FM10K_TLV_RESULTS_MAX];
     746                 :            :         unsigned char result_str[80];
     747                 :            :         unsigned char result_mac[ETH_ALEN];
     748                 :            :         s32 err = FM10K_SUCCESS;
     749                 :            :         __le32 result_le[2];
     750                 :            :         u16 result_vlan;
     751                 :            :         u64 result_u64;
     752                 :            :         u32 result_u32;
     753                 :            :         u16 result_u16;
     754                 :            :         u8  result_u8;
     755                 :            :         s64 result_s64;
     756                 :            :         s32 result_s32;
     757                 :            :         s16 result_s16;
     758                 :            :         s8  result_s8;
     759                 :            :         u32 reply[3];
     760                 :            : 
     761                 :          0 :         DEBUGFUNC("fm10k_tlv_msg_test");
     762                 :            : 
     763                 :            :         /* retrieve results of a previous test */
     764         [ #  # ]:          0 :         if (!!results[FM10K_TEST_MSG_RESULT])
     765                 :          0 :                 return fm10k_tlv_attr_get_s32(results[FM10K_TEST_MSG_RESULT],
     766                 :            :                                               &mbx->test_result);
     767                 :            : 
     768                 :          0 : parse_nested:
     769         [ #  # ]:          0 :         if (!!results[FM10K_TEST_MSG_STRING]) {
     770                 :          0 :                 err = fm10k_tlv_attr_get_null_string(
     771                 :            :                                         results[FM10K_TEST_MSG_STRING],
     772                 :            :                                         result_str);
     773   [ #  #  #  # ]:          0 :                 if (!err && memcmp(test_str, result_str, sizeof(test_str)))
     774                 :            :                         err = FM10K_ERR_INVALID_VALUE;
     775         [ #  # ]:          0 :                 if (err)
     776                 :          0 :                         goto report_result;
     777                 :            :         }
     778         [ #  # ]:          0 :         if (!!results[FM10K_TEST_MSG_MAC_ADDR]) {
     779                 :          0 :                 err = fm10k_tlv_attr_get_mac_vlan(
     780                 :            :                                         results[FM10K_TEST_MSG_MAC_ADDR],
     781                 :            :                                         result_mac, &result_vlan);
     782   [ #  #  #  # ]:          0 :                 if (!err && memcmp(test_mac, result_mac, ETH_ALEN))
     783                 :            :                         err = FM10K_ERR_INVALID_VALUE;
     784   [ #  #  #  # ]:          0 :                 if (!err && test_vlan != result_vlan)
     785                 :            :                         err = FM10K_ERR_INVALID_VALUE;
     786         [ #  # ]:          0 :                 if (err)
     787                 :          0 :                         goto report_result;
     788                 :            :         }
     789         [ #  # ]:          0 :         if (!!results[FM10K_TEST_MSG_U8]) {
     790                 :          0 :                 err = fm10k_tlv_attr_get_u8(results[FM10K_TEST_MSG_U8],
     791                 :            :                                             &result_u8);
     792   [ #  #  #  # ]:          0 :                 if (!err && test_u8 != result_u8)
     793                 :            :                         err = FM10K_ERR_INVALID_VALUE;
     794         [ #  # ]:          0 :                 if (err)
     795                 :          0 :                         goto report_result;
     796                 :            :         }
     797         [ #  # ]:          0 :         if (!!results[FM10K_TEST_MSG_U16]) {
     798                 :          0 :                 err = fm10k_tlv_attr_get_u16(results[FM10K_TEST_MSG_U16],
     799                 :            :                                              &result_u16);
     800   [ #  #  #  # ]:          0 :                 if (!err && test_u16 != result_u16)
     801                 :            :                         err = FM10K_ERR_INVALID_VALUE;
     802         [ #  # ]:          0 :                 if (err)
     803                 :          0 :                         goto report_result;
     804                 :            :         }
     805         [ #  # ]:          0 :         if (!!results[FM10K_TEST_MSG_U32]) {
     806                 :          0 :                 err = fm10k_tlv_attr_get_u32(results[FM10K_TEST_MSG_U32],
     807                 :            :                                              &result_u32);
     808   [ #  #  #  # ]:          0 :                 if (!err && test_u32 != result_u32)
     809                 :            :                         err = FM10K_ERR_INVALID_VALUE;
     810         [ #  # ]:          0 :                 if (err)
     811                 :          0 :                         goto report_result;
     812                 :            :         }
     813         [ #  # ]:          0 :         if (!!results[FM10K_TEST_MSG_U64]) {
     814                 :          0 :                 err = fm10k_tlv_attr_get_u64(results[FM10K_TEST_MSG_U64],
     815                 :            :                                              &result_u64);
     816   [ #  #  #  # ]:          0 :                 if (!err && test_u64 != result_u64)
     817                 :            :                         err = FM10K_ERR_INVALID_VALUE;
     818         [ #  # ]:          0 :                 if (err)
     819                 :          0 :                         goto report_result;
     820                 :            :         }
     821         [ #  # ]:          0 :         if (!!results[FM10K_TEST_MSG_S8]) {
     822                 :          0 :                 err = fm10k_tlv_attr_get_s8(results[FM10K_TEST_MSG_S8],
     823                 :            :                                             &result_s8);
     824   [ #  #  #  # ]:          0 :                 if (!err && test_s8 != result_s8)
     825                 :            :                         err = FM10K_ERR_INVALID_VALUE;
     826         [ #  # ]:          0 :                 if (err)
     827                 :          0 :                         goto report_result;
     828                 :            :         }
     829         [ #  # ]:          0 :         if (!!results[FM10K_TEST_MSG_S16]) {
     830                 :          0 :                 err = fm10k_tlv_attr_get_s16(results[FM10K_TEST_MSG_S16],
     831                 :            :                                              &result_s16);
     832   [ #  #  #  # ]:          0 :                 if (!err && test_s16 != result_s16)
     833                 :            :                         err = FM10K_ERR_INVALID_VALUE;
     834         [ #  # ]:          0 :                 if (err)
     835                 :          0 :                         goto report_result;
     836                 :            :         }
     837         [ #  # ]:          0 :         if (!!results[FM10K_TEST_MSG_S32]) {
     838                 :          0 :                 err = fm10k_tlv_attr_get_s32(results[FM10K_TEST_MSG_S32],
     839                 :            :                                              &result_s32);
     840   [ #  #  #  # ]:          0 :                 if (!err && test_s32 != result_s32)
     841                 :            :                         err = FM10K_ERR_INVALID_VALUE;
     842         [ #  # ]:          0 :                 if (err)
     843                 :          0 :                         goto report_result;
     844                 :            :         }
     845         [ #  # ]:          0 :         if (!!results[FM10K_TEST_MSG_S64]) {
     846                 :          0 :                 err = fm10k_tlv_attr_get_s64(results[FM10K_TEST_MSG_S64],
     847                 :            :                                              &result_s64);
     848   [ #  #  #  # ]:          0 :                 if (!err && test_s64 != result_s64)
     849                 :            :                         err = FM10K_ERR_INVALID_VALUE;
     850         [ #  # ]:          0 :                 if (err)
     851                 :          0 :                         goto report_result;
     852                 :            :         }
     853         [ #  # ]:          0 :         if (!!results[FM10K_TEST_MSG_LE_STRUCT]) {
     854                 :          0 :                 err = fm10k_tlv_attr_get_le_struct(
     855                 :            :                                         results[FM10K_TEST_MSG_LE_STRUCT],
     856                 :            :                                         result_le,
     857                 :            :                                         sizeof(result_le));
     858   [ #  #  #  # ]:          0 :                 if (!err && memcmp(test_le, result_le, sizeof(test_le)))
     859                 :            :                         err = FM10K_ERR_INVALID_VALUE;
     860         [ #  # ]:          0 :                 if (err)
     861                 :          0 :                         goto report_result;
     862                 :            :         }
     863                 :            : 
     864         [ #  # ]:          0 :         if (!!results[FM10K_TEST_MSG_NESTED]) {
     865                 :            :                 /* clear any pointers */
     866                 :            :                 memset(nest_results, 0, sizeof(nest_results));
     867                 :            : 
     868                 :            :                 /* parse the nested attributes into the nest results list */
     869                 :          0 :                 err = fm10k_tlv_attr_parse(results[FM10K_TEST_MSG_NESTED],
     870                 :            :                                            nest_results,
     871                 :            :                                            fm10k_tlv_msg_test_attr);
     872         [ #  # ]:          0 :                 if (err)
     873                 :          0 :                         goto report_result;
     874                 :            : 
     875                 :            :                 /* loop back through to the start */
     876                 :            :                 results = nest_results;
     877                 :          0 :                 goto parse_nested;
     878                 :            :         }
     879                 :            : 
     880                 :          0 : report_result:
     881                 :            :         /* generate reply with test result */
     882                 :          0 :         fm10k_tlv_msg_init(reply, FM10K_TLV_MSG_ID_TEST);
     883                 :          0 :         fm10k_tlv_attr_put_s32(reply, FM10K_TEST_MSG_RESULT, err);
     884                 :            : 
     885                 :            :         /* load onto outgoing mailbox */
     886                 :          0 :         return mbx->ops.enqueue_tx(hw, mbx, reply);
     887                 :            : }

Generated by: LCOV version 1.14