1 /* Broadcom NetXtreme-C/E network driver.
3 * Copyright (c) 2017 Broadcom Limited
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation.
10 #include <linux/pci.h>
11 #include <linux/netdevice.h>
15 #include "bnxt_devlink.h"
17 static const struct devlink_ops bnxt_dl_ops
= {
18 #ifdef CONFIG_BNXT_SRIOV
19 .eswitch_mode_set
= bnxt_dl_eswitch_mode_set
,
20 .eswitch_mode_get
= bnxt_dl_eswitch_mode_get
,
21 #endif /* CONFIG_BNXT_SRIOV */
24 static const struct bnxt_dl_nvm_param nvm_params
[] = {
25 {DEVLINK_PARAM_GENERIC_ID_ENABLE_SRIOV
, NVM_OFF_ENABLE_SRIOV
,
26 BNXT_NVM_SHARED_CFG
, 1},
29 static int bnxt_hwrm_nvm_req(struct bnxt
*bp
, u32 param_id
, void *msg
,
30 int msg_len
, union devlink_param_value
*val
)
32 struct hwrm_nvm_get_variable_input
*req
= msg
;
33 void *data_addr
= NULL
, *buf
= NULL
;
34 struct bnxt_dl_nvm_param nvm_param
;
35 int bytesize
, idx
= 0, rc
, i
;
36 dma_addr_t data_dma_addr
;
38 /* Get/Set NVM CFG parameter is supported only on PFs */
42 for (i
= 0; i
< ARRAY_SIZE(nvm_params
); i
++) {
43 if (nvm_params
[i
].id
== param_id
) {
44 nvm_param
= nvm_params
[i
];
49 if (i
== ARRAY_SIZE(nvm_params
))
52 if (nvm_param
.dir_type
== BNXT_NVM_PORT_CFG
)
54 else if (nvm_param
.dir_type
== BNXT_NVM_FUNC_CFG
)
55 idx
= bp
->pf
.fw_fid
- BNXT_FIRST_PF_FID
;
57 bytesize
= roundup(nvm_param
.num_bits
, BITS_PER_BYTE
) / BITS_PER_BYTE
;
58 if (nvm_param
.num_bits
== 1)
61 data_addr
= dma_zalloc_coherent(&bp
->pdev
->dev
, bytesize
,
62 &data_dma_addr
, GFP_KERNEL
);
66 req
->dest_data_addr
= cpu_to_le64(data_dma_addr
);
67 req
->data_len
= cpu_to_le16(nvm_param
.num_bits
);
68 req
->option_num
= cpu_to_le16(nvm_param
.offset
);
69 req
->index_0
= cpu_to_le16(idx
);
71 req
->dimensions
= cpu_to_le16(1);
73 if (req
->req_type
== cpu_to_le16(HWRM_NVM_SET_VARIABLE
))
74 memcpy(data_addr
, buf
, bytesize
);
76 rc
= hwrm_send_message(bp
, msg
, msg_len
, HWRM_CMD_TIMEOUT
);
77 if (!rc
&& req
->req_type
== cpu_to_le16(HWRM_NVM_GET_VARIABLE
))
78 memcpy(buf
, data_addr
, bytesize
);
80 dma_free_coherent(&bp
->pdev
->dev
, bytesize
, data_addr
, data_dma_addr
);
81 if (rc
== HWRM_ERR_CODE_RESOURCE_ACCESS_DENIED
) {
82 netdev_err(bp
->dev
, "PF does not have admin privileges to modify NVM config\n");
90 static int bnxt_dl_nvm_param_get(struct devlink
*dl
, u32 id
,
91 struct devlink_param_gset_ctx
*ctx
)
93 struct hwrm_nvm_get_variable_input req
= {0};
94 struct bnxt
*bp
= bnxt_get_bp_from_dl(dl
);
96 bnxt_hwrm_cmd_hdr_init(bp
, &req
, HWRM_NVM_GET_VARIABLE
, -1, -1);
97 return bnxt_hwrm_nvm_req(bp
, id
, &req
, sizeof(req
), &ctx
->val
);
100 static int bnxt_dl_nvm_param_set(struct devlink
*dl
, u32 id
,
101 struct devlink_param_gset_ctx
*ctx
)
103 struct hwrm_nvm_set_variable_input req
= {0};
104 struct bnxt
*bp
= bnxt_get_bp_from_dl(dl
);
106 bnxt_hwrm_cmd_hdr_init(bp
, &req
, HWRM_NVM_SET_VARIABLE
, -1, -1);
107 return bnxt_hwrm_nvm_req(bp
, id
, &req
, sizeof(req
), &ctx
->val
);
110 static const struct devlink_param bnxt_dl_params
[] = {
111 DEVLINK_PARAM_GENERIC(ENABLE_SRIOV
,
112 BIT(DEVLINK_PARAM_CMODE_PERMANENT
),
113 bnxt_dl_nvm_param_get
, bnxt_dl_nvm_param_set
,
117 int bnxt_dl_register(struct bnxt
*bp
)
122 if (bp
->hwrm_spec_code
< 0x10600) {
123 netdev_warn(bp
->dev
, "Firmware does not support NVM params");
127 dl
= devlink_alloc(&bnxt_dl_ops
, sizeof(struct bnxt_dl
));
129 netdev_warn(bp
->dev
, "devlink_alloc failed");
133 bnxt_link_bp_to_dl(bp
, dl
);
135 /* Add switchdev eswitch mode setting, if SRIOV supported */
136 if (pci_find_ext_capability(bp
->pdev
, PCI_EXT_CAP_ID_SRIOV
) &&
137 bp
->hwrm_spec_code
> 0x10803)
138 bp
->eswitch_mode
= DEVLINK_ESWITCH_MODE_LEGACY
;
140 rc
= devlink_register(dl
, &bp
->pdev
->dev
);
142 netdev_warn(bp
->dev
, "devlink_register failed. rc=%d", rc
);
146 rc
= devlink_params_register(dl
, bnxt_dl_params
,
147 ARRAY_SIZE(bnxt_dl_params
));
149 netdev_warn(bp
->dev
, "devlink_params_register failed. rc=%d",
157 devlink_unregister(dl
);
159 bnxt_link_bp_to_dl(bp
, NULL
);
164 void bnxt_dl_unregister(struct bnxt
*bp
)
166 struct devlink
*dl
= bp
->dl
;
171 devlink_params_unregister(dl
, bnxt_dl_params
,
172 ARRAY_SIZE(bnxt_dl_params
));
173 devlink_unregister(dl
);