root/drivers/net/dsa/sja1105/sja1105_static_config.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sja1105_pack
  2. sja1105_unpack
  3. sja1105_packing
  4. sja1105_crc32
  5. sja1105et_avb_params_entry_packing
  6. sja1105pqrs_avb_params_entry_packing
  7. sja1105et_general_params_entry_packing
  8. sja1105pqrs_general_params_entry_packing
  9. sja1105_l2_forwarding_params_entry_packing
  10. sja1105_l2_forwarding_entry_packing
  11. sja1105et_l2_lookup_params_entry_packing
  12. sja1105pqrs_l2_lookup_params_entry_packing
  13. sja1105et_l2_lookup_entry_packing
  14. sja1105pqrs_l2_lookup_entry_packing
  15. sja1105_l2_policing_entry_packing
  16. sja1105et_mac_config_entry_packing
  17. sja1105pqrs_mac_config_entry_packing
  18. sja1105_schedule_entry_points_params_entry_packing
  19. sja1105_schedule_entry_points_entry_packing
  20. sja1105_schedule_params_entry_packing
  21. sja1105_schedule_entry_packing
  22. sja1105_vlan_lookup_entry_packing
  23. sja1105_xmii_params_entry_packing
  24. sja1105_table_header_packing
  25. sja1105_table_header_pack_with_crc
  26. sja1105_table_write_crc
  27. static_config_check_memory_size
  28. sja1105_static_config_check_valid
  29. sja1105_static_config_pack
  30. sja1105_static_config_get_length
  31. sja1105_static_config_init
  32. sja1105_static_config_free
  33. sja1105_table_delete_entry
  34. sja1105_table_resize

   1 // SPDX-License-Identifier: BSD-3-Clause
   2 /* Copyright (c) 2016-2018, NXP Semiconductors
   3  * Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com>
   4  */
   5 #include "sja1105_static_config.h"
   6 #include <linux/crc32.h>
   7 #include <linux/slab.h>
   8 #include <linux/string.h>
   9 #include <linux/errno.h>
  10 
  11 /* Convenience wrappers over the generic packing functions. These take into
  12  * account the SJA1105 memory layout quirks and provide some level of
  13  * programmer protection against incorrect API use. The errors are not expected
  14  * to occur durring runtime, therefore printing and swallowing them here is
  15  * appropriate instead of clutterring up higher-level code.
  16  */
  17 void sja1105_pack(void *buf, const u64 *val, int start, int end, size_t len)
  18 {
  19         int rc = packing(buf, (u64 *)val, start, end, len,
  20                          PACK, QUIRK_LSW32_IS_FIRST);
  21 
  22         if (likely(!rc))
  23                 return;
  24 
  25         if (rc == -EINVAL) {
  26                 pr_err("Start bit (%d) expected to be larger than end (%d)\n",
  27                        start, end);
  28         } else if (rc == -ERANGE) {
  29                 if ((start - end + 1) > 64)
  30                         pr_err("Field %d-%d too large for 64 bits!\n",
  31                                start, end);
  32                 else
  33                         pr_err("Cannot store %llx inside bits %d-%d (would truncate)\n",
  34                                *val, start, end);
  35         }
  36         dump_stack();
  37 }
  38 
  39 void sja1105_unpack(const void *buf, u64 *val, int start, int end, size_t len)
  40 {
  41         int rc = packing((void *)buf, val, start, end, len,
  42                          UNPACK, QUIRK_LSW32_IS_FIRST);
  43 
  44         if (likely(!rc))
  45                 return;
  46 
  47         if (rc == -EINVAL)
  48                 pr_err("Start bit (%d) expected to be larger than end (%d)\n",
  49                        start, end);
  50         else if (rc == -ERANGE)
  51                 pr_err("Field %d-%d too large for 64 bits!\n",
  52                        start, end);
  53         dump_stack();
  54 }
  55 
  56 void sja1105_packing(void *buf, u64 *val, int start, int end,
  57                      size_t len, enum packing_op op)
  58 {
  59         int rc = packing(buf, val, start, end, len, op, QUIRK_LSW32_IS_FIRST);
  60 
  61         if (likely(!rc))
  62                 return;
  63 
  64         if (rc == -EINVAL) {
  65                 pr_err("Start bit (%d) expected to be larger than end (%d)\n",
  66                        start, end);
  67         } else if (rc == -ERANGE) {
  68                 if ((start - end + 1) > 64)
  69                         pr_err("Field %d-%d too large for 64 bits!\n",
  70                                start, end);
  71                 else
  72                         pr_err("Cannot store %llx inside bits %d-%d (would truncate)\n",
  73                                *val, start, end);
  74         }
  75         dump_stack();
  76 }
  77 
  78 /* Little-endian Ethernet CRC32 of data packed as big-endian u32 words */
  79 u32 sja1105_crc32(const void *buf, size_t len)
  80 {
  81         unsigned int i;
  82         u64 word;
  83         u32 crc;
  84 
  85         /* seed */
  86         crc = ~0;
  87         for (i = 0; i < len; i += 4) {
  88                 sja1105_unpack((void *)buf + i, &word, 31, 0, 4);
  89                 crc = crc32_le(crc, (u8 *)&word, 4);
  90         }
  91         return ~crc;
  92 }
  93 
  94 static size_t sja1105et_avb_params_entry_packing(void *buf, void *entry_ptr,
  95                                                  enum packing_op op)
  96 {
  97         const size_t size = SJA1105ET_SIZE_AVB_PARAMS_ENTRY;
  98         struct sja1105_avb_params_entry *entry = entry_ptr;
  99 
 100         sja1105_packing(buf, &entry->destmeta, 95, 48, size, op);
 101         sja1105_packing(buf, &entry->srcmeta,  47,  0, size, op);
 102         return size;
 103 }
 104 
 105 static size_t sja1105pqrs_avb_params_entry_packing(void *buf, void *entry_ptr,
 106                                                    enum packing_op op)
 107 {
 108         const size_t size = SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY;
 109         struct sja1105_avb_params_entry *entry = entry_ptr;
 110 
 111         sja1105_packing(buf, &entry->destmeta,   125,  78, size, op);
 112         sja1105_packing(buf, &entry->srcmeta,     77,  30, size, op);
 113         return size;
 114 }
 115 
 116 static size_t sja1105et_general_params_entry_packing(void *buf, void *entry_ptr,
 117                                                      enum packing_op op)
 118 {
 119         const size_t size = SJA1105ET_SIZE_GENERAL_PARAMS_ENTRY;
 120         struct sja1105_general_params_entry *entry = entry_ptr;
 121 
 122         sja1105_packing(buf, &entry->vllupformat, 319, 319, size, op);
 123         sja1105_packing(buf, &entry->mirr_ptacu,  318, 318, size, op);
 124         sja1105_packing(buf, &entry->switchid,    317, 315, size, op);
 125         sja1105_packing(buf, &entry->hostprio,    314, 312, size, op);
 126         sja1105_packing(buf, &entry->mac_fltres1, 311, 264, size, op);
 127         sja1105_packing(buf, &entry->mac_fltres0, 263, 216, size, op);
 128         sja1105_packing(buf, &entry->mac_flt1,    215, 168, size, op);
 129         sja1105_packing(buf, &entry->mac_flt0,    167, 120, size, op);
 130         sja1105_packing(buf, &entry->incl_srcpt1, 119, 119, size, op);
 131         sja1105_packing(buf, &entry->incl_srcpt0, 118, 118, size, op);
 132         sja1105_packing(buf, &entry->send_meta1,  117, 117, size, op);
 133         sja1105_packing(buf, &entry->send_meta0,  116, 116, size, op);
 134         sja1105_packing(buf, &entry->casc_port,   115, 113, size, op);
 135         sja1105_packing(buf, &entry->host_port,   112, 110, size, op);
 136         sja1105_packing(buf, &entry->mirr_port,   109, 107, size, op);
 137         sja1105_packing(buf, &entry->vlmarker,    106,  75, size, op);
 138         sja1105_packing(buf, &entry->vlmask,       74,  43, size, op);
 139         sja1105_packing(buf, &entry->tpid,         42,  27, size, op);
 140         sja1105_packing(buf, &entry->ignore2stf,   26,  26, size, op);
 141         sja1105_packing(buf, &entry->tpid2,        25,  10, size, op);
 142         return size;
 143 }
 144 
 145 /* TPID and TPID2 are intentionally reversed so that semantic
 146  * compatibility with E/T is kept.
 147  */
 148 static size_t
 149 sja1105pqrs_general_params_entry_packing(void *buf, void *entry_ptr,
 150                                          enum packing_op op)
 151 {
 152         const size_t size = SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY;
 153         struct sja1105_general_params_entry *entry = entry_ptr;
 154 
 155         sja1105_packing(buf, &entry->vllupformat, 351, 351, size, op);
 156         sja1105_packing(buf, &entry->mirr_ptacu,  350, 350, size, op);
 157         sja1105_packing(buf, &entry->switchid,    349, 347, size, op);
 158         sja1105_packing(buf, &entry->hostprio,    346, 344, size, op);
 159         sja1105_packing(buf, &entry->mac_fltres1, 343, 296, size, op);
 160         sja1105_packing(buf, &entry->mac_fltres0, 295, 248, size, op);
 161         sja1105_packing(buf, &entry->mac_flt1,    247, 200, size, op);
 162         sja1105_packing(buf, &entry->mac_flt0,    199, 152, size, op);
 163         sja1105_packing(buf, &entry->incl_srcpt1, 151, 151, size, op);
 164         sja1105_packing(buf, &entry->incl_srcpt0, 150, 150, size, op);
 165         sja1105_packing(buf, &entry->send_meta1,  149, 149, size, op);
 166         sja1105_packing(buf, &entry->send_meta0,  148, 148, size, op);
 167         sja1105_packing(buf, &entry->casc_port,   147, 145, size, op);
 168         sja1105_packing(buf, &entry->host_port,   144, 142, size, op);
 169         sja1105_packing(buf, &entry->mirr_port,   141, 139, size, op);
 170         sja1105_packing(buf, &entry->vlmarker,    138, 107, size, op);
 171         sja1105_packing(buf, &entry->vlmask,      106,  75, size, op);
 172         sja1105_packing(buf, &entry->tpid2,        74,  59, size, op);
 173         sja1105_packing(buf, &entry->ignore2stf,   58,  58, size, op);
 174         sja1105_packing(buf, &entry->tpid,         57,  42, size, op);
 175         sja1105_packing(buf, &entry->queue_ts,     41,  41, size, op);
 176         sja1105_packing(buf, &entry->egrmirrvid,   40,  29, size, op);
 177         sja1105_packing(buf, &entry->egrmirrpcp,   28,  26, size, op);
 178         sja1105_packing(buf, &entry->egrmirrdei,   25,  25, size, op);
 179         sja1105_packing(buf, &entry->replay_port,  24,  22, size, op);
 180         return size;
 181 }
 182 
 183 static size_t
 184 sja1105_l2_forwarding_params_entry_packing(void *buf, void *entry_ptr,
 185                                            enum packing_op op)
 186 {
 187         const size_t size = SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY;
 188         struct sja1105_l2_forwarding_params_entry *entry = entry_ptr;
 189         int offset, i;
 190 
 191         sja1105_packing(buf, &entry->max_dynp, 95, 93, size, op);
 192         for (i = 0, offset = 13; i < 8; i++, offset += 10)
 193                 sja1105_packing(buf, &entry->part_spc[i],
 194                                 offset + 9, offset + 0, size, op);
 195         return size;
 196 }
 197 
 198 size_t sja1105_l2_forwarding_entry_packing(void *buf, void *entry_ptr,
 199                                            enum packing_op op)
 200 {
 201         const size_t size = SJA1105_SIZE_L2_FORWARDING_ENTRY;
 202         struct sja1105_l2_forwarding_entry *entry = entry_ptr;
 203         int offset, i;
 204 
 205         sja1105_packing(buf, &entry->bc_domain,  63, 59, size, op);
 206         sja1105_packing(buf, &entry->reach_port, 58, 54, size, op);
 207         sja1105_packing(buf, &entry->fl_domain,  53, 49, size, op);
 208         for (i = 0, offset = 25; i < 8; i++, offset += 3)
 209                 sja1105_packing(buf, &entry->vlan_pmap[i],
 210                                 offset + 2, offset + 0, size, op);
 211         return size;
 212 }
 213 
 214 static size_t
 215 sja1105et_l2_lookup_params_entry_packing(void *buf, void *entry_ptr,
 216                                          enum packing_op op)
 217 {
 218         const size_t size = SJA1105ET_SIZE_L2_LOOKUP_PARAMS_ENTRY;
 219         struct sja1105_l2_lookup_params_entry *entry = entry_ptr;
 220 
 221         sja1105_packing(buf, &entry->maxage,         31, 17, size, op);
 222         sja1105_packing(buf, &entry->dyn_tbsz,       16, 14, size, op);
 223         sja1105_packing(buf, &entry->poly,           13,  6, size, op);
 224         sja1105_packing(buf, &entry->shared_learn,    5,  5, size, op);
 225         sja1105_packing(buf, &entry->no_enf_hostprt,  4,  4, size, op);
 226         sja1105_packing(buf, &entry->no_mgmt_learn,   3,  3, size, op);
 227         return size;
 228 }
 229 
 230 static size_t
 231 sja1105pqrs_l2_lookup_params_entry_packing(void *buf, void *entry_ptr,
 232                                            enum packing_op op)
 233 {
 234         const size_t size = SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY;
 235         struct sja1105_l2_lookup_params_entry *entry = entry_ptr;
 236         int offset, i;
 237 
 238         for (i = 0, offset = 58; i < 5; i++, offset += 11)
 239                 sja1105_packing(buf, &entry->maxaddrp[i],
 240                                 offset + 10, offset + 0, size, op);
 241         sja1105_packing(buf, &entry->maxage,         57,  43, size, op);
 242         sja1105_packing(buf, &entry->start_dynspc,   42,  33, size, op);
 243         sja1105_packing(buf, &entry->drpnolearn,     32,  28, size, op);
 244         sja1105_packing(buf, &entry->shared_learn,   27,  27, size, op);
 245         sja1105_packing(buf, &entry->no_enf_hostprt, 26,  26, size, op);
 246         sja1105_packing(buf, &entry->no_mgmt_learn,  25,  25, size, op);
 247         sja1105_packing(buf, &entry->use_static,     24,  24, size, op);
 248         sja1105_packing(buf, &entry->owr_dyn,        23,  23, size, op);
 249         sja1105_packing(buf, &entry->learn_once,     22,  22, size, op);
 250         return size;
 251 }
 252 
 253 size_t sja1105et_l2_lookup_entry_packing(void *buf, void *entry_ptr,
 254                                          enum packing_op op)
 255 {
 256         const size_t size = SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
 257         struct sja1105_l2_lookup_entry *entry = entry_ptr;
 258 
 259         sja1105_packing(buf, &entry->vlanid,    95, 84, size, op);
 260         sja1105_packing(buf, &entry->macaddr,   83, 36, size, op);
 261         sja1105_packing(buf, &entry->destports, 35, 31, size, op);
 262         sja1105_packing(buf, &entry->enfport,   30, 30, size, op);
 263         sja1105_packing(buf, &entry->index,     29, 20, size, op);
 264         return size;
 265 }
 266 
 267 size_t sja1105pqrs_l2_lookup_entry_packing(void *buf, void *entry_ptr,
 268                                            enum packing_op op)
 269 {
 270         const size_t size = SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY;
 271         struct sja1105_l2_lookup_entry *entry = entry_ptr;
 272 
 273         if (entry->lockeds) {
 274                 sja1105_packing(buf, &entry->tsreg,    159, 159, size, op);
 275                 sja1105_packing(buf, &entry->mirrvlan, 158, 147, size, op);
 276                 sja1105_packing(buf, &entry->takets,   146, 146, size, op);
 277                 sja1105_packing(buf, &entry->mirr,     145, 145, size, op);
 278                 sja1105_packing(buf, &entry->retag,    144, 144, size, op);
 279         } else {
 280                 sja1105_packing(buf, &entry->touched,  159, 159, size, op);
 281                 sja1105_packing(buf, &entry->age,      158, 144, size, op);
 282         }
 283         sja1105_packing(buf, &entry->mask_iotag,   143, 143, size, op);
 284         sja1105_packing(buf, &entry->mask_vlanid,  142, 131, size, op);
 285         sja1105_packing(buf, &entry->mask_macaddr, 130,  83, size, op);
 286         sja1105_packing(buf, &entry->iotag,         82,  82, size, op);
 287         sja1105_packing(buf, &entry->vlanid,        81,  70, size, op);
 288         sja1105_packing(buf, &entry->macaddr,       69,  22, size, op);
 289         sja1105_packing(buf, &entry->destports,     21,  17, size, op);
 290         sja1105_packing(buf, &entry->enfport,       16,  16, size, op);
 291         sja1105_packing(buf, &entry->index,         15,   6, size, op);
 292         return size;
 293 }
 294 
 295 static size_t sja1105_l2_policing_entry_packing(void *buf, void *entry_ptr,
 296                                                 enum packing_op op)
 297 {
 298         const size_t size = SJA1105_SIZE_L2_POLICING_ENTRY;
 299         struct sja1105_l2_policing_entry *entry = entry_ptr;
 300 
 301         sja1105_packing(buf, &entry->sharindx,  63, 58, size, op);
 302         sja1105_packing(buf, &entry->smax,      57, 42, size, op);
 303         sja1105_packing(buf, &entry->rate,      41, 26, size, op);
 304         sja1105_packing(buf, &entry->maxlen,    25, 15, size, op);
 305         sja1105_packing(buf, &entry->partition, 14, 12, size, op);
 306         return size;
 307 }
 308 
 309 static size_t sja1105et_mac_config_entry_packing(void *buf, void *entry_ptr,
 310                                                  enum packing_op op)
 311 {
 312         const size_t size = SJA1105ET_SIZE_MAC_CONFIG_ENTRY;
 313         struct sja1105_mac_config_entry *entry = entry_ptr;
 314         int offset, i;
 315 
 316         for (i = 0, offset = 72; i < 8; i++, offset += 19) {
 317                 sja1105_packing(buf, &entry->enabled[i],
 318                                 offset +  0, offset +  0, size, op);
 319                 sja1105_packing(buf, &entry->base[i],
 320                                 offset +  9, offset +  1, size, op);
 321                 sja1105_packing(buf, &entry->top[i],
 322                                 offset + 18, offset + 10, size, op);
 323         }
 324         sja1105_packing(buf, &entry->ifg,       71, 67, size, op);
 325         sja1105_packing(buf, &entry->speed,     66, 65, size, op);
 326         sja1105_packing(buf, &entry->tp_delin,  64, 49, size, op);
 327         sja1105_packing(buf, &entry->tp_delout, 48, 33, size, op);
 328         sja1105_packing(buf, &entry->maxage,    32, 25, size, op);
 329         sja1105_packing(buf, &entry->vlanprio,  24, 22, size, op);
 330         sja1105_packing(buf, &entry->vlanid,    21, 10, size, op);
 331         sja1105_packing(buf, &entry->ing_mirr,   9,  9, size, op);
 332         sja1105_packing(buf, &entry->egr_mirr,   8,  8, size, op);
 333         sja1105_packing(buf, &entry->drpnona664, 7,  7, size, op);
 334         sja1105_packing(buf, &entry->drpdtag,    6,  6, size, op);
 335         sja1105_packing(buf, &entry->drpuntag,   5,  5, size, op);
 336         sja1105_packing(buf, &entry->retag,      4,  4, size, op);
 337         sja1105_packing(buf, &entry->dyn_learn,  3,  3, size, op);
 338         sja1105_packing(buf, &entry->egress,     2,  2, size, op);
 339         sja1105_packing(buf, &entry->ingress,    1,  1, size, op);
 340         return size;
 341 }
 342 
 343 size_t sja1105pqrs_mac_config_entry_packing(void *buf, void *entry_ptr,
 344                                             enum packing_op op)
 345 {
 346         const size_t size = SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY;
 347         struct sja1105_mac_config_entry *entry = entry_ptr;
 348         int offset, i;
 349 
 350         for (i = 0, offset = 104; i < 8; i++, offset += 19) {
 351                 sja1105_packing(buf, &entry->enabled[i],
 352                                 offset +  0, offset +  0, size, op);
 353                 sja1105_packing(buf, &entry->base[i],
 354                                 offset +  9, offset +  1, size, op);
 355                 sja1105_packing(buf, &entry->top[i],
 356                                 offset + 18, offset + 10, size, op);
 357         }
 358         sja1105_packing(buf, &entry->ifg,       103, 99, size, op);
 359         sja1105_packing(buf, &entry->speed,      98, 97, size, op);
 360         sja1105_packing(buf, &entry->tp_delin,   96, 81, size, op);
 361         sja1105_packing(buf, &entry->tp_delout,  80, 65, size, op);
 362         sja1105_packing(buf, &entry->maxage,     64, 57, size, op);
 363         sja1105_packing(buf, &entry->vlanprio,   56, 54, size, op);
 364         sja1105_packing(buf, &entry->vlanid,     53, 42, size, op);
 365         sja1105_packing(buf, &entry->ing_mirr,   41, 41, size, op);
 366         sja1105_packing(buf, &entry->egr_mirr,   40, 40, size, op);
 367         sja1105_packing(buf, &entry->drpnona664, 39, 39, size, op);
 368         sja1105_packing(buf, &entry->drpdtag,    38, 38, size, op);
 369         sja1105_packing(buf, &entry->drpuntag,   35, 35, size, op);
 370         sja1105_packing(buf, &entry->retag,      34, 34, size, op);
 371         sja1105_packing(buf, &entry->dyn_learn,  33, 33, size, op);
 372         sja1105_packing(buf, &entry->egress,     32, 32, size, op);
 373         sja1105_packing(buf, &entry->ingress,    31, 31, size, op);
 374         return size;
 375 }
 376 
 377 static size_t
 378 sja1105_schedule_entry_points_params_entry_packing(void *buf, void *entry_ptr,
 379                                                    enum packing_op op)
 380 {
 381         struct sja1105_schedule_entry_points_params_entry *entry = entry_ptr;
 382         const size_t size = SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_PARAMS_ENTRY;
 383 
 384         sja1105_packing(buf, &entry->clksrc,    31, 30, size, op);
 385         sja1105_packing(buf, &entry->actsubsch, 29, 27, size, op);
 386         return size;
 387 }
 388 
 389 static size_t
 390 sja1105_schedule_entry_points_entry_packing(void *buf, void *entry_ptr,
 391                                             enum packing_op op)
 392 {
 393         struct sja1105_schedule_entry_points_entry *entry = entry_ptr;
 394         const size_t size = SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_ENTRY;
 395 
 396         sja1105_packing(buf, &entry->subschindx, 31, 29, size, op);
 397         sja1105_packing(buf, &entry->delta,      28, 11, size, op);
 398         sja1105_packing(buf, &entry->address,    10, 1,  size, op);
 399         return size;
 400 }
 401 
 402 static size_t sja1105_schedule_params_entry_packing(void *buf, void *entry_ptr,
 403                                                     enum packing_op op)
 404 {
 405         const size_t size = SJA1105_SIZE_SCHEDULE_PARAMS_ENTRY;
 406         struct sja1105_schedule_params_entry *entry = entry_ptr;
 407         int offset, i;
 408 
 409         for (i = 0, offset = 16; i < 8; i++, offset += 10)
 410                 sja1105_packing(buf, &entry->subscheind[i],
 411                                 offset + 9, offset + 0, size, op);
 412         return size;
 413 }
 414 
 415 static size_t sja1105_schedule_entry_packing(void *buf, void *entry_ptr,
 416                                              enum packing_op op)
 417 {
 418         const size_t size = SJA1105_SIZE_SCHEDULE_ENTRY;
 419         struct sja1105_schedule_entry *entry = entry_ptr;
 420 
 421         sja1105_packing(buf, &entry->winstindex,  63, 54, size, op);
 422         sja1105_packing(buf, &entry->winend,      53, 53, size, op);
 423         sja1105_packing(buf, &entry->winst,       52, 52, size, op);
 424         sja1105_packing(buf, &entry->destports,   51, 47, size, op);
 425         sja1105_packing(buf, &entry->setvalid,    46, 46, size, op);
 426         sja1105_packing(buf, &entry->txen,        45, 45, size, op);
 427         sja1105_packing(buf, &entry->resmedia_en, 44, 44, size, op);
 428         sja1105_packing(buf, &entry->resmedia,    43, 36, size, op);
 429         sja1105_packing(buf, &entry->vlindex,     35, 26, size, op);
 430         sja1105_packing(buf, &entry->delta,       25, 8,  size, op);
 431         return size;
 432 }
 433 
 434 size_t sja1105_vlan_lookup_entry_packing(void *buf, void *entry_ptr,
 435                                          enum packing_op op)
 436 {
 437         const size_t size = SJA1105_SIZE_VLAN_LOOKUP_ENTRY;
 438         struct sja1105_vlan_lookup_entry *entry = entry_ptr;
 439 
 440         sja1105_packing(buf, &entry->ving_mirr,  63, 59, size, op);
 441         sja1105_packing(buf, &entry->vegr_mirr,  58, 54, size, op);
 442         sja1105_packing(buf, &entry->vmemb_port, 53, 49, size, op);
 443         sja1105_packing(buf, &entry->vlan_bc,    48, 44, size, op);
 444         sja1105_packing(buf, &entry->tag_port,   43, 39, size, op);
 445         sja1105_packing(buf, &entry->vlanid,     38, 27, size, op);
 446         return size;
 447 }
 448 
 449 static size_t sja1105_xmii_params_entry_packing(void *buf, void *entry_ptr,
 450                                                 enum packing_op op)
 451 {
 452         const size_t size = SJA1105_SIZE_XMII_PARAMS_ENTRY;
 453         struct sja1105_xmii_params_entry *entry = entry_ptr;
 454         int offset, i;
 455 
 456         for (i = 0, offset = 17; i < 5; i++, offset += 3) {
 457                 sja1105_packing(buf, &entry->xmii_mode[i],
 458                                 offset + 1, offset + 0, size, op);
 459                 sja1105_packing(buf, &entry->phy_mac[i],
 460                                 offset + 2, offset + 2, size, op);
 461         }
 462         return size;
 463 }
 464 
 465 size_t sja1105_table_header_packing(void *buf, void *entry_ptr,
 466                                     enum packing_op op)
 467 {
 468         const size_t size = SJA1105_SIZE_TABLE_HEADER;
 469         struct sja1105_table_header *entry = entry_ptr;
 470 
 471         sja1105_packing(buf, &entry->block_id, 31, 24, size, op);
 472         sja1105_packing(buf, &entry->len,      55, 32, size, op);
 473         sja1105_packing(buf, &entry->crc,      95, 64, size, op);
 474         return size;
 475 }
 476 
 477 /* WARNING: the *hdr pointer is really non-const, because it is
 478  * modifying the CRC of the header for a 2-stage packing operation
 479  */
 480 void
 481 sja1105_table_header_pack_with_crc(void *buf, struct sja1105_table_header *hdr)
 482 {
 483         /* First pack the table as-is, then calculate the CRC, and
 484          * finally put the proper CRC into the packed buffer
 485          */
 486         memset(buf, 0, SJA1105_SIZE_TABLE_HEADER);
 487         sja1105_table_header_packing(buf, hdr, PACK);
 488         hdr->crc = sja1105_crc32(buf, SJA1105_SIZE_TABLE_HEADER - 4);
 489         sja1105_pack(buf + SJA1105_SIZE_TABLE_HEADER - 4, &hdr->crc, 31, 0, 4);
 490 }
 491 
 492 static void sja1105_table_write_crc(u8 *table_start, u8 *crc_ptr)
 493 {
 494         u64 computed_crc;
 495         int len_bytes;
 496 
 497         len_bytes = (uintptr_t)(crc_ptr - table_start);
 498         computed_crc = sja1105_crc32(table_start, len_bytes);
 499         sja1105_pack(crc_ptr, &computed_crc, 31, 0, 4);
 500 }
 501 
 502 /* The block IDs that the switches support are unfortunately sparse, so keep a
 503  * mapping table to "block indices" and translate back and forth so that we
 504  * don't waste useless memory in struct sja1105_static_config.
 505  * Also, since the block id comes from essentially untrusted input (unpacking
 506  * the static config from userspace) it has to be sanitized (range-checked)
 507  * before blindly indexing kernel memory with the blk_idx.
 508  */
 509 static u64 blk_id_map[BLK_IDX_MAX] = {
 510         [BLK_IDX_SCHEDULE] = BLKID_SCHEDULE,
 511         [BLK_IDX_SCHEDULE_ENTRY_POINTS] = BLKID_SCHEDULE_ENTRY_POINTS,
 512         [BLK_IDX_L2_LOOKUP] = BLKID_L2_LOOKUP,
 513         [BLK_IDX_L2_POLICING] = BLKID_L2_POLICING,
 514         [BLK_IDX_VLAN_LOOKUP] = BLKID_VLAN_LOOKUP,
 515         [BLK_IDX_L2_FORWARDING] = BLKID_L2_FORWARDING,
 516         [BLK_IDX_MAC_CONFIG] = BLKID_MAC_CONFIG,
 517         [BLK_IDX_SCHEDULE_PARAMS] = BLKID_SCHEDULE_PARAMS,
 518         [BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS] = BLKID_SCHEDULE_ENTRY_POINTS_PARAMS,
 519         [BLK_IDX_L2_LOOKUP_PARAMS] = BLKID_L2_LOOKUP_PARAMS,
 520         [BLK_IDX_L2_FORWARDING_PARAMS] = BLKID_L2_FORWARDING_PARAMS,
 521         [BLK_IDX_AVB_PARAMS] = BLKID_AVB_PARAMS,
 522         [BLK_IDX_GENERAL_PARAMS] = BLKID_GENERAL_PARAMS,
 523         [BLK_IDX_XMII_PARAMS] = BLKID_XMII_PARAMS,
 524 };
 525 
 526 const char *sja1105_static_config_error_msg[] = {
 527         [SJA1105_CONFIG_OK] = "",
 528         [SJA1105_TTETHERNET_NOT_SUPPORTED] =
 529                 "schedule-table present, but TTEthernet is "
 530                 "only supported on T and Q/S",
 531         [SJA1105_INCORRECT_TTETHERNET_CONFIGURATION] =
 532                 "schedule-table present, but one of "
 533                 "schedule-entry-points-table, schedule-parameters-table or "
 534                 "schedule-entry-points-parameters table is empty",
 535         [SJA1105_MISSING_L2_POLICING_TABLE] =
 536                 "l2-policing-table needs to have at least one entry",
 537         [SJA1105_MISSING_L2_FORWARDING_TABLE] =
 538                 "l2-forwarding-table is either missing or incomplete",
 539         [SJA1105_MISSING_L2_FORWARDING_PARAMS_TABLE] =
 540                 "l2-forwarding-parameters-table is missing",
 541         [SJA1105_MISSING_GENERAL_PARAMS_TABLE] =
 542                 "general-parameters-table is missing",
 543         [SJA1105_MISSING_VLAN_TABLE] =
 544                 "vlan-lookup-table needs to have at least the default untagged VLAN",
 545         [SJA1105_MISSING_XMII_TABLE] =
 546                 "xmii-table is missing",
 547         [SJA1105_MISSING_MAC_TABLE] =
 548                 "mac-configuration-table needs to contain an entry for each port",
 549         [SJA1105_OVERCOMMITTED_FRAME_MEMORY] =
 550                 "Not allowed to overcommit frame memory. L2 memory partitions "
 551                 "and VL memory partitions share the same space. The sum of all "
 552                 "16 memory partitions is not allowed to be larger than 929 "
 553                 "128-byte blocks (or 910 with retagging). Please adjust "
 554                 "l2-forwarding-parameters-table.part_spc and/or "
 555                 "vl-forwarding-parameters-table.partspc.",
 556 };
 557 
 558 static sja1105_config_valid_t
 559 static_config_check_memory_size(const struct sja1105_table *tables)
 560 {
 561         const struct sja1105_l2_forwarding_params_entry *l2_fwd_params;
 562         int i, mem = 0;
 563 
 564         l2_fwd_params = tables[BLK_IDX_L2_FORWARDING_PARAMS].entries;
 565 
 566         for (i = 0; i < 8; i++)
 567                 mem += l2_fwd_params->part_spc[i];
 568 
 569         if (mem > SJA1105_MAX_FRAME_MEMORY)
 570                 return SJA1105_OVERCOMMITTED_FRAME_MEMORY;
 571 
 572         return SJA1105_CONFIG_OK;
 573 }
 574 
 575 sja1105_config_valid_t
 576 sja1105_static_config_check_valid(const struct sja1105_static_config *config)
 577 {
 578         const struct sja1105_table *tables = config->tables;
 579 #define IS_FULL(blk_idx) \
 580         (tables[blk_idx].entry_count == tables[blk_idx].ops->max_entry_count)
 581 
 582         if (tables[BLK_IDX_SCHEDULE].entry_count) {
 583                 if (config->device_id != SJA1105T_DEVICE_ID &&
 584                     config->device_id != SJA1105QS_DEVICE_ID)
 585                         return SJA1105_TTETHERNET_NOT_SUPPORTED;
 586 
 587                 if (tables[BLK_IDX_SCHEDULE_ENTRY_POINTS].entry_count == 0)
 588                         return SJA1105_INCORRECT_TTETHERNET_CONFIGURATION;
 589 
 590                 if (!IS_FULL(BLK_IDX_SCHEDULE_PARAMS))
 591                         return SJA1105_INCORRECT_TTETHERNET_CONFIGURATION;
 592 
 593                 if (!IS_FULL(BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS))
 594                         return SJA1105_INCORRECT_TTETHERNET_CONFIGURATION;
 595         }
 596 
 597         if (tables[BLK_IDX_L2_POLICING].entry_count == 0)
 598                 return SJA1105_MISSING_L2_POLICING_TABLE;
 599 
 600         if (tables[BLK_IDX_VLAN_LOOKUP].entry_count == 0)
 601                 return SJA1105_MISSING_VLAN_TABLE;
 602 
 603         if (!IS_FULL(BLK_IDX_L2_FORWARDING))
 604                 return SJA1105_MISSING_L2_FORWARDING_TABLE;
 605 
 606         if (!IS_FULL(BLK_IDX_MAC_CONFIG))
 607                 return SJA1105_MISSING_MAC_TABLE;
 608 
 609         if (!IS_FULL(BLK_IDX_L2_FORWARDING_PARAMS))
 610                 return SJA1105_MISSING_L2_FORWARDING_PARAMS_TABLE;
 611 
 612         if (!IS_FULL(BLK_IDX_GENERAL_PARAMS))
 613                 return SJA1105_MISSING_GENERAL_PARAMS_TABLE;
 614 
 615         if (!IS_FULL(BLK_IDX_XMII_PARAMS))
 616                 return SJA1105_MISSING_XMII_TABLE;
 617 
 618         return static_config_check_memory_size(tables);
 619 #undef IS_FULL
 620 }
 621 
 622 void
 623 sja1105_static_config_pack(void *buf, struct sja1105_static_config *config)
 624 {
 625         struct sja1105_table_header header = {0};
 626         enum sja1105_blk_idx i;
 627         char *p = buf;
 628         int j;
 629 
 630         sja1105_pack(p, &config->device_id, 31, 0, 4);
 631         p += SJA1105_SIZE_DEVICE_ID;
 632 
 633         for (i = 0; i < BLK_IDX_MAX; i++) {
 634                 const struct sja1105_table *table;
 635                 char *table_start;
 636 
 637                 table = &config->tables[i];
 638                 if (!table->entry_count)
 639                         continue;
 640 
 641                 header.block_id = blk_id_map[i];
 642                 header.len = table->entry_count *
 643                              table->ops->packed_entry_size / 4;
 644                 sja1105_table_header_pack_with_crc(p, &header);
 645                 p += SJA1105_SIZE_TABLE_HEADER;
 646                 table_start = p;
 647                 for (j = 0; j < table->entry_count; j++) {
 648                         u8 *entry_ptr = table->entries;
 649 
 650                         entry_ptr += j * table->ops->unpacked_entry_size;
 651                         memset(p, 0, table->ops->packed_entry_size);
 652                         table->ops->packing(p, entry_ptr, PACK);
 653                         p += table->ops->packed_entry_size;
 654                 }
 655                 sja1105_table_write_crc(table_start, p);
 656                 p += 4;
 657         }
 658         /* Final header:
 659          * Block ID does not matter
 660          * Length of 0 marks that header is final
 661          * CRC will be replaced on-the-fly on "config upload"
 662          */
 663         header.block_id = 0;
 664         header.len = 0;
 665         header.crc = 0xDEADBEEF;
 666         memset(p, 0, SJA1105_SIZE_TABLE_HEADER);
 667         sja1105_table_header_packing(p, &header, PACK);
 668 }
 669 
 670 size_t
 671 sja1105_static_config_get_length(const struct sja1105_static_config *config)
 672 {
 673         unsigned int sum;
 674         unsigned int header_count;
 675         enum sja1105_blk_idx i;
 676 
 677         /* Ending header */
 678         header_count = 1;
 679         sum = SJA1105_SIZE_DEVICE_ID;
 680 
 681         /* Tables (headers and entries) */
 682         for (i = 0; i < BLK_IDX_MAX; i++) {
 683                 const struct sja1105_table *table;
 684 
 685                 table = &config->tables[i];
 686                 if (table->entry_count)
 687                         header_count++;
 688 
 689                 sum += table->ops->packed_entry_size * table->entry_count;
 690         }
 691         /* Headers have an additional CRC at the end */
 692         sum += header_count * (SJA1105_SIZE_TABLE_HEADER + 4);
 693         /* Last header does not have an extra CRC because there is no data */
 694         sum -= 4;
 695 
 696         return sum;
 697 }
 698 
 699 /* Compatibility matrices */
 700 
 701 /* SJA1105E: First generation, no TTEthernet */
 702 struct sja1105_table_ops sja1105e_table_ops[BLK_IDX_MAX] = {
 703         [BLK_IDX_SCHEDULE] = {0},
 704         [BLK_IDX_SCHEDULE_ENTRY_POINTS] = {0},
 705         [BLK_IDX_L2_LOOKUP] = {
 706                 .packing = sja1105et_l2_lookup_entry_packing,
 707                 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_entry),
 708                 .packed_entry_size = SJA1105ET_SIZE_L2_LOOKUP_ENTRY,
 709                 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
 710         },
 711         [BLK_IDX_L2_POLICING] = {
 712                 .packing = sja1105_l2_policing_entry_packing,
 713                 .unpacked_entry_size = sizeof(struct sja1105_l2_policing_entry),
 714                 .packed_entry_size = SJA1105_SIZE_L2_POLICING_ENTRY,
 715                 .max_entry_count = SJA1105_MAX_L2_POLICING_COUNT,
 716         },
 717         [BLK_IDX_VLAN_LOOKUP] = {
 718                 .packing = sja1105_vlan_lookup_entry_packing,
 719                 .unpacked_entry_size = sizeof(struct sja1105_vlan_lookup_entry),
 720                 .packed_entry_size = SJA1105_SIZE_VLAN_LOOKUP_ENTRY,
 721                 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
 722         },
 723         [BLK_IDX_L2_FORWARDING] = {
 724                 .packing = sja1105_l2_forwarding_entry_packing,
 725                 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_entry),
 726                 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_ENTRY,
 727                 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
 728         },
 729         [BLK_IDX_MAC_CONFIG] = {
 730                 .packing = sja1105et_mac_config_entry_packing,
 731                 .unpacked_entry_size = sizeof(struct sja1105_mac_config_entry),
 732                 .packed_entry_size = SJA1105ET_SIZE_MAC_CONFIG_ENTRY,
 733                 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
 734         },
 735         [BLK_IDX_SCHEDULE_PARAMS] = {0},
 736         [BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS] = {0},
 737         [BLK_IDX_L2_LOOKUP_PARAMS] = {
 738                 .packing = sja1105et_l2_lookup_params_entry_packing,
 739                 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_params_entry),
 740                 .packed_entry_size = SJA1105ET_SIZE_L2_LOOKUP_PARAMS_ENTRY,
 741                 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
 742         },
 743         [BLK_IDX_L2_FORWARDING_PARAMS] = {
 744                 .packing = sja1105_l2_forwarding_params_entry_packing,
 745                 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_params_entry),
 746                 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY,
 747                 .max_entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT,
 748         },
 749         [BLK_IDX_AVB_PARAMS] = {
 750                 .packing = sja1105et_avb_params_entry_packing,
 751                 .unpacked_entry_size = sizeof(struct sja1105_avb_params_entry),
 752                 .packed_entry_size = SJA1105ET_SIZE_AVB_PARAMS_ENTRY,
 753                 .max_entry_count = SJA1105_MAX_AVB_PARAMS_COUNT,
 754         },
 755         [BLK_IDX_GENERAL_PARAMS] = {
 756                 .packing = sja1105et_general_params_entry_packing,
 757                 .unpacked_entry_size = sizeof(struct sja1105_general_params_entry),
 758                 .packed_entry_size = SJA1105ET_SIZE_GENERAL_PARAMS_ENTRY,
 759                 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
 760         },
 761         [BLK_IDX_XMII_PARAMS] = {
 762                 .packing = sja1105_xmii_params_entry_packing,
 763                 .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry),
 764                 .packed_entry_size = SJA1105_SIZE_XMII_PARAMS_ENTRY,
 765                 .max_entry_count = SJA1105_MAX_XMII_PARAMS_COUNT,
 766         },
 767 };
 768 
 769 /* SJA1105T: First generation, TTEthernet */
 770 struct sja1105_table_ops sja1105t_table_ops[BLK_IDX_MAX] = {
 771         [BLK_IDX_SCHEDULE] = {
 772                 .packing = sja1105_schedule_entry_packing,
 773                 .unpacked_entry_size = sizeof(struct sja1105_schedule_entry),
 774                 .packed_entry_size = SJA1105_SIZE_SCHEDULE_ENTRY,
 775                 .max_entry_count = SJA1105_MAX_SCHEDULE_COUNT,
 776         },
 777         [BLK_IDX_SCHEDULE_ENTRY_POINTS] = {
 778                 .packing = sja1105_schedule_entry_points_entry_packing,
 779                 .unpacked_entry_size = sizeof(struct sja1105_schedule_entry_points_entry),
 780                 .packed_entry_size = SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_ENTRY,
 781                 .max_entry_count = SJA1105_MAX_SCHEDULE_ENTRY_POINTS_COUNT,
 782         },
 783         [BLK_IDX_L2_LOOKUP] = {
 784                 .packing = sja1105et_l2_lookup_entry_packing,
 785                 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_entry),
 786                 .packed_entry_size = SJA1105ET_SIZE_L2_LOOKUP_ENTRY,
 787                 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
 788         },
 789         [BLK_IDX_L2_POLICING] = {
 790                 .packing = sja1105_l2_policing_entry_packing,
 791                 .unpacked_entry_size = sizeof(struct sja1105_l2_policing_entry),
 792                 .packed_entry_size = SJA1105_SIZE_L2_POLICING_ENTRY,
 793                 .max_entry_count = SJA1105_MAX_L2_POLICING_COUNT,
 794         },
 795         [BLK_IDX_VLAN_LOOKUP] = {
 796                 .packing = sja1105_vlan_lookup_entry_packing,
 797                 .unpacked_entry_size = sizeof(struct sja1105_vlan_lookup_entry),
 798                 .packed_entry_size = SJA1105_SIZE_VLAN_LOOKUP_ENTRY,
 799                 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
 800         },
 801         [BLK_IDX_L2_FORWARDING] = {
 802                 .packing = sja1105_l2_forwarding_entry_packing,
 803                 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_entry),
 804                 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_ENTRY,
 805                 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
 806         },
 807         [BLK_IDX_MAC_CONFIG] = {
 808                 .packing = sja1105et_mac_config_entry_packing,
 809                 .unpacked_entry_size = sizeof(struct sja1105_mac_config_entry),
 810                 .packed_entry_size = SJA1105ET_SIZE_MAC_CONFIG_ENTRY,
 811                 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
 812         },
 813         [BLK_IDX_SCHEDULE_PARAMS] = {
 814                 .packing = sja1105_schedule_params_entry_packing,
 815                 .unpacked_entry_size = sizeof(struct sja1105_schedule_params_entry),
 816                 .packed_entry_size = SJA1105_SIZE_SCHEDULE_PARAMS_ENTRY,
 817                 .max_entry_count = SJA1105_MAX_SCHEDULE_PARAMS_COUNT,
 818         },
 819         [BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS] = {
 820                 .packing = sja1105_schedule_entry_points_params_entry_packing,
 821                 .unpacked_entry_size = sizeof(struct sja1105_schedule_entry_points_params_entry),
 822                 .packed_entry_size = SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_PARAMS_ENTRY,
 823                 .max_entry_count = SJA1105_MAX_SCHEDULE_ENTRY_POINTS_PARAMS_COUNT,
 824         },
 825         [BLK_IDX_L2_LOOKUP_PARAMS] = {
 826                 .packing = sja1105et_l2_lookup_params_entry_packing,
 827                 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_params_entry),
 828                 .packed_entry_size = SJA1105ET_SIZE_L2_LOOKUP_PARAMS_ENTRY,
 829                 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
 830         },
 831         [BLK_IDX_L2_FORWARDING_PARAMS] = {
 832                 .packing = sja1105_l2_forwarding_params_entry_packing,
 833                 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_params_entry),
 834                 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY,
 835                 .max_entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT,
 836         },
 837         [BLK_IDX_AVB_PARAMS] = {
 838                 .packing = sja1105et_avb_params_entry_packing,
 839                 .unpacked_entry_size = sizeof(struct sja1105_avb_params_entry),
 840                 .packed_entry_size = SJA1105ET_SIZE_AVB_PARAMS_ENTRY,
 841                 .max_entry_count = SJA1105_MAX_AVB_PARAMS_COUNT,
 842         },
 843         [BLK_IDX_GENERAL_PARAMS] = {
 844                 .packing = sja1105et_general_params_entry_packing,
 845                 .unpacked_entry_size = sizeof(struct sja1105_general_params_entry),
 846                 .packed_entry_size = SJA1105ET_SIZE_GENERAL_PARAMS_ENTRY,
 847                 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
 848         },
 849         [BLK_IDX_XMII_PARAMS] = {
 850                 .packing = sja1105_xmii_params_entry_packing,
 851                 .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry),
 852                 .packed_entry_size = SJA1105_SIZE_XMII_PARAMS_ENTRY,
 853                 .max_entry_count = SJA1105_MAX_XMII_PARAMS_COUNT,
 854         },
 855 };
 856 
 857 /* SJA1105P: Second generation, no TTEthernet, no SGMII */
 858 struct sja1105_table_ops sja1105p_table_ops[BLK_IDX_MAX] = {
 859         [BLK_IDX_SCHEDULE] = {0},
 860         [BLK_IDX_SCHEDULE_ENTRY_POINTS] = {0},
 861         [BLK_IDX_L2_LOOKUP] = {
 862                 .packing = sja1105pqrs_l2_lookup_entry_packing,
 863                 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_entry),
 864                 .packed_entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY,
 865                 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
 866         },
 867         [BLK_IDX_L2_POLICING] = {
 868                 .packing = sja1105_l2_policing_entry_packing,
 869                 .unpacked_entry_size = sizeof(struct sja1105_l2_policing_entry),
 870                 .packed_entry_size = SJA1105_SIZE_L2_POLICING_ENTRY,
 871                 .max_entry_count = SJA1105_MAX_L2_POLICING_COUNT,
 872         },
 873         [BLK_IDX_VLAN_LOOKUP] = {
 874                 .packing = sja1105_vlan_lookup_entry_packing,
 875                 .unpacked_entry_size = sizeof(struct sja1105_vlan_lookup_entry),
 876                 .packed_entry_size = SJA1105_SIZE_VLAN_LOOKUP_ENTRY,
 877                 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
 878         },
 879         [BLK_IDX_L2_FORWARDING] = {
 880                 .packing = sja1105_l2_forwarding_entry_packing,
 881                 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_entry),
 882                 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_ENTRY,
 883                 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
 884         },
 885         [BLK_IDX_MAC_CONFIG] = {
 886                 .packing = sja1105pqrs_mac_config_entry_packing,
 887                 .unpacked_entry_size = sizeof(struct sja1105_mac_config_entry),
 888                 .packed_entry_size = SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY,
 889                 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
 890         },
 891         [BLK_IDX_SCHEDULE_PARAMS] = {0},
 892         [BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS] = {0},
 893         [BLK_IDX_L2_LOOKUP_PARAMS] = {
 894                 .packing = sja1105pqrs_l2_lookup_params_entry_packing,
 895                 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_params_entry),
 896                 .packed_entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY,
 897                 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
 898         },
 899         [BLK_IDX_L2_FORWARDING_PARAMS] = {
 900                 .packing = sja1105_l2_forwarding_params_entry_packing,
 901                 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_params_entry),
 902                 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY,
 903                 .max_entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT,
 904         },
 905         [BLK_IDX_AVB_PARAMS] = {
 906                 .packing = sja1105pqrs_avb_params_entry_packing,
 907                 .unpacked_entry_size = sizeof(struct sja1105_avb_params_entry),
 908                 .packed_entry_size = SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY,
 909                 .max_entry_count = SJA1105_MAX_AVB_PARAMS_COUNT,
 910         },
 911         [BLK_IDX_GENERAL_PARAMS] = {
 912                 .packing = sja1105pqrs_general_params_entry_packing,
 913                 .unpacked_entry_size = sizeof(struct sja1105_general_params_entry),
 914                 .packed_entry_size = SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY,
 915                 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
 916         },
 917         [BLK_IDX_XMII_PARAMS] = {
 918                 .packing = sja1105_xmii_params_entry_packing,
 919                 .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry),
 920                 .packed_entry_size = SJA1105_SIZE_XMII_PARAMS_ENTRY,
 921                 .max_entry_count = SJA1105_MAX_XMII_PARAMS_COUNT,
 922         },
 923 };
 924 
 925 /* SJA1105Q: Second generation, TTEthernet, no SGMII */
 926 struct sja1105_table_ops sja1105q_table_ops[BLK_IDX_MAX] = {
 927         [BLK_IDX_SCHEDULE] = {
 928                 .packing = sja1105_schedule_entry_packing,
 929                 .unpacked_entry_size = sizeof(struct sja1105_schedule_entry),
 930                 .packed_entry_size = SJA1105_SIZE_SCHEDULE_ENTRY,
 931                 .max_entry_count = SJA1105_MAX_SCHEDULE_COUNT,
 932         },
 933         [BLK_IDX_SCHEDULE_ENTRY_POINTS] = {
 934                 .packing = sja1105_schedule_entry_points_entry_packing,
 935                 .unpacked_entry_size = sizeof(struct sja1105_schedule_entry_points_entry),
 936                 .packed_entry_size = SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_ENTRY,
 937                 .max_entry_count = SJA1105_MAX_SCHEDULE_ENTRY_POINTS_COUNT,
 938         },
 939         [BLK_IDX_L2_LOOKUP] = {
 940                 .packing = sja1105pqrs_l2_lookup_entry_packing,
 941                 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_entry),
 942                 .packed_entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY,
 943                 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
 944         },
 945         [BLK_IDX_L2_POLICING] = {
 946                 .packing = sja1105_l2_policing_entry_packing,
 947                 .unpacked_entry_size = sizeof(struct sja1105_l2_policing_entry),
 948                 .packed_entry_size = SJA1105_SIZE_L2_POLICING_ENTRY,
 949                 .max_entry_count = SJA1105_MAX_L2_POLICING_COUNT,
 950         },
 951         [BLK_IDX_VLAN_LOOKUP] = {
 952                 .packing = sja1105_vlan_lookup_entry_packing,
 953                 .unpacked_entry_size = sizeof(struct sja1105_vlan_lookup_entry),
 954                 .packed_entry_size = SJA1105_SIZE_VLAN_LOOKUP_ENTRY,
 955                 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
 956         },
 957         [BLK_IDX_L2_FORWARDING] = {
 958                 .packing = sja1105_l2_forwarding_entry_packing,
 959                 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_entry),
 960                 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_ENTRY,
 961                 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
 962         },
 963         [BLK_IDX_MAC_CONFIG] = {
 964                 .packing = sja1105pqrs_mac_config_entry_packing,
 965                 .unpacked_entry_size = sizeof(struct sja1105_mac_config_entry),
 966                 .packed_entry_size = SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY,
 967                 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
 968         },
 969         [BLK_IDX_SCHEDULE_PARAMS] = {
 970                 .packing = sja1105_schedule_params_entry_packing,
 971                 .unpacked_entry_size = sizeof(struct sja1105_schedule_params_entry),
 972                 .packed_entry_size = SJA1105_SIZE_SCHEDULE_PARAMS_ENTRY,
 973                 .max_entry_count = SJA1105_MAX_SCHEDULE_PARAMS_COUNT,
 974         },
 975         [BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS] = {
 976                 .packing = sja1105_schedule_entry_points_params_entry_packing,
 977                 .unpacked_entry_size = sizeof(struct sja1105_schedule_entry_points_params_entry),
 978                 .packed_entry_size = SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_PARAMS_ENTRY,
 979                 .max_entry_count = SJA1105_MAX_SCHEDULE_ENTRY_POINTS_PARAMS_COUNT,
 980         },
 981         [BLK_IDX_L2_LOOKUP_PARAMS] = {
 982                 .packing = sja1105pqrs_l2_lookup_params_entry_packing,
 983                 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_params_entry),
 984                 .packed_entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY,
 985                 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
 986         },
 987         [BLK_IDX_L2_FORWARDING_PARAMS] = {
 988                 .packing = sja1105_l2_forwarding_params_entry_packing,
 989                 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_params_entry),
 990                 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY,
 991                 .max_entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT,
 992         },
 993         [BLK_IDX_AVB_PARAMS] = {
 994                 .packing = sja1105pqrs_avb_params_entry_packing,
 995                 .unpacked_entry_size = sizeof(struct sja1105_avb_params_entry),
 996                 .packed_entry_size = SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY,
 997                 .max_entry_count = SJA1105_MAX_AVB_PARAMS_COUNT,
 998         },
 999         [BLK_IDX_GENERAL_PARAMS] = {
1000                 .packing = sja1105pqrs_general_params_entry_packing,
1001                 .unpacked_entry_size = sizeof(struct sja1105_general_params_entry),
1002                 .packed_entry_size = SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY,
1003                 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
1004         },
1005         [BLK_IDX_XMII_PARAMS] = {
1006                 .packing = sja1105_xmii_params_entry_packing,
1007                 .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry),
1008                 .packed_entry_size = SJA1105_SIZE_XMII_PARAMS_ENTRY,
1009                 .max_entry_count = SJA1105_MAX_XMII_PARAMS_COUNT,
1010         },
1011 };
1012 
1013 /* SJA1105R: Second generation, no TTEthernet, SGMII */
1014 struct sja1105_table_ops sja1105r_table_ops[BLK_IDX_MAX] = {
1015         [BLK_IDX_SCHEDULE] = {0},
1016         [BLK_IDX_SCHEDULE_ENTRY_POINTS] = {0},
1017         [BLK_IDX_L2_LOOKUP] = {
1018                 .packing = sja1105pqrs_l2_lookup_entry_packing,
1019                 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_entry),
1020                 .packed_entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY,
1021                 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
1022         },
1023         [BLK_IDX_L2_POLICING] = {
1024                 .packing = sja1105_l2_policing_entry_packing,
1025                 .unpacked_entry_size = sizeof(struct sja1105_l2_policing_entry),
1026                 .packed_entry_size = SJA1105_SIZE_L2_POLICING_ENTRY,
1027                 .max_entry_count = SJA1105_MAX_L2_POLICING_COUNT,
1028         },
1029         [BLK_IDX_VLAN_LOOKUP] = {
1030                 .packing = sja1105_vlan_lookup_entry_packing,
1031                 .unpacked_entry_size = sizeof(struct sja1105_vlan_lookup_entry),
1032                 .packed_entry_size = SJA1105_SIZE_VLAN_LOOKUP_ENTRY,
1033                 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
1034         },
1035         [BLK_IDX_L2_FORWARDING] = {
1036                 .packing = sja1105_l2_forwarding_entry_packing,
1037                 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_entry),
1038                 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_ENTRY,
1039                 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
1040         },
1041         [BLK_IDX_MAC_CONFIG] = {
1042                 .packing = sja1105pqrs_mac_config_entry_packing,
1043                 .unpacked_entry_size = sizeof(struct sja1105_mac_config_entry),
1044                 .packed_entry_size = SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY,
1045                 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
1046         },
1047         [BLK_IDX_SCHEDULE_PARAMS] = {0},
1048         [BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS] = {0},
1049         [BLK_IDX_L2_LOOKUP_PARAMS] = {
1050                 .packing = sja1105pqrs_l2_lookup_params_entry_packing,
1051                 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_params_entry),
1052                 .packed_entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY,
1053                 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
1054         },
1055         [BLK_IDX_L2_FORWARDING_PARAMS] = {
1056                 .packing = sja1105_l2_forwarding_params_entry_packing,
1057                 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_params_entry),
1058                 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY,
1059                 .max_entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT,
1060         },
1061         [BLK_IDX_AVB_PARAMS] = {
1062                 .packing = sja1105pqrs_avb_params_entry_packing,
1063                 .unpacked_entry_size = sizeof(struct sja1105_avb_params_entry),
1064                 .packed_entry_size = SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY,
1065                 .max_entry_count = SJA1105_MAX_AVB_PARAMS_COUNT,
1066         },
1067         [BLK_IDX_GENERAL_PARAMS] = {
1068                 .packing = sja1105pqrs_general_params_entry_packing,
1069                 .unpacked_entry_size = sizeof(struct sja1105_general_params_entry),
1070                 .packed_entry_size = SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY,
1071                 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
1072         },
1073         [BLK_IDX_XMII_PARAMS] = {
1074                 .packing = sja1105_xmii_params_entry_packing,
1075                 .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry),
1076                 .packed_entry_size = SJA1105_SIZE_XMII_PARAMS_ENTRY,
1077                 .max_entry_count = SJA1105_MAX_XMII_PARAMS_COUNT,
1078         },
1079 };
1080 
1081 /* SJA1105S: Second generation, TTEthernet, SGMII */
1082 struct sja1105_table_ops sja1105s_table_ops[BLK_IDX_MAX] = {
1083         [BLK_IDX_SCHEDULE] = {
1084                 .packing = sja1105_schedule_entry_packing,
1085                 .unpacked_entry_size = sizeof(struct sja1105_schedule_entry),
1086                 .packed_entry_size = SJA1105_SIZE_SCHEDULE_ENTRY,
1087                 .max_entry_count = SJA1105_MAX_SCHEDULE_COUNT,
1088         },
1089         [BLK_IDX_SCHEDULE_ENTRY_POINTS] = {
1090                 .packing = sja1105_schedule_entry_points_entry_packing,
1091                 .unpacked_entry_size = sizeof(struct sja1105_schedule_entry_points_entry),
1092                 .packed_entry_size = SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_ENTRY,
1093                 .max_entry_count = SJA1105_MAX_SCHEDULE_ENTRY_POINTS_COUNT,
1094         },
1095         [BLK_IDX_L2_LOOKUP] = {
1096                 .packing = sja1105pqrs_l2_lookup_entry_packing,
1097                 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_entry),
1098                 .packed_entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY,
1099                 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
1100         },
1101         [BLK_IDX_L2_POLICING] = {
1102                 .packing = sja1105_l2_policing_entry_packing,
1103                 .unpacked_entry_size = sizeof(struct sja1105_l2_policing_entry),
1104                 .packed_entry_size = SJA1105_SIZE_L2_POLICING_ENTRY,
1105                 .max_entry_count = SJA1105_MAX_L2_POLICING_COUNT,
1106         },
1107         [BLK_IDX_VLAN_LOOKUP] = {
1108                 .packing = sja1105_vlan_lookup_entry_packing,
1109                 .unpacked_entry_size = sizeof(struct sja1105_vlan_lookup_entry),
1110                 .packed_entry_size = SJA1105_SIZE_VLAN_LOOKUP_ENTRY,
1111                 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
1112         },
1113         [BLK_IDX_L2_FORWARDING] = {
1114                 .packing = sja1105_l2_forwarding_entry_packing,
1115                 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_entry),
1116                 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_ENTRY,
1117                 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
1118         },
1119         [BLK_IDX_MAC_CONFIG] = {
1120                 .packing = sja1105pqrs_mac_config_entry_packing,
1121                 .unpacked_entry_size = sizeof(struct sja1105_mac_config_entry),
1122                 .packed_entry_size = SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY,
1123                 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
1124         },
1125         [BLK_IDX_SCHEDULE_PARAMS] = {
1126                 .packing = sja1105_schedule_params_entry_packing,
1127                 .unpacked_entry_size = sizeof(struct sja1105_schedule_params_entry),
1128                 .packed_entry_size = SJA1105_SIZE_SCHEDULE_PARAMS_ENTRY,
1129                 .max_entry_count = SJA1105_MAX_SCHEDULE_PARAMS_COUNT,
1130         },
1131         [BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS] = {
1132                 .packing = sja1105_schedule_entry_points_params_entry_packing,
1133                 .unpacked_entry_size = sizeof(struct sja1105_schedule_entry_points_params_entry),
1134                 .packed_entry_size = SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_PARAMS_ENTRY,
1135                 .max_entry_count = SJA1105_MAX_SCHEDULE_ENTRY_POINTS_PARAMS_COUNT,
1136         },
1137         [BLK_IDX_L2_LOOKUP_PARAMS] = {
1138                 .packing = sja1105pqrs_l2_lookup_params_entry_packing,
1139                 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_params_entry),
1140                 .packed_entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY,
1141                 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
1142         },
1143         [BLK_IDX_L2_FORWARDING_PARAMS] = {
1144                 .packing = sja1105_l2_forwarding_params_entry_packing,
1145                 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_params_entry),
1146                 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY,
1147                 .max_entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT,
1148         },
1149         [BLK_IDX_AVB_PARAMS] = {
1150                 .packing = sja1105pqrs_avb_params_entry_packing,
1151                 .unpacked_entry_size = sizeof(struct sja1105_avb_params_entry),
1152                 .packed_entry_size = SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY,
1153                 .max_entry_count = SJA1105_MAX_AVB_PARAMS_COUNT,
1154         },
1155         [BLK_IDX_GENERAL_PARAMS] = {
1156                 .packing = sja1105pqrs_general_params_entry_packing,
1157                 .unpacked_entry_size = sizeof(struct sja1105_general_params_entry),
1158                 .packed_entry_size = SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY,
1159                 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
1160         },
1161         [BLK_IDX_XMII_PARAMS] = {
1162                 .packing = sja1105_xmii_params_entry_packing,
1163                 .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry),
1164                 .packed_entry_size = SJA1105_SIZE_XMII_PARAMS_ENTRY,
1165                 .max_entry_count = SJA1105_MAX_XMII_PARAMS_COUNT,
1166         },
1167 };
1168 
1169 int sja1105_static_config_init(struct sja1105_static_config *config,
1170                                const struct sja1105_table_ops *static_ops,
1171                                u64 device_id)
1172 {
1173         enum sja1105_blk_idx i;
1174 
1175         *config = (struct sja1105_static_config) {0};
1176 
1177         /* Transfer static_ops array from priv into per-table ops
1178          * for handier access
1179          */
1180         for (i = 0; i < BLK_IDX_MAX; i++)
1181                 config->tables[i].ops = &static_ops[i];
1182 
1183         config->device_id = device_id;
1184         return 0;
1185 }
1186 
1187 void sja1105_static_config_free(struct sja1105_static_config *config)
1188 {
1189         enum sja1105_blk_idx i;
1190 
1191         for (i = 0; i < BLK_IDX_MAX; i++) {
1192                 if (config->tables[i].entry_count) {
1193                         kfree(config->tables[i].entries);
1194                         config->tables[i].entry_count = 0;
1195                 }
1196         }
1197 }
1198 
1199 int sja1105_table_delete_entry(struct sja1105_table *table, int i)
1200 {
1201         size_t entry_size = table->ops->unpacked_entry_size;
1202         u8 *entries = table->entries;
1203 
1204         if (i > table->entry_count)
1205                 return -ERANGE;
1206 
1207         memmove(entries + i * entry_size, entries + (i + 1) * entry_size,
1208                 (table->entry_count - i) * entry_size);
1209 
1210         table->entry_count--;
1211 
1212         return 0;
1213 }
1214 
1215 /* No pointers to table->entries should be kept when this is called. */
1216 int sja1105_table_resize(struct sja1105_table *table, size_t new_count)
1217 {
1218         size_t entry_size = table->ops->unpacked_entry_size;
1219         void *new_entries, *old_entries = table->entries;
1220 
1221         if (new_count > table->ops->max_entry_count)
1222                 return -ERANGE;
1223 
1224         new_entries = kcalloc(new_count, entry_size, GFP_KERNEL);
1225         if (!new_entries)
1226                 return -ENOMEM;
1227 
1228         memcpy(new_entries, old_entries, min(new_count, table->entry_count) *
1229                 entry_size);
1230 
1231         table->entries = new_entries;
1232         table->entry_count = new_count;
1233         kfree(old_entries);
1234         return 0;
1235 }

/* [<][>][^][v][top][bottom][index][help] */