1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 /* Copyright (c) 2015-2018 Mellanox Technologies. All rights reserved */ 3 4 #include <linux/kernel.h> 5 #include <linux/module.h> 6 #include <linux/device.h> 7 #include <linux/export.h> 8 #include <linux/err.h> 9 #include <linux/if_link.h> 10 #include <linux/netdevice.h> 11 #include <linux/completion.h> 12 #include <linux/skbuff.h> 13 #include <linux/etherdevice.h> 14 #include <linux/types.h> 15 #include <linux/string.h> 16 #include <linux/gfp.h> 17 #include <linux/random.h> 18 #include <linux/jiffies.h> 19 #include <linux/mutex.h> 20 #include <linux/rcupdate.h> 21 #include <linux/slab.h> 22 #include <linux/workqueue.h> 23 #include <linux/firmware.h> 24 #include <asm/byteorder.h> 25 #include <net/devlink.h> 26 #include <trace/events/devlink.h> 27 28 #include "core.h" 29 #include "core_env.h" 30 #include "item.h" 31 #include "cmd.h" 32 #include "port.h" 33 #include "trap.h" 34 #include "emad.h" 35 #include "reg.h" 36 #include "resources.h" 37 #include "../mlxfw/mlxfw.h" 38 39 static LIST_HEAD(mlxsw_core_driver_list); 40 static DEFINE_SPINLOCK(mlxsw_core_driver_list_lock); 41 42 static const char mlxsw_core_driver_name[] = "mlxsw_core"; 43 44 static struct workqueue_struct *mlxsw_wq; 45 static struct workqueue_struct *mlxsw_owq; 46 47 struct mlxsw_core_port { 48 struct devlink_port devlink_port; 49 void *port_driver_priv; 50 u16 local_port; 51 }; 52 53 void *mlxsw_core_port_driver_priv(struct mlxsw_core_port *mlxsw_core_port) 54 { 55 return mlxsw_core_port->port_driver_priv; 56 } 57 EXPORT_SYMBOL(mlxsw_core_port_driver_priv); 58 59 static bool mlxsw_core_port_check(struct mlxsw_core_port *mlxsw_core_port) 60 { 61 return mlxsw_core_port->port_driver_priv != NULL; 62 } 63 64 struct mlxsw_core { 65 struct mlxsw_driver *driver; 66 const struct mlxsw_bus *bus; 67 void *bus_priv; 68 const struct mlxsw_bus_info *bus_info; 69 struct workqueue_struct *emad_wq; 70 struct list_head rx_listener_list; 71 struct list_head event_listener_list; 72 struct { 73 atomic64_t tid; 74 struct list_head trans_list; 75 spinlock_t trans_list_lock; /* protects trans_list writes */ 76 bool use_emad; 77 bool enable_string_tlv; 78 } emad; 79 struct { 80 u16 *mapping; /* lag_id+port_index to local_port mapping */ 81 } lag; 82 struct mlxsw_res res; 83 struct mlxsw_hwmon *hwmon; 84 struct mlxsw_thermal *thermal; 85 struct mlxsw_core_port *ports; 86 unsigned int max_ports; 87 atomic_t active_ports_count; 88 bool fw_flash_in_progress; 89 struct { 90 struct devlink_health_reporter *fw_fatal; 91 } health; 92 struct mlxsw_env *env; 93 unsigned long driver_priv[]; 94 /* driver_priv has to be always the last item */ 95 }; 96 97 #define MLXSW_PORT_MAX_PORTS_DEFAULT 0x40 98 99 static u64 mlxsw_ports_occ_get(void *priv) 100 { 101 struct mlxsw_core *mlxsw_core = priv; 102 103 return atomic_read(&mlxsw_core->active_ports_count); 104 } 105 106 static int mlxsw_core_resources_ports_register(struct mlxsw_core *mlxsw_core) 107 { 108 struct devlink *devlink = priv_to_devlink(mlxsw_core); 109 struct devlink_resource_size_params ports_num_params; 110 u32 max_ports; 111 112 max_ports = mlxsw_core->max_ports - 1; 113 devlink_resource_size_params_init(&ports_num_params, max_ports, 114 max_ports, 1, 115 DEVLINK_RESOURCE_UNIT_ENTRY); 116 117 return devlink_resource_register(devlink, 118 DEVLINK_RESOURCE_GENERIC_NAME_PORTS, 119 max_ports, MLXSW_CORE_RESOURCE_PORTS, 120 DEVLINK_RESOURCE_ID_PARENT_TOP, 121 &ports_num_params); 122 } 123 124 static int mlxsw_ports_init(struct mlxsw_core *mlxsw_core, bool reload) 125 { 126 struct devlink *devlink = priv_to_devlink(mlxsw_core); 127 int err; 128 129 /* Switch ports are numbered from 1 to queried value */ 130 if (MLXSW_CORE_RES_VALID(mlxsw_core, MAX_SYSTEM_PORT)) 131 mlxsw_core->max_ports = MLXSW_CORE_RES_GET(mlxsw_core, 132 MAX_SYSTEM_PORT) + 1; 133 else 134 mlxsw_core->max_ports = MLXSW_PORT_MAX_PORTS_DEFAULT + 1; 135 136 mlxsw_core->ports = kcalloc(mlxsw_core->max_ports, 137 sizeof(struct mlxsw_core_port), GFP_KERNEL); 138 if (!mlxsw_core->ports) 139 return -ENOMEM; 140 141 if (!reload) { 142 err = mlxsw_core_resources_ports_register(mlxsw_core); 143 if (err) 144 goto err_resources_ports_register; 145 } 146 atomic_set(&mlxsw_core->active_ports_count, 0); 147 devlink_resource_occ_get_register(devlink, MLXSW_CORE_RESOURCE_PORTS, 148 mlxsw_ports_occ_get, mlxsw_core); 149 150 return 0; 151 152 err_resources_ports_register: 153 kfree(mlxsw_core->ports); 154 return err; 155 } 156 157 static void mlxsw_ports_fini(struct mlxsw_core *mlxsw_core, bool reload) 158 { 159 struct devlink *devlink = priv_to_devlink(mlxsw_core); 160 161 devlink_resource_occ_get_unregister(devlink, MLXSW_CORE_RESOURCE_PORTS); 162 if (!reload) 163 devlink_resources_unregister(priv_to_devlink(mlxsw_core)); 164 165 kfree(mlxsw_core->ports); 166 } 167 168 unsigned int mlxsw_core_max_ports(const struct mlxsw_core *mlxsw_core) 169 { 170 return mlxsw_core->max_ports; 171 } 172 EXPORT_SYMBOL(mlxsw_core_max_ports); 173 174 void *mlxsw_core_driver_priv(struct mlxsw_core *mlxsw_core) 175 { 176 return mlxsw_core->driver_priv; 177 } 178 EXPORT_SYMBOL(mlxsw_core_driver_priv); 179 180 bool 181 mlxsw_core_fw_rev_minor_subminor_validate(const struct mlxsw_fw_rev *rev, 182 const struct mlxsw_fw_rev *req_rev) 183 { 184 return rev->minor > req_rev->minor || 185 (rev->minor == req_rev->minor && 186 rev->subminor >= req_rev->subminor); 187 } 188 EXPORT_SYMBOL(mlxsw_core_fw_rev_minor_subminor_validate); 189 190 struct mlxsw_rx_listener_item { 191 struct list_head list; 192 struct mlxsw_rx_listener rxl; 193 void *priv; 194 bool enabled; 195 }; 196 197 struct mlxsw_event_listener_item { 198 struct list_head list; 199 struct mlxsw_core *mlxsw_core; 200 struct mlxsw_event_listener el; 201 void *priv; 202 }; 203 204 static const u8 mlxsw_core_trap_groups[] = { 205 MLXSW_REG_HTGT_TRAP_GROUP_EMAD, 206 MLXSW_REG_HTGT_TRAP_GROUP_CORE_EVENT, 207 }; 208 209 static int mlxsw_core_trap_groups_set(struct mlxsw_core *mlxsw_core) 210 { 211 char htgt_pl[MLXSW_REG_HTGT_LEN]; 212 int err; 213 int i; 214 215 if (!(mlxsw_core->bus->features & MLXSW_BUS_F_TXRX)) 216 return 0; 217 218 for (i = 0; i < ARRAY_SIZE(mlxsw_core_trap_groups); i++) { 219 mlxsw_reg_htgt_pack(htgt_pl, mlxsw_core_trap_groups[i], 220 MLXSW_REG_HTGT_INVALID_POLICER, 221 MLXSW_REG_HTGT_DEFAULT_PRIORITY, 222 MLXSW_REG_HTGT_DEFAULT_TC); 223 err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl); 224 if (err) 225 return err; 226 } 227 return 0; 228 } 229 230 /****************** 231 * EMAD processing 232 ******************/ 233 234 /* emad_eth_hdr_dmac 235 * Destination MAC in EMAD's Ethernet header. 236 * Must be set to 01:02:c9:00:00:01 237 */ 238 MLXSW_ITEM_BUF(emad, eth_hdr, dmac, 0x00, 6); 239 240 /* emad_eth_hdr_smac 241 * Source MAC in EMAD's Ethernet header. 242 * Must be set to 00:02:c9:01:02:03 243 */ 244 MLXSW_ITEM_BUF(emad, eth_hdr, smac, 0x06, 6); 245 246 /* emad_eth_hdr_ethertype 247 * Ethertype in EMAD's Ethernet header. 248 * Must be set to 0x8932 249 */ 250 MLXSW_ITEM32(emad, eth_hdr, ethertype, 0x0C, 16, 16); 251 252 /* emad_eth_hdr_mlx_proto 253 * Mellanox protocol. 254 * Must be set to 0x0. 255 */ 256 MLXSW_ITEM32(emad, eth_hdr, mlx_proto, 0x0C, 8, 8); 257 258 /* emad_eth_hdr_ver 259 * Mellanox protocol version. 260 * Must be set to 0x0. 261 */ 262 MLXSW_ITEM32(emad, eth_hdr, ver, 0x0C, 4, 4); 263 264 /* emad_op_tlv_type 265 * Type of the TLV. 266 * Must be set to 0x1 (operation TLV). 267 */ 268 MLXSW_ITEM32(emad, op_tlv, type, 0x00, 27, 5); 269 270 /* emad_op_tlv_len 271 * Length of the operation TLV in u32. 272 * Must be set to 0x4. 273 */ 274 MLXSW_ITEM32(emad, op_tlv, len, 0x00, 16, 11); 275 276 /* emad_op_tlv_dr 277 * Direct route bit. Setting to 1 indicates the EMAD is a direct route 278 * EMAD. DR TLV must follow. 279 * 280 * Note: Currently not supported and must not be set. 281 */ 282 MLXSW_ITEM32(emad, op_tlv, dr, 0x00, 15, 1); 283 284 /* emad_op_tlv_status 285 * Returned status in case of EMAD response. Must be set to 0 in case 286 * of EMAD request. 287 * 0x0 - success 288 * 0x1 - device is busy. Requester should retry 289 * 0x2 - Mellanox protocol version not supported 290 * 0x3 - unknown TLV 291 * 0x4 - register not supported 292 * 0x5 - operation class not supported 293 * 0x6 - EMAD method not supported 294 * 0x7 - bad parameter (e.g. port out of range) 295 * 0x8 - resource not available 296 * 0x9 - message receipt acknowledgment. Requester should retry 297 * 0x70 - internal error 298 */ 299 MLXSW_ITEM32(emad, op_tlv, status, 0x00, 8, 7); 300 301 /* emad_op_tlv_register_id 302 * Register ID of register within register TLV. 303 */ 304 MLXSW_ITEM32(emad, op_tlv, register_id, 0x04, 16, 16); 305 306 /* emad_op_tlv_r 307 * Response bit. Setting to 1 indicates Response, otherwise request. 308 */ 309 MLXSW_ITEM32(emad, op_tlv, r, 0x04, 15, 1); 310 311 /* emad_op_tlv_method 312 * EMAD method type. 313 * 0x1 - query 314 * 0x2 - write 315 * 0x3 - send (currently not supported) 316 * 0x4 - event 317 */ 318 MLXSW_ITEM32(emad, op_tlv, method, 0x04, 8, 7); 319 320 /* emad_op_tlv_class 321 * EMAD operation class. Must be set to 0x1 (REG_ACCESS). 322 */ 323 MLXSW_ITEM32(emad, op_tlv, class, 0x04, 0, 8); 324 325 /* emad_op_tlv_tid 326 * EMAD transaction ID. Used for pairing request and response EMADs. 327 */ 328 MLXSW_ITEM64(emad, op_tlv, tid, 0x08, 0, 64); 329 330 /* emad_string_tlv_type 331 * Type of the TLV. 332 * Must be set to 0x2 (string TLV). 333 */ 334 MLXSW_ITEM32(emad, string_tlv, type, 0x00, 27, 5); 335 336 /* emad_string_tlv_len 337 * Length of the string TLV in u32. 338 */ 339 MLXSW_ITEM32(emad, string_tlv, len, 0x00, 16, 11); 340 341 #define MLXSW_EMAD_STRING_TLV_STRING_LEN 128 342 343 /* emad_string_tlv_string 344 * String provided by the device's firmware in case of erroneous register access 345 */ 346 MLXSW_ITEM_BUF(emad, string_tlv, string, 0x04, 347 MLXSW_EMAD_STRING_TLV_STRING_LEN); 348 349 /* emad_reg_tlv_type 350 * Type of the TLV. 351 * Must be set to 0x3 (register TLV). 352 */ 353 MLXSW_ITEM32(emad, reg_tlv, type, 0x00, 27, 5); 354 355 /* emad_reg_tlv_len 356 * Length of the operation TLV in u32. 357 */ 358 MLXSW_ITEM32(emad, reg_tlv, len, 0x00, 16, 11); 359 360 /* emad_end_tlv_type 361 * Type of the TLV. 362 * Must be set to 0x0 (end TLV). 363 */ 364 MLXSW_ITEM32(emad, end_tlv, type, 0x00, 27, 5); 365 366 /* emad_end_tlv_len 367 * Length of the end TLV in u32. 368 * Must be set to 1. 369 */ 370 MLXSW_ITEM32(emad, end_tlv, len, 0x00, 16, 11); 371 372 enum mlxsw_core_reg_access_type { 373 MLXSW_CORE_REG_ACCESS_TYPE_QUERY, 374 MLXSW_CORE_REG_ACCESS_TYPE_WRITE, 375 }; 376 377 static inline const char * 378 mlxsw_core_reg_access_type_str(enum mlxsw_core_reg_access_type type) 379 { 380 switch (type) { 381 case MLXSW_CORE_REG_ACCESS_TYPE_QUERY: 382 return "query"; 383 case MLXSW_CORE_REG_ACCESS_TYPE_WRITE: 384 return "write"; 385 } 386 BUG(); 387 } 388 389 static void mlxsw_emad_pack_end_tlv(char *end_tlv) 390 { 391 mlxsw_emad_end_tlv_type_set(end_tlv, MLXSW_EMAD_TLV_TYPE_END); 392 mlxsw_emad_end_tlv_len_set(end_tlv, MLXSW_EMAD_END_TLV_LEN); 393 } 394 395 static void mlxsw_emad_pack_reg_tlv(char *reg_tlv, 396 const struct mlxsw_reg_info *reg, 397 char *payload) 398 { 399 mlxsw_emad_reg_tlv_type_set(reg_tlv, MLXSW_EMAD_TLV_TYPE_REG); 400 mlxsw_emad_reg_tlv_len_set(reg_tlv, reg->len / sizeof(u32) + 1); 401 memcpy(reg_tlv + sizeof(u32), payload, reg->len); 402 } 403 404 static void mlxsw_emad_pack_string_tlv(char *string_tlv) 405 { 406 mlxsw_emad_string_tlv_type_set(string_tlv, MLXSW_EMAD_TLV_TYPE_STRING); 407 mlxsw_emad_string_tlv_len_set(string_tlv, MLXSW_EMAD_STRING_TLV_LEN); 408 } 409 410 static void mlxsw_emad_pack_op_tlv(char *op_tlv, 411 const struct mlxsw_reg_info *reg, 412 enum mlxsw_core_reg_access_type type, 413 u64 tid) 414 { 415 mlxsw_emad_op_tlv_type_set(op_tlv, MLXSW_EMAD_TLV_TYPE_OP); 416 mlxsw_emad_op_tlv_len_set(op_tlv, MLXSW_EMAD_OP_TLV_LEN); 417 mlxsw_emad_op_tlv_dr_set(op_tlv, 0); 418 mlxsw_emad_op_tlv_status_set(op_tlv, 0); 419 mlxsw_emad_op_tlv_register_id_set(op_tlv, reg->id); 420 mlxsw_emad_op_tlv_r_set(op_tlv, MLXSW_EMAD_OP_TLV_REQUEST); 421 if (type == MLXSW_CORE_REG_ACCESS_TYPE_QUERY) 422 mlxsw_emad_op_tlv_method_set(op_tlv, 423 MLXSW_EMAD_OP_TLV_METHOD_QUERY); 424 else 425 mlxsw_emad_op_tlv_method_set(op_tlv, 426 MLXSW_EMAD_OP_TLV_METHOD_WRITE); 427 mlxsw_emad_op_tlv_class_set(op_tlv, 428 MLXSW_EMAD_OP_TLV_CLASS_REG_ACCESS); 429 mlxsw_emad_op_tlv_tid_set(op_tlv, tid); 430 } 431 432 static int mlxsw_emad_construct_eth_hdr(struct sk_buff *skb) 433 { 434 char *eth_hdr = skb_push(skb, MLXSW_EMAD_ETH_HDR_LEN); 435 436 mlxsw_emad_eth_hdr_dmac_memcpy_to(eth_hdr, MLXSW_EMAD_EH_DMAC); 437 mlxsw_emad_eth_hdr_smac_memcpy_to(eth_hdr, MLXSW_EMAD_EH_SMAC); 438 mlxsw_emad_eth_hdr_ethertype_set(eth_hdr, MLXSW_EMAD_EH_ETHERTYPE); 439 mlxsw_emad_eth_hdr_mlx_proto_set(eth_hdr, MLXSW_EMAD_EH_MLX_PROTO); 440 mlxsw_emad_eth_hdr_ver_set(eth_hdr, MLXSW_EMAD_EH_PROTO_VERSION); 441 442 skb_reset_mac_header(skb); 443 444 return 0; 445 } 446 447 static void mlxsw_emad_construct(struct sk_buff *skb, 448 const struct mlxsw_reg_info *reg, 449 char *payload, 450 enum mlxsw_core_reg_access_type type, 451 u64 tid, bool enable_string_tlv) 452 { 453 char *buf; 454 455 buf = skb_push(skb, MLXSW_EMAD_END_TLV_LEN * sizeof(u32)); 456 mlxsw_emad_pack_end_tlv(buf); 457 458 buf = skb_push(skb, reg->len + sizeof(u32)); 459 mlxsw_emad_pack_reg_tlv(buf, reg, payload); 460 461 if (enable_string_tlv) { 462 buf = skb_push(skb, MLXSW_EMAD_STRING_TLV_LEN * sizeof(u32)); 463 mlxsw_emad_pack_string_tlv(buf); 464 } 465 466 buf = skb_push(skb, MLXSW_EMAD_OP_TLV_LEN * sizeof(u32)); 467 mlxsw_emad_pack_op_tlv(buf, reg, type, tid); 468 469 mlxsw_emad_construct_eth_hdr(skb); 470 } 471 472 struct mlxsw_emad_tlv_offsets { 473 u16 op_tlv; 474 u16 string_tlv; 475 u16 reg_tlv; 476 }; 477 478 static bool mlxsw_emad_tlv_is_string_tlv(const char *tlv) 479 { 480 u8 tlv_type = mlxsw_emad_string_tlv_type_get(tlv); 481 482 return tlv_type == MLXSW_EMAD_TLV_TYPE_STRING; 483 } 484 485 static void mlxsw_emad_tlv_parse(struct sk_buff *skb) 486 { 487 struct mlxsw_emad_tlv_offsets *offsets = 488 (struct mlxsw_emad_tlv_offsets *) skb->cb; 489 490 offsets->op_tlv = MLXSW_EMAD_ETH_HDR_LEN; 491 offsets->string_tlv = 0; 492 offsets->reg_tlv = MLXSW_EMAD_ETH_HDR_LEN + 493 MLXSW_EMAD_OP_TLV_LEN * sizeof(u32); 494 495 /* If string TLV is present, it must come after the operation TLV. */ 496 if (mlxsw_emad_tlv_is_string_tlv(skb->data + offsets->reg_tlv)) { 497 offsets->string_tlv = offsets->reg_tlv; 498 offsets->reg_tlv += MLXSW_EMAD_STRING_TLV_LEN * sizeof(u32); 499 } 500 } 501 502 static char *mlxsw_emad_op_tlv(const struct sk_buff *skb) 503 { 504 struct mlxsw_emad_tlv_offsets *offsets = 505 (struct mlxsw_emad_tlv_offsets *) skb->cb; 506 507 return ((char *) (skb->data + offsets->op_tlv)); 508 } 509 510 static char *mlxsw_emad_string_tlv(const struct sk_buff *skb) 511 { 512 struct mlxsw_emad_tlv_offsets *offsets = 513 (struct mlxsw_emad_tlv_offsets *) skb->cb; 514 515 if (!offsets->string_tlv) 516 return NULL; 517 518 return ((char *) (skb->data + offsets->string_tlv)); 519 } 520 521 static char *mlxsw_emad_reg_tlv(const struct sk_buff *skb) 522 { 523 struct mlxsw_emad_tlv_offsets *offsets = 524 (struct mlxsw_emad_tlv_offsets *) skb->cb; 525 526 return ((char *) (skb->data + offsets->reg_tlv)); 527 } 528 529 static char *mlxsw_emad_reg_payload(const char *reg_tlv) 530 { 531 return ((char *) (reg_tlv + sizeof(u32))); 532 } 533 534 static char *mlxsw_emad_reg_payload_cmd(const char *mbox) 535 { 536 return ((char *) (mbox + (MLXSW_EMAD_OP_TLV_LEN + 1) * sizeof(u32))); 537 } 538 539 static u64 mlxsw_emad_get_tid(const struct sk_buff *skb) 540 { 541 char *op_tlv; 542 543 op_tlv = mlxsw_emad_op_tlv(skb); 544 return mlxsw_emad_op_tlv_tid_get(op_tlv); 545 } 546 547 static bool mlxsw_emad_is_resp(const struct sk_buff *skb) 548 { 549 char *op_tlv; 550 551 op_tlv = mlxsw_emad_op_tlv(skb); 552 return (mlxsw_emad_op_tlv_r_get(op_tlv) == MLXSW_EMAD_OP_TLV_RESPONSE); 553 } 554 555 static int mlxsw_emad_process_status(char *op_tlv, 556 enum mlxsw_emad_op_tlv_status *p_status) 557 { 558 *p_status = mlxsw_emad_op_tlv_status_get(op_tlv); 559 560 switch (*p_status) { 561 case MLXSW_EMAD_OP_TLV_STATUS_SUCCESS: 562 return 0; 563 case MLXSW_EMAD_OP_TLV_STATUS_BUSY: 564 case MLXSW_EMAD_OP_TLV_STATUS_MESSAGE_RECEIPT_ACK: 565 return -EAGAIN; 566 case MLXSW_EMAD_OP_TLV_STATUS_VERSION_NOT_SUPPORTED: 567 case MLXSW_EMAD_OP_TLV_STATUS_UNKNOWN_TLV: 568 case MLXSW_EMAD_OP_TLV_STATUS_REGISTER_NOT_SUPPORTED: 569 case MLXSW_EMAD_OP_TLV_STATUS_CLASS_NOT_SUPPORTED: 570 case MLXSW_EMAD_OP_TLV_STATUS_METHOD_NOT_SUPPORTED: 571 case MLXSW_EMAD_OP_TLV_STATUS_BAD_PARAMETER: 572 case MLXSW_EMAD_OP_TLV_STATUS_RESOURCE_NOT_AVAILABLE: 573 case MLXSW_EMAD_OP_TLV_STATUS_INTERNAL_ERROR: 574 default: 575 return -EIO; 576 } 577 } 578 579 static int 580 mlxsw_emad_process_status_skb(struct sk_buff *skb, 581 enum mlxsw_emad_op_tlv_status *p_status) 582 { 583 return mlxsw_emad_process_status(mlxsw_emad_op_tlv(skb), p_status); 584 } 585 586 struct mlxsw_reg_trans { 587 struct list_head list; 588 struct list_head bulk_list; 589 struct mlxsw_core *core; 590 struct sk_buff *tx_skb; 591 struct mlxsw_tx_info tx_info; 592 struct delayed_work timeout_dw; 593 unsigned int retries; 594 u64 tid; 595 struct completion completion; 596 atomic_t active; 597 mlxsw_reg_trans_cb_t *cb; 598 unsigned long cb_priv; 599 const struct mlxsw_reg_info *reg; 600 enum mlxsw_core_reg_access_type type; 601 int err; 602 char *emad_err_string; 603 enum mlxsw_emad_op_tlv_status emad_status; 604 struct rcu_head rcu; 605 }; 606 607 static void mlxsw_emad_process_string_tlv(const struct sk_buff *skb, 608 struct mlxsw_reg_trans *trans) 609 { 610 char *string_tlv; 611 char *string; 612 613 string_tlv = mlxsw_emad_string_tlv(skb); 614 if (!string_tlv) 615 return; 616 617 trans->emad_err_string = kzalloc(MLXSW_EMAD_STRING_TLV_STRING_LEN, 618 GFP_ATOMIC); 619 if (!trans->emad_err_string) 620 return; 621 622 string = mlxsw_emad_string_tlv_string_data(string_tlv); 623 strlcpy(trans->emad_err_string, string, 624 MLXSW_EMAD_STRING_TLV_STRING_LEN); 625 } 626 627 #define MLXSW_EMAD_TIMEOUT_DURING_FW_FLASH_MS 3000 628 #define MLXSW_EMAD_TIMEOUT_MS 200 629 630 static void mlxsw_emad_trans_timeout_schedule(struct mlxsw_reg_trans *trans) 631 { 632 unsigned long timeout = msecs_to_jiffies(MLXSW_EMAD_TIMEOUT_MS); 633 634 if (trans->core->fw_flash_in_progress) 635 timeout = msecs_to_jiffies(MLXSW_EMAD_TIMEOUT_DURING_FW_FLASH_MS); 636 637 queue_delayed_work(trans->core->emad_wq, &trans->timeout_dw, 638 timeout << trans->retries); 639 } 640 641 static int mlxsw_emad_transmit(struct mlxsw_core *mlxsw_core, 642 struct mlxsw_reg_trans *trans) 643 { 644 struct sk_buff *skb; 645 int err; 646 647 skb = skb_clone(trans->tx_skb, GFP_KERNEL); 648 if (!skb) 649 return -ENOMEM; 650 651 trace_devlink_hwmsg(priv_to_devlink(mlxsw_core), false, 0, 652 skb->data + mlxsw_core->driver->txhdr_len, 653 skb->len - mlxsw_core->driver->txhdr_len); 654 655 atomic_set(&trans->active, 1); 656 err = mlxsw_core_skb_transmit(mlxsw_core, skb, &trans->tx_info); 657 if (err) { 658 dev_kfree_skb(skb); 659 return err; 660 } 661 mlxsw_emad_trans_timeout_schedule(trans); 662 return 0; 663 } 664 665 static void mlxsw_emad_trans_finish(struct mlxsw_reg_trans *trans, int err) 666 { 667 struct mlxsw_core *mlxsw_core = trans->core; 668 669 dev_kfree_skb(trans->tx_skb); 670 spin_lock_bh(&mlxsw_core->emad.trans_list_lock); 671 list_del_rcu(&trans->list); 672 spin_unlock_bh(&mlxsw_core->emad.trans_list_lock); 673 trans->err = err; 674 complete(&trans->completion); 675 } 676 677 static void mlxsw_emad_transmit_retry(struct mlxsw_core *mlxsw_core, 678 struct mlxsw_reg_trans *trans) 679 { 680 int err; 681 682 if (trans->retries < MLXSW_EMAD_MAX_RETRY) { 683 trans->retries++; 684 err = mlxsw_emad_transmit(trans->core, trans); 685 if (err == 0) 686 return; 687 688 if (!atomic_dec_and_test(&trans->active)) 689 return; 690 } else { 691 err = -EIO; 692 } 693 mlxsw_emad_trans_finish(trans, err); 694 } 695 696 static void mlxsw_emad_trans_timeout_work(struct work_struct *work) 697 { 698 struct mlxsw_reg_trans *trans = container_of(work, 699 struct mlxsw_reg_trans, 700 timeout_dw.work); 701 702 if (!atomic_dec_and_test(&trans->active)) 703 return; 704 705 mlxsw_emad_transmit_retry(trans->core, trans); 706 } 707 708 static void mlxsw_emad_process_response(struct mlxsw_core *mlxsw_core, 709 struct mlxsw_reg_trans *trans, 710 struct sk_buff *skb) 711 { 712 int err; 713 714 if (!atomic_dec_and_test(&trans->active)) 715 return; 716 717 err = mlxsw_emad_process_status_skb(skb, &trans->emad_status); 718 if (err == -EAGAIN) { 719 mlxsw_emad_transmit_retry(mlxsw_core, trans); 720 } else { 721 if (err == 0) { 722 char *reg_tlv = mlxsw_emad_reg_tlv(skb); 723 724 if (trans->cb) 725 trans->cb(mlxsw_core, 726 mlxsw_emad_reg_payload(reg_tlv), 727 trans->reg->len, trans->cb_priv); 728 } else { 729 mlxsw_emad_process_string_tlv(skb, trans); 730 } 731 mlxsw_emad_trans_finish(trans, err); 732 } 733 } 734 735 /* called with rcu read lock held */ 736 static void mlxsw_emad_rx_listener_func(struct sk_buff *skb, u16 local_port, 737 void *priv) 738 { 739 struct mlxsw_core *mlxsw_core = priv; 740 struct mlxsw_reg_trans *trans; 741 742 trace_devlink_hwmsg(priv_to_devlink(mlxsw_core), true, 0, 743 skb->data, skb->len); 744 745 mlxsw_emad_tlv_parse(skb); 746 747 if (!mlxsw_emad_is_resp(skb)) 748 goto free_skb; 749 750 list_for_each_entry_rcu(trans, &mlxsw_core->emad.trans_list, list) { 751 if (mlxsw_emad_get_tid(skb) == trans->tid) { 752 mlxsw_emad_process_response(mlxsw_core, trans, skb); 753 break; 754 } 755 } 756 757 free_skb: 758 dev_kfree_skb(skb); 759 } 760 761 static const struct mlxsw_listener mlxsw_emad_rx_listener = 762 MLXSW_RXL(mlxsw_emad_rx_listener_func, ETHEMAD, TRAP_TO_CPU, false, 763 EMAD, DISCARD); 764 765 static int mlxsw_emad_init(struct mlxsw_core *mlxsw_core) 766 { 767 struct workqueue_struct *emad_wq; 768 u64 tid; 769 int err; 770 771 if (!(mlxsw_core->bus->features & MLXSW_BUS_F_TXRX)) 772 return 0; 773 774 emad_wq = alloc_workqueue("mlxsw_core_emad", 0, 0); 775 if (!emad_wq) 776 return -ENOMEM; 777 mlxsw_core->emad_wq = emad_wq; 778 779 /* Set the upper 32 bits of the transaction ID field to a random 780 * number. This allows us to discard EMADs addressed to other 781 * devices. 782 */ 783 get_random_bytes(&tid, 4); 784 tid <<= 32; 785 atomic64_set(&mlxsw_core->emad.tid, tid); 786 787 INIT_LIST_HEAD(&mlxsw_core->emad.trans_list); 788 spin_lock_init(&mlxsw_core->emad.trans_list_lock); 789 790 err = mlxsw_core_trap_register(mlxsw_core, &mlxsw_emad_rx_listener, 791 mlxsw_core); 792 if (err) 793 goto err_trap_register; 794 795 mlxsw_core->emad.use_emad = true; 796 797 return 0; 798 799 err_trap_register: 800 destroy_workqueue(mlxsw_core->emad_wq); 801 return err; 802 } 803 804 static void mlxsw_emad_fini(struct mlxsw_core *mlxsw_core) 805 { 806 807 if (!(mlxsw_core->bus->features & MLXSW_BUS_F_TXRX)) 808 return; 809 810 mlxsw_core->emad.use_emad = false; 811 mlxsw_core_trap_unregister(mlxsw_core, &mlxsw_emad_rx_listener, 812 mlxsw_core); 813 destroy_workqueue(mlxsw_core->emad_wq); 814 } 815 816 static struct sk_buff *mlxsw_emad_alloc(const struct mlxsw_core *mlxsw_core, 817 u16 reg_len, bool enable_string_tlv) 818 { 819 struct sk_buff *skb; 820 u16 emad_len; 821 822 emad_len = (reg_len + sizeof(u32) + MLXSW_EMAD_ETH_HDR_LEN + 823 (MLXSW_EMAD_OP_TLV_LEN + MLXSW_EMAD_END_TLV_LEN) * 824 sizeof(u32) + mlxsw_core->driver->txhdr_len); 825 if (enable_string_tlv) 826 emad_len += MLXSW_EMAD_STRING_TLV_LEN * sizeof(u32); 827 if (emad_len > MLXSW_EMAD_MAX_FRAME_LEN) 828 return NULL; 829 830 skb = netdev_alloc_skb(NULL, emad_len); 831 if (!skb) 832 return NULL; 833 memset(skb->data, 0, emad_len); 834 skb_reserve(skb, emad_len); 835 836 return skb; 837 } 838 839 static int mlxsw_emad_reg_access(struct mlxsw_core *mlxsw_core, 840 const struct mlxsw_reg_info *reg, 841 char *payload, 842 enum mlxsw_core_reg_access_type type, 843 struct mlxsw_reg_trans *trans, 844 struct list_head *bulk_list, 845 mlxsw_reg_trans_cb_t *cb, 846 unsigned long cb_priv, u64 tid) 847 { 848 bool enable_string_tlv; 849 struct sk_buff *skb; 850 int err; 851 852 dev_dbg(mlxsw_core->bus_info->dev, "EMAD reg access (tid=%llx,reg_id=%x(%s),type=%s)\n", 853 tid, reg->id, mlxsw_reg_id_str(reg->id), 854 mlxsw_core_reg_access_type_str(type)); 855 856 /* Since this can be changed during emad_reg_access, read it once and 857 * use the value all the way. 858 */ 859 enable_string_tlv = mlxsw_core->emad.enable_string_tlv; 860 861 skb = mlxsw_emad_alloc(mlxsw_core, reg->len, enable_string_tlv); 862 if (!skb) 863 return -ENOMEM; 864 865 list_add_tail(&trans->bulk_list, bulk_list); 866 trans->core = mlxsw_core; 867 trans->tx_skb = skb; 868 trans->tx_info.local_port = MLXSW_PORT_CPU_PORT; 869 trans->tx_info.is_emad = true; 870 INIT_DELAYED_WORK(&trans->timeout_dw, mlxsw_emad_trans_timeout_work); 871 trans->tid = tid; 872 init_completion(&trans->completion); 873 trans->cb = cb; 874 trans->cb_priv = cb_priv; 875 trans->reg = reg; 876 trans->type = type; 877 878 mlxsw_emad_construct(skb, reg, payload, type, trans->tid, 879 enable_string_tlv); 880 mlxsw_core->driver->txhdr_construct(skb, &trans->tx_info); 881 882 spin_lock_bh(&mlxsw_core->emad.trans_list_lock); 883 list_add_tail_rcu(&trans->list, &mlxsw_core->emad.trans_list); 884 spin_unlock_bh(&mlxsw_core->emad.trans_list_lock); 885 err = mlxsw_emad_transmit(mlxsw_core, trans); 886 if (err) 887 goto err_out; 888 return 0; 889 890 err_out: 891 spin_lock_bh(&mlxsw_core->emad.trans_list_lock); 892 list_del_rcu(&trans->list); 893 spin_unlock_bh(&mlxsw_core->emad.trans_list_lock); 894 list_del(&trans->bulk_list); 895 dev_kfree_skb(trans->tx_skb); 896 return err; 897 } 898 899 /***************** 900 * Core functions 901 *****************/ 902 903 int mlxsw_core_driver_register(struct mlxsw_driver *mlxsw_driver) 904 { 905 spin_lock(&mlxsw_core_driver_list_lock); 906 list_add_tail(&mlxsw_driver->list, &mlxsw_core_driver_list); 907 spin_unlock(&mlxsw_core_driver_list_lock); 908 return 0; 909 } 910 EXPORT_SYMBOL(mlxsw_core_driver_register); 911 912 void mlxsw_core_driver_unregister(struct mlxsw_driver *mlxsw_driver) 913 { 914 spin_lock(&mlxsw_core_driver_list_lock); 915 list_del(&mlxsw_driver->list); 916 spin_unlock(&mlxsw_core_driver_list_lock); 917 } 918 EXPORT_SYMBOL(mlxsw_core_driver_unregister); 919 920 static struct mlxsw_driver *__driver_find(const char *kind) 921 { 922 struct mlxsw_driver *mlxsw_driver; 923 924 list_for_each_entry(mlxsw_driver, &mlxsw_core_driver_list, list) { 925 if (strcmp(mlxsw_driver->kind, kind) == 0) 926 return mlxsw_driver; 927 } 928 return NULL; 929 } 930 931 static struct mlxsw_driver *mlxsw_core_driver_get(const char *kind) 932 { 933 struct mlxsw_driver *mlxsw_driver; 934 935 spin_lock(&mlxsw_core_driver_list_lock); 936 mlxsw_driver = __driver_find(kind); 937 spin_unlock(&mlxsw_core_driver_list_lock); 938 return mlxsw_driver; 939 } 940 941 struct mlxsw_core_fw_info { 942 struct mlxfw_dev mlxfw_dev; 943 struct mlxsw_core *mlxsw_core; 944 }; 945 946 static int mlxsw_core_fw_component_query(struct mlxfw_dev *mlxfw_dev, 947 u16 component_index, u32 *p_max_size, 948 u8 *p_align_bits, u16 *p_max_write_size) 949 { 950 struct mlxsw_core_fw_info *mlxsw_core_fw_info = 951 container_of(mlxfw_dev, struct mlxsw_core_fw_info, mlxfw_dev); 952 struct mlxsw_core *mlxsw_core = mlxsw_core_fw_info->mlxsw_core; 953 char mcqi_pl[MLXSW_REG_MCQI_LEN]; 954 int err; 955 956 mlxsw_reg_mcqi_pack(mcqi_pl, component_index); 957 err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mcqi), mcqi_pl); 958 if (err) 959 return err; 960 mlxsw_reg_mcqi_unpack(mcqi_pl, p_max_size, p_align_bits, p_max_write_size); 961 962 *p_align_bits = max_t(u8, *p_align_bits, 2); 963 *p_max_write_size = min_t(u16, *p_max_write_size, MLXSW_REG_MCDA_MAX_DATA_LEN); 964 return 0; 965 } 966 967 static int mlxsw_core_fw_fsm_lock(struct mlxfw_dev *mlxfw_dev, u32 *fwhandle) 968 { 969 struct mlxsw_core_fw_info *mlxsw_core_fw_info = 970 container_of(mlxfw_dev, struct mlxsw_core_fw_info, mlxfw_dev); 971 struct mlxsw_core *mlxsw_core = mlxsw_core_fw_info->mlxsw_core; 972 char mcc_pl[MLXSW_REG_MCC_LEN]; 973 u8 control_state; 974 int err; 975 976 mlxsw_reg_mcc_pack(mcc_pl, 0, 0, 0, 0); 977 err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mcc), mcc_pl); 978 if (err) 979 return err; 980 981 mlxsw_reg_mcc_unpack(mcc_pl, fwhandle, NULL, &control_state); 982 if (control_state != MLXFW_FSM_STATE_IDLE) 983 return -EBUSY; 984 985 mlxsw_reg_mcc_pack(mcc_pl, MLXSW_REG_MCC_INSTRUCTION_LOCK_UPDATE_HANDLE, 0, *fwhandle, 0); 986 return mlxsw_reg_write(mlxsw_core, MLXSW_REG(mcc), mcc_pl); 987 } 988 989 static int mlxsw_core_fw_fsm_component_update(struct mlxfw_dev *mlxfw_dev, u32 fwhandle, 990 u16 component_index, u32 component_size) 991 { 992 struct mlxsw_core_fw_info *mlxsw_core_fw_info = 993 container_of(mlxfw_dev, struct mlxsw_core_fw_info, mlxfw_dev); 994 struct mlxsw_core *mlxsw_core = mlxsw_core_fw_info->mlxsw_core; 995 char mcc_pl[MLXSW_REG_MCC_LEN]; 996 997 mlxsw_reg_mcc_pack(mcc_pl, MLXSW_REG_MCC_INSTRUCTION_UPDATE_COMPONENT, 998 component_index, fwhandle, component_size); 999 return mlxsw_reg_write(mlxsw_core, MLXSW_REG(mcc), mcc_pl); 1000 } 1001 1002 static int mlxsw_core_fw_fsm_block_download(struct mlxfw_dev *mlxfw_dev, u32 fwhandle, 1003 u8 *data, u16 size, u32 offset) 1004 { 1005 struct mlxsw_core_fw_info *mlxsw_core_fw_info = 1006 container_of(mlxfw_dev, struct mlxsw_core_fw_info, mlxfw_dev); 1007 struct mlxsw_core *mlxsw_core = mlxsw_core_fw_info->mlxsw_core; 1008 char mcda_pl[MLXSW_REG_MCDA_LEN]; 1009 1010 mlxsw_reg_mcda_pack(mcda_pl, fwhandle, offset, size, data); 1011 return mlxsw_reg_write(mlxsw_core, MLXSW_REG(mcda), mcda_pl); 1012 } 1013 1014 static int mlxsw_core_fw_fsm_component_verify(struct mlxfw_dev *mlxfw_dev, u32 fwhandle, 1015 u16 component_index) 1016 { 1017 struct mlxsw_core_fw_info *mlxsw_core_fw_info = 1018 container_of(mlxfw_dev, struct mlxsw_core_fw_info, mlxfw_dev); 1019 struct mlxsw_core *mlxsw_core = mlxsw_core_fw_info->mlxsw_core; 1020 char mcc_pl[MLXSW_REG_MCC_LEN]; 1021 1022 mlxsw_reg_mcc_pack(mcc_pl, MLXSW_REG_MCC_INSTRUCTION_VERIFY_COMPONENT, 1023 component_index, fwhandle, 0); 1024 return mlxsw_reg_write(mlxsw_core, MLXSW_REG(mcc), mcc_pl); 1025 } 1026 1027 static int mlxsw_core_fw_fsm_activate(struct mlxfw_dev *mlxfw_dev, u32 fwhandle) 1028 { 1029 struct mlxsw_core_fw_info *mlxsw_core_fw_info = 1030 container_of(mlxfw_dev, struct mlxsw_core_fw_info, mlxfw_dev); 1031 struct mlxsw_core *mlxsw_core = mlxsw_core_fw_info->mlxsw_core; 1032 char mcc_pl[MLXSW_REG_MCC_LEN]; 1033 1034 mlxsw_reg_mcc_pack(mcc_pl, MLXSW_REG_MCC_INSTRUCTION_ACTIVATE, 0, fwhandle, 0); 1035 return mlxsw_reg_write(mlxsw_core, MLXSW_REG(mcc), mcc_pl); 1036 } 1037 1038 static int mlxsw_core_fw_fsm_query_state(struct mlxfw_dev *mlxfw_dev, u32 fwhandle, 1039 enum mlxfw_fsm_state *fsm_state, 1040 enum mlxfw_fsm_state_err *fsm_state_err) 1041 { 1042 struct mlxsw_core_fw_info *mlxsw_core_fw_info = 1043 container_of(mlxfw_dev, struct mlxsw_core_fw_info, mlxfw_dev); 1044 struct mlxsw_core *mlxsw_core = mlxsw_core_fw_info->mlxsw_core; 1045 char mcc_pl[MLXSW_REG_MCC_LEN]; 1046 u8 control_state; 1047 u8 error_code; 1048 int err; 1049 1050 mlxsw_reg_mcc_pack(mcc_pl, 0, 0, fwhandle, 0); 1051 err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mcc), mcc_pl); 1052 if (err) 1053 return err; 1054 1055 mlxsw_reg_mcc_unpack(mcc_pl, NULL, &error_code, &control_state); 1056 *fsm_state = control_state; 1057 *fsm_state_err = min_t(enum mlxfw_fsm_state_err, error_code, MLXFW_FSM_STATE_ERR_MAX); 1058 return 0; 1059 } 1060 1061 static void mlxsw_core_fw_fsm_cancel(struct mlxfw_dev *mlxfw_dev, u32 fwhandle) 1062 { 1063 struct mlxsw_core_fw_info *mlxsw_core_fw_info = 1064 container_of(mlxfw_dev, struct mlxsw_core_fw_info, mlxfw_dev); 1065 struct mlxsw_core *mlxsw_core = mlxsw_core_fw_info->mlxsw_core; 1066 char mcc_pl[MLXSW_REG_MCC_LEN]; 1067 1068 mlxsw_reg_mcc_pack(mcc_pl, MLXSW_REG_MCC_INSTRUCTION_CANCEL, 0, fwhandle, 0); 1069 mlxsw_reg_write(mlxsw_core, MLXSW_REG(mcc), mcc_pl); 1070 } 1071 1072 static void mlxsw_core_fw_fsm_release(struct mlxfw_dev *mlxfw_dev, u32 fwhandle) 1073 { 1074 struct mlxsw_core_fw_info *mlxsw_core_fw_info = 1075 container_of(mlxfw_dev, struct mlxsw_core_fw_info, mlxfw_dev); 1076 struct mlxsw_core *mlxsw_core = mlxsw_core_fw_info->mlxsw_core; 1077 char mcc_pl[MLXSW_REG_MCC_LEN]; 1078 1079 mlxsw_reg_mcc_pack(mcc_pl, MLXSW_REG_MCC_INSTRUCTION_RELEASE_UPDATE_HANDLE, 0, fwhandle, 0); 1080 mlxsw_reg_write(mlxsw_core, MLXSW_REG(mcc), mcc_pl); 1081 } 1082 1083 static const struct mlxfw_dev_ops mlxsw_core_fw_mlxsw_dev_ops = { 1084 .component_query = mlxsw_core_fw_component_query, 1085 .fsm_lock = mlxsw_core_fw_fsm_lock, 1086 .fsm_component_update = mlxsw_core_fw_fsm_component_update, 1087 .fsm_block_download = mlxsw_core_fw_fsm_block_download, 1088 .fsm_component_verify = mlxsw_core_fw_fsm_component_verify, 1089 .fsm_activate = mlxsw_core_fw_fsm_activate, 1090 .fsm_query_state = mlxsw_core_fw_fsm_query_state, 1091 .fsm_cancel = mlxsw_core_fw_fsm_cancel, 1092 .fsm_release = mlxsw_core_fw_fsm_release, 1093 }; 1094 1095 static int mlxsw_core_fw_flash(struct mlxsw_core *mlxsw_core, const struct firmware *firmware, 1096 struct netlink_ext_ack *extack) 1097 { 1098 struct mlxsw_core_fw_info mlxsw_core_fw_info = { 1099 .mlxfw_dev = { 1100 .ops = &mlxsw_core_fw_mlxsw_dev_ops, 1101 .psid = mlxsw_core->bus_info->psid, 1102 .psid_size = strlen(mlxsw_core->bus_info->psid), 1103 .devlink = priv_to_devlink(mlxsw_core), 1104 }, 1105 .mlxsw_core = mlxsw_core 1106 }; 1107 int err; 1108 1109 mlxsw_core->fw_flash_in_progress = true; 1110 err = mlxfw_firmware_flash(&mlxsw_core_fw_info.mlxfw_dev, firmware, extack); 1111 mlxsw_core->fw_flash_in_progress = false; 1112 1113 return err; 1114 } 1115 1116 static int mlxsw_core_fw_rev_validate(struct mlxsw_core *mlxsw_core, 1117 const struct mlxsw_bus_info *mlxsw_bus_info, 1118 const struct mlxsw_fw_rev *req_rev, 1119 const char *filename) 1120 { 1121 const struct mlxsw_fw_rev *rev = &mlxsw_bus_info->fw_rev; 1122 union devlink_param_value value; 1123 const struct firmware *firmware; 1124 int err; 1125 1126 /* Don't check if driver does not require it */ 1127 if (!req_rev || !filename) 1128 return 0; 1129 1130 /* Don't check if devlink 'fw_load_policy' param is 'flash' */ 1131 err = devlink_param_driverinit_value_get(priv_to_devlink(mlxsw_core), 1132 DEVLINK_PARAM_GENERIC_ID_FW_LOAD_POLICY, 1133 &value); 1134 if (err) 1135 return err; 1136 if (value.vu8 == DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_FLASH) 1137 return 0; 1138 1139 /* Validate driver & FW are compatible */ 1140 if (rev->major != req_rev->major) { 1141 WARN(1, "Mismatch in major FW version [%d:%d] is never expected; Please contact support\n", 1142 rev->major, req_rev->major); 1143 return -EINVAL; 1144 } 1145 if (mlxsw_core_fw_rev_minor_subminor_validate(rev, req_rev)) 1146 return 0; 1147 1148 dev_err(mlxsw_bus_info->dev, "The firmware version %d.%d.%d is incompatible with the driver (required >= %d.%d.%d)\n", 1149 rev->major, rev->minor, rev->subminor, req_rev->major, 1150 req_rev->minor, req_rev->subminor); 1151 dev_info(mlxsw_bus_info->dev, "Flashing firmware using file %s\n", filename); 1152 1153 err = request_firmware_direct(&firmware, filename, mlxsw_bus_info->dev); 1154 if (err) { 1155 dev_err(mlxsw_bus_info->dev, "Could not request firmware file %s\n", filename); 1156 return err; 1157 } 1158 1159 err = mlxsw_core_fw_flash(mlxsw_core, firmware, NULL); 1160 release_firmware(firmware); 1161 if (err) 1162 dev_err(mlxsw_bus_info->dev, "Could not upgrade firmware\n"); 1163 1164 /* On FW flash success, tell the caller FW reset is needed 1165 * if current FW supports it. 1166 */ 1167 if (rev->minor >= req_rev->can_reset_minor) 1168 return err ? err : -EAGAIN; 1169 else 1170 return 0; 1171 } 1172 1173 static int mlxsw_core_fw_flash_update(struct mlxsw_core *mlxsw_core, 1174 struct devlink_flash_update_params *params, 1175 struct netlink_ext_ack *extack) 1176 { 1177 return mlxsw_core_fw_flash(mlxsw_core, params->fw, extack); 1178 } 1179 1180 static int mlxsw_core_devlink_param_fw_load_policy_validate(struct devlink *devlink, u32 id, 1181 union devlink_param_value val, 1182 struct netlink_ext_ack *extack) 1183 { 1184 if (val.vu8 != DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DRIVER && 1185 val.vu8 != DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_FLASH) { 1186 NL_SET_ERR_MSG_MOD(extack, "'fw_load_policy' must be 'driver' or 'flash'"); 1187 return -EINVAL; 1188 } 1189 1190 return 0; 1191 } 1192 1193 static const struct devlink_param mlxsw_core_fw_devlink_params[] = { 1194 DEVLINK_PARAM_GENERIC(FW_LOAD_POLICY, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), NULL, NULL, 1195 mlxsw_core_devlink_param_fw_load_policy_validate), 1196 }; 1197 1198 static int mlxsw_core_fw_params_register(struct mlxsw_core *mlxsw_core) 1199 { 1200 struct devlink *devlink = priv_to_devlink(mlxsw_core); 1201 union devlink_param_value value; 1202 int err; 1203 1204 err = devlink_params_register(devlink, mlxsw_core_fw_devlink_params, 1205 ARRAY_SIZE(mlxsw_core_fw_devlink_params)); 1206 if (err) 1207 return err; 1208 1209 value.vu8 = DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DRIVER; 1210 devlink_param_driverinit_value_set(devlink, DEVLINK_PARAM_GENERIC_ID_FW_LOAD_POLICY, value); 1211 return 0; 1212 } 1213 1214 static void mlxsw_core_fw_params_unregister(struct mlxsw_core *mlxsw_core) 1215 { 1216 devlink_params_unregister(priv_to_devlink(mlxsw_core), mlxsw_core_fw_devlink_params, 1217 ARRAY_SIZE(mlxsw_core_fw_devlink_params)); 1218 } 1219 1220 static void *__dl_port(struct devlink_port *devlink_port) 1221 { 1222 return container_of(devlink_port, struct mlxsw_core_port, devlink_port); 1223 } 1224 1225 static int mlxsw_devlink_port_split(struct devlink *devlink, 1226 struct devlink_port *port, 1227 unsigned int count, 1228 struct netlink_ext_ack *extack) 1229 { 1230 struct mlxsw_core_port *mlxsw_core_port = __dl_port(port); 1231 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 1232 1233 if (!mlxsw_core->driver->port_split) 1234 return -EOPNOTSUPP; 1235 return mlxsw_core->driver->port_split(mlxsw_core, 1236 mlxsw_core_port->local_port, 1237 count, extack); 1238 } 1239 1240 static int mlxsw_devlink_port_unsplit(struct devlink *devlink, 1241 struct devlink_port *port, 1242 struct netlink_ext_ack *extack) 1243 { 1244 struct mlxsw_core_port *mlxsw_core_port = __dl_port(port); 1245 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 1246 1247 if (!mlxsw_core->driver->port_unsplit) 1248 return -EOPNOTSUPP; 1249 return mlxsw_core->driver->port_unsplit(mlxsw_core, 1250 mlxsw_core_port->local_port, 1251 extack); 1252 } 1253 1254 static int 1255 mlxsw_devlink_sb_pool_get(struct devlink *devlink, 1256 unsigned int sb_index, u16 pool_index, 1257 struct devlink_sb_pool_info *pool_info) 1258 { 1259 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 1260 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 1261 1262 if (!mlxsw_driver->sb_pool_get) 1263 return -EOPNOTSUPP; 1264 return mlxsw_driver->sb_pool_get(mlxsw_core, sb_index, 1265 pool_index, pool_info); 1266 } 1267 1268 static int 1269 mlxsw_devlink_sb_pool_set(struct devlink *devlink, 1270 unsigned int sb_index, u16 pool_index, u32 size, 1271 enum devlink_sb_threshold_type threshold_type, 1272 struct netlink_ext_ack *extack) 1273 { 1274 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 1275 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 1276 1277 if (!mlxsw_driver->sb_pool_set) 1278 return -EOPNOTSUPP; 1279 return mlxsw_driver->sb_pool_set(mlxsw_core, sb_index, 1280 pool_index, size, threshold_type, 1281 extack); 1282 } 1283 1284 static int mlxsw_devlink_port_type_set(struct devlink_port *devlink_port, 1285 enum devlink_port_type port_type) 1286 { 1287 struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink); 1288 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 1289 struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port); 1290 1291 if (!mlxsw_driver->port_type_set) 1292 return -EOPNOTSUPP; 1293 1294 return mlxsw_driver->port_type_set(mlxsw_core, 1295 mlxsw_core_port->local_port, 1296 port_type); 1297 } 1298 1299 static int mlxsw_devlink_sb_port_pool_get(struct devlink_port *devlink_port, 1300 unsigned int sb_index, u16 pool_index, 1301 u32 *p_threshold) 1302 { 1303 struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink); 1304 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 1305 struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port); 1306 1307 if (!mlxsw_driver->sb_port_pool_get || 1308 !mlxsw_core_port_check(mlxsw_core_port)) 1309 return -EOPNOTSUPP; 1310 return mlxsw_driver->sb_port_pool_get(mlxsw_core_port, sb_index, 1311 pool_index, p_threshold); 1312 } 1313 1314 static int mlxsw_devlink_sb_port_pool_set(struct devlink_port *devlink_port, 1315 unsigned int sb_index, u16 pool_index, 1316 u32 threshold, 1317 struct netlink_ext_ack *extack) 1318 { 1319 struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink); 1320 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 1321 struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port); 1322 1323 if (!mlxsw_driver->sb_port_pool_set || 1324 !mlxsw_core_port_check(mlxsw_core_port)) 1325 return -EOPNOTSUPP; 1326 return mlxsw_driver->sb_port_pool_set(mlxsw_core_port, sb_index, 1327 pool_index, threshold, extack); 1328 } 1329 1330 static int 1331 mlxsw_devlink_sb_tc_pool_bind_get(struct devlink_port *devlink_port, 1332 unsigned int sb_index, u16 tc_index, 1333 enum devlink_sb_pool_type pool_type, 1334 u16 *p_pool_index, u32 *p_threshold) 1335 { 1336 struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink); 1337 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 1338 struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port); 1339 1340 if (!mlxsw_driver->sb_tc_pool_bind_get || 1341 !mlxsw_core_port_check(mlxsw_core_port)) 1342 return -EOPNOTSUPP; 1343 return mlxsw_driver->sb_tc_pool_bind_get(mlxsw_core_port, sb_index, 1344 tc_index, pool_type, 1345 p_pool_index, p_threshold); 1346 } 1347 1348 static int 1349 mlxsw_devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port, 1350 unsigned int sb_index, u16 tc_index, 1351 enum devlink_sb_pool_type pool_type, 1352 u16 pool_index, u32 threshold, 1353 struct netlink_ext_ack *extack) 1354 { 1355 struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink); 1356 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 1357 struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port); 1358 1359 if (!mlxsw_driver->sb_tc_pool_bind_set || 1360 !mlxsw_core_port_check(mlxsw_core_port)) 1361 return -EOPNOTSUPP; 1362 return mlxsw_driver->sb_tc_pool_bind_set(mlxsw_core_port, sb_index, 1363 tc_index, pool_type, 1364 pool_index, threshold, extack); 1365 } 1366 1367 static int mlxsw_devlink_sb_occ_snapshot(struct devlink *devlink, 1368 unsigned int sb_index) 1369 { 1370 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 1371 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 1372 1373 if (!mlxsw_driver->sb_occ_snapshot) 1374 return -EOPNOTSUPP; 1375 return mlxsw_driver->sb_occ_snapshot(mlxsw_core, sb_index); 1376 } 1377 1378 static int mlxsw_devlink_sb_occ_max_clear(struct devlink *devlink, 1379 unsigned int sb_index) 1380 { 1381 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 1382 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 1383 1384 if (!mlxsw_driver->sb_occ_max_clear) 1385 return -EOPNOTSUPP; 1386 return mlxsw_driver->sb_occ_max_clear(mlxsw_core, sb_index); 1387 } 1388 1389 static int 1390 mlxsw_devlink_sb_occ_port_pool_get(struct devlink_port *devlink_port, 1391 unsigned int sb_index, u16 pool_index, 1392 u32 *p_cur, u32 *p_max) 1393 { 1394 struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink); 1395 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 1396 struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port); 1397 1398 if (!mlxsw_driver->sb_occ_port_pool_get || 1399 !mlxsw_core_port_check(mlxsw_core_port)) 1400 return -EOPNOTSUPP; 1401 return mlxsw_driver->sb_occ_port_pool_get(mlxsw_core_port, sb_index, 1402 pool_index, p_cur, p_max); 1403 } 1404 1405 static int 1406 mlxsw_devlink_sb_occ_tc_port_bind_get(struct devlink_port *devlink_port, 1407 unsigned int sb_index, u16 tc_index, 1408 enum devlink_sb_pool_type pool_type, 1409 u32 *p_cur, u32 *p_max) 1410 { 1411 struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink); 1412 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 1413 struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port); 1414 1415 if (!mlxsw_driver->sb_occ_tc_port_bind_get || 1416 !mlxsw_core_port_check(mlxsw_core_port)) 1417 return -EOPNOTSUPP; 1418 return mlxsw_driver->sb_occ_tc_port_bind_get(mlxsw_core_port, 1419 sb_index, tc_index, 1420 pool_type, p_cur, p_max); 1421 } 1422 1423 static int 1424 mlxsw_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req, 1425 struct netlink_ext_ack *extack) 1426 { 1427 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 1428 char fw_info_psid[MLXSW_REG_MGIR_FW_INFO_PSID_SIZE]; 1429 u32 hw_rev, fw_major, fw_minor, fw_sub_minor; 1430 char mgir_pl[MLXSW_REG_MGIR_LEN]; 1431 char buf[32]; 1432 int err; 1433 1434 err = devlink_info_driver_name_put(req, 1435 mlxsw_core->bus_info->device_kind); 1436 if (err) 1437 return err; 1438 1439 mlxsw_reg_mgir_pack(mgir_pl); 1440 err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mgir), mgir_pl); 1441 if (err) 1442 return err; 1443 mlxsw_reg_mgir_unpack(mgir_pl, &hw_rev, fw_info_psid, &fw_major, 1444 &fw_minor, &fw_sub_minor); 1445 1446 sprintf(buf, "%X", hw_rev); 1447 err = devlink_info_version_fixed_put(req, "hw.revision", buf); 1448 if (err) 1449 return err; 1450 1451 err = devlink_info_version_fixed_put(req, 1452 DEVLINK_INFO_VERSION_GENERIC_FW_PSID, 1453 fw_info_psid); 1454 if (err) 1455 return err; 1456 1457 sprintf(buf, "%d.%d.%d", fw_major, fw_minor, fw_sub_minor); 1458 err = devlink_info_version_running_put(req, "fw.version", buf); 1459 if (err) 1460 return err; 1461 1462 return devlink_info_version_running_put(req, 1463 DEVLINK_INFO_VERSION_GENERIC_FW, 1464 buf); 1465 } 1466 1467 static int 1468 mlxsw_devlink_core_bus_device_reload_down(struct devlink *devlink, 1469 bool netns_change, enum devlink_reload_action action, 1470 enum devlink_reload_limit limit, 1471 struct netlink_ext_ack *extack) 1472 { 1473 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 1474 1475 if (!(mlxsw_core->bus->features & MLXSW_BUS_F_RESET)) 1476 return -EOPNOTSUPP; 1477 1478 mlxsw_core_bus_device_unregister(mlxsw_core, true); 1479 return 0; 1480 } 1481 1482 static int 1483 mlxsw_devlink_core_bus_device_reload_up(struct devlink *devlink, enum devlink_reload_action action, 1484 enum devlink_reload_limit limit, u32 *actions_performed, 1485 struct netlink_ext_ack *extack) 1486 { 1487 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 1488 1489 *actions_performed = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) | 1490 BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE); 1491 return mlxsw_core_bus_device_register(mlxsw_core->bus_info, 1492 mlxsw_core->bus, 1493 mlxsw_core->bus_priv, true, 1494 devlink, extack); 1495 } 1496 1497 static int mlxsw_devlink_flash_update(struct devlink *devlink, 1498 struct devlink_flash_update_params *params, 1499 struct netlink_ext_ack *extack) 1500 { 1501 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 1502 1503 return mlxsw_core_fw_flash_update(mlxsw_core, params, extack); 1504 } 1505 1506 static int mlxsw_devlink_trap_init(struct devlink *devlink, 1507 const struct devlink_trap *trap, 1508 void *trap_ctx) 1509 { 1510 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 1511 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 1512 1513 if (!mlxsw_driver->trap_init) 1514 return -EOPNOTSUPP; 1515 return mlxsw_driver->trap_init(mlxsw_core, trap, trap_ctx); 1516 } 1517 1518 static void mlxsw_devlink_trap_fini(struct devlink *devlink, 1519 const struct devlink_trap *trap, 1520 void *trap_ctx) 1521 { 1522 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 1523 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 1524 1525 if (!mlxsw_driver->trap_fini) 1526 return; 1527 mlxsw_driver->trap_fini(mlxsw_core, trap, trap_ctx); 1528 } 1529 1530 static int mlxsw_devlink_trap_action_set(struct devlink *devlink, 1531 const struct devlink_trap *trap, 1532 enum devlink_trap_action action, 1533 struct netlink_ext_ack *extack) 1534 { 1535 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 1536 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 1537 1538 if (!mlxsw_driver->trap_action_set) 1539 return -EOPNOTSUPP; 1540 return mlxsw_driver->trap_action_set(mlxsw_core, trap, action, extack); 1541 } 1542 1543 static int 1544 mlxsw_devlink_trap_group_init(struct devlink *devlink, 1545 const struct devlink_trap_group *group) 1546 { 1547 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 1548 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 1549 1550 if (!mlxsw_driver->trap_group_init) 1551 return -EOPNOTSUPP; 1552 return mlxsw_driver->trap_group_init(mlxsw_core, group); 1553 } 1554 1555 static int 1556 mlxsw_devlink_trap_group_set(struct devlink *devlink, 1557 const struct devlink_trap_group *group, 1558 const struct devlink_trap_policer *policer, 1559 struct netlink_ext_ack *extack) 1560 { 1561 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 1562 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 1563 1564 if (!mlxsw_driver->trap_group_set) 1565 return -EOPNOTSUPP; 1566 return mlxsw_driver->trap_group_set(mlxsw_core, group, policer, extack); 1567 } 1568 1569 static int 1570 mlxsw_devlink_trap_policer_init(struct devlink *devlink, 1571 const struct devlink_trap_policer *policer) 1572 { 1573 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 1574 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 1575 1576 if (!mlxsw_driver->trap_policer_init) 1577 return -EOPNOTSUPP; 1578 return mlxsw_driver->trap_policer_init(mlxsw_core, policer); 1579 } 1580 1581 static void 1582 mlxsw_devlink_trap_policer_fini(struct devlink *devlink, 1583 const struct devlink_trap_policer *policer) 1584 { 1585 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 1586 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 1587 1588 if (!mlxsw_driver->trap_policer_fini) 1589 return; 1590 mlxsw_driver->trap_policer_fini(mlxsw_core, policer); 1591 } 1592 1593 static int 1594 mlxsw_devlink_trap_policer_set(struct devlink *devlink, 1595 const struct devlink_trap_policer *policer, 1596 u64 rate, u64 burst, 1597 struct netlink_ext_ack *extack) 1598 { 1599 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 1600 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 1601 1602 if (!mlxsw_driver->trap_policer_set) 1603 return -EOPNOTSUPP; 1604 return mlxsw_driver->trap_policer_set(mlxsw_core, policer, rate, burst, 1605 extack); 1606 } 1607 1608 static int 1609 mlxsw_devlink_trap_policer_counter_get(struct devlink *devlink, 1610 const struct devlink_trap_policer *policer, 1611 u64 *p_drops) 1612 { 1613 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 1614 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 1615 1616 if (!mlxsw_driver->trap_policer_counter_get) 1617 return -EOPNOTSUPP; 1618 return mlxsw_driver->trap_policer_counter_get(mlxsw_core, policer, 1619 p_drops); 1620 } 1621 1622 static const struct devlink_ops mlxsw_devlink_ops = { 1623 .reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) | 1624 BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE), 1625 .reload_down = mlxsw_devlink_core_bus_device_reload_down, 1626 .reload_up = mlxsw_devlink_core_bus_device_reload_up, 1627 .port_type_set = mlxsw_devlink_port_type_set, 1628 .port_split = mlxsw_devlink_port_split, 1629 .port_unsplit = mlxsw_devlink_port_unsplit, 1630 .sb_pool_get = mlxsw_devlink_sb_pool_get, 1631 .sb_pool_set = mlxsw_devlink_sb_pool_set, 1632 .sb_port_pool_get = mlxsw_devlink_sb_port_pool_get, 1633 .sb_port_pool_set = mlxsw_devlink_sb_port_pool_set, 1634 .sb_tc_pool_bind_get = mlxsw_devlink_sb_tc_pool_bind_get, 1635 .sb_tc_pool_bind_set = mlxsw_devlink_sb_tc_pool_bind_set, 1636 .sb_occ_snapshot = mlxsw_devlink_sb_occ_snapshot, 1637 .sb_occ_max_clear = mlxsw_devlink_sb_occ_max_clear, 1638 .sb_occ_port_pool_get = mlxsw_devlink_sb_occ_port_pool_get, 1639 .sb_occ_tc_port_bind_get = mlxsw_devlink_sb_occ_tc_port_bind_get, 1640 .info_get = mlxsw_devlink_info_get, 1641 .flash_update = mlxsw_devlink_flash_update, 1642 .trap_init = mlxsw_devlink_trap_init, 1643 .trap_fini = mlxsw_devlink_trap_fini, 1644 .trap_action_set = mlxsw_devlink_trap_action_set, 1645 .trap_group_init = mlxsw_devlink_trap_group_init, 1646 .trap_group_set = mlxsw_devlink_trap_group_set, 1647 .trap_policer_init = mlxsw_devlink_trap_policer_init, 1648 .trap_policer_fini = mlxsw_devlink_trap_policer_fini, 1649 .trap_policer_set = mlxsw_devlink_trap_policer_set, 1650 .trap_policer_counter_get = mlxsw_devlink_trap_policer_counter_get, 1651 }; 1652 1653 static int mlxsw_core_params_register(struct mlxsw_core *mlxsw_core) 1654 { 1655 int err; 1656 1657 err = mlxsw_core_fw_params_register(mlxsw_core); 1658 if (err) 1659 return err; 1660 1661 if (mlxsw_core->driver->params_register) { 1662 err = mlxsw_core->driver->params_register(mlxsw_core); 1663 if (err) 1664 goto err_params_register; 1665 } 1666 return 0; 1667 1668 err_params_register: 1669 mlxsw_core_fw_params_unregister(mlxsw_core); 1670 return err; 1671 } 1672 1673 static void mlxsw_core_params_unregister(struct mlxsw_core *mlxsw_core) 1674 { 1675 mlxsw_core_fw_params_unregister(mlxsw_core); 1676 if (mlxsw_core->driver->params_register) 1677 mlxsw_core->driver->params_unregister(mlxsw_core); 1678 } 1679 1680 struct mlxsw_core_health_event { 1681 struct mlxsw_core *mlxsw_core; 1682 char mfde_pl[MLXSW_REG_MFDE_LEN]; 1683 struct work_struct work; 1684 }; 1685 1686 static void mlxsw_core_health_event_work(struct work_struct *work) 1687 { 1688 struct mlxsw_core_health_event *event; 1689 struct mlxsw_core *mlxsw_core; 1690 1691 event = container_of(work, struct mlxsw_core_health_event, work); 1692 mlxsw_core = event->mlxsw_core; 1693 devlink_health_report(mlxsw_core->health.fw_fatal, "FW fatal event occurred", 1694 event->mfde_pl); 1695 kfree(event); 1696 } 1697 1698 static void mlxsw_core_health_listener_func(const struct mlxsw_reg_info *reg, 1699 char *mfde_pl, void *priv) 1700 { 1701 struct mlxsw_core_health_event *event; 1702 struct mlxsw_core *mlxsw_core = priv; 1703 1704 event = kmalloc(sizeof(*event), GFP_ATOMIC); 1705 if (!event) 1706 return; 1707 event->mlxsw_core = mlxsw_core; 1708 memcpy(event->mfde_pl, mfde_pl, sizeof(event->mfde_pl)); 1709 INIT_WORK(&event->work, mlxsw_core_health_event_work); 1710 mlxsw_core_schedule_work(&event->work); 1711 } 1712 1713 static const struct mlxsw_listener mlxsw_core_health_listener = 1714 MLXSW_CORE_EVENTL(mlxsw_core_health_listener_func, MFDE); 1715 1716 static int 1717 mlxsw_core_health_fw_fatal_dump_fatal_cause(const char *mfde_pl, 1718 struct devlink_fmsg *fmsg) 1719 { 1720 u32 val, tile_v; 1721 int err; 1722 1723 val = mlxsw_reg_mfde_fatal_cause_id_get(mfde_pl); 1724 err = devlink_fmsg_u32_pair_put(fmsg, "cause_id", val); 1725 if (err) 1726 return err; 1727 tile_v = mlxsw_reg_mfde_fatal_cause_tile_v_get(mfde_pl); 1728 if (tile_v) { 1729 val = mlxsw_reg_mfde_fatal_cause_tile_index_get(mfde_pl); 1730 err = devlink_fmsg_u8_pair_put(fmsg, "tile_index", val); 1731 if (err) 1732 return err; 1733 } 1734 1735 return 0; 1736 } 1737 1738 static int 1739 mlxsw_core_health_fw_fatal_dump_fw_assert(const char *mfde_pl, 1740 struct devlink_fmsg *fmsg) 1741 { 1742 u32 val, tile_v; 1743 int err; 1744 1745 val = mlxsw_reg_mfde_fw_assert_var0_get(mfde_pl); 1746 err = devlink_fmsg_u32_pair_put(fmsg, "var0", val); 1747 if (err) 1748 return err; 1749 val = mlxsw_reg_mfde_fw_assert_var1_get(mfde_pl); 1750 err = devlink_fmsg_u32_pair_put(fmsg, "var1", val); 1751 if (err) 1752 return err; 1753 val = mlxsw_reg_mfde_fw_assert_var2_get(mfde_pl); 1754 err = devlink_fmsg_u32_pair_put(fmsg, "var2", val); 1755 if (err) 1756 return err; 1757 val = mlxsw_reg_mfde_fw_assert_var3_get(mfde_pl); 1758 err = devlink_fmsg_u32_pair_put(fmsg, "var3", val); 1759 if (err) 1760 return err; 1761 val = mlxsw_reg_mfde_fw_assert_var4_get(mfde_pl); 1762 err = devlink_fmsg_u32_pair_put(fmsg, "var4", val); 1763 if (err) 1764 return err; 1765 val = mlxsw_reg_mfde_fw_assert_existptr_get(mfde_pl); 1766 err = devlink_fmsg_u32_pair_put(fmsg, "existptr", val); 1767 if (err) 1768 return err; 1769 val = mlxsw_reg_mfde_fw_assert_callra_get(mfde_pl); 1770 err = devlink_fmsg_u32_pair_put(fmsg, "callra", val); 1771 if (err) 1772 return err; 1773 val = mlxsw_reg_mfde_fw_assert_oe_get(mfde_pl); 1774 err = devlink_fmsg_bool_pair_put(fmsg, "old_event", val); 1775 if (err) 1776 return err; 1777 tile_v = mlxsw_reg_mfde_fw_assert_tile_v_get(mfde_pl); 1778 if (tile_v) { 1779 val = mlxsw_reg_mfde_fw_assert_tile_index_get(mfde_pl); 1780 err = devlink_fmsg_u8_pair_put(fmsg, "tile_index", val); 1781 if (err) 1782 return err; 1783 } 1784 val = mlxsw_reg_mfde_fw_assert_ext_synd_get(mfde_pl); 1785 err = devlink_fmsg_u32_pair_put(fmsg, "ext_synd", val); 1786 if (err) 1787 return err; 1788 1789 return 0; 1790 } 1791 1792 static int 1793 mlxsw_core_health_fw_fatal_dump_kvd_im_stop(const char *mfde_pl, 1794 struct devlink_fmsg *fmsg) 1795 { 1796 u32 val; 1797 int err; 1798 1799 val = mlxsw_reg_mfde_kvd_im_stop_oe_get(mfde_pl); 1800 err = devlink_fmsg_bool_pair_put(fmsg, "old_event", val); 1801 if (err) 1802 return err; 1803 val = mlxsw_reg_mfde_kvd_im_stop_pipes_mask_get(mfde_pl); 1804 return devlink_fmsg_u32_pair_put(fmsg, "pipes_mask", val); 1805 } 1806 1807 static int 1808 mlxsw_core_health_fw_fatal_dump_crspace_to(const char *mfde_pl, 1809 struct devlink_fmsg *fmsg) 1810 { 1811 u32 val; 1812 int err; 1813 1814 val = mlxsw_reg_mfde_crspace_to_log_address_get(mfde_pl); 1815 err = devlink_fmsg_u32_pair_put(fmsg, "log_address", val); 1816 if (err) 1817 return err; 1818 val = mlxsw_reg_mfde_crspace_to_oe_get(mfde_pl); 1819 err = devlink_fmsg_bool_pair_put(fmsg, "old_event", val); 1820 if (err) 1821 return err; 1822 val = mlxsw_reg_mfde_crspace_to_log_id_get(mfde_pl); 1823 err = devlink_fmsg_u8_pair_put(fmsg, "log_irisc_id", val); 1824 if (err) 1825 return err; 1826 val = mlxsw_reg_mfde_crspace_to_log_ip_get(mfde_pl); 1827 err = devlink_fmsg_u64_pair_put(fmsg, "log_ip", val); 1828 if (err) 1829 return err; 1830 1831 return 0; 1832 } 1833 1834 static int mlxsw_core_health_fw_fatal_dump(struct devlink_health_reporter *reporter, 1835 struct devlink_fmsg *fmsg, void *priv_ctx, 1836 struct netlink_ext_ack *extack) 1837 { 1838 char *mfde_pl = priv_ctx; 1839 char *val_str; 1840 u8 event_id; 1841 u32 val; 1842 int err; 1843 1844 if (!priv_ctx) 1845 /* User-triggered dumps are not possible */ 1846 return -EOPNOTSUPP; 1847 1848 val = mlxsw_reg_mfde_irisc_id_get(mfde_pl); 1849 err = devlink_fmsg_u8_pair_put(fmsg, "irisc_id", val); 1850 if (err) 1851 return err; 1852 err = devlink_fmsg_arr_pair_nest_start(fmsg, "event"); 1853 if (err) 1854 return err; 1855 1856 event_id = mlxsw_reg_mfde_event_id_get(mfde_pl); 1857 err = devlink_fmsg_u32_pair_put(fmsg, "id", event_id); 1858 if (err) 1859 return err; 1860 switch (event_id) { 1861 case MLXSW_REG_MFDE_EVENT_ID_CRSPACE_TO: 1862 val_str = "CR space timeout"; 1863 break; 1864 case MLXSW_REG_MFDE_EVENT_ID_KVD_IM_STOP: 1865 val_str = "KVD insertion machine stopped"; 1866 break; 1867 case MLXSW_REG_MFDE_EVENT_ID_TEST: 1868 val_str = "Test"; 1869 break; 1870 case MLXSW_REG_MFDE_EVENT_ID_FW_ASSERT: 1871 val_str = "FW assert"; 1872 break; 1873 case MLXSW_REG_MFDE_EVENT_ID_FATAL_CAUSE: 1874 val_str = "Fatal cause"; 1875 break; 1876 default: 1877 val_str = NULL; 1878 } 1879 if (val_str) { 1880 err = devlink_fmsg_string_pair_put(fmsg, "desc", val_str); 1881 if (err) 1882 return err; 1883 } 1884 1885 err = devlink_fmsg_arr_pair_nest_end(fmsg); 1886 if (err) 1887 return err; 1888 1889 err = devlink_fmsg_arr_pair_nest_start(fmsg, "severity"); 1890 if (err) 1891 return err; 1892 1893 val = mlxsw_reg_mfde_severity_get(mfde_pl); 1894 err = devlink_fmsg_u8_pair_put(fmsg, "id", val); 1895 if (err) 1896 return err; 1897 switch (val) { 1898 case MLXSW_REG_MFDE_SEVERITY_FATL: 1899 val_str = "Fatal"; 1900 break; 1901 case MLXSW_REG_MFDE_SEVERITY_NRML: 1902 val_str = "Normal"; 1903 break; 1904 case MLXSW_REG_MFDE_SEVERITY_INTR: 1905 val_str = "Debug"; 1906 break; 1907 default: 1908 val_str = NULL; 1909 } 1910 if (val_str) { 1911 err = devlink_fmsg_string_pair_put(fmsg, "desc", val_str); 1912 if (err) 1913 return err; 1914 } 1915 1916 err = devlink_fmsg_arr_pair_nest_end(fmsg); 1917 if (err) 1918 return err; 1919 1920 val = mlxsw_reg_mfde_method_get(mfde_pl); 1921 switch (val) { 1922 case MLXSW_REG_MFDE_METHOD_QUERY: 1923 val_str = "query"; 1924 break; 1925 case MLXSW_REG_MFDE_METHOD_WRITE: 1926 val_str = "write"; 1927 break; 1928 default: 1929 val_str = NULL; 1930 } 1931 if (val_str) { 1932 err = devlink_fmsg_string_pair_put(fmsg, "method", val_str); 1933 if (err) 1934 return err; 1935 } 1936 1937 val = mlxsw_reg_mfde_long_process_get(mfde_pl); 1938 err = devlink_fmsg_bool_pair_put(fmsg, "long_process", val); 1939 if (err) 1940 return err; 1941 1942 val = mlxsw_reg_mfde_command_type_get(mfde_pl); 1943 switch (val) { 1944 case MLXSW_REG_MFDE_COMMAND_TYPE_MAD: 1945 val_str = "mad"; 1946 break; 1947 case MLXSW_REG_MFDE_COMMAND_TYPE_EMAD: 1948 val_str = "emad"; 1949 break; 1950 case MLXSW_REG_MFDE_COMMAND_TYPE_CMDIF: 1951 val_str = "cmdif"; 1952 break; 1953 default: 1954 val_str = NULL; 1955 } 1956 if (val_str) { 1957 err = devlink_fmsg_string_pair_put(fmsg, "command_type", val_str); 1958 if (err) 1959 return err; 1960 } 1961 1962 val = mlxsw_reg_mfde_reg_attr_id_get(mfde_pl); 1963 err = devlink_fmsg_u32_pair_put(fmsg, "reg_attr_id", val); 1964 if (err) 1965 return err; 1966 1967 switch (event_id) { 1968 case MLXSW_REG_MFDE_EVENT_ID_CRSPACE_TO: 1969 return mlxsw_core_health_fw_fatal_dump_crspace_to(mfde_pl, 1970 fmsg); 1971 case MLXSW_REG_MFDE_EVENT_ID_KVD_IM_STOP: 1972 return mlxsw_core_health_fw_fatal_dump_kvd_im_stop(mfde_pl, 1973 fmsg); 1974 case MLXSW_REG_MFDE_EVENT_ID_FW_ASSERT: 1975 return mlxsw_core_health_fw_fatal_dump_fw_assert(mfde_pl, fmsg); 1976 case MLXSW_REG_MFDE_EVENT_ID_FATAL_CAUSE: 1977 return mlxsw_core_health_fw_fatal_dump_fatal_cause(mfde_pl, 1978 fmsg); 1979 } 1980 1981 return 0; 1982 } 1983 1984 static int 1985 mlxsw_core_health_fw_fatal_test(struct devlink_health_reporter *reporter, 1986 struct netlink_ext_ack *extack) 1987 { 1988 struct mlxsw_core *mlxsw_core = devlink_health_reporter_priv(reporter); 1989 char mfgd_pl[MLXSW_REG_MFGD_LEN]; 1990 int err; 1991 1992 /* Read the register first to make sure no other bits are changed. */ 1993 err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mfgd), mfgd_pl); 1994 if (err) 1995 return err; 1996 mlxsw_reg_mfgd_trigger_test_set(mfgd_pl, true); 1997 return mlxsw_reg_write(mlxsw_core, MLXSW_REG(mfgd), mfgd_pl); 1998 } 1999 2000 static const struct devlink_health_reporter_ops 2001 mlxsw_core_health_fw_fatal_ops = { 2002 .name = "fw_fatal", 2003 .dump = mlxsw_core_health_fw_fatal_dump, 2004 .test = mlxsw_core_health_fw_fatal_test, 2005 }; 2006 2007 static int mlxsw_core_health_fw_fatal_config(struct mlxsw_core *mlxsw_core, 2008 bool enable) 2009 { 2010 char mfgd_pl[MLXSW_REG_MFGD_LEN]; 2011 int err; 2012 2013 /* Read the register first to make sure no other bits are changed. */ 2014 err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mfgd), mfgd_pl); 2015 if (err) 2016 return err; 2017 mlxsw_reg_mfgd_fatal_event_mode_set(mfgd_pl, enable); 2018 return mlxsw_reg_write(mlxsw_core, MLXSW_REG(mfgd), mfgd_pl); 2019 } 2020 2021 static int mlxsw_core_health_init(struct mlxsw_core *mlxsw_core) 2022 { 2023 struct devlink *devlink = priv_to_devlink(mlxsw_core); 2024 struct devlink_health_reporter *fw_fatal; 2025 int err; 2026 2027 if (!(mlxsw_core->bus->features & MLXSW_BUS_F_TXRX)) 2028 return 0; 2029 2030 fw_fatal = devlink_health_reporter_create(devlink, &mlxsw_core_health_fw_fatal_ops, 2031 0, mlxsw_core); 2032 if (IS_ERR(fw_fatal)) { 2033 dev_err(mlxsw_core->bus_info->dev, "Failed to create fw fatal reporter"); 2034 return PTR_ERR(fw_fatal); 2035 } 2036 mlxsw_core->health.fw_fatal = fw_fatal; 2037 2038 err = mlxsw_core_trap_register(mlxsw_core, &mlxsw_core_health_listener, mlxsw_core); 2039 if (err) 2040 goto err_trap_register; 2041 2042 err = mlxsw_core_health_fw_fatal_config(mlxsw_core, true); 2043 if (err) 2044 goto err_fw_fatal_config; 2045 2046 return 0; 2047 2048 err_fw_fatal_config: 2049 mlxsw_core_trap_unregister(mlxsw_core, &mlxsw_core_health_listener, mlxsw_core); 2050 err_trap_register: 2051 devlink_health_reporter_destroy(mlxsw_core->health.fw_fatal); 2052 return err; 2053 } 2054 2055 static void mlxsw_core_health_fini(struct mlxsw_core *mlxsw_core) 2056 { 2057 if (!(mlxsw_core->bus->features & MLXSW_BUS_F_TXRX)) 2058 return; 2059 2060 mlxsw_core_health_fw_fatal_config(mlxsw_core, false); 2061 mlxsw_core_trap_unregister(mlxsw_core, &mlxsw_core_health_listener, mlxsw_core); 2062 /* Make sure there is no more event work scheduled */ 2063 mlxsw_core_flush_owq(); 2064 devlink_health_reporter_destroy(mlxsw_core->health.fw_fatal); 2065 } 2066 2067 static int 2068 __mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info, 2069 const struct mlxsw_bus *mlxsw_bus, 2070 void *bus_priv, bool reload, 2071 struct devlink *devlink, 2072 struct netlink_ext_ack *extack) 2073 { 2074 const char *device_kind = mlxsw_bus_info->device_kind; 2075 struct mlxsw_core *mlxsw_core; 2076 struct mlxsw_driver *mlxsw_driver; 2077 size_t alloc_size; 2078 int err; 2079 2080 mlxsw_driver = mlxsw_core_driver_get(device_kind); 2081 if (!mlxsw_driver) 2082 return -EINVAL; 2083 2084 if (!reload) { 2085 alloc_size = sizeof(*mlxsw_core) + mlxsw_driver->priv_size; 2086 devlink = devlink_alloc(&mlxsw_devlink_ops, alloc_size, 2087 mlxsw_bus_info->dev); 2088 if (!devlink) { 2089 err = -ENOMEM; 2090 goto err_devlink_alloc; 2091 } 2092 } 2093 2094 mlxsw_core = devlink_priv(devlink); 2095 INIT_LIST_HEAD(&mlxsw_core->rx_listener_list); 2096 INIT_LIST_HEAD(&mlxsw_core->event_listener_list); 2097 mlxsw_core->driver = mlxsw_driver; 2098 mlxsw_core->bus = mlxsw_bus; 2099 mlxsw_core->bus_priv = bus_priv; 2100 mlxsw_core->bus_info = mlxsw_bus_info; 2101 2102 err = mlxsw_bus->init(bus_priv, mlxsw_core, mlxsw_driver->profile, 2103 &mlxsw_core->res); 2104 if (err) 2105 goto err_bus_init; 2106 2107 if (mlxsw_driver->resources_register && !reload) { 2108 err = mlxsw_driver->resources_register(mlxsw_core); 2109 if (err) 2110 goto err_register_resources; 2111 } 2112 2113 err = mlxsw_ports_init(mlxsw_core, reload); 2114 if (err) 2115 goto err_ports_init; 2116 2117 if (MLXSW_CORE_RES_VALID(mlxsw_core, MAX_LAG) && 2118 MLXSW_CORE_RES_VALID(mlxsw_core, MAX_LAG_MEMBERS)) { 2119 alloc_size = sizeof(*mlxsw_core->lag.mapping) * 2120 MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG) * 2121 MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG_MEMBERS); 2122 mlxsw_core->lag.mapping = kzalloc(alloc_size, GFP_KERNEL); 2123 if (!mlxsw_core->lag.mapping) { 2124 err = -ENOMEM; 2125 goto err_alloc_lag_mapping; 2126 } 2127 } 2128 2129 err = mlxsw_core_trap_groups_set(mlxsw_core); 2130 if (err) 2131 goto err_trap_groups_set; 2132 2133 err = mlxsw_emad_init(mlxsw_core); 2134 if (err) 2135 goto err_emad_init; 2136 2137 if (!reload) { 2138 err = mlxsw_core_params_register(mlxsw_core); 2139 if (err) 2140 goto err_register_params; 2141 } 2142 2143 err = mlxsw_core_fw_rev_validate(mlxsw_core, mlxsw_bus_info, mlxsw_driver->fw_req_rev, 2144 mlxsw_driver->fw_filename); 2145 if (err) 2146 goto err_fw_rev_validate; 2147 2148 err = mlxsw_core_health_init(mlxsw_core); 2149 if (err) 2150 goto err_health_init; 2151 2152 err = mlxsw_hwmon_init(mlxsw_core, mlxsw_bus_info, &mlxsw_core->hwmon); 2153 if (err) 2154 goto err_hwmon_init; 2155 2156 err = mlxsw_thermal_init(mlxsw_core, mlxsw_bus_info, 2157 &mlxsw_core->thermal); 2158 if (err) 2159 goto err_thermal_init; 2160 2161 err = mlxsw_env_init(mlxsw_core, &mlxsw_core->env); 2162 if (err) 2163 goto err_env_init; 2164 2165 if (mlxsw_driver->init) { 2166 err = mlxsw_driver->init(mlxsw_core, mlxsw_bus_info, extack); 2167 if (err) 2168 goto err_driver_init; 2169 } 2170 2171 if (!reload) { 2172 devlink_set_features(devlink, DEVLINK_F_RELOAD); 2173 devlink_register(devlink); 2174 } 2175 return 0; 2176 2177 err_driver_init: 2178 mlxsw_env_fini(mlxsw_core->env); 2179 err_env_init: 2180 mlxsw_thermal_fini(mlxsw_core->thermal); 2181 err_thermal_init: 2182 mlxsw_hwmon_fini(mlxsw_core->hwmon); 2183 err_hwmon_init: 2184 mlxsw_core_health_fini(mlxsw_core); 2185 err_health_init: 2186 err_fw_rev_validate: 2187 if (!reload) 2188 mlxsw_core_params_unregister(mlxsw_core); 2189 err_register_params: 2190 mlxsw_emad_fini(mlxsw_core); 2191 err_emad_init: 2192 err_trap_groups_set: 2193 kfree(mlxsw_core->lag.mapping); 2194 err_alloc_lag_mapping: 2195 mlxsw_ports_fini(mlxsw_core, reload); 2196 err_ports_init: 2197 if (!reload) 2198 devlink_resources_unregister(devlink); 2199 err_register_resources: 2200 mlxsw_bus->fini(bus_priv); 2201 err_bus_init: 2202 if (!reload) 2203 devlink_free(devlink); 2204 err_devlink_alloc: 2205 return err; 2206 } 2207 2208 int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info, 2209 const struct mlxsw_bus *mlxsw_bus, 2210 void *bus_priv, bool reload, 2211 struct devlink *devlink, 2212 struct netlink_ext_ack *extack) 2213 { 2214 bool called_again = false; 2215 int err; 2216 2217 again: 2218 err = __mlxsw_core_bus_device_register(mlxsw_bus_info, mlxsw_bus, 2219 bus_priv, reload, 2220 devlink, extack); 2221 /* -EAGAIN is returned in case the FW was updated. FW needs 2222 * a reset, so lets try to call __mlxsw_core_bus_device_register() 2223 * again. 2224 */ 2225 if (err == -EAGAIN && !called_again) { 2226 called_again = true; 2227 goto again; 2228 } 2229 2230 return err; 2231 } 2232 EXPORT_SYMBOL(mlxsw_core_bus_device_register); 2233 2234 void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core, 2235 bool reload) 2236 { 2237 struct devlink *devlink = priv_to_devlink(mlxsw_core); 2238 2239 if (!reload) 2240 devlink_unregister(devlink); 2241 2242 if (devlink_is_reload_failed(devlink)) { 2243 if (!reload) 2244 /* Only the parts that were not de-initialized in the 2245 * failed reload attempt need to be de-initialized. 2246 */ 2247 goto reload_fail_deinit; 2248 else 2249 return; 2250 } 2251 2252 if (mlxsw_core->driver->fini) 2253 mlxsw_core->driver->fini(mlxsw_core); 2254 mlxsw_env_fini(mlxsw_core->env); 2255 mlxsw_thermal_fini(mlxsw_core->thermal); 2256 mlxsw_hwmon_fini(mlxsw_core->hwmon); 2257 mlxsw_core_health_fini(mlxsw_core); 2258 if (!reload) 2259 mlxsw_core_params_unregister(mlxsw_core); 2260 mlxsw_emad_fini(mlxsw_core); 2261 kfree(mlxsw_core->lag.mapping); 2262 mlxsw_ports_fini(mlxsw_core, reload); 2263 if (!reload) 2264 devlink_resources_unregister(devlink); 2265 mlxsw_core->bus->fini(mlxsw_core->bus_priv); 2266 if (!reload) 2267 devlink_free(devlink); 2268 2269 return; 2270 2271 reload_fail_deinit: 2272 mlxsw_core_params_unregister(mlxsw_core); 2273 devlink_resources_unregister(devlink); 2274 devlink_free(devlink); 2275 } 2276 EXPORT_SYMBOL(mlxsw_core_bus_device_unregister); 2277 2278 bool mlxsw_core_skb_transmit_busy(struct mlxsw_core *mlxsw_core, 2279 const struct mlxsw_tx_info *tx_info) 2280 { 2281 return mlxsw_core->bus->skb_transmit_busy(mlxsw_core->bus_priv, 2282 tx_info); 2283 } 2284 EXPORT_SYMBOL(mlxsw_core_skb_transmit_busy); 2285 2286 int mlxsw_core_skb_transmit(struct mlxsw_core *mlxsw_core, struct sk_buff *skb, 2287 const struct mlxsw_tx_info *tx_info) 2288 { 2289 return mlxsw_core->bus->skb_transmit(mlxsw_core->bus_priv, skb, 2290 tx_info); 2291 } 2292 EXPORT_SYMBOL(mlxsw_core_skb_transmit); 2293 2294 void mlxsw_core_ptp_transmitted(struct mlxsw_core *mlxsw_core, 2295 struct sk_buff *skb, u16 local_port) 2296 { 2297 if (mlxsw_core->driver->ptp_transmitted) 2298 mlxsw_core->driver->ptp_transmitted(mlxsw_core, skb, 2299 local_port); 2300 } 2301 EXPORT_SYMBOL(mlxsw_core_ptp_transmitted); 2302 2303 static bool __is_rx_listener_equal(const struct mlxsw_rx_listener *rxl_a, 2304 const struct mlxsw_rx_listener *rxl_b) 2305 { 2306 return (rxl_a->func == rxl_b->func && 2307 rxl_a->local_port == rxl_b->local_port && 2308 rxl_a->trap_id == rxl_b->trap_id && 2309 rxl_a->mirror_reason == rxl_b->mirror_reason); 2310 } 2311 2312 static struct mlxsw_rx_listener_item * 2313 __find_rx_listener_item(struct mlxsw_core *mlxsw_core, 2314 const struct mlxsw_rx_listener *rxl) 2315 { 2316 struct mlxsw_rx_listener_item *rxl_item; 2317 2318 list_for_each_entry(rxl_item, &mlxsw_core->rx_listener_list, list) { 2319 if (__is_rx_listener_equal(&rxl_item->rxl, rxl)) 2320 return rxl_item; 2321 } 2322 return NULL; 2323 } 2324 2325 int mlxsw_core_rx_listener_register(struct mlxsw_core *mlxsw_core, 2326 const struct mlxsw_rx_listener *rxl, 2327 void *priv, bool enabled) 2328 { 2329 struct mlxsw_rx_listener_item *rxl_item; 2330 2331 rxl_item = __find_rx_listener_item(mlxsw_core, rxl); 2332 if (rxl_item) 2333 return -EEXIST; 2334 rxl_item = kmalloc(sizeof(*rxl_item), GFP_KERNEL); 2335 if (!rxl_item) 2336 return -ENOMEM; 2337 rxl_item->rxl = *rxl; 2338 rxl_item->priv = priv; 2339 rxl_item->enabled = enabled; 2340 2341 list_add_rcu(&rxl_item->list, &mlxsw_core->rx_listener_list); 2342 return 0; 2343 } 2344 EXPORT_SYMBOL(mlxsw_core_rx_listener_register); 2345 2346 void mlxsw_core_rx_listener_unregister(struct mlxsw_core *mlxsw_core, 2347 const struct mlxsw_rx_listener *rxl) 2348 { 2349 struct mlxsw_rx_listener_item *rxl_item; 2350 2351 rxl_item = __find_rx_listener_item(mlxsw_core, rxl); 2352 if (!rxl_item) 2353 return; 2354 list_del_rcu(&rxl_item->list); 2355 synchronize_rcu(); 2356 kfree(rxl_item); 2357 } 2358 EXPORT_SYMBOL(mlxsw_core_rx_listener_unregister); 2359 2360 static void 2361 mlxsw_core_rx_listener_state_set(struct mlxsw_core *mlxsw_core, 2362 const struct mlxsw_rx_listener *rxl, 2363 bool enabled) 2364 { 2365 struct mlxsw_rx_listener_item *rxl_item; 2366 2367 rxl_item = __find_rx_listener_item(mlxsw_core, rxl); 2368 if (WARN_ON(!rxl_item)) 2369 return; 2370 rxl_item->enabled = enabled; 2371 } 2372 2373 static void mlxsw_core_event_listener_func(struct sk_buff *skb, u16 local_port, 2374 void *priv) 2375 { 2376 struct mlxsw_event_listener_item *event_listener_item = priv; 2377 struct mlxsw_core *mlxsw_core; 2378 struct mlxsw_reg_info reg; 2379 char *payload; 2380 char *reg_tlv; 2381 char *op_tlv; 2382 2383 mlxsw_core = event_listener_item->mlxsw_core; 2384 trace_devlink_hwmsg(priv_to_devlink(mlxsw_core), true, 0, 2385 skb->data, skb->len); 2386 2387 mlxsw_emad_tlv_parse(skb); 2388 op_tlv = mlxsw_emad_op_tlv(skb); 2389 reg_tlv = mlxsw_emad_reg_tlv(skb); 2390 2391 reg.id = mlxsw_emad_op_tlv_register_id_get(op_tlv); 2392 reg.len = (mlxsw_emad_reg_tlv_len_get(reg_tlv) - 1) * sizeof(u32); 2393 payload = mlxsw_emad_reg_payload(reg_tlv); 2394 event_listener_item->el.func(®, payload, event_listener_item->priv); 2395 dev_kfree_skb(skb); 2396 } 2397 2398 static bool __is_event_listener_equal(const struct mlxsw_event_listener *el_a, 2399 const struct mlxsw_event_listener *el_b) 2400 { 2401 return (el_a->func == el_b->func && 2402 el_a->trap_id == el_b->trap_id); 2403 } 2404 2405 static struct mlxsw_event_listener_item * 2406 __find_event_listener_item(struct mlxsw_core *mlxsw_core, 2407 const struct mlxsw_event_listener *el) 2408 { 2409 struct mlxsw_event_listener_item *el_item; 2410 2411 list_for_each_entry(el_item, &mlxsw_core->event_listener_list, list) { 2412 if (__is_event_listener_equal(&el_item->el, el)) 2413 return el_item; 2414 } 2415 return NULL; 2416 } 2417 2418 int mlxsw_core_event_listener_register(struct mlxsw_core *mlxsw_core, 2419 const struct mlxsw_event_listener *el, 2420 void *priv) 2421 { 2422 int err; 2423 struct mlxsw_event_listener_item *el_item; 2424 const struct mlxsw_rx_listener rxl = { 2425 .func = mlxsw_core_event_listener_func, 2426 .local_port = MLXSW_PORT_DONT_CARE, 2427 .trap_id = el->trap_id, 2428 }; 2429 2430 el_item = __find_event_listener_item(mlxsw_core, el); 2431 if (el_item) 2432 return -EEXIST; 2433 el_item = kmalloc(sizeof(*el_item), GFP_KERNEL); 2434 if (!el_item) 2435 return -ENOMEM; 2436 el_item->mlxsw_core = mlxsw_core; 2437 el_item->el = *el; 2438 el_item->priv = priv; 2439 2440 err = mlxsw_core_rx_listener_register(mlxsw_core, &rxl, el_item, true); 2441 if (err) 2442 goto err_rx_listener_register; 2443 2444 /* No reason to save item if we did not manage to register an RX 2445 * listener for it. 2446 */ 2447 list_add_rcu(&el_item->list, &mlxsw_core->event_listener_list); 2448 2449 return 0; 2450 2451 err_rx_listener_register: 2452 kfree(el_item); 2453 return err; 2454 } 2455 EXPORT_SYMBOL(mlxsw_core_event_listener_register); 2456 2457 void mlxsw_core_event_listener_unregister(struct mlxsw_core *mlxsw_core, 2458 const struct mlxsw_event_listener *el) 2459 { 2460 struct mlxsw_event_listener_item *el_item; 2461 const struct mlxsw_rx_listener rxl = { 2462 .func = mlxsw_core_event_listener_func, 2463 .local_port = MLXSW_PORT_DONT_CARE, 2464 .trap_id = el->trap_id, 2465 }; 2466 2467 el_item = __find_event_listener_item(mlxsw_core, el); 2468 if (!el_item) 2469 return; 2470 mlxsw_core_rx_listener_unregister(mlxsw_core, &rxl); 2471 list_del(&el_item->list); 2472 kfree(el_item); 2473 } 2474 EXPORT_SYMBOL(mlxsw_core_event_listener_unregister); 2475 2476 static int mlxsw_core_listener_register(struct mlxsw_core *mlxsw_core, 2477 const struct mlxsw_listener *listener, 2478 void *priv, bool enabled) 2479 { 2480 if (listener->is_event) { 2481 WARN_ON(!enabled); 2482 return mlxsw_core_event_listener_register(mlxsw_core, 2483 &listener->event_listener, 2484 priv); 2485 } else { 2486 return mlxsw_core_rx_listener_register(mlxsw_core, 2487 &listener->rx_listener, 2488 priv, enabled); 2489 } 2490 } 2491 2492 static void mlxsw_core_listener_unregister(struct mlxsw_core *mlxsw_core, 2493 const struct mlxsw_listener *listener, 2494 void *priv) 2495 { 2496 if (listener->is_event) 2497 mlxsw_core_event_listener_unregister(mlxsw_core, 2498 &listener->event_listener); 2499 else 2500 mlxsw_core_rx_listener_unregister(mlxsw_core, 2501 &listener->rx_listener); 2502 } 2503 2504 int mlxsw_core_trap_register(struct mlxsw_core *mlxsw_core, 2505 const struct mlxsw_listener *listener, void *priv) 2506 { 2507 enum mlxsw_reg_htgt_trap_group trap_group; 2508 enum mlxsw_reg_hpkt_action action; 2509 char hpkt_pl[MLXSW_REG_HPKT_LEN]; 2510 int err; 2511 2512 if (!(mlxsw_core->bus->features & MLXSW_BUS_F_TXRX)) 2513 return 0; 2514 2515 err = mlxsw_core_listener_register(mlxsw_core, listener, priv, 2516 listener->enabled_on_register); 2517 if (err) 2518 return err; 2519 2520 action = listener->enabled_on_register ? listener->en_action : 2521 listener->dis_action; 2522 trap_group = listener->enabled_on_register ? listener->en_trap_group : 2523 listener->dis_trap_group; 2524 mlxsw_reg_hpkt_pack(hpkt_pl, action, listener->trap_id, 2525 trap_group, listener->is_ctrl); 2526 err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl); 2527 if (err) 2528 goto err_trap_set; 2529 2530 return 0; 2531 2532 err_trap_set: 2533 mlxsw_core_listener_unregister(mlxsw_core, listener, priv); 2534 return err; 2535 } 2536 EXPORT_SYMBOL(mlxsw_core_trap_register); 2537 2538 void mlxsw_core_trap_unregister(struct mlxsw_core *mlxsw_core, 2539 const struct mlxsw_listener *listener, 2540 void *priv) 2541 { 2542 char hpkt_pl[MLXSW_REG_HPKT_LEN]; 2543 2544 if (!(mlxsw_core->bus->features & MLXSW_BUS_F_TXRX)) 2545 return; 2546 2547 if (!listener->is_event) { 2548 mlxsw_reg_hpkt_pack(hpkt_pl, listener->dis_action, 2549 listener->trap_id, listener->dis_trap_group, 2550 listener->is_ctrl); 2551 mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl); 2552 } 2553 2554 mlxsw_core_listener_unregister(mlxsw_core, listener, priv); 2555 } 2556 EXPORT_SYMBOL(mlxsw_core_trap_unregister); 2557 2558 int mlxsw_core_traps_register(struct mlxsw_core *mlxsw_core, 2559 const struct mlxsw_listener *listeners, 2560 size_t listeners_count, void *priv) 2561 { 2562 int i, err; 2563 2564 for (i = 0; i < listeners_count; i++) { 2565 err = mlxsw_core_trap_register(mlxsw_core, 2566 &listeners[i], 2567 priv); 2568 if (err) 2569 goto err_listener_register; 2570 } 2571 return 0; 2572 2573 err_listener_register: 2574 for (i--; i >= 0; i--) { 2575 mlxsw_core_trap_unregister(mlxsw_core, 2576 &listeners[i], 2577 priv); 2578 } 2579 return err; 2580 } 2581 EXPORT_SYMBOL(mlxsw_core_traps_register); 2582 2583 void mlxsw_core_traps_unregister(struct mlxsw_core *mlxsw_core, 2584 const struct mlxsw_listener *listeners, 2585 size_t listeners_count, void *priv) 2586 { 2587 int i; 2588 2589 for (i = 0; i < listeners_count; i++) { 2590 mlxsw_core_trap_unregister(mlxsw_core, 2591 &listeners[i], 2592 priv); 2593 } 2594 } 2595 EXPORT_SYMBOL(mlxsw_core_traps_unregister); 2596 2597 int mlxsw_core_trap_state_set(struct mlxsw_core *mlxsw_core, 2598 const struct mlxsw_listener *listener, 2599 bool enabled) 2600 { 2601 enum mlxsw_reg_htgt_trap_group trap_group; 2602 enum mlxsw_reg_hpkt_action action; 2603 char hpkt_pl[MLXSW_REG_HPKT_LEN]; 2604 int err; 2605 2606 /* Not supported for event listener */ 2607 if (WARN_ON(listener->is_event)) 2608 return -EINVAL; 2609 2610 action = enabled ? listener->en_action : listener->dis_action; 2611 trap_group = enabled ? listener->en_trap_group : 2612 listener->dis_trap_group; 2613 mlxsw_reg_hpkt_pack(hpkt_pl, action, listener->trap_id, 2614 trap_group, listener->is_ctrl); 2615 err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl); 2616 if (err) 2617 return err; 2618 2619 mlxsw_core_rx_listener_state_set(mlxsw_core, &listener->rx_listener, 2620 enabled); 2621 return 0; 2622 } 2623 EXPORT_SYMBOL(mlxsw_core_trap_state_set); 2624 2625 static u64 mlxsw_core_tid_get(struct mlxsw_core *mlxsw_core) 2626 { 2627 return atomic64_inc_return(&mlxsw_core->emad.tid); 2628 } 2629 2630 static int mlxsw_core_reg_access_emad(struct mlxsw_core *mlxsw_core, 2631 const struct mlxsw_reg_info *reg, 2632 char *payload, 2633 enum mlxsw_core_reg_access_type type, 2634 struct list_head *bulk_list, 2635 mlxsw_reg_trans_cb_t *cb, 2636 unsigned long cb_priv) 2637 { 2638 u64 tid = mlxsw_core_tid_get(mlxsw_core); 2639 struct mlxsw_reg_trans *trans; 2640 int err; 2641 2642 trans = kzalloc(sizeof(*trans), GFP_KERNEL); 2643 if (!trans) 2644 return -ENOMEM; 2645 2646 err = mlxsw_emad_reg_access(mlxsw_core, reg, payload, type, trans, 2647 bulk_list, cb, cb_priv, tid); 2648 if (err) { 2649 kfree_rcu(trans, rcu); 2650 return err; 2651 } 2652 return 0; 2653 } 2654 2655 int mlxsw_reg_trans_query(struct mlxsw_core *mlxsw_core, 2656 const struct mlxsw_reg_info *reg, char *payload, 2657 struct list_head *bulk_list, 2658 mlxsw_reg_trans_cb_t *cb, unsigned long cb_priv) 2659 { 2660 return mlxsw_core_reg_access_emad(mlxsw_core, reg, payload, 2661 MLXSW_CORE_REG_ACCESS_TYPE_QUERY, 2662 bulk_list, cb, cb_priv); 2663 } 2664 EXPORT_SYMBOL(mlxsw_reg_trans_query); 2665 2666 int mlxsw_reg_trans_write(struct mlxsw_core *mlxsw_core, 2667 const struct mlxsw_reg_info *reg, char *payload, 2668 struct list_head *bulk_list, 2669 mlxsw_reg_trans_cb_t *cb, unsigned long cb_priv) 2670 { 2671 return mlxsw_core_reg_access_emad(mlxsw_core, reg, payload, 2672 MLXSW_CORE_REG_ACCESS_TYPE_WRITE, 2673 bulk_list, cb, cb_priv); 2674 } 2675 EXPORT_SYMBOL(mlxsw_reg_trans_write); 2676 2677 #define MLXSW_REG_TRANS_ERR_STRING_SIZE 256 2678 2679 static int mlxsw_reg_trans_wait(struct mlxsw_reg_trans *trans) 2680 { 2681 char err_string[MLXSW_REG_TRANS_ERR_STRING_SIZE]; 2682 struct mlxsw_core *mlxsw_core = trans->core; 2683 int err; 2684 2685 wait_for_completion(&trans->completion); 2686 cancel_delayed_work_sync(&trans->timeout_dw); 2687 err = trans->err; 2688 2689 if (trans->retries) 2690 dev_warn(mlxsw_core->bus_info->dev, "EMAD retries (%d/%d) (tid=%llx)\n", 2691 trans->retries, MLXSW_EMAD_MAX_RETRY, trans->tid); 2692 if (err) { 2693 dev_err(mlxsw_core->bus_info->dev, "EMAD reg access failed (tid=%llx,reg_id=%x(%s),type=%s,status=%x(%s))\n", 2694 trans->tid, trans->reg->id, 2695 mlxsw_reg_id_str(trans->reg->id), 2696 mlxsw_core_reg_access_type_str(trans->type), 2697 trans->emad_status, 2698 mlxsw_emad_op_tlv_status_str(trans->emad_status)); 2699 2700 snprintf(err_string, MLXSW_REG_TRANS_ERR_STRING_SIZE, 2701 "(tid=%llx,reg_id=%x(%s)) %s (%s)\n", trans->tid, 2702 trans->reg->id, mlxsw_reg_id_str(trans->reg->id), 2703 mlxsw_emad_op_tlv_status_str(trans->emad_status), 2704 trans->emad_err_string ? trans->emad_err_string : ""); 2705 2706 trace_devlink_hwerr(priv_to_devlink(mlxsw_core), 2707 trans->emad_status, err_string); 2708 2709 kfree(trans->emad_err_string); 2710 } 2711 2712 list_del(&trans->bulk_list); 2713 kfree_rcu(trans, rcu); 2714 return err; 2715 } 2716 2717 int mlxsw_reg_trans_bulk_wait(struct list_head *bulk_list) 2718 { 2719 struct mlxsw_reg_trans *trans; 2720 struct mlxsw_reg_trans *tmp; 2721 int sum_err = 0; 2722 int err; 2723 2724 list_for_each_entry_safe(trans, tmp, bulk_list, bulk_list) { 2725 err = mlxsw_reg_trans_wait(trans); 2726 if (err && sum_err == 0) 2727 sum_err = err; /* first error to be returned */ 2728 } 2729 return sum_err; 2730 } 2731 EXPORT_SYMBOL(mlxsw_reg_trans_bulk_wait); 2732 2733 static int mlxsw_core_reg_access_cmd(struct mlxsw_core *mlxsw_core, 2734 const struct mlxsw_reg_info *reg, 2735 char *payload, 2736 enum mlxsw_core_reg_access_type type) 2737 { 2738 enum mlxsw_emad_op_tlv_status status; 2739 int err, n_retry; 2740 bool reset_ok; 2741 char *in_mbox, *out_mbox, *tmp; 2742 2743 dev_dbg(mlxsw_core->bus_info->dev, "Reg cmd access (reg_id=%x(%s),type=%s)\n", 2744 reg->id, mlxsw_reg_id_str(reg->id), 2745 mlxsw_core_reg_access_type_str(type)); 2746 2747 in_mbox = mlxsw_cmd_mbox_alloc(); 2748 if (!in_mbox) 2749 return -ENOMEM; 2750 2751 out_mbox = mlxsw_cmd_mbox_alloc(); 2752 if (!out_mbox) { 2753 err = -ENOMEM; 2754 goto free_in_mbox; 2755 } 2756 2757 mlxsw_emad_pack_op_tlv(in_mbox, reg, type, 2758 mlxsw_core_tid_get(mlxsw_core)); 2759 tmp = in_mbox + MLXSW_EMAD_OP_TLV_LEN * sizeof(u32); 2760 mlxsw_emad_pack_reg_tlv(tmp, reg, payload); 2761 2762 /* There is a special treatment needed for MRSR (reset) register. 2763 * The command interface will return error after the command 2764 * is executed, so tell the lower layer to expect it 2765 * and cope accordingly. 2766 */ 2767 reset_ok = reg->id == MLXSW_REG_MRSR_ID; 2768 2769 n_retry = 0; 2770 retry: 2771 err = mlxsw_cmd_access_reg(mlxsw_core, reset_ok, in_mbox, out_mbox); 2772 if (!err) { 2773 err = mlxsw_emad_process_status(out_mbox, &status); 2774 if (err) { 2775 if (err == -EAGAIN && n_retry++ < MLXSW_EMAD_MAX_RETRY) 2776 goto retry; 2777 dev_err(mlxsw_core->bus_info->dev, "Reg cmd access status failed (status=%x(%s))\n", 2778 status, mlxsw_emad_op_tlv_status_str(status)); 2779 } 2780 } 2781 2782 if (!err) 2783 memcpy(payload, mlxsw_emad_reg_payload_cmd(out_mbox), 2784 reg->len); 2785 2786 mlxsw_cmd_mbox_free(out_mbox); 2787 free_in_mbox: 2788 mlxsw_cmd_mbox_free(in_mbox); 2789 if (err) 2790 dev_err(mlxsw_core->bus_info->dev, "Reg cmd access failed (reg_id=%x(%s),type=%s)\n", 2791 reg->id, mlxsw_reg_id_str(reg->id), 2792 mlxsw_core_reg_access_type_str(type)); 2793 return err; 2794 } 2795 2796 static void mlxsw_core_reg_access_cb(struct mlxsw_core *mlxsw_core, 2797 char *payload, size_t payload_len, 2798 unsigned long cb_priv) 2799 { 2800 char *orig_payload = (char *) cb_priv; 2801 2802 memcpy(orig_payload, payload, payload_len); 2803 } 2804 2805 static int mlxsw_core_reg_access(struct mlxsw_core *mlxsw_core, 2806 const struct mlxsw_reg_info *reg, 2807 char *payload, 2808 enum mlxsw_core_reg_access_type type) 2809 { 2810 LIST_HEAD(bulk_list); 2811 int err; 2812 2813 /* During initialization EMAD interface is not available to us, 2814 * so we default to command interface. We switch to EMAD interface 2815 * after setting the appropriate traps. 2816 */ 2817 if (!mlxsw_core->emad.use_emad) 2818 return mlxsw_core_reg_access_cmd(mlxsw_core, reg, 2819 payload, type); 2820 2821 err = mlxsw_core_reg_access_emad(mlxsw_core, reg, 2822 payload, type, &bulk_list, 2823 mlxsw_core_reg_access_cb, 2824 (unsigned long) payload); 2825 if (err) 2826 return err; 2827 return mlxsw_reg_trans_bulk_wait(&bulk_list); 2828 } 2829 2830 int mlxsw_reg_query(struct mlxsw_core *mlxsw_core, 2831 const struct mlxsw_reg_info *reg, char *payload) 2832 { 2833 return mlxsw_core_reg_access(mlxsw_core, reg, payload, 2834 MLXSW_CORE_REG_ACCESS_TYPE_QUERY); 2835 } 2836 EXPORT_SYMBOL(mlxsw_reg_query); 2837 2838 int mlxsw_reg_write(struct mlxsw_core *mlxsw_core, 2839 const struct mlxsw_reg_info *reg, char *payload) 2840 { 2841 return mlxsw_core_reg_access(mlxsw_core, reg, payload, 2842 MLXSW_CORE_REG_ACCESS_TYPE_WRITE); 2843 } 2844 EXPORT_SYMBOL(mlxsw_reg_write); 2845 2846 void mlxsw_core_skb_receive(struct mlxsw_core *mlxsw_core, struct sk_buff *skb, 2847 struct mlxsw_rx_info *rx_info) 2848 { 2849 struct mlxsw_rx_listener_item *rxl_item; 2850 const struct mlxsw_rx_listener *rxl; 2851 u16 local_port; 2852 bool found = false; 2853 2854 if (rx_info->is_lag) { 2855 dev_dbg_ratelimited(mlxsw_core->bus_info->dev, "%s: lag_id = %d, lag_port_index = 0x%x\n", 2856 __func__, rx_info->u.lag_id, 2857 rx_info->trap_id); 2858 /* Upper layer does not care if the skb came from LAG or not, 2859 * so just get the local_port for the lag port and push it up. 2860 */ 2861 local_port = mlxsw_core_lag_mapping_get(mlxsw_core, 2862 rx_info->u.lag_id, 2863 rx_info->lag_port_index); 2864 } else { 2865 local_port = rx_info->u.sys_port; 2866 } 2867 2868 dev_dbg_ratelimited(mlxsw_core->bus_info->dev, "%s: local_port = %d, trap_id = 0x%x\n", 2869 __func__, local_port, rx_info->trap_id); 2870 2871 if ((rx_info->trap_id >= MLXSW_TRAP_ID_MAX) || 2872 (local_port >= mlxsw_core->max_ports)) 2873 goto drop; 2874 2875 rcu_read_lock(); 2876 list_for_each_entry_rcu(rxl_item, &mlxsw_core->rx_listener_list, list) { 2877 rxl = &rxl_item->rxl; 2878 if ((rxl->local_port == MLXSW_PORT_DONT_CARE || 2879 rxl->local_port == local_port) && 2880 rxl->trap_id == rx_info->trap_id && 2881 rxl->mirror_reason == rx_info->mirror_reason) { 2882 if (rxl_item->enabled) 2883 found = true; 2884 break; 2885 } 2886 } 2887 if (!found) { 2888 rcu_read_unlock(); 2889 goto drop; 2890 } 2891 2892 rxl->func(skb, local_port, rxl_item->priv); 2893 rcu_read_unlock(); 2894 return; 2895 2896 drop: 2897 dev_kfree_skb(skb); 2898 } 2899 EXPORT_SYMBOL(mlxsw_core_skb_receive); 2900 2901 static int mlxsw_core_lag_mapping_index(struct mlxsw_core *mlxsw_core, 2902 u16 lag_id, u8 port_index) 2903 { 2904 return MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG_MEMBERS) * lag_id + 2905 port_index; 2906 } 2907 2908 void mlxsw_core_lag_mapping_set(struct mlxsw_core *mlxsw_core, 2909 u16 lag_id, u8 port_index, u16 local_port) 2910 { 2911 int index = mlxsw_core_lag_mapping_index(mlxsw_core, 2912 lag_id, port_index); 2913 2914 mlxsw_core->lag.mapping[index] = local_port; 2915 } 2916 EXPORT_SYMBOL(mlxsw_core_lag_mapping_set); 2917 2918 u16 mlxsw_core_lag_mapping_get(struct mlxsw_core *mlxsw_core, 2919 u16 lag_id, u8 port_index) 2920 { 2921 int index = mlxsw_core_lag_mapping_index(mlxsw_core, 2922 lag_id, port_index); 2923 2924 return mlxsw_core->lag.mapping[index]; 2925 } 2926 EXPORT_SYMBOL(mlxsw_core_lag_mapping_get); 2927 2928 void mlxsw_core_lag_mapping_clear(struct mlxsw_core *mlxsw_core, 2929 u16 lag_id, u16 local_port) 2930 { 2931 int i; 2932 2933 for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG_MEMBERS); i++) { 2934 int index = mlxsw_core_lag_mapping_index(mlxsw_core, 2935 lag_id, i); 2936 2937 if (mlxsw_core->lag.mapping[index] == local_port) 2938 mlxsw_core->lag.mapping[index] = 0; 2939 } 2940 } 2941 EXPORT_SYMBOL(mlxsw_core_lag_mapping_clear); 2942 2943 bool mlxsw_core_res_valid(struct mlxsw_core *mlxsw_core, 2944 enum mlxsw_res_id res_id) 2945 { 2946 return mlxsw_res_valid(&mlxsw_core->res, res_id); 2947 } 2948 EXPORT_SYMBOL(mlxsw_core_res_valid); 2949 2950 u64 mlxsw_core_res_get(struct mlxsw_core *mlxsw_core, 2951 enum mlxsw_res_id res_id) 2952 { 2953 return mlxsw_res_get(&mlxsw_core->res, res_id); 2954 } 2955 EXPORT_SYMBOL(mlxsw_core_res_get); 2956 2957 static int __mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u16 local_port, 2958 enum devlink_port_flavour flavour, 2959 u32 port_number, bool split, 2960 u32 split_port_subnumber, 2961 bool splittable, u32 lanes, 2962 const unsigned char *switch_id, 2963 unsigned char switch_id_len) 2964 { 2965 struct devlink *devlink = priv_to_devlink(mlxsw_core); 2966 struct mlxsw_core_port *mlxsw_core_port = 2967 &mlxsw_core->ports[local_port]; 2968 struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port; 2969 struct devlink_port_attrs attrs = {}; 2970 int err; 2971 2972 attrs.split = split; 2973 attrs.lanes = lanes; 2974 attrs.splittable = splittable; 2975 attrs.flavour = flavour; 2976 attrs.phys.port_number = port_number; 2977 attrs.phys.split_subport_number = split_port_subnumber; 2978 memcpy(attrs.switch_id.id, switch_id, switch_id_len); 2979 attrs.switch_id.id_len = switch_id_len; 2980 mlxsw_core_port->local_port = local_port; 2981 devlink_port_attrs_set(devlink_port, &attrs); 2982 err = devl_port_register(devlink, devlink_port, local_port); 2983 if (err) 2984 memset(mlxsw_core_port, 0, sizeof(*mlxsw_core_port)); 2985 return err; 2986 } 2987 2988 static void __mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u16 local_port) 2989 { 2990 struct mlxsw_core_port *mlxsw_core_port = 2991 &mlxsw_core->ports[local_port]; 2992 struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port; 2993 2994 devl_port_unregister(devlink_port); 2995 memset(mlxsw_core_port, 0, sizeof(*mlxsw_core_port)); 2996 } 2997 2998 int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u16 local_port, 2999 u32 port_number, bool split, 3000 u32 split_port_subnumber, 3001 bool splittable, u32 lanes, 3002 const unsigned char *switch_id, 3003 unsigned char switch_id_len) 3004 { 3005 int err; 3006 3007 err = __mlxsw_core_port_init(mlxsw_core, local_port, 3008 DEVLINK_PORT_FLAVOUR_PHYSICAL, 3009 port_number, split, split_port_subnumber, 3010 splittable, lanes, 3011 switch_id, switch_id_len); 3012 if (err) 3013 return err; 3014 3015 atomic_inc(&mlxsw_core->active_ports_count); 3016 return 0; 3017 } 3018 EXPORT_SYMBOL(mlxsw_core_port_init); 3019 3020 void mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u16 local_port) 3021 { 3022 atomic_dec(&mlxsw_core->active_ports_count); 3023 3024 __mlxsw_core_port_fini(mlxsw_core, local_port); 3025 } 3026 EXPORT_SYMBOL(mlxsw_core_port_fini); 3027 3028 int mlxsw_core_cpu_port_init(struct mlxsw_core *mlxsw_core, 3029 void *port_driver_priv, 3030 const unsigned char *switch_id, 3031 unsigned char switch_id_len) 3032 { 3033 struct mlxsw_core_port *mlxsw_core_port = 3034 &mlxsw_core->ports[MLXSW_PORT_CPU_PORT]; 3035 int err; 3036 3037 err = __mlxsw_core_port_init(mlxsw_core, MLXSW_PORT_CPU_PORT, 3038 DEVLINK_PORT_FLAVOUR_CPU, 3039 0, false, 0, false, 0, 3040 switch_id, switch_id_len); 3041 if (err) 3042 return err; 3043 3044 mlxsw_core_port->port_driver_priv = port_driver_priv; 3045 return 0; 3046 } 3047 EXPORT_SYMBOL(mlxsw_core_cpu_port_init); 3048 3049 void mlxsw_core_cpu_port_fini(struct mlxsw_core *mlxsw_core) 3050 { 3051 __mlxsw_core_port_fini(mlxsw_core, MLXSW_PORT_CPU_PORT); 3052 } 3053 EXPORT_SYMBOL(mlxsw_core_cpu_port_fini); 3054 3055 void mlxsw_core_port_eth_set(struct mlxsw_core *mlxsw_core, u16 local_port, 3056 void *port_driver_priv, struct net_device *dev) 3057 { 3058 struct mlxsw_core_port *mlxsw_core_port = 3059 &mlxsw_core->ports[local_port]; 3060 struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port; 3061 3062 mlxsw_core_port->port_driver_priv = port_driver_priv; 3063 devlink_port_type_eth_set(devlink_port, dev); 3064 } 3065 EXPORT_SYMBOL(mlxsw_core_port_eth_set); 3066 3067 void mlxsw_core_port_ib_set(struct mlxsw_core *mlxsw_core, u16 local_port, 3068 void *port_driver_priv) 3069 { 3070 struct mlxsw_core_port *mlxsw_core_port = 3071 &mlxsw_core->ports[local_port]; 3072 struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port; 3073 3074 mlxsw_core_port->port_driver_priv = port_driver_priv; 3075 devlink_port_type_ib_set(devlink_port, NULL); 3076 } 3077 EXPORT_SYMBOL(mlxsw_core_port_ib_set); 3078 3079 void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u16 local_port, 3080 void *port_driver_priv) 3081 { 3082 struct mlxsw_core_port *mlxsw_core_port = 3083 &mlxsw_core->ports[local_port]; 3084 struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port; 3085 3086 mlxsw_core_port->port_driver_priv = port_driver_priv; 3087 devlink_port_type_clear(devlink_port); 3088 } 3089 EXPORT_SYMBOL(mlxsw_core_port_clear); 3090 3091 enum devlink_port_type mlxsw_core_port_type_get(struct mlxsw_core *mlxsw_core, 3092 u16 local_port) 3093 { 3094 struct mlxsw_core_port *mlxsw_core_port = 3095 &mlxsw_core->ports[local_port]; 3096 struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port; 3097 3098 return devlink_port->type; 3099 } 3100 EXPORT_SYMBOL(mlxsw_core_port_type_get); 3101 3102 3103 struct devlink_port * 3104 mlxsw_core_port_devlink_port_get(struct mlxsw_core *mlxsw_core, 3105 u16 local_port) 3106 { 3107 struct mlxsw_core_port *mlxsw_core_port = 3108 &mlxsw_core->ports[local_port]; 3109 struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port; 3110 3111 return devlink_port; 3112 } 3113 EXPORT_SYMBOL(mlxsw_core_port_devlink_port_get); 3114 3115 bool mlxsw_core_port_is_xm(const struct mlxsw_core *mlxsw_core, u16 local_port) 3116 { 3117 const struct mlxsw_bus_info *bus_info = mlxsw_core->bus_info; 3118 int i; 3119 3120 for (i = 0; i < bus_info->xm_local_ports_count; i++) 3121 if (bus_info->xm_local_ports[i] == local_port) 3122 return true; 3123 return false; 3124 } 3125 EXPORT_SYMBOL(mlxsw_core_port_is_xm); 3126 3127 struct mlxsw_env *mlxsw_core_env(const struct mlxsw_core *mlxsw_core) 3128 { 3129 return mlxsw_core->env; 3130 } 3131 3132 static void mlxsw_core_buf_dump_dbg(struct mlxsw_core *mlxsw_core, 3133 const char *buf, size_t size) 3134 { 3135 __be32 *m = (__be32 *) buf; 3136 int i; 3137 int count = size / sizeof(__be32); 3138 3139 for (i = count - 1; i >= 0; i--) 3140 if (m[i]) 3141 break; 3142 i++; 3143 count = i ? i : 1; 3144 for (i = 0; i < count; i += 4) 3145 dev_dbg(mlxsw_core->bus_info->dev, "%04x - %08x %08x %08x %08x\n", 3146 i * 4, be32_to_cpu(m[i]), be32_to_cpu(m[i + 1]), 3147 be32_to_cpu(m[i + 2]), be32_to_cpu(m[i + 3])); 3148 } 3149 3150 int mlxsw_cmd_exec(struct mlxsw_core *mlxsw_core, u16 opcode, u8 opcode_mod, 3151 u32 in_mod, bool out_mbox_direct, bool reset_ok, 3152 char *in_mbox, size_t in_mbox_size, 3153 char *out_mbox, size_t out_mbox_size) 3154 { 3155 u8 status; 3156 int err; 3157 3158 BUG_ON(in_mbox_size % sizeof(u32) || out_mbox_size % sizeof(u32)); 3159 if (!mlxsw_core->bus->cmd_exec) 3160 return -EOPNOTSUPP; 3161 3162 dev_dbg(mlxsw_core->bus_info->dev, "Cmd exec (opcode=%x(%s),opcode_mod=%x,in_mod=%x)\n", 3163 opcode, mlxsw_cmd_opcode_str(opcode), opcode_mod, in_mod); 3164 if (in_mbox) { 3165 dev_dbg(mlxsw_core->bus_info->dev, "Input mailbox:\n"); 3166 mlxsw_core_buf_dump_dbg(mlxsw_core, in_mbox, in_mbox_size); 3167 } 3168 3169 err = mlxsw_core->bus->cmd_exec(mlxsw_core->bus_priv, opcode, 3170 opcode_mod, in_mod, out_mbox_direct, 3171 in_mbox, in_mbox_size, 3172 out_mbox, out_mbox_size, &status); 3173 3174 if (!err && out_mbox) { 3175 dev_dbg(mlxsw_core->bus_info->dev, "Output mailbox:\n"); 3176 mlxsw_core_buf_dump_dbg(mlxsw_core, out_mbox, out_mbox_size); 3177 } 3178 3179 if (reset_ok && err == -EIO && 3180 status == MLXSW_CMD_STATUS_RUNNING_RESET) { 3181 err = 0; 3182 } else if (err == -EIO && status != MLXSW_CMD_STATUS_OK) { 3183 dev_err(mlxsw_core->bus_info->dev, "Cmd exec failed (opcode=%x(%s),opcode_mod=%x,in_mod=%x,status=%x(%s))\n", 3184 opcode, mlxsw_cmd_opcode_str(opcode), opcode_mod, 3185 in_mod, status, mlxsw_cmd_status_str(status)); 3186 } else if (err == -ETIMEDOUT) { 3187 dev_err(mlxsw_core->bus_info->dev, "Cmd exec timed-out (opcode=%x(%s),opcode_mod=%x,in_mod=%x)\n", 3188 opcode, mlxsw_cmd_opcode_str(opcode), opcode_mod, 3189 in_mod); 3190 } 3191 3192 return err; 3193 } 3194 EXPORT_SYMBOL(mlxsw_cmd_exec); 3195 3196 int mlxsw_core_schedule_dw(struct delayed_work *dwork, unsigned long delay) 3197 { 3198 return queue_delayed_work(mlxsw_wq, dwork, delay); 3199 } 3200 EXPORT_SYMBOL(mlxsw_core_schedule_dw); 3201 3202 bool mlxsw_core_schedule_work(struct work_struct *work) 3203 { 3204 return queue_work(mlxsw_owq, work); 3205 } 3206 EXPORT_SYMBOL(mlxsw_core_schedule_work); 3207 3208 void mlxsw_core_flush_owq(void) 3209 { 3210 flush_workqueue(mlxsw_owq); 3211 } 3212 EXPORT_SYMBOL(mlxsw_core_flush_owq); 3213 3214 int mlxsw_core_kvd_sizes_get(struct mlxsw_core *mlxsw_core, 3215 const struct mlxsw_config_profile *profile, 3216 u64 *p_single_size, u64 *p_double_size, 3217 u64 *p_linear_size) 3218 { 3219 struct mlxsw_driver *driver = mlxsw_core->driver; 3220 3221 if (!driver->kvd_sizes_get) 3222 return -EINVAL; 3223 3224 return driver->kvd_sizes_get(mlxsw_core, profile, 3225 p_single_size, p_double_size, 3226 p_linear_size); 3227 } 3228 EXPORT_SYMBOL(mlxsw_core_kvd_sizes_get); 3229 3230 int mlxsw_core_resources_query(struct mlxsw_core *mlxsw_core, char *mbox, 3231 struct mlxsw_res *res) 3232 { 3233 int index, i; 3234 u64 data; 3235 u16 id; 3236 int err; 3237 3238 mlxsw_cmd_mbox_zero(mbox); 3239 3240 for (index = 0; index < MLXSW_CMD_QUERY_RESOURCES_MAX_QUERIES; 3241 index++) { 3242 err = mlxsw_cmd_query_resources(mlxsw_core, mbox, index); 3243 if (err) 3244 return err; 3245 3246 for (i = 0; i < MLXSW_CMD_QUERY_RESOURCES_PER_QUERY; i++) { 3247 id = mlxsw_cmd_mbox_query_resource_id_get(mbox, i); 3248 data = mlxsw_cmd_mbox_query_resource_data_get(mbox, i); 3249 3250 if (id == MLXSW_CMD_QUERY_RESOURCES_TABLE_END_ID) 3251 return 0; 3252 3253 mlxsw_res_parse(res, id, data); 3254 } 3255 } 3256 3257 /* If after MLXSW_RESOURCES_QUERY_MAX_QUERIES we still didn't get 3258 * MLXSW_RESOURCES_TABLE_END_ID, something went bad in the FW. 3259 */ 3260 return -EIO; 3261 } 3262 EXPORT_SYMBOL(mlxsw_core_resources_query); 3263 3264 u32 mlxsw_core_read_frc_h(struct mlxsw_core *mlxsw_core) 3265 { 3266 return mlxsw_core->bus->read_frc_h(mlxsw_core->bus_priv); 3267 } 3268 EXPORT_SYMBOL(mlxsw_core_read_frc_h); 3269 3270 u32 mlxsw_core_read_frc_l(struct mlxsw_core *mlxsw_core) 3271 { 3272 return mlxsw_core->bus->read_frc_l(mlxsw_core->bus_priv); 3273 } 3274 EXPORT_SYMBOL(mlxsw_core_read_frc_l); 3275 3276 void mlxsw_core_emad_string_tlv_enable(struct mlxsw_core *mlxsw_core) 3277 { 3278 mlxsw_core->emad.enable_string_tlv = true; 3279 } 3280 EXPORT_SYMBOL(mlxsw_core_emad_string_tlv_enable); 3281 3282 static int __init mlxsw_core_module_init(void) 3283 { 3284 int err; 3285 3286 mlxsw_wq = alloc_workqueue(mlxsw_core_driver_name, 0, 0); 3287 if (!mlxsw_wq) 3288 return -ENOMEM; 3289 mlxsw_owq = alloc_ordered_workqueue("%s_ordered", 0, 3290 mlxsw_core_driver_name); 3291 if (!mlxsw_owq) { 3292 err = -ENOMEM; 3293 goto err_alloc_ordered_workqueue; 3294 } 3295 return 0; 3296 3297 err_alloc_ordered_workqueue: 3298 destroy_workqueue(mlxsw_wq); 3299 return err; 3300 } 3301 3302 static void __exit mlxsw_core_module_exit(void) 3303 { 3304 destroy_workqueue(mlxsw_owq); 3305 destroy_workqueue(mlxsw_wq); 3306 } 3307 3308 module_init(mlxsw_core_module_init); 3309 module_exit(mlxsw_core_module_exit); 3310 3311 MODULE_LICENSE("Dual BSD/GPL"); 3312 MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>"); 3313 MODULE_DESCRIPTION("Mellanox switch device core driver"); 3314