FILE
octep_vf_mbox.c
File preview with syntax highlighting.
linux-6.19.14/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_mbox.c
1// SPDX-License-Identifier: GPL-2.0 2/* Marvell Octeon EP (EndPoint) VF Ethernet Driver 3 * 4 * Copyright (C) 2020 Marvell. 5 * 6 */ 7#include <linux/types.h> 8#include <linux/pci.h> 9#include <linux/netdevice.h> 10#include <linux/vmalloc.h> 11#include "octep_vf_config.h" 12#include "octep_vf_main.h" 13 14/* When a new command is implemented, the below table should be updated 15 * with new command and it's version info. 16 */ 17static u32 pfvf_cmd_versions[OCTEP_PFVF_MBOX_CMD_MAX] = { 18 [0 ... OCTEP_PFVF_MBOX_CMD_DEV_REMOVE] = OCTEP_PFVF_MBOX_VERSION_V1, 19 [OCTEP_PFVF_MBOX_CMD_GET_FW_INFO ... OCTEP_PFVF_MBOX_NOTIF_LINK_STATUS] = 20 OCTEP_PFVF_MBOX_VERSION_V2 21}; 22 23int octep_vf_setup_mbox(struct octep_vf_device *oct) 24{ 25 int ring = 0; 26 27 oct->mbox = vzalloc(sizeof(*oct->mbox)); 28 if (!oct->mbox) 29 return -1; 30 31 mutex_init(&oct->mbox->lock); 32 33 oct->hw_ops.setup_mbox_regs(oct, ring); 34 INIT_WORK(&oct->mbox->wk.work, octep_vf_mbox_work); 35 oct->mbox->wk.ctxptr = oct; 36 oct->mbox_neg_ver = OCTEP_PFVF_MBOX_VERSION_CURRENT; 37 dev_info(&oct->pdev->dev, "setup vf mbox successfully\n"); 38 return 0; 39} 40 41void octep_vf_delete_mbox(struct octep_vf_device *oct) 42{ 43 if (oct->mbox) { 44 if (work_pending(&oct->mbox->wk.work)) 45 cancel_work_sync(&oct->mbox->wk.work); 46 47 mutex_destroy(&oct->mbox->lock); 48 vfree(oct->mbox); 49 oct->mbox = NULL; 50 dev_info(&oct->pdev->dev, "Deleted vf mbox successfully\n"); 51 } 52} 53 54int octep_vf_mbox_version_check(struct octep_vf_device *oct) 55{ 56 union octep_pfvf_mbox_word cmd; 57 union octep_pfvf_mbox_word rsp; 58 int ret; 59 60 cmd.u64 = 0; 61 cmd.s_version.opcode = OCTEP_PFVF_MBOX_CMD_VERSION; 62 cmd.s_version.version = OCTEP_PFVF_MBOX_VERSION_CURRENT; 63 ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp); 64 if (ret == OCTEP_PFVF_MBOX_CMD_STATUS_NACK) { 65 dev_err(&oct->pdev->dev, 66 "VF Mbox version is incompatible with PF\n"); 67 return -EINVAL; 68 } 69 oct->mbox_neg_ver = (u32)rsp.s_version.version; 70 dev_dbg(&oct->pdev->dev, 71 "VF Mbox version:%u Negotiated VF version with PF:%u\n", 72 (u32)cmd.s_version.version, 73 (u32)rsp.s_version.version); 74 return 0; 75} 76 77void octep_vf_mbox_work(struct work_struct *work) 78{ 79 struct octep_vf_mbox_wk *wk = container_of(work, struct octep_vf_mbox_wk, work); 80 struct octep_vf_iface_link_info *link_info; 81 struct octep_vf_device *oct = NULL; 82 struct octep_vf_mbox *mbox = NULL; 83 union octep_pfvf_mbox_word *notif; 84 u64 pf_vf_data; 85 86 oct = (struct octep_vf_device *)wk->ctxptr; 87 link_info = &oct->link_info; 88 mbox = oct->mbox; 89 pf_vf_data = readq(mbox->mbox_read_reg); 90 91 notif = (union octep_pfvf_mbox_word *)&pf_vf_data; 92 93 switch (notif->s.opcode) { 94 case OCTEP_PFVF_MBOX_NOTIF_LINK_STATUS: 95 if (notif->s_link_status.status) { 96 link_info->oper_up = OCTEP_PFVF_LINK_STATUS_UP; 97 netif_carrier_on(oct->netdev); 98 dev_info(&oct->pdev->dev, "netif_carrier_on\n"); 99 } else { 100 link_info->oper_up = OCTEP_PFVF_LINK_STATUS_DOWN; 101 netif_carrier_off(oct->netdev); 102 dev_info(&oct->pdev->dev, "netif_carrier_off\n"); 103 } 104 break; 105 default: 106 dev_err(&oct->pdev->dev, 107 "Received unsupported notif %d\n", notif->s.opcode); 108 break; 109 } 110} 111 112static int __octep_vf_mbox_send_cmd(struct octep_vf_device *oct, 113 union octep_pfvf_mbox_word cmd, 114 union octep_pfvf_mbox_word *rsp) 115{ 116 struct octep_vf_mbox *mbox = oct->mbox; 117 u64 reg_val = 0ull; 118 int count; 119 120 if (!mbox) 121 return OCTEP_PFVF_MBOX_CMD_STATUS_NOT_SETUP; 122 123 cmd.s.type = OCTEP_PFVF_MBOX_TYPE_CMD; 124 writeq(cmd.u64, mbox->mbox_write_reg); 125 126 /* No response for notification messages */ 127 if (!rsp) 128 return 0; 129 130 for (count = 0; count < OCTEP_PFVF_MBOX_TIMEOUT_WAIT_COUNT; count++) { 131 usleep_range(1000, 1500); 132 reg_val = readq(mbox->mbox_write_reg); 133 if (reg_val != cmd.u64) { 134 rsp->u64 = reg_val; 135 break; 136 } 137 } 138 if (count == OCTEP_PFVF_MBOX_TIMEOUT_WAIT_COUNT) { 139 dev_err(&oct->pdev->dev, "mbox send command timed out\n"); 140 return OCTEP_PFVF_MBOX_CMD_STATUS_TIMEDOUT; 141 } 142 if (rsp->s.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) { 143 dev_err(&oct->pdev->dev, "mbox_send: Received NACK\n"); 144 return OCTEP_PFVF_MBOX_CMD_STATUS_NACK; 145 } 146 rsp->u64 = reg_val; 147 return 0; 148} 149 150int octep_vf_mbox_send_cmd(struct octep_vf_device *oct, union octep_pfvf_mbox_word cmd, 151 union octep_pfvf_mbox_word *rsp) 152{ 153 struct octep_vf_mbox *mbox = oct->mbox; 154 int ret; 155 156 if (!mbox) 157 return OCTEP_PFVF_MBOX_CMD_STATUS_NOT_SETUP; 158 mutex_lock(&mbox->lock); 159 if (pfvf_cmd_versions[cmd.s.opcode] > oct->mbox_neg_ver) { 160 dev_dbg(&oct->pdev->dev, "CMD:%d not supported in Version:%d\n", 161 cmd.s.opcode, oct->mbox_neg_ver); 162 mutex_unlock(&mbox->lock); 163 return -EOPNOTSUPP; 164 } 165 ret = __octep_vf_mbox_send_cmd(oct, cmd, rsp); 166 mutex_unlock(&mbox->lock); 167 return ret; 168} 169 170int octep_vf_mbox_bulk_read(struct octep_vf_device *oct, enum octep_pfvf_mbox_opcode opcode, 171 u8 *data, int *size) 172{ 173 struct octep_vf_mbox *mbox = oct->mbox; 174 union octep_pfvf_mbox_word cmd; 175 union octep_pfvf_mbox_word rsp; 176 int data_len = 0, tmp_len = 0; 177 int read_cnt, i = 0, ret; 178 179 if (!mbox) 180 return OCTEP_PFVF_MBOX_CMD_STATUS_NOT_SETUP; 181 182 mutex_lock(&mbox->lock); 183 cmd.u64 = 0; 184 cmd.s_data.opcode = opcode; 185 cmd.s_data.frag = 0; 186 /* Send cmd to read data from PF */ 187 ret = __octep_vf_mbox_send_cmd(oct, cmd, &rsp); 188 if (ret) { 189 dev_err(&oct->pdev->dev, "send mbox cmd fail for data request\n"); 190 mutex_unlock(&mbox->lock); 191 return ret; 192 } 193 /* PF sends the data length of requested CMD 194 * in ACK 195 */ 196 data_len = *((int32_t *)rsp.s_data.data); 197 tmp_len = data_len; 198 cmd.u64 = 0; 199 rsp.u64 = 0; 200 cmd.s_data.opcode = opcode; 201 cmd.s_data.frag = 1; 202 while (data_len) { 203 ret = __octep_vf_mbox_send_cmd(oct, cmd, &rsp); 204 if (ret) { 205 dev_err(&oct->pdev->dev, "send mbox cmd fail for data request\n"); 206 mutex_unlock(&mbox->lock); 207 mbox->mbox_data.data_index = 0; 208 memset(mbox->mbox_data.recv_data, 0, OCTEP_PFVF_MBOX_MAX_DATA_BUF_SIZE); 209 return ret; 210 } 211 if (data_len > OCTEP_PFVF_MBOX_MAX_DATA_SIZE) { 212 data_len -= OCTEP_PFVF_MBOX_MAX_DATA_SIZE; 213 read_cnt = OCTEP_PFVF_MBOX_MAX_DATA_SIZE; 214 } else { 215 read_cnt = data_len; 216 data_len = 0; 217 } 218 for (i = 0; i < read_cnt; i++) { 219 mbox->mbox_data.recv_data[mbox->mbox_data.data_index] = 220 rsp.s_data.data[i]; 221 mbox->mbox_data.data_index++; 222 } 223 cmd.u64 = 0; 224 rsp.u64 = 0; 225 cmd.s_data.opcode = opcode; 226 cmd.s_data.frag = 1; 227 } 228 memcpy(data, mbox->mbox_data.recv_data, tmp_len); 229 *size = tmp_len; 230 mbox->mbox_data.data_index = 0; 231 memset(mbox->mbox_data.recv_data, 0, OCTEP_PFVF_MBOX_MAX_DATA_BUF_SIZE); 232 mutex_unlock(&mbox->lock); 233 return 0; 234} 235 236int octep_vf_mbox_set_mtu(struct octep_vf_device *oct, int mtu) 237{ 238 int frame_size = mtu + ETH_HLEN + ETH_FCS_LEN; 239 union octep_pfvf_mbox_word cmd; 240 union octep_pfvf_mbox_word rsp; 241 int ret = 0; 242 243 if (mtu < ETH_MIN_MTU || frame_size > ETH_MAX_MTU) { 244 dev_err(&oct->pdev->dev, 245 "Failed to set MTU to %d MIN MTU:%d MAX MTU:%d\n", 246 mtu, ETH_MIN_MTU, ETH_MAX_MTU); 247 return -EINVAL; 248 } 249 250 cmd.u64 = 0; 251 cmd.s_set_mtu.opcode = OCTEP_PFVF_MBOX_CMD_SET_MTU; 252 cmd.s_set_mtu.mtu = mtu; 253 254 ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp); 255 if (ret) { 256 dev_err(&oct->pdev->dev, "Mbox send failed; err=%d\n", ret); 257 return ret; 258 } 259 if (rsp.s_set_mtu.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) { 260 dev_err(&oct->pdev->dev, "Received Mbox NACK from PF for MTU:%d\n", mtu); 261 return -EINVAL; 262 } 263 264 return 0; 265} 266 267int octep_vf_mbox_set_mac_addr(struct octep_vf_device *oct, char *mac_addr) 268{ 269 union octep_pfvf_mbox_word cmd; 270 union octep_pfvf_mbox_word rsp; 271 int i, ret; 272 273 cmd.u64 = 0; 274 cmd.s_set_mac.opcode = OCTEP_PFVF_MBOX_CMD_SET_MAC_ADDR; 275 for (i = 0; i < ETH_ALEN; i++) 276 cmd.s_set_mac.mac_addr[i] = mac_addr[i]; 277 ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp); 278 if (ret) { 279 dev_err(&oct->pdev->dev, "Mbox send failed; err = %d\n", ret); 280 return ret; 281 } 282 if (rsp.s_set_mac.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) { 283 dev_err(&oct->pdev->dev, "received NACK\n"); 284 return -EINVAL; 285 } 286 return 0; 287} 288 289int octep_vf_mbox_get_mac_addr(struct octep_vf_device *oct, char *mac_addr) 290{ 291 union octep_pfvf_mbox_word cmd; 292 union octep_pfvf_mbox_word rsp; 293 int i, ret; 294 295 cmd.u64 = 0; 296 cmd.s_set_mac.opcode = OCTEP_PFVF_MBOX_CMD_GET_MAC_ADDR; 297 ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp); 298 if (ret) { 299 dev_err(&oct->pdev->dev, "get_mac: mbox send failed; err = %d\n", ret); 300 return ret; 301 } 302 if (rsp.s_set_mac.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) { 303 dev_err(&oct->pdev->dev, "get_mac: received NACK\n"); 304 return -EINVAL; 305 } 306 for (i = 0; i < ETH_ALEN; i++) 307 mac_addr[i] = rsp.s_set_mac.mac_addr[i]; 308 return 0; 309} 310 311int octep_vf_mbox_set_rx_state(struct octep_vf_device *oct, bool state) 312{ 313 union octep_pfvf_mbox_word cmd; 314 union octep_pfvf_mbox_word rsp; 315 int ret; 316 317 cmd.u64 = 0; 318 cmd.s_link_state.opcode = OCTEP_PFVF_MBOX_CMD_SET_RX_STATE; 319 cmd.s_link_state.state = state; 320 ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp); 321 if (ret) { 322 dev_err(&oct->pdev->dev, "Set Rx state via VF Mbox send failed\n"); 323 return ret; 324 } 325 if (rsp.s_link_state.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) { 326 dev_err(&oct->pdev->dev, "Set Rx state received NACK\n"); 327 return -EINVAL; 328 } 329 return 0; 330} 331 332int octep_vf_mbox_set_link_status(struct octep_vf_device *oct, bool status) 333{ 334 union octep_pfvf_mbox_word cmd; 335 union octep_pfvf_mbox_word rsp; 336 int ret; 337 338 cmd.u64 = 0; 339 cmd.s_link_status.opcode = OCTEP_PFVF_MBOX_CMD_SET_LINK_STATUS; 340 cmd.s_link_status.status = status; 341 ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp); 342 if (ret) { 343 dev_err(&oct->pdev->dev, "Set link status via VF Mbox send failed\n"); 344 return ret; 345 } 346 if (rsp.s_link_status.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) { 347 dev_err(&oct->pdev->dev, "Set link status received NACK\n"); 348 return -EINVAL; 349 } 350 return 0; 351} 352 353int octep_vf_mbox_get_link_status(struct octep_vf_device *oct, u8 *oper_up) 354{ 355 union octep_pfvf_mbox_word cmd; 356 union octep_pfvf_mbox_word rsp; 357 int ret; 358 359 cmd.u64 = 0; 360 cmd.s_link_status.opcode = OCTEP_PFVF_MBOX_CMD_GET_LINK_STATUS; 361 ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp); 362 if (ret) { 363 dev_err(&oct->pdev->dev, "Get link status via VF Mbox send failed\n"); 364 return ret; 365 } 366 if (rsp.s_link_status.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) { 367 dev_err(&oct->pdev->dev, "Get link status received NACK\n"); 368 return -EINVAL; 369 } 370 *oper_up = rsp.s_link_status.status; 371 return 0; 372} 373 374int octep_vf_mbox_dev_remove(struct octep_vf_device *oct) 375{ 376 union octep_pfvf_mbox_word cmd; 377 int ret; 378 379 cmd.u64 = 0; 380 cmd.s.opcode = OCTEP_PFVF_MBOX_CMD_DEV_REMOVE; 381 ret = octep_vf_mbox_send_cmd(oct, cmd, NULL); 382 return ret; 383} 384 385int octep_vf_mbox_get_fw_info(struct octep_vf_device *oct) 386{ 387 union octep_pfvf_mbox_word cmd; 388 union octep_pfvf_mbox_word rsp; 389 int ret; 390 391 cmd.u64 = 0; 392 cmd.s_fw_info.opcode = OCTEP_PFVF_MBOX_CMD_GET_FW_INFO; 393 ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp); 394 if (ret) { 395 dev_err(&oct->pdev->dev, "Get link status via VF Mbox send failed\n"); 396 return ret; 397 } 398 if (rsp.s_fw_info.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) { 399 dev_err(&oct->pdev->dev, "Get link status received NACK\n"); 400 return -EINVAL; 401 } 402 oct->fw_info.pkind = rsp.s_fw_info.pkind; 403 oct->fw_info.fsz = rsp.s_fw_info.fsz; 404 oct->fw_info.rx_ol_flags = rsp.s_fw_info.rx_ol_flags; 405 oct->fw_info.tx_ol_flags = rsp.s_fw_info.tx_ol_flags; 406 407 return 0; 408} 409 410int octep_vf_mbox_set_offloads(struct octep_vf_device *oct, u16 tx_offloads, 411 u16 rx_offloads) 412{ 413 union octep_pfvf_mbox_word cmd; 414 union octep_pfvf_mbox_word rsp; 415 int ret; 416 417 cmd.u64 = 0; 418 cmd.s_offloads.opcode = OCTEP_PFVF_MBOX_CMD_SET_OFFLOADS; 419 cmd.s_offloads.rx_ol_flags = rx_offloads; 420 cmd.s_offloads.tx_ol_flags = tx_offloads; 421 ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp); 422 if (ret) { 423 dev_err(&oct->pdev->dev, "Set offloads via VF Mbox send failed\n"); 424 return ret; 425 } 426 if (rsp.s_link_state.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) { 427 dev_err(&oct->pdev->dev, "Set offloads received NACK\n"); 428 return -EINVAL; 429 } 430 return 0; 431}
~/
Read-only file preview.