Commit | Line | Data |
---|---|---|
3c467bf3 SL |
1 | /* Broadcom NetXtreme-C/E network driver. |
2 | * | |
3 | * Copyright (c) 2017 Broadcom Limited | |
4 | * | |
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. | |
8 | */ | |
9 | ||
10 | #include <linux/pci.h> | |
11 | #include <linux/netdevice.h> | |
12 | #include "bnxt_hsi.h" | |
13 | #include "bnxt.h" | |
14 | #include "bnxt_vfr.h" | |
15 | #include "bnxt_devlink.h" | |
16 | ||
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 */ | |
22 | }; | |
23 | ||
6354b95e VV |
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}, | |
27 | }; | |
28 | ||
29 | static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg, | |
30 | int msg_len, union devlink_param_value *val) | |
31 | { | |
6fc92c33 | 32 | struct hwrm_nvm_get_variable_input *req = msg; |
6354b95e VV |
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; | |
37 | ||
38 | /* Get/Set NVM CFG parameter is supported only on PFs */ | |
39 | if (BNXT_VF(bp)) | |
40 | return -EPERM; | |
41 | ||
42 | for (i = 0; i < ARRAY_SIZE(nvm_params); i++) { | |
43 | if (nvm_params[i].id == param_id) { | |
44 | nvm_param = nvm_params[i]; | |
45 | break; | |
46 | } | |
47 | } | |
48 | ||
49 | if (nvm_param.dir_type == BNXT_NVM_PORT_CFG) | |
50 | idx = bp->pf.port_id; | |
51 | else if (nvm_param.dir_type == BNXT_NVM_FUNC_CFG) | |
52 | idx = bp->pf.fw_fid - BNXT_FIRST_PF_FID; | |
53 | ||
54 | bytesize = roundup(nvm_param.num_bits, BITS_PER_BYTE) / BITS_PER_BYTE; | |
55 | if (nvm_param.num_bits == 1) | |
56 | buf = &val->vbool; | |
57 | ||
58 | data_addr = dma_zalloc_coherent(&bp->pdev->dev, bytesize, | |
59 | &data_dma_addr, GFP_KERNEL); | |
60 | if (!data_addr) | |
61 | return -ENOMEM; | |
62 | ||
6fc92c33 | 63 | req->dest_data_addr = cpu_to_le64(data_dma_addr); |
6354b95e VV |
64 | req->data_len = cpu_to_le16(nvm_param.num_bits); |
65 | req->option_num = cpu_to_le16(nvm_param.offset); | |
66 | req->index_0 = cpu_to_le16(idx); | |
67 | if (idx) | |
68 | req->dimensions = cpu_to_le16(1); | |
69 | ||
6fc92c33 | 70 | if (req->req_type == cpu_to_le16(HWRM_NVM_SET_VARIABLE)) |
6354b95e VV |
71 | memcpy(data_addr, buf, bytesize); |
72 | ||
73 | rc = hwrm_send_message(bp, msg, msg_len, HWRM_CMD_TIMEOUT); | |
6fc92c33 | 74 | if (!rc && req->req_type == cpu_to_le16(HWRM_NVM_GET_VARIABLE)) |
6354b95e VV |
75 | memcpy(buf, data_addr, bytesize); |
76 | ||
77 | dma_free_coherent(&bp->pdev->dev, bytesize, data_addr, data_dma_addr); | |
78 | if (rc) | |
79 | return -EIO; | |
80 | return 0; | |
81 | } | |
82 | ||
83 | static int bnxt_dl_nvm_param_get(struct devlink *dl, u32 id, | |
84 | struct devlink_param_gset_ctx *ctx) | |
85 | { | |
86 | struct hwrm_nvm_get_variable_input req = {0}; | |
87 | struct bnxt *bp = bnxt_get_bp_from_dl(dl); | |
88 | ||
89 | bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_NVM_GET_VARIABLE, -1, -1); | |
90 | return bnxt_hwrm_nvm_req(bp, id, &req, sizeof(req), &ctx->val); | |
91 | } | |
92 | ||
93 | static int bnxt_dl_nvm_param_set(struct devlink *dl, u32 id, | |
94 | struct devlink_param_gset_ctx *ctx) | |
95 | { | |
96 | struct hwrm_nvm_set_variable_input req = {0}; | |
97 | struct bnxt *bp = bnxt_get_bp_from_dl(dl); | |
98 | ||
99 | bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_NVM_SET_VARIABLE, -1, -1); | |
100 | return bnxt_hwrm_nvm_req(bp, id, &req, sizeof(req), &ctx->val); | |
101 | } | |
102 | ||
103 | static const struct devlink_param bnxt_dl_params[] = { | |
104 | DEVLINK_PARAM_GENERIC(ENABLE_SRIOV, | |
105 | BIT(DEVLINK_PARAM_CMODE_PERMANENT), | |
106 | bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set, | |
107 | NULL), | |
108 | }; | |
109 | ||
3c467bf3 SL |
110 | int bnxt_dl_register(struct bnxt *bp) |
111 | { | |
112 | struct devlink *dl; | |
113 | int rc; | |
114 | ||
6354b95e VV |
115 | if (bp->hwrm_spec_code < 0x10600) { |
116 | netdev_warn(bp->dev, "Firmware does not support NVM params"); | |
3c467bf3 SL |
117 | return -ENOTSUPP; |
118 | } | |
119 | ||
120 | dl = devlink_alloc(&bnxt_dl_ops, sizeof(struct bnxt_dl)); | |
121 | if (!dl) { | |
122 | netdev_warn(bp->dev, "devlink_alloc failed"); | |
123 | return -ENOMEM; | |
124 | } | |
125 | ||
126 | bnxt_link_bp_to_dl(bp, dl); | |
6354b95e VV |
127 | |
128 | /* Add switchdev eswitch mode setting, if SRIOV supported */ | |
129 | if (pci_find_ext_capability(bp->pdev, PCI_EXT_CAP_ID_SRIOV) && | |
130 | bp->hwrm_spec_code > 0x10803) | |
131 | bp->eswitch_mode = DEVLINK_ESWITCH_MODE_LEGACY; | |
132 | ||
3c467bf3 SL |
133 | rc = devlink_register(dl, &bp->pdev->dev); |
134 | if (rc) { | |
3c467bf3 | 135 | netdev_warn(bp->dev, "devlink_register failed. rc=%d", rc); |
6354b95e VV |
136 | goto err_dl_free; |
137 | } | |
138 | ||
139 | rc = devlink_params_register(dl, bnxt_dl_params, | |
140 | ARRAY_SIZE(bnxt_dl_params)); | |
141 | if (rc) { | |
142 | netdev_warn(bp->dev, "devlink_params_register failed. rc=%d", | |
143 | rc); | |
144 | goto err_dl_unreg; | |
3c467bf3 SL |
145 | } |
146 | ||
147 | return 0; | |
6354b95e VV |
148 | |
149 | err_dl_unreg: | |
150 | devlink_unregister(dl); | |
151 | err_dl_free: | |
152 | bnxt_link_bp_to_dl(bp, NULL); | |
153 | devlink_free(dl); | |
154 | return rc; | |
3c467bf3 SL |
155 | } |
156 | ||
157 | void bnxt_dl_unregister(struct bnxt *bp) | |
158 | { | |
159 | struct devlink *dl = bp->dl; | |
160 | ||
161 | if (!dl) | |
162 | return; | |
163 | ||
6354b95e VV |
164 | devlink_params_unregister(dl, bnxt_dl_params, |
165 | ARRAY_SIZE(bnxt_dl_params)); | |
3c467bf3 SL |
166 | devlink_unregister(dl); |
167 | devlink_free(dl); | |
168 | } |