1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /* Copyright (c) 2015-2018 Mellanox Technologies. All rights reserved */
4 #include <linux/kernel.h>
5 #include <linux/module.h>
6 #include <linux/device.h>
7 #include <linux/export.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>
34 #include "resources.h"
36 static LIST_HEAD(mlxsw_core_driver_list);
37 static DEFINE_SPINLOCK(mlxsw_core_driver_list_lock);
39 static const char mlxsw_core_driver_name[] = "mlxsw_core";
41 static struct workqueue_struct *mlxsw_wq;
42 static struct workqueue_struct *mlxsw_owq;
44 struct mlxsw_core_port {
45 struct devlink_port devlink_port;
46 void *port_driver_priv;
50 void *mlxsw_core_port_driver_priv(struct mlxsw_core_port *mlxsw_core_port)
52 return mlxsw_core_port->port_driver_priv;
54 EXPORT_SYMBOL(mlxsw_core_port_driver_priv);
56 static bool mlxsw_core_port_check(struct mlxsw_core_port *mlxsw_core_port)
58 return mlxsw_core_port->port_driver_priv != NULL;
62 struct mlxsw_driver *driver;
63 const struct mlxsw_bus *bus;
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;
71 struct list_head trans_list;
72 spinlock_t trans_list_lock; /* protects trans_list writes */
74 bool enable_string_tlv;
77 u8 *mapping; /* lag_id+port_index to local_port mapping */
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[];
86 /* driver_priv has to be always the last item */
89 #define MLXSW_PORT_MAX_PORTS_DEFAULT 0x40
91 static int mlxsw_ports_init(struct mlxsw_core *mlxsw_core)
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,
98 mlxsw_core->max_ports = MLXSW_PORT_MAX_PORTS_DEFAULT + 1;
100 mlxsw_core->ports = kcalloc(mlxsw_core->max_ports,
101 sizeof(struct mlxsw_core_port), GFP_KERNEL);
102 if (!mlxsw_core->ports)
108 static void mlxsw_ports_fini(struct mlxsw_core *mlxsw_core)
110 kfree(mlxsw_core->ports);
113 unsigned int mlxsw_core_max_ports(const struct mlxsw_core *mlxsw_core)
115 return mlxsw_core->max_ports;
117 EXPORT_SYMBOL(mlxsw_core_max_ports);
119 void *mlxsw_core_driver_priv(struct mlxsw_core *mlxsw_core)
121 return mlxsw_core->driver_priv;
123 EXPORT_SYMBOL(mlxsw_core_driver_priv);
125 bool mlxsw_core_res_query_enabled(const struct mlxsw_core *mlxsw_core)
127 return mlxsw_core->driver->res_query_enabled;
129 EXPORT_SYMBOL(mlxsw_core_res_query_enabled);
132 mlxsw_core_fw_rev_minor_subminor_validate(const struct mlxsw_fw_rev *rev,
133 const struct mlxsw_fw_rev *req_rev)
135 return rev->minor > req_rev->minor ||
136 (rev->minor == req_rev->minor &&
137 rev->subminor >= req_rev->subminor);
139 EXPORT_SYMBOL(mlxsw_core_fw_rev_minor_subminor_validate);
141 struct mlxsw_rx_listener_item {
142 struct list_head list;
143 struct mlxsw_rx_listener rxl;
148 struct mlxsw_event_listener_item {
149 struct list_head list;
150 struct mlxsw_event_listener el;
159 * Destination MAC in EMAD's Ethernet header.
160 * Must be set to 01:02:c9:00:00:01
162 MLXSW_ITEM_BUF(emad, eth_hdr, dmac, 0x00, 6);
165 * Source MAC in EMAD's Ethernet header.
166 * Must be set to 00:02:c9:01:02:03
168 MLXSW_ITEM_BUF(emad, eth_hdr, smac, 0x06, 6);
170 /* emad_eth_hdr_ethertype
171 * Ethertype in EMAD's Ethernet header.
172 * Must be set to 0x8932
174 MLXSW_ITEM32(emad, eth_hdr, ethertype, 0x0C, 16, 16);
176 /* emad_eth_hdr_mlx_proto
178 * Must be set to 0x0.
180 MLXSW_ITEM32(emad, eth_hdr, mlx_proto, 0x0C, 8, 8);
183 * Mellanox protocol version.
184 * Must be set to 0x0.
186 MLXSW_ITEM32(emad, eth_hdr, ver, 0x0C, 4, 4);
190 * Must be set to 0x1 (operation TLV).
192 MLXSW_ITEM32(emad, op_tlv, type, 0x00, 27, 5);
195 * Length of the operation TLV in u32.
196 * Must be set to 0x4.
198 MLXSW_ITEM32(emad, op_tlv, len, 0x00, 16, 11);
201 * Direct route bit. Setting to 1 indicates the EMAD is a direct route
202 * EMAD. DR TLV must follow.
204 * Note: Currently not supported and must not be set.
206 MLXSW_ITEM32(emad, op_tlv, dr, 0x00, 15, 1);
208 /* emad_op_tlv_status
209 * Returned status in case of EMAD response. Must be set to 0 in case
212 * 0x1 - device is busy. Requester should retry
213 * 0x2 - Mellanox protocol version not supported
215 * 0x4 - register not supported
216 * 0x5 - operation class not supported
217 * 0x6 - EMAD method not supported
218 * 0x7 - bad parameter (e.g. port out of range)
219 * 0x8 - resource not available
220 * 0x9 - message receipt acknowledgment. Requester should retry
221 * 0x70 - internal error
223 MLXSW_ITEM32(emad, op_tlv, status, 0x00, 8, 7);
225 /* emad_op_tlv_register_id
226 * Register ID of register within register TLV.
228 MLXSW_ITEM32(emad, op_tlv, register_id, 0x04, 16, 16);
231 * Response bit. Setting to 1 indicates Response, otherwise request.
233 MLXSW_ITEM32(emad, op_tlv, r, 0x04, 15, 1);
235 /* emad_op_tlv_method
239 * 0x3 - send (currently not supported)
242 MLXSW_ITEM32(emad, op_tlv, method, 0x04, 8, 7);
245 * EMAD operation class. Must be set to 0x1 (REG_ACCESS).
247 MLXSW_ITEM32(emad, op_tlv, class, 0x04, 0, 8);
250 * EMAD transaction ID. Used for pairing request and response EMADs.
252 MLXSW_ITEM64(emad, op_tlv, tid, 0x08, 0, 64);
254 /* emad_string_tlv_type
256 * Must be set to 0x2 (string TLV).
258 MLXSW_ITEM32(emad, string_tlv, type, 0x00, 27, 5);
260 /* emad_string_tlv_len
261 * Length of the string TLV in u32.
263 MLXSW_ITEM32(emad, string_tlv, len, 0x00, 16, 11);
265 #define MLXSW_EMAD_STRING_TLV_STRING_LEN 128
267 /* emad_string_tlv_string
268 * String provided by the device's firmware in case of erroneous register access
270 MLXSW_ITEM_BUF(emad, string_tlv, string, 0x04,
271 MLXSW_EMAD_STRING_TLV_STRING_LEN);
275 * Must be set to 0x3 (register TLV).
277 MLXSW_ITEM32(emad, reg_tlv, type, 0x00, 27, 5);
280 * Length of the operation TLV in u32.
282 MLXSW_ITEM32(emad, reg_tlv, len, 0x00, 16, 11);
286 * Must be set to 0x0 (end TLV).
288 MLXSW_ITEM32(emad, end_tlv, type, 0x00, 27, 5);
291 * Length of the end TLV in u32.
294 MLXSW_ITEM32(emad, end_tlv, len, 0x00, 16, 11);
296 enum mlxsw_core_reg_access_type {
297 MLXSW_CORE_REG_ACCESS_TYPE_QUERY,
298 MLXSW_CORE_REG_ACCESS_TYPE_WRITE,
301 static inline const char *
302 mlxsw_core_reg_access_type_str(enum mlxsw_core_reg_access_type type)
305 case MLXSW_CORE_REG_ACCESS_TYPE_QUERY:
307 case MLXSW_CORE_REG_ACCESS_TYPE_WRITE:
313 static void mlxsw_emad_pack_end_tlv(char *end_tlv)
315 mlxsw_emad_end_tlv_type_set(end_tlv, MLXSW_EMAD_TLV_TYPE_END);
316 mlxsw_emad_end_tlv_len_set(end_tlv, MLXSW_EMAD_END_TLV_LEN);
319 static void mlxsw_emad_pack_reg_tlv(char *reg_tlv,
320 const struct mlxsw_reg_info *reg,
323 mlxsw_emad_reg_tlv_type_set(reg_tlv, MLXSW_EMAD_TLV_TYPE_REG);
324 mlxsw_emad_reg_tlv_len_set(reg_tlv, reg->len / sizeof(u32) + 1);
325 memcpy(reg_tlv + sizeof(u32), payload, reg->len);
328 static void mlxsw_emad_pack_string_tlv(char *string_tlv)
330 mlxsw_emad_string_tlv_type_set(string_tlv, MLXSW_EMAD_TLV_TYPE_STRING);
331 mlxsw_emad_string_tlv_len_set(string_tlv, MLXSW_EMAD_STRING_TLV_LEN);
334 static void mlxsw_emad_pack_op_tlv(char *op_tlv,
335 const struct mlxsw_reg_info *reg,
336 enum mlxsw_core_reg_access_type type,
339 mlxsw_emad_op_tlv_type_set(op_tlv, MLXSW_EMAD_TLV_TYPE_OP);
340 mlxsw_emad_op_tlv_len_set(op_tlv, MLXSW_EMAD_OP_TLV_LEN);
341 mlxsw_emad_op_tlv_dr_set(op_tlv, 0);
342 mlxsw_emad_op_tlv_status_set(op_tlv, 0);
343 mlxsw_emad_op_tlv_register_id_set(op_tlv, reg->id);
344 mlxsw_emad_op_tlv_r_set(op_tlv, MLXSW_EMAD_OP_TLV_REQUEST);
345 if (type == MLXSW_CORE_REG_ACCESS_TYPE_QUERY)
346 mlxsw_emad_op_tlv_method_set(op_tlv,
347 MLXSW_EMAD_OP_TLV_METHOD_QUERY);
349 mlxsw_emad_op_tlv_method_set(op_tlv,
350 MLXSW_EMAD_OP_TLV_METHOD_WRITE);
351 mlxsw_emad_op_tlv_class_set(op_tlv,
352 MLXSW_EMAD_OP_TLV_CLASS_REG_ACCESS);
353 mlxsw_emad_op_tlv_tid_set(op_tlv, tid);
356 static int mlxsw_emad_construct_eth_hdr(struct sk_buff *skb)
358 char *eth_hdr = skb_push(skb, MLXSW_EMAD_ETH_HDR_LEN);
360 mlxsw_emad_eth_hdr_dmac_memcpy_to(eth_hdr, MLXSW_EMAD_EH_DMAC);
361 mlxsw_emad_eth_hdr_smac_memcpy_to(eth_hdr, MLXSW_EMAD_EH_SMAC);
362 mlxsw_emad_eth_hdr_ethertype_set(eth_hdr, MLXSW_EMAD_EH_ETHERTYPE);
363 mlxsw_emad_eth_hdr_mlx_proto_set(eth_hdr, MLXSW_EMAD_EH_MLX_PROTO);
364 mlxsw_emad_eth_hdr_ver_set(eth_hdr, MLXSW_EMAD_EH_PROTO_VERSION);
366 skb_reset_mac_header(skb);
371 static void mlxsw_emad_construct(struct sk_buff *skb,
372 const struct mlxsw_reg_info *reg,
374 enum mlxsw_core_reg_access_type type,
375 u64 tid, bool enable_string_tlv)
379 buf = skb_push(skb, MLXSW_EMAD_END_TLV_LEN * sizeof(u32));
380 mlxsw_emad_pack_end_tlv(buf);
382 buf = skb_push(skb, reg->len + sizeof(u32));
383 mlxsw_emad_pack_reg_tlv(buf, reg, payload);
385 if (enable_string_tlv) {
386 buf = skb_push(skb, MLXSW_EMAD_STRING_TLV_LEN * sizeof(u32));
387 mlxsw_emad_pack_string_tlv(buf);
390 buf = skb_push(skb, MLXSW_EMAD_OP_TLV_LEN * sizeof(u32));
391 mlxsw_emad_pack_op_tlv(buf, reg, type, tid);
393 mlxsw_emad_construct_eth_hdr(skb);
396 struct mlxsw_emad_tlv_offsets {
402 static bool mlxsw_emad_tlv_is_string_tlv(const char *tlv)
404 u8 tlv_type = mlxsw_emad_string_tlv_type_get(tlv);
406 return tlv_type == MLXSW_EMAD_TLV_TYPE_STRING;
409 static void mlxsw_emad_tlv_parse(struct sk_buff *skb)
411 struct mlxsw_emad_tlv_offsets *offsets =
412 (struct mlxsw_emad_tlv_offsets *) skb->cb;
414 offsets->op_tlv = MLXSW_EMAD_ETH_HDR_LEN;
415 offsets->string_tlv = 0;
416 offsets->reg_tlv = MLXSW_EMAD_ETH_HDR_LEN +
417 MLXSW_EMAD_OP_TLV_LEN * sizeof(u32);
419 /* If string TLV is present, it must come after the operation TLV. */
420 if (mlxsw_emad_tlv_is_string_tlv(skb->data + offsets->reg_tlv)) {
421 offsets->string_tlv = offsets->reg_tlv;
422 offsets->reg_tlv += MLXSW_EMAD_STRING_TLV_LEN * sizeof(u32);
426 static char *mlxsw_emad_op_tlv(const struct sk_buff *skb)
428 struct mlxsw_emad_tlv_offsets *offsets =
429 (struct mlxsw_emad_tlv_offsets *) skb->cb;
431 return ((char *) (skb->data + offsets->op_tlv));
434 static char *mlxsw_emad_string_tlv(const struct sk_buff *skb)
436 struct mlxsw_emad_tlv_offsets *offsets =
437 (struct mlxsw_emad_tlv_offsets *) skb->cb;
439 if (!offsets->string_tlv)
442 return ((char *) (skb->data + offsets->string_tlv));
445 static char *mlxsw_emad_reg_tlv(const struct sk_buff *skb)
447 struct mlxsw_emad_tlv_offsets *offsets =
448 (struct mlxsw_emad_tlv_offsets *) skb->cb;
450 return ((char *) (skb->data + offsets->reg_tlv));
453 static char *mlxsw_emad_reg_payload(const char *reg_tlv)
455 return ((char *) (reg_tlv + sizeof(u32)));
458 static char *mlxsw_emad_reg_payload_cmd(const char *mbox)
460 return ((char *) (mbox + (MLXSW_EMAD_OP_TLV_LEN + 1) * sizeof(u32)));
463 static u64 mlxsw_emad_get_tid(const struct sk_buff *skb)
467 op_tlv = mlxsw_emad_op_tlv(skb);
468 return mlxsw_emad_op_tlv_tid_get(op_tlv);
471 static bool mlxsw_emad_is_resp(const struct sk_buff *skb)
475 op_tlv = mlxsw_emad_op_tlv(skb);
476 return (mlxsw_emad_op_tlv_r_get(op_tlv) == MLXSW_EMAD_OP_TLV_RESPONSE);
479 static int mlxsw_emad_process_status(char *op_tlv,
480 enum mlxsw_emad_op_tlv_status *p_status)
482 *p_status = mlxsw_emad_op_tlv_status_get(op_tlv);
485 case MLXSW_EMAD_OP_TLV_STATUS_SUCCESS:
487 case MLXSW_EMAD_OP_TLV_STATUS_BUSY:
488 case MLXSW_EMAD_OP_TLV_STATUS_MESSAGE_RECEIPT_ACK:
490 case MLXSW_EMAD_OP_TLV_STATUS_VERSION_NOT_SUPPORTED:
491 case MLXSW_EMAD_OP_TLV_STATUS_UNKNOWN_TLV:
492 case MLXSW_EMAD_OP_TLV_STATUS_REGISTER_NOT_SUPPORTED:
493 case MLXSW_EMAD_OP_TLV_STATUS_CLASS_NOT_SUPPORTED:
494 case MLXSW_EMAD_OP_TLV_STATUS_METHOD_NOT_SUPPORTED:
495 case MLXSW_EMAD_OP_TLV_STATUS_BAD_PARAMETER:
496 case MLXSW_EMAD_OP_TLV_STATUS_RESOURCE_NOT_AVAILABLE:
497 case MLXSW_EMAD_OP_TLV_STATUS_INTERNAL_ERROR:
504 mlxsw_emad_process_status_skb(struct sk_buff *skb,
505 enum mlxsw_emad_op_tlv_status *p_status)
507 return mlxsw_emad_process_status(mlxsw_emad_op_tlv(skb), p_status);
510 struct mlxsw_reg_trans {
511 struct list_head list;
512 struct list_head bulk_list;
513 struct mlxsw_core *core;
514 struct sk_buff *tx_skb;
515 struct mlxsw_tx_info tx_info;
516 struct delayed_work timeout_dw;
517 unsigned int retries;
519 struct completion completion;
521 mlxsw_reg_trans_cb_t *cb;
522 unsigned long cb_priv;
523 const struct mlxsw_reg_info *reg;
524 enum mlxsw_core_reg_access_type type;
526 char *emad_err_string;
527 enum mlxsw_emad_op_tlv_status emad_status;
531 static void mlxsw_emad_process_string_tlv(const struct sk_buff *skb,
532 struct mlxsw_reg_trans *trans)
537 string_tlv = mlxsw_emad_string_tlv(skb);
541 trans->emad_err_string = kzalloc(MLXSW_EMAD_STRING_TLV_STRING_LEN,
543 if (!trans->emad_err_string)
546 string = mlxsw_emad_string_tlv_string_data(string_tlv);
547 strlcpy(trans->emad_err_string, string,
548 MLXSW_EMAD_STRING_TLV_STRING_LEN);
551 #define MLXSW_EMAD_TIMEOUT_DURING_FW_FLASH_MS 3000
552 #define MLXSW_EMAD_TIMEOUT_MS 200
554 static void mlxsw_emad_trans_timeout_schedule(struct mlxsw_reg_trans *trans)
556 unsigned long timeout = msecs_to_jiffies(MLXSW_EMAD_TIMEOUT_MS);
558 if (trans->core->fw_flash_in_progress)
559 timeout = msecs_to_jiffies(MLXSW_EMAD_TIMEOUT_DURING_FW_FLASH_MS);
561 queue_delayed_work(trans->core->emad_wq, &trans->timeout_dw, timeout);
564 static int mlxsw_emad_transmit(struct mlxsw_core *mlxsw_core,
565 struct mlxsw_reg_trans *trans)
570 skb = skb_copy(trans->tx_skb, GFP_KERNEL);
574 trace_devlink_hwmsg(priv_to_devlink(mlxsw_core), false, 0,
575 skb->data + mlxsw_core->driver->txhdr_len,
576 skb->len - mlxsw_core->driver->txhdr_len);
578 atomic_set(&trans->active, 1);
579 err = mlxsw_core_skb_transmit(mlxsw_core, skb, &trans->tx_info);
584 mlxsw_emad_trans_timeout_schedule(trans);
588 static void mlxsw_emad_trans_finish(struct mlxsw_reg_trans *trans, int err)
590 struct mlxsw_core *mlxsw_core = trans->core;
592 dev_kfree_skb(trans->tx_skb);
593 spin_lock_bh(&mlxsw_core->emad.trans_list_lock);
594 list_del_rcu(&trans->list);
595 spin_unlock_bh(&mlxsw_core->emad.trans_list_lock);
597 complete(&trans->completion);
600 static void mlxsw_emad_transmit_retry(struct mlxsw_core *mlxsw_core,
601 struct mlxsw_reg_trans *trans)
605 if (trans->retries < MLXSW_EMAD_MAX_RETRY) {
607 err = mlxsw_emad_transmit(trans->core, trans);
613 mlxsw_emad_trans_finish(trans, err);
616 static void mlxsw_emad_trans_timeout_work(struct work_struct *work)
618 struct mlxsw_reg_trans *trans = container_of(work,
619 struct mlxsw_reg_trans,
622 if (!atomic_dec_and_test(&trans->active))
625 mlxsw_emad_transmit_retry(trans->core, trans);
628 static void mlxsw_emad_process_response(struct mlxsw_core *mlxsw_core,
629 struct mlxsw_reg_trans *trans,
634 if (!atomic_dec_and_test(&trans->active))
637 err = mlxsw_emad_process_status_skb(skb, &trans->emad_status);
638 if (err == -EAGAIN) {
639 mlxsw_emad_transmit_retry(mlxsw_core, trans);
642 char *reg_tlv = mlxsw_emad_reg_tlv(skb);
645 trans->cb(mlxsw_core,
646 mlxsw_emad_reg_payload(reg_tlv),
647 trans->reg->len, trans->cb_priv);
649 mlxsw_emad_process_string_tlv(skb, trans);
651 mlxsw_emad_trans_finish(trans, err);
655 /* called with rcu read lock held */
656 static void mlxsw_emad_rx_listener_func(struct sk_buff *skb, u8 local_port,
659 struct mlxsw_core *mlxsw_core = priv;
660 struct mlxsw_reg_trans *trans;
662 trace_devlink_hwmsg(priv_to_devlink(mlxsw_core), true, 0,
663 skb->data, skb->len);
665 mlxsw_emad_tlv_parse(skb);
667 if (!mlxsw_emad_is_resp(skb))
670 list_for_each_entry_rcu(trans, &mlxsw_core->emad.trans_list, list) {
671 if (mlxsw_emad_get_tid(skb) == trans->tid) {
672 mlxsw_emad_process_response(mlxsw_core, trans, skb);
681 static const struct mlxsw_listener mlxsw_emad_rx_listener =
682 MLXSW_RXL(mlxsw_emad_rx_listener_func, ETHEMAD, TRAP_TO_CPU, false,
685 static int mlxsw_emad_init(struct mlxsw_core *mlxsw_core)
687 struct workqueue_struct *emad_wq;
691 if (!(mlxsw_core->bus->features & MLXSW_BUS_F_TXRX))
694 emad_wq = alloc_workqueue("mlxsw_core_emad", 0, 0);
697 mlxsw_core->emad_wq = emad_wq;
699 /* Set the upper 32 bits of the transaction ID field to a random
700 * number. This allows us to discard EMADs addressed to other
703 get_random_bytes(&tid, 4);
705 atomic64_set(&mlxsw_core->emad.tid, tid);
707 INIT_LIST_HEAD(&mlxsw_core->emad.trans_list);
708 spin_lock_init(&mlxsw_core->emad.trans_list_lock);
710 err = mlxsw_core_trap_register(mlxsw_core, &mlxsw_emad_rx_listener,
715 err = mlxsw_core->driver->basic_trap_groups_set(mlxsw_core);
717 goto err_emad_trap_set;
718 mlxsw_core->emad.use_emad = true;
723 mlxsw_core_trap_unregister(mlxsw_core, &mlxsw_emad_rx_listener,
725 destroy_workqueue(mlxsw_core->emad_wq);
729 static void mlxsw_emad_fini(struct mlxsw_core *mlxsw_core)
732 if (!(mlxsw_core->bus->features & MLXSW_BUS_F_TXRX))
735 mlxsw_core->emad.use_emad = false;
736 mlxsw_core_trap_unregister(mlxsw_core, &mlxsw_emad_rx_listener,
738 destroy_workqueue(mlxsw_core->emad_wq);
741 static struct sk_buff *mlxsw_emad_alloc(const struct mlxsw_core *mlxsw_core,
742 u16 reg_len, bool enable_string_tlv)
747 emad_len = (reg_len + sizeof(u32) + MLXSW_EMAD_ETH_HDR_LEN +
748 (MLXSW_EMAD_OP_TLV_LEN + MLXSW_EMAD_END_TLV_LEN) *
749 sizeof(u32) + mlxsw_core->driver->txhdr_len);
750 if (enable_string_tlv)
751 emad_len += MLXSW_EMAD_STRING_TLV_LEN * sizeof(u32);
752 if (emad_len > MLXSW_EMAD_MAX_FRAME_LEN)
755 skb = netdev_alloc_skb(NULL, emad_len);
758 memset(skb->data, 0, emad_len);
759 skb_reserve(skb, emad_len);
764 static int mlxsw_emad_reg_access(struct mlxsw_core *mlxsw_core,
765 const struct mlxsw_reg_info *reg,
767 enum mlxsw_core_reg_access_type type,
768 struct mlxsw_reg_trans *trans,
769 struct list_head *bulk_list,
770 mlxsw_reg_trans_cb_t *cb,
771 unsigned long cb_priv, u64 tid)
773 bool enable_string_tlv;
777 dev_dbg(mlxsw_core->bus_info->dev, "EMAD reg access (tid=%llx,reg_id=%x(%s),type=%s)\n",
778 tid, reg->id, mlxsw_reg_id_str(reg->id),
779 mlxsw_core_reg_access_type_str(type));
781 /* Since this can be changed during emad_reg_access, read it once and
782 * use the value all the way.
784 enable_string_tlv = mlxsw_core->emad.enable_string_tlv;
786 skb = mlxsw_emad_alloc(mlxsw_core, reg->len, enable_string_tlv);
790 list_add_tail(&trans->bulk_list, bulk_list);
791 trans->core = mlxsw_core;
793 trans->tx_info.local_port = MLXSW_PORT_CPU_PORT;
794 trans->tx_info.is_emad = true;
795 INIT_DELAYED_WORK(&trans->timeout_dw, mlxsw_emad_trans_timeout_work);
797 init_completion(&trans->completion);
799 trans->cb_priv = cb_priv;
803 mlxsw_emad_construct(skb, reg, payload, type, trans->tid,
805 mlxsw_core->driver->txhdr_construct(skb, &trans->tx_info);
807 spin_lock_bh(&mlxsw_core->emad.trans_list_lock);
808 list_add_tail_rcu(&trans->list, &mlxsw_core->emad.trans_list);
809 spin_unlock_bh(&mlxsw_core->emad.trans_list_lock);
810 err = mlxsw_emad_transmit(mlxsw_core, trans);
816 spin_lock_bh(&mlxsw_core->emad.trans_list_lock);
817 list_del_rcu(&trans->list);
818 spin_unlock_bh(&mlxsw_core->emad.trans_list_lock);
819 list_del(&trans->bulk_list);
820 dev_kfree_skb(trans->tx_skb);
828 int mlxsw_core_driver_register(struct mlxsw_driver *mlxsw_driver)
830 spin_lock(&mlxsw_core_driver_list_lock);
831 list_add_tail(&mlxsw_driver->list, &mlxsw_core_driver_list);
832 spin_unlock(&mlxsw_core_driver_list_lock);
835 EXPORT_SYMBOL(mlxsw_core_driver_register);
837 void mlxsw_core_driver_unregister(struct mlxsw_driver *mlxsw_driver)
839 spin_lock(&mlxsw_core_driver_list_lock);
840 list_del(&mlxsw_driver->list);
841 spin_unlock(&mlxsw_core_driver_list_lock);
843 EXPORT_SYMBOL(mlxsw_core_driver_unregister);
845 static struct mlxsw_driver *__driver_find(const char *kind)
847 struct mlxsw_driver *mlxsw_driver;
849 list_for_each_entry(mlxsw_driver, &mlxsw_core_driver_list, list) {
850 if (strcmp(mlxsw_driver->kind, kind) == 0)
856 static struct mlxsw_driver *mlxsw_core_driver_get(const char *kind)
858 struct mlxsw_driver *mlxsw_driver;
860 spin_lock(&mlxsw_core_driver_list_lock);
861 mlxsw_driver = __driver_find(kind);
862 spin_unlock(&mlxsw_core_driver_list_lock);
866 static int mlxsw_devlink_port_split(struct devlink *devlink,
867 unsigned int port_index,
869 struct netlink_ext_ack *extack)
871 struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
873 if (port_index >= mlxsw_core->max_ports) {
874 NL_SET_ERR_MSG_MOD(extack, "Port index exceeds maximum number of ports");
877 if (!mlxsw_core->driver->port_split)
879 return mlxsw_core->driver->port_split(mlxsw_core, port_index, count,
883 static int mlxsw_devlink_port_unsplit(struct devlink *devlink,
884 unsigned int port_index,
885 struct netlink_ext_ack *extack)
887 struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
889 if (port_index >= mlxsw_core->max_ports) {
890 NL_SET_ERR_MSG_MOD(extack, "Port index exceeds maximum number of ports");
893 if (!mlxsw_core->driver->port_unsplit)
895 return mlxsw_core->driver->port_unsplit(mlxsw_core, port_index,
900 mlxsw_devlink_sb_pool_get(struct devlink *devlink,
901 unsigned int sb_index, u16 pool_index,
902 struct devlink_sb_pool_info *pool_info)
904 struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
905 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
907 if (!mlxsw_driver->sb_pool_get)
909 return mlxsw_driver->sb_pool_get(mlxsw_core, sb_index,
910 pool_index, pool_info);
914 mlxsw_devlink_sb_pool_set(struct devlink *devlink,
915 unsigned int sb_index, u16 pool_index, u32 size,
916 enum devlink_sb_threshold_type threshold_type,
917 struct netlink_ext_ack *extack)
919 struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
920 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
922 if (!mlxsw_driver->sb_pool_set)
924 return mlxsw_driver->sb_pool_set(mlxsw_core, sb_index,
925 pool_index, size, threshold_type,
929 static void *__dl_port(struct devlink_port *devlink_port)
931 return container_of(devlink_port, struct mlxsw_core_port, devlink_port);
934 static int mlxsw_devlink_port_type_set(struct devlink_port *devlink_port,
935 enum devlink_port_type port_type)
937 struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink);
938 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
939 struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);
941 if (!mlxsw_driver->port_type_set)
944 return mlxsw_driver->port_type_set(mlxsw_core,
945 mlxsw_core_port->local_port,
949 static int mlxsw_devlink_sb_port_pool_get(struct devlink_port *devlink_port,
950 unsigned int sb_index, u16 pool_index,
953 struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink);
954 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
955 struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);
957 if (!mlxsw_driver->sb_port_pool_get ||
958 !mlxsw_core_port_check(mlxsw_core_port))
960 return mlxsw_driver->sb_port_pool_get(mlxsw_core_port, sb_index,
961 pool_index, p_threshold);
964 static int mlxsw_devlink_sb_port_pool_set(struct devlink_port *devlink_port,
965 unsigned int sb_index, u16 pool_index,
967 struct netlink_ext_ack *extack)
969 struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink);
970 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
971 struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);
973 if (!mlxsw_driver->sb_port_pool_set ||
974 !mlxsw_core_port_check(mlxsw_core_port))
976 return mlxsw_driver->sb_port_pool_set(mlxsw_core_port, sb_index,
977 pool_index, threshold, extack);
981 mlxsw_devlink_sb_tc_pool_bind_get(struct devlink_port *devlink_port,
982 unsigned int sb_index, u16 tc_index,
983 enum devlink_sb_pool_type pool_type,
984 u16 *p_pool_index, u32 *p_threshold)
986 struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink);
987 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
988 struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);
990 if (!mlxsw_driver->sb_tc_pool_bind_get ||
991 !mlxsw_core_port_check(mlxsw_core_port))
993 return mlxsw_driver->sb_tc_pool_bind_get(mlxsw_core_port, sb_index,
995 p_pool_index, p_threshold);
999 mlxsw_devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port,
1000 unsigned int sb_index, u16 tc_index,
1001 enum devlink_sb_pool_type pool_type,
1002 u16 pool_index, u32 threshold,
1003 struct netlink_ext_ack *extack)
1005 struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink);
1006 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
1007 struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);
1009 if (!mlxsw_driver->sb_tc_pool_bind_set ||
1010 !mlxsw_core_port_check(mlxsw_core_port))
1012 return mlxsw_driver->sb_tc_pool_bind_set(mlxsw_core_port, sb_index,
1013 tc_index, pool_type,
1014 pool_index, threshold, extack);
1017 static int mlxsw_devlink_sb_occ_snapshot(struct devlink *devlink,
1018 unsigned int sb_index)
1020 struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
1021 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
1023 if (!mlxsw_driver->sb_occ_snapshot)
1025 return mlxsw_driver->sb_occ_snapshot(mlxsw_core, sb_index);
1028 static int mlxsw_devlink_sb_occ_max_clear(struct devlink *devlink,
1029 unsigned int sb_index)
1031 struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
1032 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
1034 if (!mlxsw_driver->sb_occ_max_clear)
1036 return mlxsw_driver->sb_occ_max_clear(mlxsw_core, sb_index);
1040 mlxsw_devlink_sb_occ_port_pool_get(struct devlink_port *devlink_port,
1041 unsigned int sb_index, u16 pool_index,
1042 u32 *p_cur, u32 *p_max)
1044 struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink);
1045 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
1046 struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);
1048 if (!mlxsw_driver->sb_occ_port_pool_get ||
1049 !mlxsw_core_port_check(mlxsw_core_port))
1051 return mlxsw_driver->sb_occ_port_pool_get(mlxsw_core_port, sb_index,
1052 pool_index, p_cur, p_max);
1056 mlxsw_devlink_sb_occ_tc_port_bind_get(struct devlink_port *devlink_port,
1057 unsigned int sb_index, u16 tc_index,
1058 enum devlink_sb_pool_type pool_type,
1059 u32 *p_cur, u32 *p_max)
1061 struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink);
1062 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
1063 struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);
1065 if (!mlxsw_driver->sb_occ_tc_port_bind_get ||
1066 !mlxsw_core_port_check(mlxsw_core_port))
1068 return mlxsw_driver->sb_occ_tc_port_bind_get(mlxsw_core_port,
1070 pool_type, p_cur, p_max);
1074 mlxsw_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req,
1075 struct netlink_ext_ack *extack)
1077 struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
1078 char fw_info_psid[MLXSW_REG_MGIR_FW_INFO_PSID_SIZE];
1079 u32 hw_rev, fw_major, fw_minor, fw_sub_minor;
1080 char mgir_pl[MLXSW_REG_MGIR_LEN];
1084 err = devlink_info_driver_name_put(req,
1085 mlxsw_core->bus_info->device_kind);
1089 mlxsw_reg_mgir_pack(mgir_pl);
1090 err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mgir), mgir_pl);
1093 mlxsw_reg_mgir_unpack(mgir_pl, &hw_rev, fw_info_psid, &fw_major,
1094 &fw_minor, &fw_sub_minor);
1096 sprintf(buf, "%X", hw_rev);
1097 err = devlink_info_version_fixed_put(req, "hw.revision", buf);
1101 err = devlink_info_version_fixed_put(req, "fw.psid", fw_info_psid);
1105 sprintf(buf, "%d.%d.%d", fw_major, fw_minor, fw_sub_minor);
1106 err = devlink_info_version_running_put(req, "fw.version", buf);
1114 mlxsw_devlink_core_bus_device_reload_down(struct devlink *devlink,
1116 struct netlink_ext_ack *extack)
1118 struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
1120 if (!(mlxsw_core->bus->features & MLXSW_BUS_F_RESET))
1123 mlxsw_core_bus_device_unregister(mlxsw_core, true);
1128 mlxsw_devlink_core_bus_device_reload_up(struct devlink *devlink,
1129 struct netlink_ext_ack *extack)
1131 struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
1133 return mlxsw_core_bus_device_register(mlxsw_core->bus_info,
1135 mlxsw_core->bus_priv, true,
1139 static int mlxsw_devlink_flash_update(struct devlink *devlink,
1140 const char *file_name,
1141 const char *component,
1142 struct netlink_ext_ack *extack)
1144 struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
1145 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
1147 if (!mlxsw_driver->flash_update)
1149 return mlxsw_driver->flash_update(mlxsw_core, file_name,
1153 static int mlxsw_devlink_trap_init(struct devlink *devlink,
1154 const struct devlink_trap *trap,
1157 struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
1158 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
1160 if (!mlxsw_driver->trap_init)
1162 return mlxsw_driver->trap_init(mlxsw_core, trap, trap_ctx);
1165 static void mlxsw_devlink_trap_fini(struct devlink *devlink,
1166 const struct devlink_trap *trap,
1169 struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
1170 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
1172 if (!mlxsw_driver->trap_fini)
1174 mlxsw_driver->trap_fini(mlxsw_core, trap, trap_ctx);
1177 static int mlxsw_devlink_trap_action_set(struct devlink *devlink,
1178 const struct devlink_trap *trap,
1179 enum devlink_trap_action action)
1181 struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
1182 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
1184 if (!mlxsw_driver->trap_action_set)
1186 return mlxsw_driver->trap_action_set(mlxsw_core, trap, action);
1190 mlxsw_devlink_trap_group_init(struct devlink *devlink,
1191 const struct devlink_trap_group *group)
1193 struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
1194 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
1196 if (!mlxsw_driver->trap_group_init)
1198 return mlxsw_driver->trap_group_init(mlxsw_core, group);
1202 mlxsw_devlink_trap_group_set(struct devlink *devlink,
1203 const struct devlink_trap_group *group,
1204 const struct devlink_trap_policer *policer)
1206 struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
1207 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
1209 if (!mlxsw_driver->trap_group_set)
1211 return mlxsw_driver->trap_group_set(mlxsw_core, group, policer);
1215 mlxsw_devlink_trap_policer_init(struct devlink *devlink,
1216 const struct devlink_trap_policer *policer)
1218 struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
1219 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
1221 if (!mlxsw_driver->trap_policer_init)
1223 return mlxsw_driver->trap_policer_init(mlxsw_core, policer);
1227 mlxsw_devlink_trap_policer_fini(struct devlink *devlink,
1228 const struct devlink_trap_policer *policer)
1230 struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
1231 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
1233 if (!mlxsw_driver->trap_policer_fini)
1235 mlxsw_driver->trap_policer_fini(mlxsw_core, policer);
1239 mlxsw_devlink_trap_policer_set(struct devlink *devlink,
1240 const struct devlink_trap_policer *policer,
1241 u64 rate, u64 burst,
1242 struct netlink_ext_ack *extack)
1244 struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
1245 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
1247 if (!mlxsw_driver->trap_policer_set)
1249 return mlxsw_driver->trap_policer_set(mlxsw_core, policer, rate, burst,
1254 mlxsw_devlink_trap_policer_counter_get(struct devlink *devlink,
1255 const struct devlink_trap_policer *policer,
1258 struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
1259 struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
1261 if (!mlxsw_driver->trap_policer_counter_get)
1263 return mlxsw_driver->trap_policer_counter_get(mlxsw_core, policer,
1267 static const struct devlink_ops mlxsw_devlink_ops = {
1268 .reload_down = mlxsw_devlink_core_bus_device_reload_down,
1269 .reload_up = mlxsw_devlink_core_bus_device_reload_up,
1270 .port_type_set = mlxsw_devlink_port_type_set,
1271 .port_split = mlxsw_devlink_port_split,
1272 .port_unsplit = mlxsw_devlink_port_unsplit,
1273 .sb_pool_get = mlxsw_devlink_sb_pool_get,
1274 .sb_pool_set = mlxsw_devlink_sb_pool_set,
1275 .sb_port_pool_get = mlxsw_devlink_sb_port_pool_get,
1276 .sb_port_pool_set = mlxsw_devlink_sb_port_pool_set,
1277 .sb_tc_pool_bind_get = mlxsw_devlink_sb_tc_pool_bind_get,
1278 .sb_tc_pool_bind_set = mlxsw_devlink_sb_tc_pool_bind_set,
1279 .sb_occ_snapshot = mlxsw_devlink_sb_occ_snapshot,
1280 .sb_occ_max_clear = mlxsw_devlink_sb_occ_max_clear,
1281 .sb_occ_port_pool_get = mlxsw_devlink_sb_occ_port_pool_get,
1282 .sb_occ_tc_port_bind_get = mlxsw_devlink_sb_occ_tc_port_bind_get,
1283 .info_get = mlxsw_devlink_info_get,
1284 .flash_update = mlxsw_devlink_flash_update,
1285 .trap_init = mlxsw_devlink_trap_init,
1286 .trap_fini = mlxsw_devlink_trap_fini,
1287 .trap_action_set = mlxsw_devlink_trap_action_set,
1288 .trap_group_init = mlxsw_devlink_trap_group_init,
1289 .trap_group_set = mlxsw_devlink_trap_group_set,
1290 .trap_policer_init = mlxsw_devlink_trap_policer_init,
1291 .trap_policer_fini = mlxsw_devlink_trap_policer_fini,
1292 .trap_policer_set = mlxsw_devlink_trap_policer_set,
1293 .trap_policer_counter_get = mlxsw_devlink_trap_policer_counter_get,
1297 __mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
1298 const struct mlxsw_bus *mlxsw_bus,
1299 void *bus_priv, bool reload,
1300 struct devlink *devlink,
1301 struct netlink_ext_ack *extack)
1303 const char *device_kind = mlxsw_bus_info->device_kind;
1304 struct mlxsw_core *mlxsw_core;
1305 struct mlxsw_driver *mlxsw_driver;
1306 struct mlxsw_res *res;
1310 mlxsw_driver = mlxsw_core_driver_get(device_kind);
1315 alloc_size = sizeof(*mlxsw_core) + mlxsw_driver->priv_size;
1316 devlink = devlink_alloc(&mlxsw_devlink_ops, alloc_size);
1319 goto err_devlink_alloc;
1323 mlxsw_core = devlink_priv(devlink);
1324 INIT_LIST_HEAD(&mlxsw_core->rx_listener_list);
1325 INIT_LIST_HEAD(&mlxsw_core->event_listener_list);
1326 mlxsw_core->driver = mlxsw_driver;
1327 mlxsw_core->bus = mlxsw_bus;
1328 mlxsw_core->bus_priv = bus_priv;
1329 mlxsw_core->bus_info = mlxsw_bus_info;
1331 res = mlxsw_driver->res_query_enabled ? &mlxsw_core->res : NULL;
1332 err = mlxsw_bus->init(bus_priv, mlxsw_core, mlxsw_driver->profile, res);
1336 if (mlxsw_driver->resources_register && !reload) {
1337 err = mlxsw_driver->resources_register(mlxsw_core);
1339 goto err_register_resources;
1342 err = mlxsw_ports_init(mlxsw_core);
1344 goto err_ports_init;
1346 if (MLXSW_CORE_RES_VALID(mlxsw_core, MAX_LAG) &&
1347 MLXSW_CORE_RES_VALID(mlxsw_core, MAX_LAG_MEMBERS)) {
1348 alloc_size = sizeof(u8) *
1349 MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG) *
1350 MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG_MEMBERS);
1351 mlxsw_core->lag.mapping = kzalloc(alloc_size, GFP_KERNEL);
1352 if (!mlxsw_core->lag.mapping) {
1354 goto err_alloc_lag_mapping;
1358 err = mlxsw_emad_init(mlxsw_core);
1363 err = devlink_register(devlink, mlxsw_bus_info->dev);
1365 goto err_devlink_register;
1368 if (mlxsw_driver->params_register && !reload) {
1369 err = mlxsw_driver->params_register(mlxsw_core);
1371 goto err_register_params;
1374 if (mlxsw_driver->init) {
1375 err = mlxsw_driver->init(mlxsw_core, mlxsw_bus_info, extack);
1377 goto err_driver_init;
1380 err = mlxsw_hwmon_init(mlxsw_core, mlxsw_bus_info, &mlxsw_core->hwmon);
1382 goto err_hwmon_init;
1384 err = mlxsw_thermal_init(mlxsw_core, mlxsw_bus_info,
1385 &mlxsw_core->thermal);
1387 goto err_thermal_init;
1389 if (mlxsw_driver->params_register)
1390 devlink_params_publish(devlink);
1393 devlink_reload_enable(devlink);
1398 mlxsw_hwmon_fini(mlxsw_core->hwmon);
1400 if (mlxsw_core->driver->fini)
1401 mlxsw_core->driver->fini(mlxsw_core);
1403 if (mlxsw_driver->params_unregister && !reload)
1404 mlxsw_driver->params_unregister(mlxsw_core);
1405 err_register_params:
1407 devlink_unregister(devlink);
1408 err_devlink_register:
1409 mlxsw_emad_fini(mlxsw_core);
1411 kfree(mlxsw_core->lag.mapping);
1412 err_alloc_lag_mapping:
1413 mlxsw_ports_fini(mlxsw_core);
1416 devlink_resources_unregister(devlink, NULL);
1417 err_register_resources:
1418 mlxsw_bus->fini(bus_priv);
1421 devlink_free(devlink);
1426 int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
1427 const struct mlxsw_bus *mlxsw_bus,
1428 void *bus_priv, bool reload,
1429 struct devlink *devlink,
1430 struct netlink_ext_ack *extack)
1432 bool called_again = false;
1436 err = __mlxsw_core_bus_device_register(mlxsw_bus_info, mlxsw_bus,
1439 /* -EAGAIN is returned in case the FW was updated. FW needs
1440 * a reset, so lets try to call __mlxsw_core_bus_device_register()
1443 if (err == -EAGAIN && !called_again) {
1444 called_again = true;
1450 EXPORT_SYMBOL(mlxsw_core_bus_device_register);
1452 void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core,
1455 struct devlink *devlink = priv_to_devlink(mlxsw_core);
1458 devlink_reload_disable(devlink);
1459 if (devlink_is_reload_failed(devlink)) {
1461 /* Only the parts that were not de-initialized in the
1462 * failed reload attempt need to be de-initialized.
1464 goto reload_fail_deinit;
1469 if (mlxsw_core->driver->params_unregister)
1470 devlink_params_unpublish(devlink);
1471 mlxsw_thermal_fini(mlxsw_core->thermal);
1472 mlxsw_hwmon_fini(mlxsw_core->hwmon);
1473 if (mlxsw_core->driver->fini)
1474 mlxsw_core->driver->fini(mlxsw_core);
1475 if (mlxsw_core->driver->params_unregister && !reload)
1476 mlxsw_core->driver->params_unregister(mlxsw_core);
1478 devlink_unregister(devlink);
1479 mlxsw_emad_fini(mlxsw_core);
1480 kfree(mlxsw_core->lag.mapping);
1481 mlxsw_ports_fini(mlxsw_core);
1483 devlink_resources_unregister(devlink, NULL);
1484 mlxsw_core->bus->fini(mlxsw_core->bus_priv);
1489 if (mlxsw_core->driver->params_unregister)
1490 mlxsw_core->driver->params_unregister(mlxsw_core);
1491 devlink_unregister(devlink);
1492 devlink_resources_unregister(devlink, NULL);
1493 devlink_free(devlink);
1495 EXPORT_SYMBOL(mlxsw_core_bus_device_unregister);
1497 bool mlxsw_core_skb_transmit_busy(struct mlxsw_core *mlxsw_core,
1498 const struct mlxsw_tx_info *tx_info)
1500 return mlxsw_core->bus->skb_transmit_busy(mlxsw_core->bus_priv,
1503 EXPORT_SYMBOL(mlxsw_core_skb_transmit_busy);
1505 int mlxsw_core_skb_transmit(struct mlxsw_core *mlxsw_core, struct sk_buff *skb,
1506 const struct mlxsw_tx_info *tx_info)
1508 return mlxsw_core->bus->skb_transmit(mlxsw_core->bus_priv, skb,
1511 EXPORT_SYMBOL(mlxsw_core_skb_transmit);
1513 void mlxsw_core_ptp_transmitted(struct mlxsw_core *mlxsw_core,
1514 struct sk_buff *skb, u8 local_port)
1516 if (mlxsw_core->driver->ptp_transmitted)
1517 mlxsw_core->driver->ptp_transmitted(mlxsw_core, skb,
1520 EXPORT_SYMBOL(mlxsw_core_ptp_transmitted);
1522 static bool __is_rx_listener_equal(const struct mlxsw_rx_listener *rxl_a,
1523 const struct mlxsw_rx_listener *rxl_b)
1525 return (rxl_a->func == rxl_b->func &&
1526 rxl_a->local_port == rxl_b->local_port &&
1527 rxl_a->trap_id == rxl_b->trap_id);
1530 static struct mlxsw_rx_listener_item *
1531 __find_rx_listener_item(struct mlxsw_core *mlxsw_core,
1532 const struct mlxsw_rx_listener *rxl)
1534 struct mlxsw_rx_listener_item *rxl_item;
1536 list_for_each_entry(rxl_item, &mlxsw_core->rx_listener_list, list) {
1537 if (__is_rx_listener_equal(&rxl_item->rxl, rxl))
1543 int mlxsw_core_rx_listener_register(struct mlxsw_core *mlxsw_core,
1544 const struct mlxsw_rx_listener *rxl,
1545 void *priv, bool enabled)
1547 struct mlxsw_rx_listener_item *rxl_item;
1549 rxl_item = __find_rx_listener_item(mlxsw_core, rxl);
1552 rxl_item = kmalloc(sizeof(*rxl_item), GFP_KERNEL);
1555 rxl_item->rxl = *rxl;
1556 rxl_item->priv = priv;
1557 rxl_item->enabled = enabled;
1559 list_add_rcu(&rxl_item->list, &mlxsw_core->rx_listener_list);
1562 EXPORT_SYMBOL(mlxsw_core_rx_listener_register);
1564 void mlxsw_core_rx_listener_unregister(struct mlxsw_core *mlxsw_core,
1565 const struct mlxsw_rx_listener *rxl)
1567 struct mlxsw_rx_listener_item *rxl_item;
1569 rxl_item = __find_rx_listener_item(mlxsw_core, rxl);
1572 list_del_rcu(&rxl_item->list);
1576 EXPORT_SYMBOL(mlxsw_core_rx_listener_unregister);
1579 mlxsw_core_rx_listener_state_set(struct mlxsw_core *mlxsw_core,
1580 const struct mlxsw_rx_listener *rxl,
1583 struct mlxsw_rx_listener_item *rxl_item;
1585 rxl_item = __find_rx_listener_item(mlxsw_core, rxl);
1586 if (WARN_ON(!rxl_item))
1588 rxl_item->enabled = enabled;
1591 static void mlxsw_core_event_listener_func(struct sk_buff *skb, u8 local_port,
1594 struct mlxsw_event_listener_item *event_listener_item = priv;
1595 struct mlxsw_reg_info reg;
1600 mlxsw_emad_tlv_parse(skb);
1601 op_tlv = mlxsw_emad_op_tlv(skb);
1602 reg_tlv = mlxsw_emad_reg_tlv(skb);
1604 reg.id = mlxsw_emad_op_tlv_register_id_get(op_tlv);
1605 reg.len = (mlxsw_emad_reg_tlv_len_get(reg_tlv) - 1) * sizeof(u32);
1606 payload = mlxsw_emad_reg_payload(reg_tlv);
1607 event_listener_item->el.func(®, payload, event_listener_item->priv);
1611 static bool __is_event_listener_equal(const struct mlxsw_event_listener *el_a,
1612 const struct mlxsw_event_listener *el_b)
1614 return (el_a->func == el_b->func &&
1615 el_a->trap_id == el_b->trap_id);
1618 static struct mlxsw_event_listener_item *
1619 __find_event_listener_item(struct mlxsw_core *mlxsw_core,
1620 const struct mlxsw_event_listener *el)
1622 struct mlxsw_event_listener_item *el_item;
1624 list_for_each_entry(el_item, &mlxsw_core->event_listener_list, list) {
1625 if (__is_event_listener_equal(&el_item->el, el))
1631 int mlxsw_core_event_listener_register(struct mlxsw_core *mlxsw_core,
1632 const struct mlxsw_event_listener *el,
1636 struct mlxsw_event_listener_item *el_item;
1637 const struct mlxsw_rx_listener rxl = {
1638 .func = mlxsw_core_event_listener_func,
1639 .local_port = MLXSW_PORT_DONT_CARE,
1640 .trap_id = el->trap_id,
1643 el_item = __find_event_listener_item(mlxsw_core, el);
1646 el_item = kmalloc(sizeof(*el_item), GFP_KERNEL);
1650 el_item->priv = priv;
1652 err = mlxsw_core_rx_listener_register(mlxsw_core, &rxl, el_item, true);
1654 goto err_rx_listener_register;
1656 /* No reason to save item if we did not manage to register an RX
1659 list_add_rcu(&el_item->list, &mlxsw_core->event_listener_list);
1663 err_rx_listener_register:
1667 EXPORT_SYMBOL(mlxsw_core_event_listener_register);
1669 void mlxsw_core_event_listener_unregister(struct mlxsw_core *mlxsw_core,
1670 const struct mlxsw_event_listener *el)
1672 struct mlxsw_event_listener_item *el_item;
1673 const struct mlxsw_rx_listener rxl = {
1674 .func = mlxsw_core_event_listener_func,
1675 .local_port = MLXSW_PORT_DONT_CARE,
1676 .trap_id = el->trap_id,
1679 el_item = __find_event_listener_item(mlxsw_core, el);
1682 mlxsw_core_rx_listener_unregister(mlxsw_core, &rxl);
1683 list_del(&el_item->list);
1686 EXPORT_SYMBOL(mlxsw_core_event_listener_unregister);
1688 static int mlxsw_core_listener_register(struct mlxsw_core *mlxsw_core,
1689 const struct mlxsw_listener *listener,
1690 void *priv, bool enabled)
1692 if (listener->is_event) {
1694 return mlxsw_core_event_listener_register(mlxsw_core,
1695 &listener->event_listener,
1698 return mlxsw_core_rx_listener_register(mlxsw_core,
1699 &listener->rx_listener,
1704 static void mlxsw_core_listener_unregister(struct mlxsw_core *mlxsw_core,
1705 const struct mlxsw_listener *listener,
1708 if (listener->is_event)
1709 mlxsw_core_event_listener_unregister(mlxsw_core,
1710 &listener->event_listener);
1712 mlxsw_core_rx_listener_unregister(mlxsw_core,
1713 &listener->rx_listener);
1716 int mlxsw_core_trap_register(struct mlxsw_core *mlxsw_core,
1717 const struct mlxsw_listener *listener, void *priv)
1719 enum mlxsw_reg_htgt_trap_group trap_group;
1720 enum mlxsw_reg_hpkt_action action;
1721 char hpkt_pl[MLXSW_REG_HPKT_LEN];
1724 err = mlxsw_core_listener_register(mlxsw_core, listener, priv,
1725 listener->enabled_on_register);
1729 action = listener->enabled_on_register ? listener->en_action :
1730 listener->dis_action;
1731 trap_group = listener->enabled_on_register ? listener->en_trap_group :
1732 listener->dis_trap_group;
1733 mlxsw_reg_hpkt_pack(hpkt_pl, action, listener->trap_id,
1734 trap_group, listener->is_ctrl);
1735 err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl);
1742 mlxsw_core_listener_unregister(mlxsw_core, listener, priv);
1745 EXPORT_SYMBOL(mlxsw_core_trap_register);
1747 void mlxsw_core_trap_unregister(struct mlxsw_core *mlxsw_core,
1748 const struct mlxsw_listener *listener,
1751 char hpkt_pl[MLXSW_REG_HPKT_LEN];
1753 if (!listener->is_event) {
1754 mlxsw_reg_hpkt_pack(hpkt_pl, listener->dis_action,
1755 listener->trap_id, listener->dis_trap_group,
1757 mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl);
1760 mlxsw_core_listener_unregister(mlxsw_core, listener, priv);
1762 EXPORT_SYMBOL(mlxsw_core_trap_unregister);
1764 int mlxsw_core_trap_state_set(struct mlxsw_core *mlxsw_core,
1765 const struct mlxsw_listener *listener,
1768 enum mlxsw_reg_htgt_trap_group trap_group;
1769 enum mlxsw_reg_hpkt_action action;
1770 char hpkt_pl[MLXSW_REG_HPKT_LEN];
1773 /* Not supported for event listener */
1774 if (WARN_ON(listener->is_event))
1777 action = enabled ? listener->en_action : listener->dis_action;
1778 trap_group = enabled ? listener->en_trap_group :
1779 listener->dis_trap_group;
1780 mlxsw_reg_hpkt_pack(hpkt_pl, action, listener->trap_id,
1781 trap_group, listener->is_ctrl);
1782 err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl);
1786 mlxsw_core_rx_listener_state_set(mlxsw_core, &listener->rx_listener,
1790 EXPORT_SYMBOL(mlxsw_core_trap_state_set);
1792 static u64 mlxsw_core_tid_get(struct mlxsw_core *mlxsw_core)
1794 return atomic64_inc_return(&mlxsw_core->emad.tid);
1797 static int mlxsw_core_reg_access_emad(struct mlxsw_core *mlxsw_core,
1798 const struct mlxsw_reg_info *reg,
1800 enum mlxsw_core_reg_access_type type,
1801 struct list_head *bulk_list,
1802 mlxsw_reg_trans_cb_t *cb,
1803 unsigned long cb_priv)
1805 u64 tid = mlxsw_core_tid_get(mlxsw_core);
1806 struct mlxsw_reg_trans *trans;
1809 trans = kzalloc(sizeof(*trans), GFP_KERNEL);
1813 err = mlxsw_emad_reg_access(mlxsw_core, reg, payload, type, trans,
1814 bulk_list, cb, cb_priv, tid);
1822 int mlxsw_reg_trans_query(struct mlxsw_core *mlxsw_core,
1823 const struct mlxsw_reg_info *reg, char *payload,
1824 struct list_head *bulk_list,
1825 mlxsw_reg_trans_cb_t *cb, unsigned long cb_priv)
1827 return mlxsw_core_reg_access_emad(mlxsw_core, reg, payload,
1828 MLXSW_CORE_REG_ACCESS_TYPE_QUERY,
1829 bulk_list, cb, cb_priv);
1831 EXPORT_SYMBOL(mlxsw_reg_trans_query);
1833 int mlxsw_reg_trans_write(struct mlxsw_core *mlxsw_core,
1834 const struct mlxsw_reg_info *reg, char *payload,
1835 struct list_head *bulk_list,
1836 mlxsw_reg_trans_cb_t *cb, unsigned long cb_priv)
1838 return mlxsw_core_reg_access_emad(mlxsw_core, reg, payload,
1839 MLXSW_CORE_REG_ACCESS_TYPE_WRITE,
1840 bulk_list, cb, cb_priv);
1842 EXPORT_SYMBOL(mlxsw_reg_trans_write);
1844 #define MLXSW_REG_TRANS_ERR_STRING_SIZE 256
1846 static int mlxsw_reg_trans_wait(struct mlxsw_reg_trans *trans)
1848 char err_string[MLXSW_REG_TRANS_ERR_STRING_SIZE];
1849 struct mlxsw_core *mlxsw_core = trans->core;
1852 wait_for_completion(&trans->completion);
1853 cancel_delayed_work_sync(&trans->timeout_dw);
1857 dev_warn(mlxsw_core->bus_info->dev, "EMAD retries (%d/%d) (tid=%llx)\n",
1858 trans->retries, MLXSW_EMAD_MAX_RETRY, trans->tid);
1860 dev_err(mlxsw_core->bus_info->dev, "EMAD reg access failed (tid=%llx,reg_id=%x(%s),type=%s,status=%x(%s))\n",
1861 trans->tid, trans->reg->id,
1862 mlxsw_reg_id_str(trans->reg->id),
1863 mlxsw_core_reg_access_type_str(trans->type),
1865 mlxsw_emad_op_tlv_status_str(trans->emad_status));
1867 snprintf(err_string, MLXSW_REG_TRANS_ERR_STRING_SIZE,
1868 "(tid=%llx,reg_id=%x(%s)) %s (%s)\n", trans->tid,
1869 trans->reg->id, mlxsw_reg_id_str(trans->reg->id),
1870 mlxsw_emad_op_tlv_status_str(trans->emad_status),
1871 trans->emad_err_string ? trans->emad_err_string : "");
1873 trace_devlink_hwerr(priv_to_devlink(mlxsw_core),
1874 trans->emad_status, err_string);
1876 kfree(trans->emad_err_string);
1879 list_del(&trans->bulk_list);
1880 kfree_rcu(trans, rcu);
1884 int mlxsw_reg_trans_bulk_wait(struct list_head *bulk_list)
1886 struct mlxsw_reg_trans *trans;
1887 struct mlxsw_reg_trans *tmp;
1891 list_for_each_entry_safe(trans, tmp, bulk_list, bulk_list) {
1892 err = mlxsw_reg_trans_wait(trans);
1893 if (err && sum_err == 0)
1894 sum_err = err; /* first error to be returned */
1898 EXPORT_SYMBOL(mlxsw_reg_trans_bulk_wait);
1900 static int mlxsw_core_reg_access_cmd(struct mlxsw_core *mlxsw_core,
1901 const struct mlxsw_reg_info *reg,
1903 enum mlxsw_core_reg_access_type type)
1905 enum mlxsw_emad_op_tlv_status status;
1908 char *in_mbox, *out_mbox, *tmp;
1910 dev_dbg(mlxsw_core->bus_info->dev, "Reg cmd access (reg_id=%x(%s),type=%s)\n",
1911 reg->id, mlxsw_reg_id_str(reg->id),
1912 mlxsw_core_reg_access_type_str(type));
1914 in_mbox = mlxsw_cmd_mbox_alloc();
1918 out_mbox = mlxsw_cmd_mbox_alloc();
1924 mlxsw_emad_pack_op_tlv(in_mbox, reg, type,
1925 mlxsw_core_tid_get(mlxsw_core));
1926 tmp = in_mbox + MLXSW_EMAD_OP_TLV_LEN * sizeof(u32);
1927 mlxsw_emad_pack_reg_tlv(tmp, reg, payload);
1929 /* There is a special treatment needed for MRSR (reset) register.
1930 * The command interface will return error after the command
1931 * is executed, so tell the lower layer to expect it
1932 * and cope accordingly.
1934 reset_ok = reg->id == MLXSW_REG_MRSR_ID;
1938 err = mlxsw_cmd_access_reg(mlxsw_core, reset_ok, in_mbox, out_mbox);
1940 err = mlxsw_emad_process_status(out_mbox, &status);
1942 if (err == -EAGAIN && n_retry++ < MLXSW_EMAD_MAX_RETRY)
1944 dev_err(mlxsw_core->bus_info->dev, "Reg cmd access status failed (status=%x(%s))\n",
1945 status, mlxsw_emad_op_tlv_status_str(status));
1950 memcpy(payload, mlxsw_emad_reg_payload_cmd(out_mbox),
1953 mlxsw_cmd_mbox_free(out_mbox);
1955 mlxsw_cmd_mbox_free(in_mbox);
1957 dev_err(mlxsw_core->bus_info->dev, "Reg cmd access failed (reg_id=%x(%s),type=%s)\n",
1958 reg->id, mlxsw_reg_id_str(reg->id),
1959 mlxsw_core_reg_access_type_str(type));
1963 static void mlxsw_core_reg_access_cb(struct mlxsw_core *mlxsw_core,
1964 char *payload, size_t payload_len,
1965 unsigned long cb_priv)
1967 char *orig_payload = (char *) cb_priv;
1969 memcpy(orig_payload, payload, payload_len);
1972 static int mlxsw_core_reg_access(struct mlxsw_core *mlxsw_core,
1973 const struct mlxsw_reg_info *reg,
1975 enum mlxsw_core_reg_access_type type)
1977 LIST_HEAD(bulk_list);
1980 /* During initialization EMAD interface is not available to us,
1981 * so we default to command interface. We switch to EMAD interface
1982 * after setting the appropriate traps.
1984 if (!mlxsw_core->emad.use_emad)
1985 return mlxsw_core_reg_access_cmd(mlxsw_core, reg,
1988 err = mlxsw_core_reg_access_emad(mlxsw_core, reg,
1989 payload, type, &bulk_list,
1990 mlxsw_core_reg_access_cb,
1991 (unsigned long) payload);
1994 return mlxsw_reg_trans_bulk_wait(&bulk_list);
1997 int mlxsw_reg_query(struct mlxsw_core *mlxsw_core,
1998 const struct mlxsw_reg_info *reg, char *payload)
2000 return mlxsw_core_reg_access(mlxsw_core, reg, payload,
2001 MLXSW_CORE_REG_ACCESS_TYPE_QUERY);
2003 EXPORT_SYMBOL(mlxsw_reg_query);
2005 int mlxsw_reg_write(struct mlxsw_core *mlxsw_core,
2006 const struct mlxsw_reg_info *reg, char *payload)
2008 return mlxsw_core_reg_access(mlxsw_core, reg, payload,
2009 MLXSW_CORE_REG_ACCESS_TYPE_WRITE);
2011 EXPORT_SYMBOL(mlxsw_reg_write);
2013 void mlxsw_core_skb_receive(struct mlxsw_core *mlxsw_core, struct sk_buff *skb,
2014 struct mlxsw_rx_info *rx_info)
2016 struct mlxsw_rx_listener_item *rxl_item;
2017 const struct mlxsw_rx_listener *rxl;
2021 if (rx_info->is_lag) {
2022 dev_dbg_ratelimited(mlxsw_core->bus_info->dev, "%s: lag_id = %d, lag_port_index = 0x%x\n",
2023 __func__, rx_info->u.lag_id,
2025 /* Upper layer does not care if the skb came from LAG or not,
2026 * so just get the local_port for the lag port and push it up.
2028 local_port = mlxsw_core_lag_mapping_get(mlxsw_core,
2030 rx_info->lag_port_index);
2032 local_port = rx_info->u.sys_port;
2035 dev_dbg_ratelimited(mlxsw_core->bus_info->dev, "%s: local_port = %d, trap_id = 0x%x\n",
2036 __func__, local_port, rx_info->trap_id);
2038 if ((rx_info->trap_id >= MLXSW_TRAP_ID_MAX) ||
2039 (local_port >= mlxsw_core->max_ports))
2043 list_for_each_entry_rcu(rxl_item, &mlxsw_core->rx_listener_list, list) {
2044 rxl = &rxl_item->rxl;
2045 if ((rxl->local_port == MLXSW_PORT_DONT_CARE ||
2046 rxl->local_port == local_port) &&
2047 rxl->trap_id == rx_info->trap_id) {
2048 if (rxl_item->enabled)
2057 rxl->func(skb, local_port, rxl_item->priv);
2063 EXPORT_SYMBOL(mlxsw_core_skb_receive);
2065 static int mlxsw_core_lag_mapping_index(struct mlxsw_core *mlxsw_core,
2066 u16 lag_id, u8 port_index)
2068 return MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG_MEMBERS) * lag_id +
2072 void mlxsw_core_lag_mapping_set(struct mlxsw_core *mlxsw_core,
2073 u16 lag_id, u8 port_index, u8 local_port)
2075 int index = mlxsw_core_lag_mapping_index(mlxsw_core,
2076 lag_id, port_index);
2078 mlxsw_core->lag.mapping[index] = local_port;
2080 EXPORT_SYMBOL(mlxsw_core_lag_mapping_set);
2082 u8 mlxsw_core_lag_mapping_get(struct mlxsw_core *mlxsw_core,
2083 u16 lag_id, u8 port_index)
2085 int index = mlxsw_core_lag_mapping_index(mlxsw_core,
2086 lag_id, port_index);
2088 return mlxsw_core->lag.mapping[index];
2090 EXPORT_SYMBOL(mlxsw_core_lag_mapping_get);
2092 void mlxsw_core_lag_mapping_clear(struct mlxsw_core *mlxsw_core,
2093 u16 lag_id, u8 local_port)
2097 for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG_MEMBERS); i++) {
2098 int index = mlxsw_core_lag_mapping_index(mlxsw_core,
2101 if (mlxsw_core->lag.mapping[index] == local_port)
2102 mlxsw_core->lag.mapping[index] = 0;
2105 EXPORT_SYMBOL(mlxsw_core_lag_mapping_clear);
2107 bool mlxsw_core_res_valid(struct mlxsw_core *mlxsw_core,
2108 enum mlxsw_res_id res_id)
2110 return mlxsw_res_valid(&mlxsw_core->res, res_id);
2112 EXPORT_SYMBOL(mlxsw_core_res_valid);
2114 u64 mlxsw_core_res_get(struct mlxsw_core *mlxsw_core,
2115 enum mlxsw_res_id res_id)
2117 return mlxsw_res_get(&mlxsw_core->res, res_id);
2119 EXPORT_SYMBOL(mlxsw_core_res_get);
2121 static int __mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u8 local_port,
2122 enum devlink_port_flavour flavour,
2123 u32 port_number, bool split,
2124 u32 split_port_subnumber,
2125 const unsigned char *switch_id,
2126 unsigned char switch_id_len)
2128 struct devlink *devlink = priv_to_devlink(mlxsw_core);
2129 struct mlxsw_core_port *mlxsw_core_port =
2130 &mlxsw_core->ports[local_port];
2131 struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;
2134 mlxsw_core_port->local_port = local_port;
2135 devlink_port_attrs_set(devlink_port, flavour, port_number,
2136 split, split_port_subnumber,
2137 switch_id, switch_id_len);
2138 err = devlink_port_register(devlink, devlink_port, local_port);
2140 memset(mlxsw_core_port, 0, sizeof(*mlxsw_core_port));
2144 static void __mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u8 local_port)
2146 struct mlxsw_core_port *mlxsw_core_port =
2147 &mlxsw_core->ports[local_port];
2148 struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;
2150 devlink_port_unregister(devlink_port);
2151 memset(mlxsw_core_port, 0, sizeof(*mlxsw_core_port));
2154 int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u8 local_port,
2155 u32 port_number, bool split,
2156 u32 split_port_subnumber,
2157 const unsigned char *switch_id,
2158 unsigned char switch_id_len)
2160 return __mlxsw_core_port_init(mlxsw_core, local_port,
2161 DEVLINK_PORT_FLAVOUR_PHYSICAL,
2162 port_number, split, split_port_subnumber,
2163 switch_id, switch_id_len);
2165 EXPORT_SYMBOL(mlxsw_core_port_init);
2167 void mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u8 local_port)
2169 __mlxsw_core_port_fini(mlxsw_core, local_port);
2171 EXPORT_SYMBOL(mlxsw_core_port_fini);
2173 int mlxsw_core_cpu_port_init(struct mlxsw_core *mlxsw_core,
2174 void *port_driver_priv,
2175 const unsigned char *switch_id,
2176 unsigned char switch_id_len)
2178 struct mlxsw_core_port *mlxsw_core_port =
2179 &mlxsw_core->ports[MLXSW_PORT_CPU_PORT];
2182 err = __mlxsw_core_port_init(mlxsw_core, MLXSW_PORT_CPU_PORT,
2183 DEVLINK_PORT_FLAVOUR_CPU,
2185 switch_id, switch_id_len);
2189 mlxsw_core_port->port_driver_priv = port_driver_priv;
2192 EXPORT_SYMBOL(mlxsw_core_cpu_port_init);
2194 void mlxsw_core_cpu_port_fini(struct mlxsw_core *mlxsw_core)
2196 __mlxsw_core_port_fini(mlxsw_core, MLXSW_PORT_CPU_PORT);
2198 EXPORT_SYMBOL(mlxsw_core_cpu_port_fini);
2200 void mlxsw_core_port_eth_set(struct mlxsw_core *mlxsw_core, u8 local_port,
2201 void *port_driver_priv, struct net_device *dev)
2203 struct mlxsw_core_port *mlxsw_core_port =
2204 &mlxsw_core->ports[local_port];
2205 struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;
2207 mlxsw_core_port->port_driver_priv = port_driver_priv;
2208 devlink_port_type_eth_set(devlink_port, dev);
2210 EXPORT_SYMBOL(mlxsw_core_port_eth_set);
2212 void mlxsw_core_port_ib_set(struct mlxsw_core *mlxsw_core, u8 local_port,
2213 void *port_driver_priv)
2215 struct mlxsw_core_port *mlxsw_core_port =
2216 &mlxsw_core->ports[local_port];
2217 struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;
2219 mlxsw_core_port->port_driver_priv = port_driver_priv;
2220 devlink_port_type_ib_set(devlink_port, NULL);
2222 EXPORT_SYMBOL(mlxsw_core_port_ib_set);
2224 void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u8 local_port,
2225 void *port_driver_priv)
2227 struct mlxsw_core_port *mlxsw_core_port =
2228 &mlxsw_core->ports[local_port];
2229 struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;
2231 mlxsw_core_port->port_driver_priv = port_driver_priv;
2232 devlink_port_type_clear(devlink_port);
2234 EXPORT_SYMBOL(mlxsw_core_port_clear);
2236 enum devlink_port_type mlxsw_core_port_type_get(struct mlxsw_core *mlxsw_core,
2239 struct mlxsw_core_port *mlxsw_core_port =
2240 &mlxsw_core->ports[local_port];
2241 struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;
2243 return devlink_port->type;
2245 EXPORT_SYMBOL(mlxsw_core_port_type_get);
2248 struct devlink_port *
2249 mlxsw_core_port_devlink_port_get(struct mlxsw_core *mlxsw_core,
2252 struct mlxsw_core_port *mlxsw_core_port =
2253 &mlxsw_core->ports[local_port];
2254 struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;
2256 return devlink_port;
2258 EXPORT_SYMBOL(mlxsw_core_port_devlink_port_get);
2260 int mlxsw_core_module_max_width(struct mlxsw_core *mlxsw_core, u8 module)
2262 enum mlxsw_reg_pmtm_module_type module_type;
2263 char pmtm_pl[MLXSW_REG_PMTM_LEN];
2266 mlxsw_reg_pmtm_pack(pmtm_pl, module);
2267 err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(pmtm), pmtm_pl);
2270 mlxsw_reg_pmtm_unpack(pmtm_pl, &module_type);
2272 /* Here we need to get the module width according to the module type. */
2274 switch (module_type) {
2275 case MLXSW_REG_PMTM_MODULE_TYPE_C2C8X: /* fall through */
2276 case MLXSW_REG_PMTM_MODULE_TYPE_QSFP_DD: /* fall through */
2277 case MLXSW_REG_PMTM_MODULE_TYPE_OSFP:
2279 case MLXSW_REG_PMTM_MODULE_TYPE_C2C4X: /* fall through */
2280 case MLXSW_REG_PMTM_MODULE_TYPE_BP_4X: /* fall through */
2281 case MLXSW_REG_PMTM_MODULE_TYPE_QSFP:
2283 case MLXSW_REG_PMTM_MODULE_TYPE_C2C2X: /* fall through */
2284 case MLXSW_REG_PMTM_MODULE_TYPE_BP_2X: /* fall through */
2285 case MLXSW_REG_PMTM_MODULE_TYPE_SFP_DD: /* fall through */
2286 case MLXSW_REG_PMTM_MODULE_TYPE_DSFP:
2288 case MLXSW_REG_PMTM_MODULE_TYPE_C2C1X: /* fall through */
2289 case MLXSW_REG_PMTM_MODULE_TYPE_BP_1X: /* fall through */
2290 case MLXSW_REG_PMTM_MODULE_TYPE_SFP:
2296 EXPORT_SYMBOL(mlxsw_core_module_max_width);
2298 static void mlxsw_core_buf_dump_dbg(struct mlxsw_core *mlxsw_core,
2299 const char *buf, size_t size)
2301 __be32 *m = (__be32 *) buf;
2303 int count = size / sizeof(__be32);
2305 for (i = count - 1; i >= 0; i--)
2310 for (i = 0; i < count; i += 4)
2311 dev_dbg(mlxsw_core->bus_info->dev, "%04x - %08x %08x %08x %08x\n",
2312 i * 4, be32_to_cpu(m[i]), be32_to_cpu(m[i + 1]),
2313 be32_to_cpu(m[i + 2]), be32_to_cpu(m[i + 3]));
2316 int mlxsw_cmd_exec(struct mlxsw_core *mlxsw_core, u16 opcode, u8 opcode_mod,
2317 u32 in_mod, bool out_mbox_direct, bool reset_ok,
2318 char *in_mbox, size_t in_mbox_size,
2319 char *out_mbox, size_t out_mbox_size)
2324 BUG_ON(in_mbox_size % sizeof(u32) || out_mbox_size % sizeof(u32));
2325 if (!mlxsw_core->bus->cmd_exec)
2328 dev_dbg(mlxsw_core->bus_info->dev, "Cmd exec (opcode=%x(%s),opcode_mod=%x,in_mod=%x)\n",
2329 opcode, mlxsw_cmd_opcode_str(opcode), opcode_mod, in_mod);
2331 dev_dbg(mlxsw_core->bus_info->dev, "Input mailbox:\n");
2332 mlxsw_core_buf_dump_dbg(mlxsw_core, in_mbox, in_mbox_size);
2335 err = mlxsw_core->bus->cmd_exec(mlxsw_core->bus_priv, opcode,
2336 opcode_mod, in_mod, out_mbox_direct,
2337 in_mbox, in_mbox_size,
2338 out_mbox, out_mbox_size, &status);
2340 if (!err && out_mbox) {
2341 dev_dbg(mlxsw_core->bus_info->dev, "Output mailbox:\n");
2342 mlxsw_core_buf_dump_dbg(mlxsw_core, out_mbox, out_mbox_size);
2345 if (reset_ok && err == -EIO &&
2346 status == MLXSW_CMD_STATUS_RUNNING_RESET) {
2348 } else if (err == -EIO && status != MLXSW_CMD_STATUS_OK) {
2349 dev_err(mlxsw_core->bus_info->dev, "Cmd exec failed (opcode=%x(%s),opcode_mod=%x,in_mod=%x,status=%x(%s))\n",
2350 opcode, mlxsw_cmd_opcode_str(opcode), opcode_mod,
2351 in_mod, status, mlxsw_cmd_status_str(status));
2352 } else if (err == -ETIMEDOUT) {
2353 dev_err(mlxsw_core->bus_info->dev, "Cmd exec timed-out (opcode=%x(%s),opcode_mod=%x,in_mod=%x)\n",
2354 opcode, mlxsw_cmd_opcode_str(opcode), opcode_mod,
2360 EXPORT_SYMBOL(mlxsw_cmd_exec);
2362 int mlxsw_core_schedule_dw(struct delayed_work *dwork, unsigned long delay)
2364 return queue_delayed_work(mlxsw_wq, dwork, delay);
2366 EXPORT_SYMBOL(mlxsw_core_schedule_dw);
2368 bool mlxsw_core_schedule_work(struct work_struct *work)
2370 return queue_work(mlxsw_owq, work);
2372 EXPORT_SYMBOL(mlxsw_core_schedule_work);
2374 void mlxsw_core_flush_owq(void)
2376 flush_workqueue(mlxsw_owq);
2378 EXPORT_SYMBOL(mlxsw_core_flush_owq);
2380 int mlxsw_core_kvd_sizes_get(struct mlxsw_core *mlxsw_core,
2381 const struct mlxsw_config_profile *profile,
2382 u64 *p_single_size, u64 *p_double_size,
2385 struct mlxsw_driver *driver = mlxsw_core->driver;
2387 if (!driver->kvd_sizes_get)
2390 return driver->kvd_sizes_get(mlxsw_core, profile,
2391 p_single_size, p_double_size,
2394 EXPORT_SYMBOL(mlxsw_core_kvd_sizes_get);
2396 void mlxsw_core_fw_flash_start(struct mlxsw_core *mlxsw_core)
2398 mlxsw_core->fw_flash_in_progress = true;
2400 EXPORT_SYMBOL(mlxsw_core_fw_flash_start);
2402 void mlxsw_core_fw_flash_end(struct mlxsw_core *mlxsw_core)
2404 mlxsw_core->fw_flash_in_progress = false;
2406 EXPORT_SYMBOL(mlxsw_core_fw_flash_end);
2408 int mlxsw_core_resources_query(struct mlxsw_core *mlxsw_core, char *mbox,
2409 struct mlxsw_res *res)
2419 mlxsw_cmd_mbox_zero(mbox);
2421 for (index = 0; index < MLXSW_CMD_QUERY_RESOURCES_MAX_QUERIES;
2423 err = mlxsw_cmd_query_resources(mlxsw_core, mbox, index);
2427 for (i = 0; i < MLXSW_CMD_QUERY_RESOURCES_PER_QUERY; i++) {
2428 id = mlxsw_cmd_mbox_query_resource_id_get(mbox, i);
2429 data = mlxsw_cmd_mbox_query_resource_data_get(mbox, i);
2431 if (id == MLXSW_CMD_QUERY_RESOURCES_TABLE_END_ID)
2434 mlxsw_res_parse(res, id, data);
2438 /* If after MLXSW_RESOURCES_QUERY_MAX_QUERIES we still didn't get
2439 * MLXSW_RESOURCES_TABLE_END_ID, something went bad in the FW.
2443 EXPORT_SYMBOL(mlxsw_core_resources_query);
2445 u32 mlxsw_core_read_frc_h(struct mlxsw_core *mlxsw_core)
2447 return mlxsw_core->bus->read_frc_h(mlxsw_core->bus_priv);
2449 EXPORT_SYMBOL(mlxsw_core_read_frc_h);
2451 u32 mlxsw_core_read_frc_l(struct mlxsw_core *mlxsw_core)
2453 return mlxsw_core->bus->read_frc_l(mlxsw_core->bus_priv);
2455 EXPORT_SYMBOL(mlxsw_core_read_frc_l);
2457 void mlxsw_core_emad_string_tlv_enable(struct mlxsw_core *mlxsw_core)
2459 mlxsw_core->emad.enable_string_tlv = true;
2461 EXPORT_SYMBOL(mlxsw_core_emad_string_tlv_enable);
2463 static int __init mlxsw_core_module_init(void)
2467 mlxsw_wq = alloc_workqueue(mlxsw_core_driver_name, 0, 0);
2470 mlxsw_owq = alloc_ordered_workqueue("%s_ordered", 0,
2471 mlxsw_core_driver_name);
2474 goto err_alloc_ordered_workqueue;
2478 err_alloc_ordered_workqueue:
2479 destroy_workqueue(mlxsw_wq);
2483 static void __exit mlxsw_core_module_exit(void)
2485 destroy_workqueue(mlxsw_owq);
2486 destroy_workqueue(mlxsw_wq);
2489 module_init(mlxsw_core_module_init);
2490 module_exit(mlxsw_core_module_exit);
2492 MODULE_LICENSE("Dual BSD/GPL");
2493 MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>");
2494 MODULE_DESCRIPTION("Mellanox switch device core driver");