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