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 <asm/byteorder.h> 24 #include <net/devlink.h> 25 #include <trace/events/devlink.h> 26 27 #include "core.h" 28 #include "item.h" 29 #include "cmd.h" 30 #include "port.h" 31 #include "trap.h" 32 #include "emad.h" 33 #include "reg.h" 34 #include "resources.h" 35 36 static LIST_HEAD(mlxsw_core_driver_list); 37 static DEFINE_SPINLOCK(mlxsw_core_driver_list_lock); 38 39 static const char mlxsw_core_driver_name[] = "mlxsw_core"; 40 41 static struct workqueue_struct *mlxsw_wq; 42 static struct workqueue_struct *mlxsw_owq; 43 44 struct mlxsw_core_port { 45 struct devlink_port devlink_port; 46 void *port_driver_priv; 47 u8 local_port; 48 }; 49 50 void *mlxsw_core_port_driver_priv(struct mlxsw_core_port *mlxsw_core_port) 51 { 52 return mlxsw_core_port->port_driver_priv; 53 } 54 EXPORT_SYMBOL(mlxsw_core_port_driver_priv); 55 56 static bool mlxsw_core_port_check(struct mlxsw_core_port *mlxsw_core_port) 57 { 58 return mlxsw_core_port->port_driver_priv != NULL; 59 } 60 61 struct mlxsw_core { 62 struct mlxsw_driver *driver; 63 const struct mlxsw_bus *bus; 64 void *bus_priv; 65 const struct mlxsw_bus_info *bus_info; 66 struct workqueue_struct *emad_wq; 67 struct list_head rx_listener_list; 68 struct list_head event_listener_list; 69 struct { 70 atomic64_t tid; 71 struct list_head trans_list; 72 spinlock_t trans_list_lock; /* protects trans_list writes */ 73 bool use_emad; 74 bool enable_string_tlv; 75 } emad; 76 struct { 77 u8 *mapping; /* lag_id+port_index to local_port mapping */ 78 } lag; 79 struct mlxsw_res res; 80 struct mlxsw_hwmon *hwmon; 81 struct mlxsw_thermal *thermal; 82 struct mlxsw_core_port *ports; 83 unsigned int max_ports; 84 bool fw_flash_in_progress; 85 unsigned long driver_priv[0]; 86 /* driver_priv has to be always the last item */ 87 }; 88 89 #define MLXSW_PORT_MAX_PORTS_DEFAULT 0x40 90 91 static int mlxsw_ports_init(struct mlxsw_core *mlxsw_core) 92 { 93 /* Switch ports are numbered from 1 to queried value */ 94 if (MLXSW_CORE_RES_VALID(mlxsw_core, MAX_SYSTEM_PORT)) 95 mlxsw_core->max_ports = MLXSW_CORE_RES_GET(mlxsw_core, 96 MAX_SYSTEM_PORT) + 1; 97 else 98 mlxsw_core->max_ports = MLXSW_PORT_MAX_PORTS_DEFAULT + 1; 99 100 mlxsw_core->ports = kcalloc(mlxsw_core->max_ports, 101 sizeof(struct mlxsw_core_port), GFP_KERNEL); 102 if (!mlxsw_core->ports) 103 return -ENOMEM; 104 105 return 0; 106 } 107 108 static void mlxsw_ports_fini(struct mlxsw_core *mlxsw_core) 109 { 110 kfree(mlxsw_core->ports); 111 } 112 113 unsigned int mlxsw_core_max_ports(const struct mlxsw_core *mlxsw_core) 114 { 115 return mlxsw_core->max_ports; 116 } 117 EXPORT_SYMBOL(mlxsw_core_max_ports); 118 119 void *mlxsw_core_driver_priv(struct mlxsw_core *mlxsw_core) 120 { 121 return mlxsw_core->driver_priv; 122 } 123 EXPORT_SYMBOL(mlxsw_core_driver_priv); 124 125 bool mlxsw_core_res_query_enabled(const struct mlxsw_core *mlxsw_core) 126 { 127 return mlxsw_core->driver->res_query_enabled; 128 } 129 EXPORT_SYMBOL(mlxsw_core_res_query_enabled); 130 131 bool 132 mlxsw_core_fw_rev_minor_subminor_validate(const struct mlxsw_fw_rev *rev, 133 const struct mlxsw_fw_rev *req_rev) 134 { 135 return rev->minor > req_rev->minor || 136 (rev->minor == req_rev->minor && 137 rev->subminor >= req_rev->subminor); 138 } 139 EXPORT_SYMBOL(mlxsw_core_fw_rev_minor_subminor_validate); 140 141 struct mlxsw_rx_listener_item { 142 struct list_head list; 143 struct mlxsw_rx_listener rxl; 144 void *priv; 145 }; 146 147 struct mlxsw_event_listener_item { 148 struct list_head list; 149 struct mlxsw_event_listener el; 150 void *priv; 151 }; 152 153 /****************** 154 * EMAD processing 155 ******************/ 156 157 /* emad_eth_hdr_dmac 158 * Destination MAC in EMAD's Ethernet header. 159 * Must be set to 01:02:c9:00:00:01 160 */ 161 MLXSW_ITEM_BUF(emad, eth_hdr, dmac, 0x00, 6); 162 163 /* emad_eth_hdr_smac 164 * Source MAC in EMAD's Ethernet header. 165 * Must be set to 00:02:c9:01:02:03 166 */ 167 MLXSW_ITEM_BUF(emad, eth_hdr, smac, 0x06, 6); 168 169 /* emad_eth_hdr_ethertype 170 * Ethertype in EMAD's Ethernet header. 171 * Must be set to 0x8932 172 */ 173 MLXSW_ITEM32(emad, eth_hdr, ethertype, 0x0C, 16, 16); 174 175 /* emad_eth_hdr_mlx_proto 176 * Mellanox protocol. 177 * Must be set to 0x0. 178 */ 179 MLXSW_ITEM32(emad, eth_hdr, mlx_proto, 0x0C, 8, 8); 180 181 /* emad_eth_hdr_ver 182 * Mellanox protocol version. 183 * Must be set to 0x0. 184 */ 185 MLXSW_ITEM32(emad, eth_hdr, ver, 0x0C, 4, 4); 186 187 /* emad_op_tlv_type 188 * Type of the TLV. 189 * Must be set to 0x1 (operation TLV). 190 */ 191 MLXSW_ITEM32(emad, op_tlv, type, 0x00, 27, 5); 192 193 /* emad_op_tlv_len 194 * Length of the operation TLV in u32. 195 * Must be set to 0x4. 196 */ 197 MLXSW_ITEM32(emad, op_tlv, len, 0x00, 16, 11); 198 199 /* emad_op_tlv_dr 200 * Direct route bit. Setting to 1 indicates the EMAD is a direct route 201 * EMAD. DR TLV must follow. 202 * 203 * Note: Currently not supported and must not be set. 204 */ 205 MLXSW_ITEM32(emad, op_tlv, dr, 0x00, 15, 1); 206 207 /* emad_op_tlv_status 208 * Returned status in case of EMAD response. Must be set to 0 in case 209 * of EMAD request. 210 * 0x0 - success 211 * 0x1 - device is busy. Requester should retry 212 * 0x2 - Mellanox protocol version not supported 213 * 0x3 - unknown TLV 214 * 0x4 - register not supported 215 * 0x5 - operation class not supported 216 * 0x6 - EMAD method not supported 217 * 0x7 - bad parameter (e.g. port out of range) 218 * 0x8 - resource not available 219 * 0x9 - message receipt acknowledgment. Requester should retry 220 * 0x70 - internal error 221 */ 222 MLXSW_ITEM32(emad, op_tlv, status, 0x00, 8, 7); 223 224 /* emad_op_tlv_register_id 225 * Register ID of register within register TLV. 226 */ 227 MLXSW_ITEM32(emad, op_tlv, register_id, 0x04, 16, 16); 228 229 /* emad_op_tlv_r 230 * Response bit. Setting to 1 indicates Response, otherwise request. 231 */ 232 MLXSW_ITEM32(emad, op_tlv, r, 0x04, 15, 1); 233 234 /* emad_op_tlv_method 235 * EMAD method type. 236 * 0x1 - query 237 * 0x2 - write 238 * 0x3 - send (currently not supported) 239 * 0x4 - event 240 */ 241 MLXSW_ITEM32(emad, op_tlv, method, 0x04, 8, 7); 242 243 /* emad_op_tlv_class 244 * EMAD operation class. Must be set to 0x1 (REG_ACCESS). 245 */ 246 MLXSW_ITEM32(emad, op_tlv, class, 0x04, 0, 8); 247 248 /* emad_op_tlv_tid 249 * EMAD transaction ID. Used for pairing request and response EMADs. 250 */ 251 MLXSW_ITEM64(emad, op_tlv, tid, 0x08, 0, 64); 252 253 /* emad_string_tlv_type 254 * Type of the TLV. 255 * Must be set to 0x2 (string TLV). 256 */ 257 MLXSW_ITEM32(emad, string_tlv, type, 0x00, 27, 5); 258 259 /* emad_string_tlv_len 260 * Length of the string TLV in u32. 261 */ 262 MLXSW_ITEM32(emad, string_tlv, len, 0x00, 16, 11); 263 264 #define MLXSW_EMAD_STRING_TLV_STRING_LEN 128 265 266 /* emad_string_tlv_string 267 * String provided by the device's firmware in case of erroneous register access 268 */ 269 MLXSW_ITEM_BUF(emad, string_tlv, string, 0x04, 270 MLXSW_EMAD_STRING_TLV_STRING_LEN); 271 272 /* emad_reg_tlv_type 273 * Type of the TLV. 274 * Must be set to 0x3 (register TLV). 275 */ 276 MLXSW_ITEM32(emad, reg_tlv, type, 0x00, 27, 5); 277 278 /* emad_reg_tlv_len 279 * Length of the operation TLV in u32. 280 */ 281 MLXSW_ITEM32(emad, reg_tlv, len, 0x00, 16, 11); 282 283 /* emad_end_tlv_type 284 * Type of the TLV. 285 * Must be set to 0x0 (end TLV). 286 */ 287 MLXSW_ITEM32(emad, end_tlv, type, 0x00, 27, 5); 288 289 /* emad_end_tlv_len 290 * Length of the end TLV in u32. 291 * Must be set to 1. 292 */ 293 MLXSW_ITEM32(emad, end_tlv, len, 0x00, 16, 11); 294 295 enum mlxsw_core_reg_access_type { 296 MLXSW_CORE_REG_ACCESS_TYPE_QUERY, 297 MLXSW_CORE_REG_ACCESS_TYPE_WRITE, 298 }; 299 300 static inline const char * 301 mlxsw_core_reg_access_type_str(enum mlxsw_core_reg_access_type type) 302 { 303 switch (type) { 304 case MLXSW_CORE_REG_ACCESS_TYPE_QUERY: 305 return "query"; 306 case MLXSW_CORE_REG_ACCESS_TYPE_WRITE: 307 return "write"; 308 } 309 BUG(); 310 } 311 312 static void mlxsw_emad_pack_end_tlv(char *end_tlv) 313 { 314 mlxsw_emad_end_tlv_type_set(end_tlv, MLXSW_EMAD_TLV_TYPE_END); 315 mlxsw_emad_end_tlv_len_set(end_tlv, MLXSW_EMAD_END_TLV_LEN); 316 } 317 318 static void mlxsw_emad_pack_reg_tlv(char *reg_tlv, 319 const struct mlxsw_reg_info *reg, 320 char *payload) 321 { 322 mlxsw_emad_reg_tlv_type_set(reg_tlv, MLXSW_EMAD_TLV_TYPE_REG); 323 mlxsw_emad_reg_tlv_len_set(reg_tlv, reg->len / sizeof(u32) + 1); 324 memcpy(reg_tlv + sizeof(u32), payload, reg->len); 325 } 326 327 static void mlxsw_emad_pack_string_tlv(char *string_tlv) 328 { 329 mlxsw_emad_string_tlv_type_set(string_tlv, MLXSW_EMAD_TLV_TYPE_STRING); 330 mlxsw_emad_string_tlv_len_set(string_tlv, MLXSW_EMAD_STRING_TLV_LEN); 331 } 332 333 static void mlxsw_emad_pack_op_tlv(char *op_tlv, 334 const struct mlxsw_reg_info *reg, 335 enum mlxsw_core_reg_access_type type, 336 u64 tid) 337 { 338 mlxsw_emad_op_tlv_type_set(op_tlv, MLXSW_EMAD_TLV_TYPE_OP); 339 mlxsw_emad_op_tlv_len_set(op_tlv, MLXSW_EMAD_OP_TLV_LEN); 340 mlxsw_emad_op_tlv_dr_set(op_tlv, 0); 341 mlxsw_emad_op_tlv_status_set(op_tlv, 0); 342 mlxsw_emad_op_tlv_register_id_set(op_tlv, reg->id); 343 mlxsw_emad_op_tlv_r_set(op_tlv, MLXSW_EMAD_OP_TLV_REQUEST); 344 if (type == MLXSW_CORE_REG_ACCESS_TYPE_QUERY) 345 mlxsw_emad_op_tlv_method_set(op_tlv, 346 MLXSW_EMAD_OP_TLV_METHOD_QUERY); 347 else 348 mlxsw_emad_op_tlv_method_set(op_tlv, 349 MLXSW_EMAD_OP_TLV_METHOD_WRITE); 350 mlxsw_emad_op_tlv_class_set(op_tlv, 351 MLXSW_EMAD_OP_TLV_CLASS_REG_ACCESS); 352 mlxsw_emad_op_tlv_tid_set(op_tlv, tid); 353 } 354 355 static int mlxsw_emad_construct_eth_hdr(struct sk_buff *skb) 356 { 357 char *eth_hdr = skb_push(skb, MLXSW_EMAD_ETH_HDR_LEN); 358 359 mlxsw_emad_eth_hdr_dmac_memcpy_to(eth_hdr, MLXSW_EMAD_EH_DMAC); 360 mlxsw_emad_eth_hdr_smac_memcpy_to(eth_hdr, MLXSW_EMAD_EH_SMAC); 361 mlxsw_emad_eth_hdr_ethertype_set(eth_hdr, MLXSW_EMAD_EH_ETHERTYPE); 362 mlxsw_emad_eth_hdr_mlx_proto_set(eth_hdr, MLXSW_EMAD_EH_MLX_PROTO); 363 mlxsw_emad_eth_hdr_ver_set(eth_hdr, MLXSW_EMAD_EH_PROTO_VERSION); 364 365 skb_reset_mac_header(skb); 366 367 return 0; 368 } 369 370 static void mlxsw_emad_construct(struct sk_buff *skb, 371 const struct mlxsw_reg_info *reg, 372 char *payload, 373 enum mlxsw_core_reg_access_type type, 374 u64 tid, bool enable_string_tlv) 375 { 376 char *buf; 377 378 buf = skb_push(skb, MLXSW_EMAD_END_TLV_LEN * sizeof(u32)); 379 mlxsw_emad_pack_end_tlv(buf); 380 381 buf = skb_push(skb, reg->len + sizeof(u32)); 382 mlxsw_emad_pack_reg_tlv(buf, reg, payload); 383 384 if (enable_string_tlv) { 385 buf = skb_push(skb, MLXSW_EMAD_STRING_TLV_LEN * sizeof(u32)); 386 mlxsw_emad_pack_string_tlv(buf); 387 } 388 389 buf = skb_push(skb, MLXSW_EMAD_OP_TLV_LEN * sizeof(u32)); 390 mlxsw_emad_pack_op_tlv(buf, reg, type, tid); 391 392 mlxsw_emad_construct_eth_hdr(skb); 393 } 394 395 struct mlxsw_emad_tlv_offsets { 396 u16 op_tlv; 397 u16 string_tlv; 398 u16 reg_tlv; 399 }; 400 401 static bool mlxsw_emad_tlv_is_string_tlv(const char *tlv) 402 { 403 u8 tlv_type = mlxsw_emad_string_tlv_type_get(tlv); 404 405 return tlv_type == MLXSW_EMAD_TLV_TYPE_STRING; 406 } 407 408 static void mlxsw_emad_tlv_parse(struct sk_buff *skb) 409 { 410 struct mlxsw_emad_tlv_offsets *offsets = 411 (struct mlxsw_emad_tlv_offsets *) skb->cb; 412 413 offsets->op_tlv = MLXSW_EMAD_ETH_HDR_LEN; 414 offsets->string_tlv = 0; 415 offsets->reg_tlv = MLXSW_EMAD_ETH_HDR_LEN + 416 MLXSW_EMAD_OP_TLV_LEN * sizeof(u32); 417 418 /* If string TLV is present, it must come after the operation TLV. */ 419 if (mlxsw_emad_tlv_is_string_tlv(skb->data + offsets->reg_tlv)) { 420 offsets->string_tlv = offsets->reg_tlv; 421 offsets->reg_tlv += MLXSW_EMAD_STRING_TLV_LEN * sizeof(u32); 422 } 423 } 424 425 static char *mlxsw_emad_op_tlv(const struct sk_buff *skb) 426 { 427 struct mlxsw_emad_tlv_offsets *offsets = 428 (struct mlxsw_emad_tlv_offsets *) skb->cb; 429 430 return ((char *) (skb->data + offsets->op_tlv)); 431 } 432 433 static char *mlxsw_emad_string_tlv(const struct sk_buff *skb) 434 { 435 struct mlxsw_emad_tlv_offsets *offsets = 436 (struct mlxsw_emad_tlv_offsets *) skb->cb; 437 438 if (!offsets->string_tlv) 439 return NULL; 440 441 return ((char *) (skb->data + offsets->string_tlv)); 442 } 443 444 static char *mlxsw_emad_reg_tlv(const struct sk_buff *skb) 445 { 446 struct mlxsw_emad_tlv_offsets *offsets = 447 (struct mlxsw_emad_tlv_offsets *) skb->cb; 448 449 return ((char *) (skb->data + offsets->reg_tlv)); 450 } 451 452 static char *mlxsw_emad_reg_payload(const char *reg_tlv) 453 { 454 return ((char *) (reg_tlv + sizeof(u32))); 455 } 456 457 static char *mlxsw_emad_reg_payload_cmd(const char *mbox) 458 { 459 return ((char *) (mbox + (MLXSW_EMAD_OP_TLV_LEN + 1) * sizeof(u32))); 460 } 461 462 static u64 mlxsw_emad_get_tid(const struct sk_buff *skb) 463 { 464 char *op_tlv; 465 466 op_tlv = mlxsw_emad_op_tlv(skb); 467 return mlxsw_emad_op_tlv_tid_get(op_tlv); 468 } 469 470 static bool mlxsw_emad_is_resp(const struct sk_buff *skb) 471 { 472 char *op_tlv; 473 474 op_tlv = mlxsw_emad_op_tlv(skb); 475 return (mlxsw_emad_op_tlv_r_get(op_tlv) == MLXSW_EMAD_OP_TLV_RESPONSE); 476 } 477 478 static int mlxsw_emad_process_status(char *op_tlv, 479 enum mlxsw_emad_op_tlv_status *p_status) 480 { 481 *p_status = mlxsw_emad_op_tlv_status_get(op_tlv); 482 483 switch (*p_status) { 484 case MLXSW_EMAD_OP_TLV_STATUS_SUCCESS: 485 return 0; 486 case MLXSW_EMAD_OP_TLV_STATUS_BUSY: 487 case MLXSW_EMAD_OP_TLV_STATUS_MESSAGE_RECEIPT_ACK: 488 return -EAGAIN; 489 case MLXSW_EMAD_OP_TLV_STATUS_VERSION_NOT_SUPPORTED: 490 case MLXSW_EMAD_OP_TLV_STATUS_UNKNOWN_TLV: 491 case MLXSW_EMAD_OP_TLV_STATUS_REGISTER_NOT_SUPPORTED: 492 case MLXSW_EMAD_OP_TLV_STATUS_CLASS_NOT_SUPPORTED: 493 case MLXSW_EMAD_OP_TLV_STATUS_METHOD_NOT_SUPPORTED: 494 case MLXSW_EMAD_OP_TLV_STATUS_BAD_PARAMETER: 495 case MLXSW_EMAD_OP_TLV_STATUS_RESOURCE_NOT_AVAILABLE: 496 case MLXSW_EMAD_OP_TLV_STATUS_INTERNAL_ERROR: 497 default: 498 return -EIO; 499 } 500 } 501 502 static int 503 mlxsw_emad_process_status_skb(struct sk_buff *skb, 504 enum mlxsw_emad_op_tlv_status *p_status) 505 { 506 return mlxsw_emad_process_status(mlxsw_emad_op_tlv(skb), p_status); 507 } 508 509 struct mlxsw_reg_trans { 510 struct list_head list; 511 struct list_head bulk_list; 512 struct mlxsw_core *core; 513 struct sk_buff *tx_skb; 514 struct mlxsw_tx_info tx_info; 515 struct delayed_work timeout_dw; 516 unsigned int retries; 517 u64 tid; 518 struct completion completion; 519 atomic_t active; 520 mlxsw_reg_trans_cb_t *cb; 521 unsigned long cb_priv; 522 const struct mlxsw_reg_info *reg; 523 enum mlxsw_core_reg_access_type type; 524 int err; 525 char *emad_err_string; 526 enum mlxsw_emad_op_tlv_status emad_status; 527 struct rcu_head rcu; 528 }; 529 530 static void mlxsw_emad_process_string_tlv(const struct sk_buff *skb, 531 struct mlxsw_reg_trans *trans) 532 { 533 char *string_tlv; 534 char *string; 535 536 string_tlv = mlxsw_emad_string_tlv(skb); 537 if (!string_tlv) 538 return; 539 540 trans->emad_err_string = kzalloc(MLXSW_EMAD_STRING_TLV_STRING_LEN, 541 GFP_ATOMIC); 542 if (!trans->emad_err_string) 543 return; 544 545 string = mlxsw_emad_string_tlv_string_data(string_tlv); 546 strlcpy(trans->emad_err_string, string, 547 MLXSW_EMAD_STRING_TLV_STRING_LEN); 548 } 549 550 #define MLXSW_EMAD_TIMEOUT_DURING_FW_FLASH_MS 3000 551 #define MLXSW_EMAD_TIMEOUT_MS 200 552 553 static void mlxsw_emad_trans_timeout_schedule(struct mlxsw_reg_trans *trans) 554 { 555 unsigned long timeout = msecs_to_jiffies(MLXSW_EMAD_TIMEOUT_MS); 556 557 if (trans->core->fw_flash_in_progress) 558 timeout = msecs_to_jiffies(MLXSW_EMAD_TIMEOUT_DURING_FW_FLASH_MS); 559 560 queue_delayed_work(trans->core->emad_wq, &trans->timeout_dw, timeout); 561 } 562 563 static int mlxsw_emad_transmit(struct mlxsw_core *mlxsw_core, 564 struct mlxsw_reg_trans *trans) 565 { 566 struct sk_buff *skb; 567 int err; 568 569 skb = skb_copy(trans->tx_skb, GFP_KERNEL); 570 if (!skb) 571 return -ENOMEM; 572 573 trace_devlink_hwmsg(priv_to_devlink(mlxsw_core), false, 0, 574 skb->data + mlxsw_core->driver->txhdr_len, 575 skb->len - mlxsw_core->driver->txhdr_len); 576 577 atomic_set(&trans->active, 1); 578 err = mlxsw_core_skb_transmit(mlxsw_core, skb, &trans->tx_info); 579 if (err) { 580 dev_kfree_skb(skb); 581 return err; 582 } 583 mlxsw_emad_trans_timeout_schedule(trans); 584 return 0; 585 } 586 587 static void mlxsw_emad_trans_finish(struct mlxsw_reg_trans *trans, int err) 588 { 589 struct mlxsw_core *mlxsw_core = trans->core; 590 591 dev_kfree_skb(trans->tx_skb); 592 spin_lock_bh(&mlxsw_core->emad.trans_list_lock); 593 list_del_rcu(&trans->list); 594 spin_unlock_bh(&mlxsw_core->emad.trans_list_lock); 595 trans->err = err; 596 complete(&trans->completion); 597 } 598 599 static void mlxsw_emad_transmit_retry(struct mlxsw_core *mlxsw_core, 600 struct mlxsw_reg_trans *trans) 601 { 602 int err; 603 604 if (trans->retries < MLXSW_EMAD_MAX_RETRY) { 605 trans->retries++; 606 err = mlxsw_emad_transmit(trans->core, trans); 607 if (err == 0) 608 return; 609 } else { 610 err = -EIO; 611 } 612 mlxsw_emad_trans_finish(trans, err); 613 } 614 615 static void mlxsw_emad_trans_timeout_work(struct work_struct *work) 616 { 617 struct mlxsw_reg_trans *trans = container_of(work, 618 struct mlxsw_reg_trans, 619 timeout_dw.work); 620 621 if (!atomic_dec_and_test(&trans->active)) 622 return; 623 624 mlxsw_emad_transmit_retry(trans->core, trans); 625 } 626 627 static void mlxsw_emad_process_response(struct mlxsw_core *mlxsw_core, 628 struct mlxsw_reg_trans *trans, 629 struct sk_buff *skb) 630 { 631 int err; 632 633 if (!atomic_dec_and_test(&trans->active)) 634 return; 635 636 err = mlxsw_emad_process_status_skb(skb, &trans->emad_status); 637 if (err == -EAGAIN) { 638 mlxsw_emad_transmit_retry(mlxsw_core, trans); 639 } else { 640 if (err == 0) { 641 char *reg_tlv = mlxsw_emad_reg_tlv(skb); 642 643 if (trans->cb) 644 trans->cb(mlxsw_core, 645 mlxsw_emad_reg_payload(reg_tlv), 646 trans->reg->len, trans->cb_priv); 647 } else { 648 mlxsw_emad_process_string_tlv(skb, trans); 649 } 650 mlxsw_emad_trans_finish(trans, err); 651 } 652 } 653 654 /* called with rcu read lock held */ 655 static void mlxsw_emad_rx_listener_func(struct sk_buff *skb, u8 local_port, 656 void *priv) 657 { 658 struct mlxsw_core *mlxsw_core = priv; 659 struct mlxsw_reg_trans *trans; 660 661 trace_devlink_hwmsg(priv_to_devlink(mlxsw_core), true, 0, 662 skb->data, skb->len); 663 664 mlxsw_emad_tlv_parse(skb); 665 666 if (!mlxsw_emad_is_resp(skb)) 667 goto free_skb; 668 669 list_for_each_entry_rcu(trans, &mlxsw_core->emad.trans_list, list) { 670 if (mlxsw_emad_get_tid(skb) == trans->tid) { 671 mlxsw_emad_process_response(mlxsw_core, trans, skb); 672 break; 673 } 674 } 675 676 free_skb: 677 dev_kfree_skb(skb); 678 } 679 680 static const struct mlxsw_listener mlxsw_emad_rx_listener = 681 MLXSW_RXL(mlxsw_emad_rx_listener_func, ETHEMAD, TRAP_TO_CPU, false, 682 EMAD, DISCARD); 683 684 static int mlxsw_emad_init(struct mlxsw_core *mlxsw_core) 685 { 686 struct workqueue_struct *emad_wq; 687 u64 tid; 688 int err; 689 690 if (!(mlxsw_core->bus->features & MLXSW_BUS_F_TXRX)) 691 return 0; 692 693 emad_wq = alloc_workqueue("mlxsw_core_emad", 0, 0); 694 if (!emad_wq) 695 return -ENOMEM; 696 mlxsw_core->emad_wq = emad_wq; 697 698 /* Set the upper 32 bits of the transaction ID field to a random 699 * number. This allows us to discard EMADs addressed to other 700 * devices. 701 */ 702 get_random_bytes(&tid, 4); 703 tid <<= 32; 704 atomic64_set(&mlxsw_core->emad.tid, tid); 705 706 INIT_LIST_HEAD(&mlxsw_core->emad.trans_list); 707 spin_lock_init(&mlxsw_core->emad.trans_list_lock); 708 709 err = mlxsw_core_trap_register(mlxsw_core, &mlxsw_emad_rx_listener, 710 mlxsw_core); 711 if (err) 712 return err; 713 714 err = mlxsw_core->driver->basic_trap_groups_set(mlxsw_core); 715 if (err) 716 goto err_emad_trap_set; 717 mlxsw_core->emad.use_emad = true; 718 719 return 0; 720 721 err_emad_trap_set: 722 mlxsw_core_trap_unregister(mlxsw_core, &mlxsw_emad_rx_listener, 723 mlxsw_core); 724 destroy_workqueue(mlxsw_core->emad_wq); 725 return err; 726 } 727 728 static void mlxsw_emad_fini(struct mlxsw_core *mlxsw_core) 729 { 730 731 if (!(mlxsw_core->bus->features & MLXSW_BUS_F_TXRX)) 732 return; 733 734 mlxsw_core->emad.use_emad = false; 735 mlxsw_core_trap_unregister(mlxsw_core, &mlxsw_emad_rx_listener, 736 mlxsw_core); 737 destroy_workqueue(mlxsw_core->emad_wq); 738 } 739 740 static struct sk_buff *mlxsw_emad_alloc(const struct mlxsw_core *mlxsw_core, 741 u16 reg_len, bool enable_string_tlv) 742 { 743 struct sk_buff *skb; 744 u16 emad_len; 745 746 emad_len = (reg_len + sizeof(u32) + MLXSW_EMAD_ETH_HDR_LEN + 747 (MLXSW_EMAD_OP_TLV_LEN + MLXSW_EMAD_END_TLV_LEN) * 748 sizeof(u32) + mlxsw_core->driver->txhdr_len); 749 if (enable_string_tlv) 750 emad_len += MLXSW_EMAD_STRING_TLV_LEN * sizeof(u32); 751 if (emad_len > MLXSW_EMAD_MAX_FRAME_LEN) 752 return NULL; 753 754 skb = netdev_alloc_skb(NULL, emad_len); 755 if (!skb) 756 return NULL; 757 memset(skb->data, 0, emad_len); 758 skb_reserve(skb, emad_len); 759 760 return skb; 761 } 762 763 static int mlxsw_emad_reg_access(struct mlxsw_core *mlxsw_core, 764 const struct mlxsw_reg_info *reg, 765 char *payload, 766 enum mlxsw_core_reg_access_type type, 767 struct mlxsw_reg_trans *trans, 768 struct list_head *bulk_list, 769 mlxsw_reg_trans_cb_t *cb, 770 unsigned long cb_priv, u64 tid) 771 { 772 bool enable_string_tlv; 773 struct sk_buff *skb; 774 int err; 775 776 dev_dbg(mlxsw_core->bus_info->dev, "EMAD reg access (tid=%llx,reg_id=%x(%s),type=%s)\n", 777 tid, reg->id, mlxsw_reg_id_str(reg->id), 778 mlxsw_core_reg_access_type_str(type)); 779 780 /* Since this can be changed during emad_reg_access, read it once and 781 * use the value all the way. 782 */ 783 enable_string_tlv = mlxsw_core->emad.enable_string_tlv; 784 785 skb = mlxsw_emad_alloc(mlxsw_core, reg->len, enable_string_tlv); 786 if (!skb) 787 return -ENOMEM; 788 789 list_add_tail(&trans->bulk_list, bulk_list); 790 trans->core = mlxsw_core; 791 trans->tx_skb = skb; 792 trans->tx_info.local_port = MLXSW_PORT_CPU_PORT; 793 trans->tx_info.is_emad = true; 794 INIT_DELAYED_WORK(&trans->timeout_dw, mlxsw_emad_trans_timeout_work); 795 trans->tid = tid; 796 init_completion(&trans->completion); 797 trans->cb = cb; 798 trans->cb_priv = cb_priv; 799 trans->reg = reg; 800 trans->type = type; 801 802 mlxsw_emad_construct(skb, reg, payload, type, trans->tid, 803 enable_string_tlv); 804 mlxsw_core->driver->txhdr_construct(skb, &trans->tx_info); 805 806 spin_lock_bh(&mlxsw_core->emad.trans_list_lock); 807 list_add_tail_rcu(&trans->list, &mlxsw_core->emad.trans_list); 808 spin_unlock_bh(&mlxsw_core->emad.trans_list_lock); 809 err = mlxsw_emad_transmit(mlxsw_core, trans); 810 if (err) 811 goto err_out; 812 return 0; 813 814 err_out: 815 spin_lock_bh(&mlxsw_core->emad.trans_list_lock); 816 list_del_rcu(&trans->list); 817 spin_unlock_bh(&mlxsw_core->emad.trans_list_lock); 818 list_del(&trans->bulk_list); 819 dev_kfree_skb(trans->tx_skb); 820 return err; 821 } 822 823 /***************** 824 * Core functions 825 *****************/ 826 827 int mlxsw_core_driver_register(struct mlxsw_driver *mlxsw_driver) 828 { 829 spin_lock(&mlxsw_core_driver_list_lock); 830 list_add_tail(&mlxsw_driver->list, &mlxsw_core_driver_list); 831 spin_unlock(&mlxsw_core_driver_list_lock); 832 return 0; 833 } 834 EXPORT_SYMBOL(mlxsw_core_driver_register); 835 836 void mlxsw_core_driver_unregister(struct mlxsw_driver *mlxsw_driver) 837 { 838 spin_lock(&mlxsw_core_driver_list_lock); 839 list_del(&mlxsw_driver->list); 840 spin_unlock(&mlxsw_core_driver_list_lock); 841 } 842 EXPORT_SYMBOL(mlxsw_core_driver_unregister); 843 844 static struct mlxsw_driver *__driver_find(const char *kind) 845 { 846 struct mlxsw_driver *mlxsw_driver; 847 848 list_for_each_entry(mlxsw_driver, &mlxsw_core_driver_list, list) { 849 if (strcmp(mlxsw_driver->kind, kind) == 0) 850 return mlxsw_driver; 851 } 852 return NULL; 853 } 854 855 static struct mlxsw_driver *mlxsw_core_driver_get(const char *kind) 856 { 857 struct mlxsw_driver *mlxsw_driver; 858 859 spin_lock(&mlxsw_core_driver_list_lock); 860 mlxsw_driver = __driver_find(kind); 861 spin_unlock(&mlxsw_core_driver_list_lock); 862 return mlxsw_driver; 863 } 864 865 static int mlxsw_devlink_port_split(struct devlink *devlink, 866 unsigned int port_index, 867 unsigned int count, 868 struct netlink_ext_ack *extack) 869 { 870 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 871 872 if (port_index >= mlxsw_core->max_ports) { 873 NL_SET_ERR_MSG_MOD(extack, "Port index exceeds maximum number of ports"); 874 return -EINVAL; 875 } 876 if (!mlxsw_core->driver->port_split) 877 return -EOPNOTSUPP; 878 return mlxsw_core->driver->port_split(mlxsw_core, port_index, count, 879 extack); 880 } 881 882 static int mlxsw_devlink_port_unsplit(struct devlink *devlink, 883 unsigned int port_index, 884 struct netlink_ext_ack *extack) 885 { 886 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 887 888 if (port_index >= mlxsw_core->max_ports) { 889 NL_SET_ERR_MSG_MOD(extack, "Port index exceeds maximum number of ports"); 890 return -EINVAL; 891 } 892 if (!mlxsw_core->driver->port_unsplit) 893 return -EOPNOTSUPP; 894 return mlxsw_core->driver->port_unsplit(mlxsw_core, port_index, 895 extack); 896 } 897 898 static int 899 mlxsw_devlink_sb_pool_get(struct devlink *devlink, 900 unsigned int sb_index, u16 pool_index, 901 struct devlink_sb_pool_info *pool_info) 902 { 903 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 904 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 905 906 if (!mlxsw_driver->sb_pool_get) 907 return -EOPNOTSUPP; 908 return mlxsw_driver->sb_pool_get(mlxsw_core, sb_index, 909 pool_index, pool_info); 910 } 911 912 static int 913 mlxsw_devlink_sb_pool_set(struct devlink *devlink, 914 unsigned int sb_index, u16 pool_index, u32 size, 915 enum devlink_sb_threshold_type threshold_type, 916 struct netlink_ext_ack *extack) 917 { 918 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 919 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 920 921 if (!mlxsw_driver->sb_pool_set) 922 return -EOPNOTSUPP; 923 return mlxsw_driver->sb_pool_set(mlxsw_core, sb_index, 924 pool_index, size, threshold_type, 925 extack); 926 } 927 928 static void *__dl_port(struct devlink_port *devlink_port) 929 { 930 return container_of(devlink_port, struct mlxsw_core_port, devlink_port); 931 } 932 933 static int mlxsw_devlink_port_type_set(struct devlink_port *devlink_port, 934 enum devlink_port_type port_type) 935 { 936 struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink); 937 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 938 struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port); 939 940 if (!mlxsw_driver->port_type_set) 941 return -EOPNOTSUPP; 942 943 return mlxsw_driver->port_type_set(mlxsw_core, 944 mlxsw_core_port->local_port, 945 port_type); 946 } 947 948 static int mlxsw_devlink_sb_port_pool_get(struct devlink_port *devlink_port, 949 unsigned int sb_index, u16 pool_index, 950 u32 *p_threshold) 951 { 952 struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink); 953 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 954 struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port); 955 956 if (!mlxsw_driver->sb_port_pool_get || 957 !mlxsw_core_port_check(mlxsw_core_port)) 958 return -EOPNOTSUPP; 959 return mlxsw_driver->sb_port_pool_get(mlxsw_core_port, sb_index, 960 pool_index, p_threshold); 961 } 962 963 static int mlxsw_devlink_sb_port_pool_set(struct devlink_port *devlink_port, 964 unsigned int sb_index, u16 pool_index, 965 u32 threshold, 966 struct netlink_ext_ack *extack) 967 { 968 struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink); 969 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 970 struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port); 971 972 if (!mlxsw_driver->sb_port_pool_set || 973 !mlxsw_core_port_check(mlxsw_core_port)) 974 return -EOPNOTSUPP; 975 return mlxsw_driver->sb_port_pool_set(mlxsw_core_port, sb_index, 976 pool_index, threshold, extack); 977 } 978 979 static int 980 mlxsw_devlink_sb_tc_pool_bind_get(struct devlink_port *devlink_port, 981 unsigned int sb_index, u16 tc_index, 982 enum devlink_sb_pool_type pool_type, 983 u16 *p_pool_index, u32 *p_threshold) 984 { 985 struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink); 986 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 987 struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port); 988 989 if (!mlxsw_driver->sb_tc_pool_bind_get || 990 !mlxsw_core_port_check(mlxsw_core_port)) 991 return -EOPNOTSUPP; 992 return mlxsw_driver->sb_tc_pool_bind_get(mlxsw_core_port, sb_index, 993 tc_index, pool_type, 994 p_pool_index, p_threshold); 995 } 996 997 static int 998 mlxsw_devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port, 999 unsigned int sb_index, u16 tc_index, 1000 enum devlink_sb_pool_type pool_type, 1001 u16 pool_index, u32 threshold, 1002 struct netlink_ext_ack *extack) 1003 { 1004 struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink); 1005 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 1006 struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port); 1007 1008 if (!mlxsw_driver->sb_tc_pool_bind_set || 1009 !mlxsw_core_port_check(mlxsw_core_port)) 1010 return -EOPNOTSUPP; 1011 return mlxsw_driver->sb_tc_pool_bind_set(mlxsw_core_port, sb_index, 1012 tc_index, pool_type, 1013 pool_index, threshold, extack); 1014 } 1015 1016 static int mlxsw_devlink_sb_occ_snapshot(struct devlink *devlink, 1017 unsigned int sb_index) 1018 { 1019 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 1020 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 1021 1022 if (!mlxsw_driver->sb_occ_snapshot) 1023 return -EOPNOTSUPP; 1024 return mlxsw_driver->sb_occ_snapshot(mlxsw_core, sb_index); 1025 } 1026 1027 static int mlxsw_devlink_sb_occ_max_clear(struct devlink *devlink, 1028 unsigned int sb_index) 1029 { 1030 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 1031 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 1032 1033 if (!mlxsw_driver->sb_occ_max_clear) 1034 return -EOPNOTSUPP; 1035 return mlxsw_driver->sb_occ_max_clear(mlxsw_core, sb_index); 1036 } 1037 1038 static int 1039 mlxsw_devlink_sb_occ_port_pool_get(struct devlink_port *devlink_port, 1040 unsigned int sb_index, u16 pool_index, 1041 u32 *p_cur, u32 *p_max) 1042 { 1043 struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink); 1044 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 1045 struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port); 1046 1047 if (!mlxsw_driver->sb_occ_port_pool_get || 1048 !mlxsw_core_port_check(mlxsw_core_port)) 1049 return -EOPNOTSUPP; 1050 return mlxsw_driver->sb_occ_port_pool_get(mlxsw_core_port, sb_index, 1051 pool_index, p_cur, p_max); 1052 } 1053 1054 static int 1055 mlxsw_devlink_sb_occ_tc_port_bind_get(struct devlink_port *devlink_port, 1056 unsigned int sb_index, u16 tc_index, 1057 enum devlink_sb_pool_type pool_type, 1058 u32 *p_cur, u32 *p_max) 1059 { 1060 struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink); 1061 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 1062 struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port); 1063 1064 if (!mlxsw_driver->sb_occ_tc_port_bind_get || 1065 !mlxsw_core_port_check(mlxsw_core_port)) 1066 return -EOPNOTSUPP; 1067 return mlxsw_driver->sb_occ_tc_port_bind_get(mlxsw_core_port, 1068 sb_index, tc_index, 1069 pool_type, p_cur, p_max); 1070 } 1071 1072 static int 1073 mlxsw_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req, 1074 struct netlink_ext_ack *extack) 1075 { 1076 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 1077 char fw_info_psid[MLXSW_REG_MGIR_FW_INFO_PSID_SIZE]; 1078 u32 hw_rev, fw_major, fw_minor, fw_sub_minor; 1079 char mgir_pl[MLXSW_REG_MGIR_LEN]; 1080 char buf[32]; 1081 int err; 1082 1083 err = devlink_info_driver_name_put(req, 1084 mlxsw_core->bus_info->device_kind); 1085 if (err) 1086 return err; 1087 1088 mlxsw_reg_mgir_pack(mgir_pl); 1089 err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mgir), mgir_pl); 1090 if (err) 1091 return err; 1092 mlxsw_reg_mgir_unpack(mgir_pl, &hw_rev, fw_info_psid, &fw_major, 1093 &fw_minor, &fw_sub_minor); 1094 1095 sprintf(buf, "%X", hw_rev); 1096 err = devlink_info_version_fixed_put(req, "hw.revision", buf); 1097 if (err) 1098 return err; 1099 1100 err = devlink_info_version_fixed_put(req, "fw.psid", fw_info_psid); 1101 if (err) 1102 return err; 1103 1104 sprintf(buf, "%d.%d.%d", fw_major, fw_minor, fw_sub_minor); 1105 err = devlink_info_version_running_put(req, "fw.version", buf); 1106 if (err) 1107 return err; 1108 1109 return 0; 1110 } 1111 1112 static int 1113 mlxsw_devlink_core_bus_device_reload_down(struct devlink *devlink, 1114 bool netns_change, 1115 struct netlink_ext_ack *extack) 1116 { 1117 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 1118 1119 if (!(mlxsw_core->bus->features & MLXSW_BUS_F_RESET)) 1120 return -EOPNOTSUPP; 1121 1122 mlxsw_core_bus_device_unregister(mlxsw_core, true); 1123 return 0; 1124 } 1125 1126 static int 1127 mlxsw_devlink_core_bus_device_reload_up(struct devlink *devlink, 1128 struct netlink_ext_ack *extack) 1129 { 1130 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 1131 1132 return mlxsw_core_bus_device_register(mlxsw_core->bus_info, 1133 mlxsw_core->bus, 1134 mlxsw_core->bus_priv, true, 1135 devlink, extack); 1136 } 1137 1138 static int mlxsw_devlink_flash_update(struct devlink *devlink, 1139 const char *file_name, 1140 const char *component, 1141 struct netlink_ext_ack *extack) 1142 { 1143 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 1144 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 1145 1146 if (!mlxsw_driver->flash_update) 1147 return -EOPNOTSUPP; 1148 return mlxsw_driver->flash_update(mlxsw_core, file_name, 1149 component, extack); 1150 } 1151 1152 static int mlxsw_devlink_trap_init(struct devlink *devlink, 1153 const struct devlink_trap *trap, 1154 void *trap_ctx) 1155 { 1156 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 1157 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 1158 1159 if (!mlxsw_driver->trap_init) 1160 return -EOPNOTSUPP; 1161 return mlxsw_driver->trap_init(mlxsw_core, trap, trap_ctx); 1162 } 1163 1164 static void mlxsw_devlink_trap_fini(struct devlink *devlink, 1165 const struct devlink_trap *trap, 1166 void *trap_ctx) 1167 { 1168 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 1169 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 1170 1171 if (!mlxsw_driver->trap_fini) 1172 return; 1173 mlxsw_driver->trap_fini(mlxsw_core, trap, trap_ctx); 1174 } 1175 1176 static int mlxsw_devlink_trap_action_set(struct devlink *devlink, 1177 const struct devlink_trap *trap, 1178 enum devlink_trap_action action) 1179 { 1180 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 1181 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 1182 1183 if (!mlxsw_driver->trap_action_set) 1184 return -EOPNOTSUPP; 1185 return mlxsw_driver->trap_action_set(mlxsw_core, trap, action); 1186 } 1187 1188 static int 1189 mlxsw_devlink_trap_group_init(struct devlink *devlink, 1190 const struct devlink_trap_group *group) 1191 { 1192 struct mlxsw_core *mlxsw_core = devlink_priv(devlink); 1193 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; 1194 1195 if (!mlxsw_driver->trap_group_init) 1196 return -EOPNOTSUPP; 1197 return mlxsw_driver->trap_group_init(mlxsw_core, group); 1198 } 1199 1200 static const struct devlink_ops mlxsw_devlink_ops = { 1201 .reload_down = mlxsw_devlink_core_bus_device_reload_down, 1202 .reload_up = mlxsw_devlink_core_bus_device_reload_up, 1203 .port_type_set = mlxsw_devlink_port_type_set, 1204 .port_split = mlxsw_devlink_port_split, 1205 .port_unsplit = mlxsw_devlink_port_unsplit, 1206 .sb_pool_get = mlxsw_devlink_sb_pool_get, 1207 .sb_pool_set = mlxsw_devlink_sb_pool_set, 1208 .sb_port_pool_get = mlxsw_devlink_sb_port_pool_get, 1209 .sb_port_pool_set = mlxsw_devlink_sb_port_pool_set, 1210 .sb_tc_pool_bind_get = mlxsw_devlink_sb_tc_pool_bind_get, 1211 .sb_tc_pool_bind_set = mlxsw_devlink_sb_tc_pool_bind_set, 1212 .sb_occ_snapshot = mlxsw_devlink_sb_occ_snapshot, 1213 .sb_occ_max_clear = mlxsw_devlink_sb_occ_max_clear, 1214 .sb_occ_port_pool_get = mlxsw_devlink_sb_occ_port_pool_get, 1215 .sb_occ_tc_port_bind_get = mlxsw_devlink_sb_occ_tc_port_bind_get, 1216 .info_get = mlxsw_devlink_info_get, 1217 .flash_update = mlxsw_devlink_flash_update, 1218 .trap_init = mlxsw_devlink_trap_init, 1219 .trap_fini = mlxsw_devlink_trap_fini, 1220 .trap_action_set = mlxsw_devlink_trap_action_set, 1221 .trap_group_init = mlxsw_devlink_trap_group_init, 1222 }; 1223 1224 static int 1225 __mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info, 1226 const struct mlxsw_bus *mlxsw_bus, 1227 void *bus_priv, bool reload, 1228 struct devlink *devlink, 1229 struct netlink_ext_ack *extack) 1230 { 1231 const char *device_kind = mlxsw_bus_info->device_kind; 1232 struct mlxsw_core *mlxsw_core; 1233 struct mlxsw_driver *mlxsw_driver; 1234 struct mlxsw_res *res; 1235 size_t alloc_size; 1236 int err; 1237 1238 mlxsw_driver = mlxsw_core_driver_get(device_kind); 1239 if (!mlxsw_driver) 1240 return -EINVAL; 1241 1242 if (!reload) { 1243 alloc_size = sizeof(*mlxsw_core) + mlxsw_driver->priv_size; 1244 devlink = devlink_alloc(&mlxsw_devlink_ops, alloc_size); 1245 if (!devlink) { 1246 err = -ENOMEM; 1247 goto err_devlink_alloc; 1248 } 1249 } 1250 1251 mlxsw_core = devlink_priv(devlink); 1252 INIT_LIST_HEAD(&mlxsw_core->rx_listener_list); 1253 INIT_LIST_HEAD(&mlxsw_core->event_listener_list); 1254 mlxsw_core->driver = mlxsw_driver; 1255 mlxsw_core->bus = mlxsw_bus; 1256 mlxsw_core->bus_priv = bus_priv; 1257 mlxsw_core->bus_info = mlxsw_bus_info; 1258 1259 res = mlxsw_driver->res_query_enabled ? &mlxsw_core->res : NULL; 1260 err = mlxsw_bus->init(bus_priv, mlxsw_core, mlxsw_driver->profile, res); 1261 if (err) 1262 goto err_bus_init; 1263 1264 if (mlxsw_driver->resources_register && !reload) { 1265 err = mlxsw_driver->resources_register(mlxsw_core); 1266 if (err) 1267 goto err_register_resources; 1268 } 1269 1270 err = mlxsw_ports_init(mlxsw_core); 1271 if (err) 1272 goto err_ports_init; 1273 1274 if (MLXSW_CORE_RES_VALID(mlxsw_core, MAX_LAG) && 1275 MLXSW_CORE_RES_VALID(mlxsw_core, MAX_LAG_MEMBERS)) { 1276 alloc_size = sizeof(u8) * 1277 MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG) * 1278 MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG_MEMBERS); 1279 mlxsw_core->lag.mapping = kzalloc(alloc_size, GFP_KERNEL); 1280 if (!mlxsw_core->lag.mapping) { 1281 err = -ENOMEM; 1282 goto err_alloc_lag_mapping; 1283 } 1284 } 1285 1286 err = mlxsw_emad_init(mlxsw_core); 1287 if (err) 1288 goto err_emad_init; 1289 1290 if (!reload) { 1291 err = devlink_register(devlink, mlxsw_bus_info->dev); 1292 if (err) 1293 goto err_devlink_register; 1294 } 1295 1296 if (mlxsw_driver->params_register && !reload) { 1297 err = mlxsw_driver->params_register(mlxsw_core); 1298 if (err) 1299 goto err_register_params; 1300 } 1301 1302 if (mlxsw_driver->init) { 1303 err = mlxsw_driver->init(mlxsw_core, mlxsw_bus_info, extack); 1304 if (err) 1305 goto err_driver_init; 1306 } 1307 1308 err = mlxsw_hwmon_init(mlxsw_core, mlxsw_bus_info, &mlxsw_core->hwmon); 1309 if (err) 1310 goto err_hwmon_init; 1311 1312 err = mlxsw_thermal_init(mlxsw_core, mlxsw_bus_info, 1313 &mlxsw_core->thermal); 1314 if (err) 1315 goto err_thermal_init; 1316 1317 if (mlxsw_driver->params_register) 1318 devlink_params_publish(devlink); 1319 1320 if (!reload) 1321 devlink_reload_enable(devlink); 1322 1323 return 0; 1324 1325 err_thermal_init: 1326 mlxsw_hwmon_fini(mlxsw_core->hwmon); 1327 err_hwmon_init: 1328 if (mlxsw_core->driver->fini) 1329 mlxsw_core->driver->fini(mlxsw_core); 1330 err_driver_init: 1331 if (mlxsw_driver->params_unregister && !reload) 1332 mlxsw_driver->params_unregister(mlxsw_core); 1333 err_register_params: 1334 if (!reload) 1335 devlink_unregister(devlink); 1336 err_devlink_register: 1337 mlxsw_emad_fini(mlxsw_core); 1338 err_emad_init: 1339 kfree(mlxsw_core->lag.mapping); 1340 err_alloc_lag_mapping: 1341 mlxsw_ports_fini(mlxsw_core); 1342 err_ports_init: 1343 if (!reload) 1344 devlink_resources_unregister(devlink, NULL); 1345 err_register_resources: 1346 mlxsw_bus->fini(bus_priv); 1347 err_bus_init: 1348 if (!reload) 1349 devlink_free(devlink); 1350 err_devlink_alloc: 1351 return err; 1352 } 1353 1354 int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info, 1355 const struct mlxsw_bus *mlxsw_bus, 1356 void *bus_priv, bool reload, 1357 struct devlink *devlink, 1358 struct netlink_ext_ack *extack) 1359 { 1360 bool called_again = false; 1361 int err; 1362 1363 again: 1364 err = __mlxsw_core_bus_device_register(mlxsw_bus_info, mlxsw_bus, 1365 bus_priv, reload, 1366 devlink, extack); 1367 /* -EAGAIN is returned in case the FW was updated. FW needs 1368 * a reset, so lets try to call __mlxsw_core_bus_device_register() 1369 * again. 1370 */ 1371 if (err == -EAGAIN && !called_again) { 1372 called_again = true; 1373 goto again; 1374 } 1375 1376 return err; 1377 } 1378 EXPORT_SYMBOL(mlxsw_core_bus_device_register); 1379 1380 void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core, 1381 bool reload) 1382 { 1383 struct devlink *devlink = priv_to_devlink(mlxsw_core); 1384 1385 if (!reload) 1386 devlink_reload_disable(devlink); 1387 if (devlink_is_reload_failed(devlink)) { 1388 if (!reload) 1389 /* Only the parts that were not de-initialized in the 1390 * failed reload attempt need to be de-initialized. 1391 */ 1392 goto reload_fail_deinit; 1393 else 1394 return; 1395 } 1396 1397 if (mlxsw_core->driver->params_unregister) 1398 devlink_params_unpublish(devlink); 1399 mlxsw_thermal_fini(mlxsw_core->thermal); 1400 mlxsw_hwmon_fini(mlxsw_core->hwmon); 1401 if (mlxsw_core->driver->fini) 1402 mlxsw_core->driver->fini(mlxsw_core); 1403 if (mlxsw_core->driver->params_unregister && !reload) 1404 mlxsw_core->driver->params_unregister(mlxsw_core); 1405 if (!reload) 1406 devlink_unregister(devlink); 1407 mlxsw_emad_fini(mlxsw_core); 1408 kfree(mlxsw_core->lag.mapping); 1409 mlxsw_ports_fini(mlxsw_core); 1410 if (!reload) 1411 devlink_resources_unregister(devlink, NULL); 1412 mlxsw_core->bus->fini(mlxsw_core->bus_priv); 1413 1414 return; 1415 1416 reload_fail_deinit: 1417 if (mlxsw_core->driver->params_unregister) 1418 mlxsw_core->driver->params_unregister(mlxsw_core); 1419 devlink_unregister(devlink); 1420 devlink_resources_unregister(devlink, NULL); 1421 devlink_free(devlink); 1422 } 1423 EXPORT_SYMBOL(mlxsw_core_bus_device_unregister); 1424 1425 bool mlxsw_core_skb_transmit_busy(struct mlxsw_core *mlxsw_core, 1426 const struct mlxsw_tx_info *tx_info) 1427 { 1428 return mlxsw_core->bus->skb_transmit_busy(mlxsw_core->bus_priv, 1429 tx_info); 1430 } 1431 EXPORT_SYMBOL(mlxsw_core_skb_transmit_busy); 1432 1433 int mlxsw_core_skb_transmit(struct mlxsw_core *mlxsw_core, struct sk_buff *skb, 1434 const struct mlxsw_tx_info *tx_info) 1435 { 1436 return mlxsw_core->bus->skb_transmit(mlxsw_core->bus_priv, skb, 1437 tx_info); 1438 } 1439 EXPORT_SYMBOL(mlxsw_core_skb_transmit); 1440 1441 void mlxsw_core_ptp_transmitted(struct mlxsw_core *mlxsw_core, 1442 struct sk_buff *skb, u8 local_port) 1443 { 1444 if (mlxsw_core->driver->ptp_transmitted) 1445 mlxsw_core->driver->ptp_transmitted(mlxsw_core, skb, 1446 local_port); 1447 } 1448 EXPORT_SYMBOL(mlxsw_core_ptp_transmitted); 1449 1450 static bool __is_rx_listener_equal(const struct mlxsw_rx_listener *rxl_a, 1451 const struct mlxsw_rx_listener *rxl_b) 1452 { 1453 return (rxl_a->func == rxl_b->func && 1454 rxl_a->local_port == rxl_b->local_port && 1455 rxl_a->trap_id == rxl_b->trap_id); 1456 } 1457 1458 static struct mlxsw_rx_listener_item * 1459 __find_rx_listener_item(struct mlxsw_core *mlxsw_core, 1460 const struct mlxsw_rx_listener *rxl, 1461 void *priv) 1462 { 1463 struct mlxsw_rx_listener_item *rxl_item; 1464 1465 list_for_each_entry(rxl_item, &mlxsw_core->rx_listener_list, list) { 1466 if (__is_rx_listener_equal(&rxl_item->rxl, rxl) && 1467 rxl_item->priv == priv) 1468 return rxl_item; 1469 } 1470 return NULL; 1471 } 1472 1473 int mlxsw_core_rx_listener_register(struct mlxsw_core *mlxsw_core, 1474 const struct mlxsw_rx_listener *rxl, 1475 void *priv) 1476 { 1477 struct mlxsw_rx_listener_item *rxl_item; 1478 1479 rxl_item = __find_rx_listener_item(mlxsw_core, rxl, priv); 1480 if (rxl_item) 1481 return -EEXIST; 1482 rxl_item = kmalloc(sizeof(*rxl_item), GFP_KERNEL); 1483 if (!rxl_item) 1484 return -ENOMEM; 1485 rxl_item->rxl = *rxl; 1486 rxl_item->priv = priv; 1487 1488 list_add_rcu(&rxl_item->list, &mlxsw_core->rx_listener_list); 1489 return 0; 1490 } 1491 EXPORT_SYMBOL(mlxsw_core_rx_listener_register); 1492 1493 void mlxsw_core_rx_listener_unregister(struct mlxsw_core *mlxsw_core, 1494 const struct mlxsw_rx_listener *rxl, 1495 void *priv) 1496 { 1497 struct mlxsw_rx_listener_item *rxl_item; 1498 1499 rxl_item = __find_rx_listener_item(mlxsw_core, rxl, priv); 1500 if (!rxl_item) 1501 return; 1502 list_del_rcu(&rxl_item->list); 1503 synchronize_rcu(); 1504 kfree(rxl_item); 1505 } 1506 EXPORT_SYMBOL(mlxsw_core_rx_listener_unregister); 1507 1508 static void mlxsw_core_event_listener_func(struct sk_buff *skb, u8 local_port, 1509 void *priv) 1510 { 1511 struct mlxsw_event_listener_item *event_listener_item = priv; 1512 struct mlxsw_reg_info reg; 1513 char *payload; 1514 char *reg_tlv; 1515 char *op_tlv; 1516 1517 mlxsw_emad_tlv_parse(skb); 1518 op_tlv = mlxsw_emad_op_tlv(skb); 1519 reg_tlv = mlxsw_emad_reg_tlv(skb); 1520 1521 reg.id = mlxsw_emad_op_tlv_register_id_get(op_tlv); 1522 reg.len = (mlxsw_emad_reg_tlv_len_get(reg_tlv) - 1) * sizeof(u32); 1523 payload = mlxsw_emad_reg_payload(reg_tlv); 1524 event_listener_item->el.func(®, payload, event_listener_item->priv); 1525 dev_kfree_skb(skb); 1526 } 1527 1528 static bool __is_event_listener_equal(const struct mlxsw_event_listener *el_a, 1529 const struct mlxsw_event_listener *el_b) 1530 { 1531 return (el_a->func == el_b->func && 1532 el_a->trap_id == el_b->trap_id); 1533 } 1534 1535 static struct mlxsw_event_listener_item * 1536 __find_event_listener_item(struct mlxsw_core *mlxsw_core, 1537 const struct mlxsw_event_listener *el, 1538 void *priv) 1539 { 1540 struct mlxsw_event_listener_item *el_item; 1541 1542 list_for_each_entry(el_item, &mlxsw_core->event_listener_list, list) { 1543 if (__is_event_listener_equal(&el_item->el, el) && 1544 el_item->priv == priv) 1545 return el_item; 1546 } 1547 return NULL; 1548 } 1549 1550 int mlxsw_core_event_listener_register(struct mlxsw_core *mlxsw_core, 1551 const struct mlxsw_event_listener *el, 1552 void *priv) 1553 { 1554 int err; 1555 struct mlxsw_event_listener_item *el_item; 1556 const struct mlxsw_rx_listener rxl = { 1557 .func = mlxsw_core_event_listener_func, 1558 .local_port = MLXSW_PORT_DONT_CARE, 1559 .trap_id = el->trap_id, 1560 }; 1561 1562 el_item = __find_event_listener_item(mlxsw_core, el, priv); 1563 if (el_item) 1564 return -EEXIST; 1565 el_item = kmalloc(sizeof(*el_item), GFP_KERNEL); 1566 if (!el_item) 1567 return -ENOMEM; 1568 el_item->el = *el; 1569 el_item->priv = priv; 1570 1571 err = mlxsw_core_rx_listener_register(mlxsw_core, &rxl, el_item); 1572 if (err) 1573 goto err_rx_listener_register; 1574 1575 /* No reason to save item if we did not manage to register an RX 1576 * listener for it. 1577 */ 1578 list_add_rcu(&el_item->list, &mlxsw_core->event_listener_list); 1579 1580 return 0; 1581 1582 err_rx_listener_register: 1583 kfree(el_item); 1584 return err; 1585 } 1586 EXPORT_SYMBOL(mlxsw_core_event_listener_register); 1587 1588 void mlxsw_core_event_listener_unregister(struct mlxsw_core *mlxsw_core, 1589 const struct mlxsw_event_listener *el, 1590 void *priv) 1591 { 1592 struct mlxsw_event_listener_item *el_item; 1593 const struct mlxsw_rx_listener rxl = { 1594 .func = mlxsw_core_event_listener_func, 1595 .local_port = MLXSW_PORT_DONT_CARE, 1596 .trap_id = el->trap_id, 1597 }; 1598 1599 el_item = __find_event_listener_item(mlxsw_core, el, priv); 1600 if (!el_item) 1601 return; 1602 mlxsw_core_rx_listener_unregister(mlxsw_core, &rxl, el_item); 1603 list_del(&el_item->list); 1604 kfree(el_item); 1605 } 1606 EXPORT_SYMBOL(mlxsw_core_event_listener_unregister); 1607 1608 static int mlxsw_core_listener_register(struct mlxsw_core *mlxsw_core, 1609 const struct mlxsw_listener *listener, 1610 void *priv) 1611 { 1612 if (listener->is_event) 1613 return mlxsw_core_event_listener_register(mlxsw_core, 1614 &listener->u.event_listener, 1615 priv); 1616 else 1617 return mlxsw_core_rx_listener_register(mlxsw_core, 1618 &listener->u.rx_listener, 1619 priv); 1620 } 1621 1622 static void mlxsw_core_listener_unregister(struct mlxsw_core *mlxsw_core, 1623 const struct mlxsw_listener *listener, 1624 void *priv) 1625 { 1626 if (listener->is_event) 1627 mlxsw_core_event_listener_unregister(mlxsw_core, 1628 &listener->u.event_listener, 1629 priv); 1630 else 1631 mlxsw_core_rx_listener_unregister(mlxsw_core, 1632 &listener->u.rx_listener, 1633 priv); 1634 } 1635 1636 int mlxsw_core_trap_register(struct mlxsw_core *mlxsw_core, 1637 const struct mlxsw_listener *listener, void *priv) 1638 { 1639 char hpkt_pl[MLXSW_REG_HPKT_LEN]; 1640 int err; 1641 1642 err = mlxsw_core_listener_register(mlxsw_core, listener, priv); 1643 if (err) 1644 return err; 1645 1646 mlxsw_reg_hpkt_pack(hpkt_pl, listener->action, listener->trap_id, 1647 listener->trap_group, listener->is_ctrl); 1648 err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl); 1649 if (err) 1650 goto err_trap_set; 1651 1652 return 0; 1653 1654 err_trap_set: 1655 mlxsw_core_listener_unregister(mlxsw_core, listener, priv); 1656 return err; 1657 } 1658 EXPORT_SYMBOL(mlxsw_core_trap_register); 1659 1660 void mlxsw_core_trap_unregister(struct mlxsw_core *mlxsw_core, 1661 const struct mlxsw_listener *listener, 1662 void *priv) 1663 { 1664 char hpkt_pl[MLXSW_REG_HPKT_LEN]; 1665 1666 if (!listener->is_event) { 1667 mlxsw_reg_hpkt_pack(hpkt_pl, listener->unreg_action, 1668 listener->trap_id, listener->trap_group, 1669 listener->is_ctrl); 1670 mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl); 1671 } 1672 1673 mlxsw_core_listener_unregister(mlxsw_core, listener, priv); 1674 } 1675 EXPORT_SYMBOL(mlxsw_core_trap_unregister); 1676 1677 int mlxsw_core_trap_action_set(struct mlxsw_core *mlxsw_core, 1678 const struct mlxsw_listener *listener, 1679 enum mlxsw_reg_hpkt_action action) 1680 { 1681 char hpkt_pl[MLXSW_REG_HPKT_LEN]; 1682 1683 mlxsw_reg_hpkt_pack(hpkt_pl, action, listener->trap_id, 1684 listener->trap_group, listener->is_ctrl); 1685 return mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl); 1686 } 1687 EXPORT_SYMBOL(mlxsw_core_trap_action_set); 1688 1689 static u64 mlxsw_core_tid_get(struct mlxsw_core *mlxsw_core) 1690 { 1691 return atomic64_inc_return(&mlxsw_core->emad.tid); 1692 } 1693 1694 static int mlxsw_core_reg_access_emad(struct mlxsw_core *mlxsw_core, 1695 const struct mlxsw_reg_info *reg, 1696 char *payload, 1697 enum mlxsw_core_reg_access_type type, 1698 struct list_head *bulk_list, 1699 mlxsw_reg_trans_cb_t *cb, 1700 unsigned long cb_priv) 1701 { 1702 u64 tid = mlxsw_core_tid_get(mlxsw_core); 1703 struct mlxsw_reg_trans *trans; 1704 int err; 1705 1706 trans = kzalloc(sizeof(*trans), GFP_KERNEL); 1707 if (!trans) 1708 return -ENOMEM; 1709 1710 err = mlxsw_emad_reg_access(mlxsw_core, reg, payload, type, trans, 1711 bulk_list, cb, cb_priv, tid); 1712 if (err) { 1713 kfree(trans); 1714 return err; 1715 } 1716 return 0; 1717 } 1718 1719 int mlxsw_reg_trans_query(struct mlxsw_core *mlxsw_core, 1720 const struct mlxsw_reg_info *reg, char *payload, 1721 struct list_head *bulk_list, 1722 mlxsw_reg_trans_cb_t *cb, unsigned long cb_priv) 1723 { 1724 return mlxsw_core_reg_access_emad(mlxsw_core, reg, payload, 1725 MLXSW_CORE_REG_ACCESS_TYPE_QUERY, 1726 bulk_list, cb, cb_priv); 1727 } 1728 EXPORT_SYMBOL(mlxsw_reg_trans_query); 1729 1730 int mlxsw_reg_trans_write(struct mlxsw_core *mlxsw_core, 1731 const struct mlxsw_reg_info *reg, char *payload, 1732 struct list_head *bulk_list, 1733 mlxsw_reg_trans_cb_t *cb, unsigned long cb_priv) 1734 { 1735 return mlxsw_core_reg_access_emad(mlxsw_core, reg, payload, 1736 MLXSW_CORE_REG_ACCESS_TYPE_WRITE, 1737 bulk_list, cb, cb_priv); 1738 } 1739 EXPORT_SYMBOL(mlxsw_reg_trans_write); 1740 1741 #define MLXSW_REG_TRANS_ERR_STRING_SIZE 256 1742 1743 static int mlxsw_reg_trans_wait(struct mlxsw_reg_trans *trans) 1744 { 1745 char err_string[MLXSW_REG_TRANS_ERR_STRING_SIZE]; 1746 struct mlxsw_core *mlxsw_core = trans->core; 1747 int err; 1748 1749 wait_for_completion(&trans->completion); 1750 cancel_delayed_work_sync(&trans->timeout_dw); 1751 err = trans->err; 1752 1753 if (trans->retries) 1754 dev_warn(mlxsw_core->bus_info->dev, "EMAD retries (%d/%d) (tid=%llx)\n", 1755 trans->retries, MLXSW_EMAD_MAX_RETRY, trans->tid); 1756 if (err) { 1757 dev_err(mlxsw_core->bus_info->dev, "EMAD reg access failed (tid=%llx,reg_id=%x(%s),type=%s,status=%x(%s))\n", 1758 trans->tid, trans->reg->id, 1759 mlxsw_reg_id_str(trans->reg->id), 1760 mlxsw_core_reg_access_type_str(trans->type), 1761 trans->emad_status, 1762 mlxsw_emad_op_tlv_status_str(trans->emad_status)); 1763 1764 snprintf(err_string, MLXSW_REG_TRANS_ERR_STRING_SIZE, 1765 "(tid=%llx,reg_id=%x(%s)) %s (%s)\n", trans->tid, 1766 trans->reg->id, mlxsw_reg_id_str(trans->reg->id), 1767 mlxsw_emad_op_tlv_status_str(trans->emad_status), 1768 trans->emad_err_string ? trans->emad_err_string : ""); 1769 1770 trace_devlink_hwerr(priv_to_devlink(mlxsw_core), 1771 trans->emad_status, err_string); 1772 1773 kfree(trans->emad_err_string); 1774 } 1775 1776 list_del(&trans->bulk_list); 1777 kfree_rcu(trans, rcu); 1778 return err; 1779 } 1780 1781 int mlxsw_reg_trans_bulk_wait(struct list_head *bulk_list) 1782 { 1783 struct mlxsw_reg_trans *trans; 1784 struct mlxsw_reg_trans *tmp; 1785 int sum_err = 0; 1786 int err; 1787 1788 list_for_each_entry_safe(trans, tmp, bulk_list, bulk_list) { 1789 err = mlxsw_reg_trans_wait(trans); 1790 if (err && sum_err == 0) 1791 sum_err = err; /* first error to be returned */ 1792 } 1793 return sum_err; 1794 } 1795 EXPORT_SYMBOL(mlxsw_reg_trans_bulk_wait); 1796 1797 static int mlxsw_core_reg_access_cmd(struct mlxsw_core *mlxsw_core, 1798 const struct mlxsw_reg_info *reg, 1799 char *payload, 1800 enum mlxsw_core_reg_access_type type) 1801 { 1802 enum mlxsw_emad_op_tlv_status status; 1803 int err, n_retry; 1804 bool reset_ok; 1805 char *in_mbox, *out_mbox, *tmp; 1806 1807 dev_dbg(mlxsw_core->bus_info->dev, "Reg cmd access (reg_id=%x(%s),type=%s)\n", 1808 reg->id, mlxsw_reg_id_str(reg->id), 1809 mlxsw_core_reg_access_type_str(type)); 1810 1811 in_mbox = mlxsw_cmd_mbox_alloc(); 1812 if (!in_mbox) 1813 return -ENOMEM; 1814 1815 out_mbox = mlxsw_cmd_mbox_alloc(); 1816 if (!out_mbox) { 1817 err = -ENOMEM; 1818 goto free_in_mbox; 1819 } 1820 1821 mlxsw_emad_pack_op_tlv(in_mbox, reg, type, 1822 mlxsw_core_tid_get(mlxsw_core)); 1823 tmp = in_mbox + MLXSW_EMAD_OP_TLV_LEN * sizeof(u32); 1824 mlxsw_emad_pack_reg_tlv(tmp, reg, payload); 1825 1826 /* There is a special treatment needed for MRSR (reset) register. 1827 * The command interface will return error after the command 1828 * is executed, so tell the lower layer to expect it 1829 * and cope accordingly. 1830 */ 1831 reset_ok = reg->id == MLXSW_REG_MRSR_ID; 1832 1833 n_retry = 0; 1834 retry: 1835 err = mlxsw_cmd_access_reg(mlxsw_core, reset_ok, in_mbox, out_mbox); 1836 if (!err) { 1837 err = mlxsw_emad_process_status(out_mbox, &status); 1838 if (err) { 1839 if (err == -EAGAIN && n_retry++ < MLXSW_EMAD_MAX_RETRY) 1840 goto retry; 1841 dev_err(mlxsw_core->bus_info->dev, "Reg cmd access status failed (status=%x(%s))\n", 1842 status, mlxsw_emad_op_tlv_status_str(status)); 1843 } 1844 } 1845 1846 if (!err) 1847 memcpy(payload, mlxsw_emad_reg_payload_cmd(out_mbox), 1848 reg->len); 1849 1850 mlxsw_cmd_mbox_free(out_mbox); 1851 free_in_mbox: 1852 mlxsw_cmd_mbox_free(in_mbox); 1853 if (err) 1854 dev_err(mlxsw_core->bus_info->dev, "Reg cmd access failed (reg_id=%x(%s),type=%s)\n", 1855 reg->id, mlxsw_reg_id_str(reg->id), 1856 mlxsw_core_reg_access_type_str(type)); 1857 return err; 1858 } 1859 1860 static void mlxsw_core_reg_access_cb(struct mlxsw_core *mlxsw_core, 1861 char *payload, size_t payload_len, 1862 unsigned long cb_priv) 1863 { 1864 char *orig_payload = (char *) cb_priv; 1865 1866 memcpy(orig_payload, payload, payload_len); 1867 } 1868 1869 static int mlxsw_core_reg_access(struct mlxsw_core *mlxsw_core, 1870 const struct mlxsw_reg_info *reg, 1871 char *payload, 1872 enum mlxsw_core_reg_access_type type) 1873 { 1874 LIST_HEAD(bulk_list); 1875 int err; 1876 1877 /* During initialization EMAD interface is not available to us, 1878 * so we default to command interface. We switch to EMAD interface 1879 * after setting the appropriate traps. 1880 */ 1881 if (!mlxsw_core->emad.use_emad) 1882 return mlxsw_core_reg_access_cmd(mlxsw_core, reg, 1883 payload, type); 1884 1885 err = mlxsw_core_reg_access_emad(mlxsw_core, reg, 1886 payload, type, &bulk_list, 1887 mlxsw_core_reg_access_cb, 1888 (unsigned long) payload); 1889 if (err) 1890 return err; 1891 return mlxsw_reg_trans_bulk_wait(&bulk_list); 1892 } 1893 1894 int mlxsw_reg_query(struct mlxsw_core *mlxsw_core, 1895 const struct mlxsw_reg_info *reg, char *payload) 1896 { 1897 return mlxsw_core_reg_access(mlxsw_core, reg, payload, 1898 MLXSW_CORE_REG_ACCESS_TYPE_QUERY); 1899 } 1900 EXPORT_SYMBOL(mlxsw_reg_query); 1901 1902 int mlxsw_reg_write(struct mlxsw_core *mlxsw_core, 1903 const struct mlxsw_reg_info *reg, char *payload) 1904 { 1905 return mlxsw_core_reg_access(mlxsw_core, reg, payload, 1906 MLXSW_CORE_REG_ACCESS_TYPE_WRITE); 1907 } 1908 EXPORT_SYMBOL(mlxsw_reg_write); 1909 1910 void mlxsw_core_skb_receive(struct mlxsw_core *mlxsw_core, struct sk_buff *skb, 1911 struct mlxsw_rx_info *rx_info) 1912 { 1913 struct mlxsw_rx_listener_item *rxl_item; 1914 const struct mlxsw_rx_listener *rxl; 1915 u8 local_port; 1916 bool found = false; 1917 1918 if (rx_info->is_lag) { 1919 dev_dbg_ratelimited(mlxsw_core->bus_info->dev, "%s: lag_id = %d, lag_port_index = 0x%x\n", 1920 __func__, rx_info->u.lag_id, 1921 rx_info->trap_id); 1922 /* Upper layer does not care if the skb came from LAG or not, 1923 * so just get the local_port for the lag port and push it up. 1924 */ 1925 local_port = mlxsw_core_lag_mapping_get(mlxsw_core, 1926 rx_info->u.lag_id, 1927 rx_info->lag_port_index); 1928 } else { 1929 local_port = rx_info->u.sys_port; 1930 } 1931 1932 dev_dbg_ratelimited(mlxsw_core->bus_info->dev, "%s: local_port = %d, trap_id = 0x%x\n", 1933 __func__, local_port, rx_info->trap_id); 1934 1935 if ((rx_info->trap_id >= MLXSW_TRAP_ID_MAX) || 1936 (local_port >= mlxsw_core->max_ports)) 1937 goto drop; 1938 1939 rcu_read_lock(); 1940 list_for_each_entry_rcu(rxl_item, &mlxsw_core->rx_listener_list, list) { 1941 rxl = &rxl_item->rxl; 1942 if ((rxl->local_port == MLXSW_PORT_DONT_CARE || 1943 rxl->local_port == local_port) && 1944 rxl->trap_id == rx_info->trap_id) { 1945 found = true; 1946 break; 1947 } 1948 } 1949 rcu_read_unlock(); 1950 if (!found) 1951 goto drop; 1952 1953 rxl->func(skb, local_port, rxl_item->priv); 1954 return; 1955 1956 drop: 1957 dev_kfree_skb(skb); 1958 } 1959 EXPORT_SYMBOL(mlxsw_core_skb_receive); 1960 1961 static int mlxsw_core_lag_mapping_index(struct mlxsw_core *mlxsw_core, 1962 u16 lag_id, u8 port_index) 1963 { 1964 return MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG_MEMBERS) * lag_id + 1965 port_index; 1966 } 1967 1968 void mlxsw_core_lag_mapping_set(struct mlxsw_core *mlxsw_core, 1969 u16 lag_id, u8 port_index, u8 local_port) 1970 { 1971 int index = mlxsw_core_lag_mapping_index(mlxsw_core, 1972 lag_id, port_index); 1973 1974 mlxsw_core->lag.mapping[index] = local_port; 1975 } 1976 EXPORT_SYMBOL(mlxsw_core_lag_mapping_set); 1977 1978 u8 mlxsw_core_lag_mapping_get(struct mlxsw_core *mlxsw_core, 1979 u16 lag_id, u8 port_index) 1980 { 1981 int index = mlxsw_core_lag_mapping_index(mlxsw_core, 1982 lag_id, port_index); 1983 1984 return mlxsw_core->lag.mapping[index]; 1985 } 1986 EXPORT_SYMBOL(mlxsw_core_lag_mapping_get); 1987 1988 void mlxsw_core_lag_mapping_clear(struct mlxsw_core *mlxsw_core, 1989 u16 lag_id, u8 local_port) 1990 { 1991 int i; 1992 1993 for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG_MEMBERS); i++) { 1994 int index = mlxsw_core_lag_mapping_index(mlxsw_core, 1995 lag_id, i); 1996 1997 if (mlxsw_core->lag.mapping[index] == local_port) 1998 mlxsw_core->lag.mapping[index] = 0; 1999 } 2000 } 2001 EXPORT_SYMBOL(mlxsw_core_lag_mapping_clear); 2002 2003 bool mlxsw_core_res_valid(struct mlxsw_core *mlxsw_core, 2004 enum mlxsw_res_id res_id) 2005 { 2006 return mlxsw_res_valid(&mlxsw_core->res, res_id); 2007 } 2008 EXPORT_SYMBOL(mlxsw_core_res_valid); 2009 2010 u64 mlxsw_core_res_get(struct mlxsw_core *mlxsw_core, 2011 enum mlxsw_res_id res_id) 2012 { 2013 return mlxsw_res_get(&mlxsw_core->res, res_id); 2014 } 2015 EXPORT_SYMBOL(mlxsw_core_res_get); 2016 2017 static int __mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u8 local_port, 2018 enum devlink_port_flavour flavour, 2019 u32 port_number, bool split, 2020 u32 split_port_subnumber, 2021 const unsigned char *switch_id, 2022 unsigned char switch_id_len) 2023 { 2024 struct devlink *devlink = priv_to_devlink(mlxsw_core); 2025 struct mlxsw_core_port *mlxsw_core_port = 2026 &mlxsw_core->ports[local_port]; 2027 struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port; 2028 int err; 2029 2030 mlxsw_core_port->local_port = local_port; 2031 devlink_port_attrs_set(devlink_port, flavour, port_number, 2032 split, split_port_subnumber, 2033 switch_id, switch_id_len); 2034 err = devlink_port_register(devlink, devlink_port, local_port); 2035 if (err) 2036 memset(mlxsw_core_port, 0, sizeof(*mlxsw_core_port)); 2037 return err; 2038 } 2039 2040 static void __mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u8 local_port) 2041 { 2042 struct mlxsw_core_port *mlxsw_core_port = 2043 &mlxsw_core->ports[local_port]; 2044 struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port; 2045 2046 devlink_port_unregister(devlink_port); 2047 memset(mlxsw_core_port, 0, sizeof(*mlxsw_core_port)); 2048 } 2049 2050 int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u8 local_port, 2051 u32 port_number, bool split, 2052 u32 split_port_subnumber, 2053 const unsigned char *switch_id, 2054 unsigned char switch_id_len) 2055 { 2056 return __mlxsw_core_port_init(mlxsw_core, local_port, 2057 DEVLINK_PORT_FLAVOUR_PHYSICAL, 2058 port_number, split, split_port_subnumber, 2059 switch_id, switch_id_len); 2060 } 2061 EXPORT_SYMBOL(mlxsw_core_port_init); 2062 2063 void mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u8 local_port) 2064 { 2065 __mlxsw_core_port_fini(mlxsw_core, local_port); 2066 } 2067 EXPORT_SYMBOL(mlxsw_core_port_fini); 2068 2069 int mlxsw_core_cpu_port_init(struct mlxsw_core *mlxsw_core, 2070 void *port_driver_priv, 2071 const unsigned char *switch_id, 2072 unsigned char switch_id_len) 2073 { 2074 struct mlxsw_core_port *mlxsw_core_port = 2075 &mlxsw_core->ports[MLXSW_PORT_CPU_PORT]; 2076 int err; 2077 2078 err = __mlxsw_core_port_init(mlxsw_core, MLXSW_PORT_CPU_PORT, 2079 DEVLINK_PORT_FLAVOUR_CPU, 2080 0, false, 0, 2081 switch_id, switch_id_len); 2082 if (err) 2083 return err; 2084 2085 mlxsw_core_port->port_driver_priv = port_driver_priv; 2086 return 0; 2087 } 2088 EXPORT_SYMBOL(mlxsw_core_cpu_port_init); 2089 2090 void mlxsw_core_cpu_port_fini(struct mlxsw_core *mlxsw_core) 2091 { 2092 __mlxsw_core_port_fini(mlxsw_core, MLXSW_PORT_CPU_PORT); 2093 } 2094 EXPORT_SYMBOL(mlxsw_core_cpu_port_fini); 2095 2096 void mlxsw_core_port_eth_set(struct mlxsw_core *mlxsw_core, u8 local_port, 2097 void *port_driver_priv, struct net_device *dev) 2098 { 2099 struct mlxsw_core_port *mlxsw_core_port = 2100 &mlxsw_core->ports[local_port]; 2101 struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port; 2102 2103 mlxsw_core_port->port_driver_priv = port_driver_priv; 2104 devlink_port_type_eth_set(devlink_port, dev); 2105 } 2106 EXPORT_SYMBOL(mlxsw_core_port_eth_set); 2107 2108 void mlxsw_core_port_ib_set(struct mlxsw_core *mlxsw_core, u8 local_port, 2109 void *port_driver_priv) 2110 { 2111 struct mlxsw_core_port *mlxsw_core_port = 2112 &mlxsw_core->ports[local_port]; 2113 struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port; 2114 2115 mlxsw_core_port->port_driver_priv = port_driver_priv; 2116 devlink_port_type_ib_set(devlink_port, NULL); 2117 } 2118 EXPORT_SYMBOL(mlxsw_core_port_ib_set); 2119 2120 void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u8 local_port, 2121 void *port_driver_priv) 2122 { 2123 struct mlxsw_core_port *mlxsw_core_port = 2124 &mlxsw_core->ports[local_port]; 2125 struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port; 2126 2127 mlxsw_core_port->port_driver_priv = port_driver_priv; 2128 devlink_port_type_clear(devlink_port); 2129 } 2130 EXPORT_SYMBOL(mlxsw_core_port_clear); 2131 2132 enum devlink_port_type mlxsw_core_port_type_get(struct mlxsw_core *mlxsw_core, 2133 u8 local_port) 2134 { 2135 struct mlxsw_core_port *mlxsw_core_port = 2136 &mlxsw_core->ports[local_port]; 2137 struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port; 2138 2139 return devlink_port->type; 2140 } 2141 EXPORT_SYMBOL(mlxsw_core_port_type_get); 2142 2143 2144 struct devlink_port * 2145 mlxsw_core_port_devlink_port_get(struct mlxsw_core *mlxsw_core, 2146 u8 local_port) 2147 { 2148 struct mlxsw_core_port *mlxsw_core_port = 2149 &mlxsw_core->ports[local_port]; 2150 struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port; 2151 2152 return devlink_port; 2153 } 2154 EXPORT_SYMBOL(mlxsw_core_port_devlink_port_get); 2155 2156 int mlxsw_core_module_max_width(struct mlxsw_core *mlxsw_core, u8 module) 2157 { 2158 enum mlxsw_reg_pmtm_module_type module_type; 2159 char pmtm_pl[MLXSW_REG_PMTM_LEN]; 2160 int err; 2161 2162 mlxsw_reg_pmtm_pack(pmtm_pl, module); 2163 err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(pmtm), pmtm_pl); 2164 if (err) 2165 return err; 2166 mlxsw_reg_pmtm_unpack(pmtm_pl, &module_type); 2167 2168 /* Here we need to get the module width according to the module type. */ 2169 2170 switch (module_type) { 2171 case MLXSW_REG_PMTM_MODULE_TYPE_BP_4X: /* fall through */ 2172 case MLXSW_REG_PMTM_MODULE_TYPE_BP_QSFP: 2173 return 4; 2174 case MLXSW_REG_PMTM_MODULE_TYPE_BP_2X: 2175 return 2; 2176 case MLXSW_REG_PMTM_MODULE_TYPE_BP_SFP: /* fall through */ 2177 case MLXSW_REG_PMTM_MODULE_TYPE_BP_1X: 2178 return 1; 2179 default: 2180 return -EINVAL; 2181 } 2182 } 2183 EXPORT_SYMBOL(mlxsw_core_module_max_width); 2184 2185 static void mlxsw_core_buf_dump_dbg(struct mlxsw_core *mlxsw_core, 2186 const char *buf, size_t size) 2187 { 2188 __be32 *m = (__be32 *) buf; 2189 int i; 2190 int count = size / sizeof(__be32); 2191 2192 for (i = count - 1; i >= 0; i--) 2193 if (m[i]) 2194 break; 2195 i++; 2196 count = i ? i : 1; 2197 for (i = 0; i < count; i += 4) 2198 dev_dbg(mlxsw_core->bus_info->dev, "%04x - %08x %08x %08x %08x\n", 2199 i * 4, be32_to_cpu(m[i]), be32_to_cpu(m[i + 1]), 2200 be32_to_cpu(m[i + 2]), be32_to_cpu(m[i + 3])); 2201 } 2202 2203 int mlxsw_cmd_exec(struct mlxsw_core *mlxsw_core, u16 opcode, u8 opcode_mod, 2204 u32 in_mod, bool out_mbox_direct, bool reset_ok, 2205 char *in_mbox, size_t in_mbox_size, 2206 char *out_mbox, size_t out_mbox_size) 2207 { 2208 u8 status; 2209 int err; 2210 2211 BUG_ON(in_mbox_size % sizeof(u32) || out_mbox_size % sizeof(u32)); 2212 if (!mlxsw_core->bus->cmd_exec) 2213 return -EOPNOTSUPP; 2214 2215 dev_dbg(mlxsw_core->bus_info->dev, "Cmd exec (opcode=%x(%s),opcode_mod=%x,in_mod=%x)\n", 2216 opcode, mlxsw_cmd_opcode_str(opcode), opcode_mod, in_mod); 2217 if (in_mbox) { 2218 dev_dbg(mlxsw_core->bus_info->dev, "Input mailbox:\n"); 2219 mlxsw_core_buf_dump_dbg(mlxsw_core, in_mbox, in_mbox_size); 2220 } 2221 2222 err = mlxsw_core->bus->cmd_exec(mlxsw_core->bus_priv, opcode, 2223 opcode_mod, in_mod, out_mbox_direct, 2224 in_mbox, in_mbox_size, 2225 out_mbox, out_mbox_size, &status); 2226 2227 if (!err && out_mbox) { 2228 dev_dbg(mlxsw_core->bus_info->dev, "Output mailbox:\n"); 2229 mlxsw_core_buf_dump_dbg(mlxsw_core, out_mbox, out_mbox_size); 2230 } 2231 2232 if (reset_ok && err == -EIO && 2233 status == MLXSW_CMD_STATUS_RUNNING_RESET) { 2234 err = 0; 2235 } else if (err == -EIO && status != MLXSW_CMD_STATUS_OK) { 2236 dev_err(mlxsw_core->bus_info->dev, "Cmd exec failed (opcode=%x(%s),opcode_mod=%x,in_mod=%x,status=%x(%s))\n", 2237 opcode, mlxsw_cmd_opcode_str(opcode), opcode_mod, 2238 in_mod, status, mlxsw_cmd_status_str(status)); 2239 } else if (err == -ETIMEDOUT) { 2240 dev_err(mlxsw_core->bus_info->dev, "Cmd exec timed-out (opcode=%x(%s),opcode_mod=%x,in_mod=%x)\n", 2241 opcode, mlxsw_cmd_opcode_str(opcode), opcode_mod, 2242 in_mod); 2243 } 2244 2245 return err; 2246 } 2247 EXPORT_SYMBOL(mlxsw_cmd_exec); 2248 2249 int mlxsw_core_schedule_dw(struct delayed_work *dwork, unsigned long delay) 2250 { 2251 return queue_delayed_work(mlxsw_wq, dwork, delay); 2252 } 2253 EXPORT_SYMBOL(mlxsw_core_schedule_dw); 2254 2255 bool mlxsw_core_schedule_work(struct work_struct *work) 2256 { 2257 return queue_work(mlxsw_owq, work); 2258 } 2259 EXPORT_SYMBOL(mlxsw_core_schedule_work); 2260 2261 void mlxsw_core_flush_owq(void) 2262 { 2263 flush_workqueue(mlxsw_owq); 2264 } 2265 EXPORT_SYMBOL(mlxsw_core_flush_owq); 2266 2267 int mlxsw_core_kvd_sizes_get(struct mlxsw_core *mlxsw_core, 2268 const struct mlxsw_config_profile *profile, 2269 u64 *p_single_size, u64 *p_double_size, 2270 u64 *p_linear_size) 2271 { 2272 struct mlxsw_driver *driver = mlxsw_core->driver; 2273 2274 if (!driver->kvd_sizes_get) 2275 return -EINVAL; 2276 2277 return driver->kvd_sizes_get(mlxsw_core, profile, 2278 p_single_size, p_double_size, 2279 p_linear_size); 2280 } 2281 EXPORT_SYMBOL(mlxsw_core_kvd_sizes_get); 2282 2283 void mlxsw_core_fw_flash_start(struct mlxsw_core *mlxsw_core) 2284 { 2285 mlxsw_core->fw_flash_in_progress = true; 2286 } 2287 EXPORT_SYMBOL(mlxsw_core_fw_flash_start); 2288 2289 void mlxsw_core_fw_flash_end(struct mlxsw_core *mlxsw_core) 2290 { 2291 mlxsw_core->fw_flash_in_progress = false; 2292 } 2293 EXPORT_SYMBOL(mlxsw_core_fw_flash_end); 2294 2295 int mlxsw_core_resources_query(struct mlxsw_core *mlxsw_core, char *mbox, 2296 struct mlxsw_res *res) 2297 { 2298 int index, i; 2299 u64 data; 2300 u16 id; 2301 int err; 2302 2303 if (!res) 2304 return 0; 2305 2306 mlxsw_cmd_mbox_zero(mbox); 2307 2308 for (index = 0; index < MLXSW_CMD_QUERY_RESOURCES_MAX_QUERIES; 2309 index++) { 2310 err = mlxsw_cmd_query_resources(mlxsw_core, mbox, index); 2311 if (err) 2312 return err; 2313 2314 for (i = 0; i < MLXSW_CMD_QUERY_RESOURCES_PER_QUERY; i++) { 2315 id = mlxsw_cmd_mbox_query_resource_id_get(mbox, i); 2316 data = mlxsw_cmd_mbox_query_resource_data_get(mbox, i); 2317 2318 if (id == MLXSW_CMD_QUERY_RESOURCES_TABLE_END_ID) 2319 return 0; 2320 2321 mlxsw_res_parse(res, id, data); 2322 } 2323 } 2324 2325 /* If after MLXSW_RESOURCES_QUERY_MAX_QUERIES we still didn't get 2326 * MLXSW_RESOURCES_TABLE_END_ID, something went bad in the FW. 2327 */ 2328 return -EIO; 2329 } 2330 EXPORT_SYMBOL(mlxsw_core_resources_query); 2331 2332 u32 mlxsw_core_read_frc_h(struct mlxsw_core *mlxsw_core) 2333 { 2334 return mlxsw_core->bus->read_frc_h(mlxsw_core->bus_priv); 2335 } 2336 EXPORT_SYMBOL(mlxsw_core_read_frc_h); 2337 2338 u32 mlxsw_core_read_frc_l(struct mlxsw_core *mlxsw_core) 2339 { 2340 return mlxsw_core->bus->read_frc_l(mlxsw_core->bus_priv); 2341 } 2342 EXPORT_SYMBOL(mlxsw_core_read_frc_l); 2343 2344 void mlxsw_core_emad_string_tlv_enable(struct mlxsw_core *mlxsw_core) 2345 { 2346 mlxsw_core->emad.enable_string_tlv = true; 2347 } 2348 EXPORT_SYMBOL(mlxsw_core_emad_string_tlv_enable); 2349 2350 static int __init mlxsw_core_module_init(void) 2351 { 2352 int err; 2353 2354 mlxsw_wq = alloc_workqueue(mlxsw_core_driver_name, 0, 0); 2355 if (!mlxsw_wq) 2356 return -ENOMEM; 2357 mlxsw_owq = alloc_ordered_workqueue("%s_ordered", 0, 2358 mlxsw_core_driver_name); 2359 if (!mlxsw_owq) { 2360 err = -ENOMEM; 2361 goto err_alloc_ordered_workqueue; 2362 } 2363 return 0; 2364 2365 err_alloc_ordered_workqueue: 2366 destroy_workqueue(mlxsw_wq); 2367 return err; 2368 } 2369 2370 static void __exit mlxsw_core_module_exit(void) 2371 { 2372 destroy_workqueue(mlxsw_owq); 2373 destroy_workqueue(mlxsw_wq); 2374 } 2375 2376 module_init(mlxsw_core_module_init); 2377 module_exit(mlxsw_core_module_exit); 2378 2379 MODULE_LICENSE("Dual BSD/GPL"); 2380 MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>"); 2381 MODULE_DESCRIPTION("Mellanox switch device core driver"); 2382