3727 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* Copyright (C) 2023 Intel Corporation */3 4#include <net/libeth/rx.h>5 6#include "idpf.h"7#include "idpf_virtchnl.h"8 9#define IDPF_VC_XN_MIN_TIMEOUT_MSEC 200010#define IDPF_VC_XN_DEFAULT_TIMEOUT_MSEC (60 * 1000)11#define IDPF_VC_XN_IDX_M GENMASK(7, 0)12#define IDPF_VC_XN_SALT_M GENMASK(15, 8)13#define IDPF_VC_XN_RING_LEN U8_MAX14 15/**16 * enum idpf_vc_xn_state - Virtchnl transaction status17 * @IDPF_VC_XN_IDLE: not expecting a reply, ready to be used18 * @IDPF_VC_XN_WAITING: expecting a reply, not yet received19 * @IDPF_VC_XN_COMPLETED_SUCCESS: a reply was expected and received,20 * buffer updated21 * @IDPF_VC_XN_COMPLETED_FAILED: a reply was expected and received, but there22 * was an error, buffer not updated23 * @IDPF_VC_XN_SHUTDOWN: transaction object cannot be used, VC torn down24 * @IDPF_VC_XN_ASYNC: transaction sent asynchronously and doesn't have the25 * return context; a callback may be provided to handle26 * return27 */28enum idpf_vc_xn_state {29 IDPF_VC_XN_IDLE = 1,30 IDPF_VC_XN_WAITING,31 IDPF_VC_XN_COMPLETED_SUCCESS,32 IDPF_VC_XN_COMPLETED_FAILED,33 IDPF_VC_XN_SHUTDOWN,34 IDPF_VC_XN_ASYNC,35};36 37struct idpf_vc_xn;38/* Callback for asynchronous messages */39typedef int (*async_vc_cb) (struct idpf_adapter *, struct idpf_vc_xn *,40 const struct idpf_ctlq_msg *);41 42/**43 * struct idpf_vc_xn - Data structure representing virtchnl transactions44 * @completed: virtchnl event loop uses that to signal when a reply is45 * available, uses kernel completion API46 * @state: virtchnl event loop stores the data below, protected by the47 * completion's lock.48 * @reply_sz: Original size of reply, may be > reply_buf.iov_len; it will be49 * truncated on its way to the receiver thread according to50 * reply_buf.iov_len.51 * @reply: Reference to the buffer(s) where the reply data should be written52 * to. May be 0-length (then NULL address permitted) if the reply data53 * should be ignored.54 * @async_handler: if sent asynchronously, a callback can be provided to handle55 * the reply when it's received56 * @vc_op: corresponding opcode sent with this transaction57 * @idx: index used as retrieval on reply receive, used for cookie58 * @salt: changed every message to make unique, used for cookie59 */60struct idpf_vc_xn {61 struct completion completed;62 enum idpf_vc_xn_state state;63 size_t reply_sz;64 struct kvec reply;65 async_vc_cb async_handler;66 u32 vc_op;67 u8 idx;68 u8 salt;69};70 71/**72 * struct idpf_vc_xn_params - Parameters for executing transaction73 * @send_buf: kvec for send buffer74 * @recv_buf: kvec for recv buffer, may be NULL, must then have zero length75 * @timeout_ms: timeout to wait for reply76 * @async: send message asynchronously, will not wait on completion77 * @async_handler: If sent asynchronously, optional callback handler. The user78 * must be careful when using async handlers as the memory for79 * the recv_buf _cannot_ be on stack if this is async.80 * @vc_op: virtchnl op to send81 */82struct idpf_vc_xn_params {83 struct kvec send_buf;84 struct kvec recv_buf;85 int timeout_ms;86 bool async;87 async_vc_cb async_handler;88 u32 vc_op;89};90 91/**92 * struct idpf_vc_xn_manager - Manager for tracking transactions93 * @ring: backing and lookup for transactions94 * @free_xn_bm: bitmap for free transactions95 * @xn_bm_lock: make bitmap access synchronous where necessary96 * @salt: used to make cookie unique every message97 */98struct idpf_vc_xn_manager {99 struct idpf_vc_xn ring[IDPF_VC_XN_RING_LEN];100 DECLARE_BITMAP(free_xn_bm, IDPF_VC_XN_RING_LEN);101 spinlock_t xn_bm_lock;102 u8 salt;103};104 105/**106 * idpf_vid_to_vport - Translate vport id to vport pointer107 * @adapter: private data struct108 * @v_id: vport id to translate109 *110 * Returns vport matching v_id, NULL if not found.111 */112static113struct idpf_vport *idpf_vid_to_vport(struct idpf_adapter *adapter, u32 v_id)114{115 u16 num_max_vports = idpf_get_max_vports(adapter);116 int i;117 118 for (i = 0; i < num_max_vports; i++)119 if (adapter->vport_ids[i] == v_id)120 return adapter->vports[i];121 122 return NULL;123}124 125/**126 * idpf_handle_event_link - Handle link event message127 * @adapter: private data struct128 * @v2e: virtchnl event message129 */130static void idpf_handle_event_link(struct idpf_adapter *adapter,131 const struct virtchnl2_event *v2e)132{133 struct idpf_netdev_priv *np;134 struct idpf_vport *vport;135 136 vport = idpf_vid_to_vport(adapter, le32_to_cpu(v2e->vport_id));137 if (!vport) {138 dev_err_ratelimited(&adapter->pdev->dev, "Failed to find vport_id %d for link event\n",139 v2e->vport_id);140 return;141 }142 np = netdev_priv(vport->netdev);143 144 np->link_speed_mbps = le32_to_cpu(v2e->link_speed);145 146 if (vport->link_up == v2e->link_status)147 return;148 149 vport->link_up = v2e->link_status;150 151 if (np->state != __IDPF_VPORT_UP)152 return;153 154 if (vport->link_up) {155 netif_tx_start_all_queues(vport->netdev);156 netif_carrier_on(vport->netdev);157 } else {158 netif_tx_stop_all_queues(vport->netdev);159 netif_carrier_off(vport->netdev);160 }161}162 163/**164 * idpf_recv_event_msg - Receive virtchnl event message165 * @adapter: Driver specific private structure166 * @ctlq_msg: message to copy from167 *168 * Receive virtchnl event message169 */170static void idpf_recv_event_msg(struct idpf_adapter *adapter,171 struct idpf_ctlq_msg *ctlq_msg)172{173 int payload_size = ctlq_msg->ctx.indirect.payload->size;174 struct virtchnl2_event *v2e;175 u32 event;176 177 if (payload_size < sizeof(*v2e)) {178 dev_err_ratelimited(&adapter->pdev->dev, "Failed to receive valid payload for event msg (op %d len %d)\n",179 ctlq_msg->cookie.mbx.chnl_opcode,180 payload_size);181 return;182 }183 184 v2e = (struct virtchnl2_event *)ctlq_msg->ctx.indirect.payload->va;185 event = le32_to_cpu(v2e->event);186 187 switch (event) {188 case VIRTCHNL2_EVENT_LINK_CHANGE:189 idpf_handle_event_link(adapter, v2e);190 return;191 default:192 dev_err(&adapter->pdev->dev,193 "Unknown event %d from PF\n", event);194 break;195 }196}197 198/**199 * idpf_mb_clean - Reclaim the send mailbox queue entries200 * @adapter: Driver specific private structure201 *202 * Reclaim the send mailbox queue entries to be used to send further messages203 *204 * Returns 0 on success, negative on failure205 */206static int idpf_mb_clean(struct idpf_adapter *adapter)207{208 u16 i, num_q_msg = IDPF_DFLT_MBX_Q_LEN;209 struct idpf_ctlq_msg **q_msg;210 struct idpf_dma_mem *dma_mem;211 int err;212 213 q_msg = kcalloc(num_q_msg, sizeof(struct idpf_ctlq_msg *), GFP_ATOMIC);214 if (!q_msg)215 return -ENOMEM;216 217 err = idpf_ctlq_clean_sq(adapter->hw.asq, &num_q_msg, q_msg);218 if (err)219 goto err_kfree;220 221 for (i = 0; i < num_q_msg; i++) {222 if (!q_msg[i])223 continue;224 dma_mem = q_msg[i]->ctx.indirect.payload;225 if (dma_mem)226 dma_free_coherent(&adapter->pdev->dev, dma_mem->size,227 dma_mem->va, dma_mem->pa);228 kfree(q_msg[i]);229 kfree(dma_mem);230 }231 232err_kfree:233 kfree(q_msg);234 235 return err;236}237 238/**239 * idpf_send_mb_msg - Send message over mailbox240 * @adapter: Driver specific private structure241 * @op: virtchnl opcode242 * @msg_size: size of the payload243 * @msg: pointer to buffer holding the payload244 * @cookie: unique SW generated cookie per message245 *246 * Will prepare the control queue message and initiates the send api247 *248 * Returns 0 on success, negative on failure249 */250int idpf_send_mb_msg(struct idpf_adapter *adapter, u32 op,251 u16 msg_size, u8 *msg, u16 cookie)252{253 struct idpf_ctlq_msg *ctlq_msg;254 struct idpf_dma_mem *dma_mem;255 int err;256 257 /* If we are here and a reset is detected nothing much can be258 * done. This thread should silently abort and expected to259 * be corrected with a new run either by user or driver260 * flows after reset261 */262 if (idpf_is_reset_detected(adapter))263 return 0;264 265 err = idpf_mb_clean(adapter);266 if (err)267 return err;268 269 ctlq_msg = kzalloc(sizeof(*ctlq_msg), GFP_ATOMIC);270 if (!ctlq_msg)271 return -ENOMEM;272 273 dma_mem = kzalloc(sizeof(*dma_mem), GFP_ATOMIC);274 if (!dma_mem) {275 err = -ENOMEM;276 goto dma_mem_error;277 }278 279 ctlq_msg->opcode = idpf_mbq_opc_send_msg_to_cp;280 ctlq_msg->func_id = 0;281 ctlq_msg->data_len = msg_size;282 ctlq_msg->cookie.mbx.chnl_opcode = op;283 ctlq_msg->cookie.mbx.chnl_retval = 0;284 dma_mem->size = IDPF_CTLQ_MAX_BUF_LEN;285 dma_mem->va = dma_alloc_coherent(&adapter->pdev->dev, dma_mem->size,286 &dma_mem->pa, GFP_ATOMIC);287 if (!dma_mem->va) {288 err = -ENOMEM;289 goto dma_alloc_error;290 }291 292 /* It's possible we're just sending an opcode but no buffer */293 if (msg && msg_size)294 memcpy(dma_mem->va, msg, msg_size);295 ctlq_msg->ctx.indirect.payload = dma_mem;296 ctlq_msg->ctx.sw_cookie.data = cookie;297 298 err = idpf_ctlq_send(&adapter->hw, adapter->hw.asq, 1, ctlq_msg);299 if (err)300 goto send_error;301 302 return 0;303 304send_error:305 dma_free_coherent(&adapter->pdev->dev, dma_mem->size, dma_mem->va,306 dma_mem->pa);307dma_alloc_error:308 kfree(dma_mem);309dma_mem_error:310 kfree(ctlq_msg);311 312 return err;313}314 315/* API for virtchnl "transaction" support ("xn" for short).316 *317 * We are reusing the completion lock to serialize the accesses to the318 * transaction state for simplicity, but it could be its own separate synchro319 * as well. For now, this API is only used from within a workqueue context;320 * raw_spin_lock() is enough.321 */322/**323 * idpf_vc_xn_lock - Request exclusive access to vc transaction324 * @xn: struct idpf_vc_xn* to access325 */326#define idpf_vc_xn_lock(xn) \327 raw_spin_lock(&(xn)->completed.wait.lock)328 329/**330 * idpf_vc_xn_unlock - Release exclusive access to vc transaction331 * @xn: struct idpf_vc_xn* to access332 */333#define idpf_vc_xn_unlock(xn) \334 raw_spin_unlock(&(xn)->completed.wait.lock)335 336/**337 * idpf_vc_xn_release_bufs - Release reference to reply buffer(s) and338 * reset the transaction state.339 * @xn: struct idpf_vc_xn to update340 */341static void idpf_vc_xn_release_bufs(struct idpf_vc_xn *xn)342{343 xn->reply.iov_base = NULL;344 xn->reply.iov_len = 0;345 346 if (xn->state != IDPF_VC_XN_SHUTDOWN)347 xn->state = IDPF_VC_XN_IDLE;348}349 350/**351 * idpf_vc_xn_init - Initialize virtchnl transaction object352 * @vcxn_mngr: pointer to vc transaction manager struct353 */354static void idpf_vc_xn_init(struct idpf_vc_xn_manager *vcxn_mngr)355{356 int i;357 358 spin_lock_init(&vcxn_mngr->xn_bm_lock);359 360 for (i = 0; i < ARRAY_SIZE(vcxn_mngr->ring); i++) {361 struct idpf_vc_xn *xn = &vcxn_mngr->ring[i];362 363 xn->state = IDPF_VC_XN_IDLE;364 xn->idx = i;365 idpf_vc_xn_release_bufs(xn);366 init_completion(&xn->completed);367 }368 369 bitmap_fill(vcxn_mngr->free_xn_bm, IDPF_VC_XN_RING_LEN);370}371 372/**373 * idpf_vc_xn_shutdown - Uninitialize virtchnl transaction object374 * @vcxn_mngr: pointer to vc transaction manager struct375 *376 * All waiting threads will be woken-up and their transaction aborted. Further377 * operations on that object will fail.378 */379static void idpf_vc_xn_shutdown(struct idpf_vc_xn_manager *vcxn_mngr)380{381 int i;382 383 spin_lock_bh(&vcxn_mngr->xn_bm_lock);384 bitmap_zero(vcxn_mngr->free_xn_bm, IDPF_VC_XN_RING_LEN);385 spin_unlock_bh(&vcxn_mngr->xn_bm_lock);386 387 for (i = 0; i < ARRAY_SIZE(vcxn_mngr->ring); i++) {388 struct idpf_vc_xn *xn = &vcxn_mngr->ring[i];389 390 idpf_vc_xn_lock(xn);391 xn->state = IDPF_VC_XN_SHUTDOWN;392 idpf_vc_xn_release_bufs(xn);393 idpf_vc_xn_unlock(xn);394 complete_all(&xn->completed);395 }396}397 398/**399 * idpf_vc_xn_pop_free - Pop a free transaction from free list400 * @vcxn_mngr: transaction manager to pop from401 *402 * Returns NULL if no free transactions403 */404static405struct idpf_vc_xn *idpf_vc_xn_pop_free(struct idpf_vc_xn_manager *vcxn_mngr)406{407 struct idpf_vc_xn *xn = NULL;408 unsigned long free_idx;409 410 spin_lock_bh(&vcxn_mngr->xn_bm_lock);411 free_idx = find_first_bit(vcxn_mngr->free_xn_bm, IDPF_VC_XN_RING_LEN);412 if (free_idx == IDPF_VC_XN_RING_LEN)413 goto do_unlock;414 415 clear_bit(free_idx, vcxn_mngr->free_xn_bm);416 xn = &vcxn_mngr->ring[free_idx];417 xn->salt = vcxn_mngr->salt++;418 419do_unlock:420 spin_unlock_bh(&vcxn_mngr->xn_bm_lock);421 422 return xn;423}424 425/**426 * idpf_vc_xn_push_free - Push a free transaction to free list427 * @vcxn_mngr: transaction manager to push to428 * @xn: transaction to push429 */430static void idpf_vc_xn_push_free(struct idpf_vc_xn_manager *vcxn_mngr,431 struct idpf_vc_xn *xn)432{433 idpf_vc_xn_release_bufs(xn);434 set_bit(xn->idx, vcxn_mngr->free_xn_bm);435}436 437/**438 * idpf_vc_xn_exec - Perform a send/recv virtchnl transaction439 * @adapter: driver specific private structure with vcxn_mngr440 * @params: parameters for this particular transaction including441 * -vc_op: virtchannel operation to send442 * -send_buf: kvec iov for send buf and len443 * -recv_buf: kvec iov for recv buf and len (ignored if NULL)444 * -timeout_ms: timeout waiting for a reply (milliseconds)445 * -async: don't wait for message reply, will lose caller context446 * -async_handler: callback to handle async replies447 *448 * @returns >= 0 for success, the size of the initial reply (may or may not be449 * >= @recv_buf.iov_len, but we never overflow @@recv_buf_iov_base). < 0 for450 * error.451 */452static ssize_t idpf_vc_xn_exec(struct idpf_adapter *adapter,453 const struct idpf_vc_xn_params *params)454{455 const struct kvec *send_buf = ¶ms->send_buf;456 struct idpf_vc_xn *xn;457 ssize_t retval;458 u16 cookie;459 460 xn = idpf_vc_xn_pop_free(adapter->vcxn_mngr);461 /* no free transactions available */462 if (!xn)463 return -ENOSPC;464 465 idpf_vc_xn_lock(xn);466 if (xn->state == IDPF_VC_XN_SHUTDOWN) {467 retval = -ENXIO;468 goto only_unlock;469 } else if (xn->state != IDPF_VC_XN_IDLE) {470 /* We're just going to clobber this transaction even though471 * it's not IDLE. If we don't reuse it we could theoretically472 * eventually leak all the free transactions and not be able to473 * send any messages. At least this way we make an attempt to474 * remain functional even though something really bad is475 * happening that's corrupting what was supposed to be free476 * transactions.477 */478 WARN_ONCE(1, "There should only be idle transactions in free list (idx %d op %d)\n",479 xn->idx, xn->vc_op);480 }481 482 xn->reply = params->recv_buf;483 xn->reply_sz = 0;484 xn->state = params->async ? IDPF_VC_XN_ASYNC : IDPF_VC_XN_WAITING;485 xn->vc_op = params->vc_op;486 xn->async_handler = params->async_handler;487 idpf_vc_xn_unlock(xn);488 489 if (!params->async)490 reinit_completion(&xn->completed);491 cookie = FIELD_PREP(IDPF_VC_XN_SALT_M, xn->salt) |492 FIELD_PREP(IDPF_VC_XN_IDX_M, xn->idx);493 494 retval = idpf_send_mb_msg(adapter, params->vc_op,495 send_buf->iov_len, send_buf->iov_base,496 cookie);497 if (retval) {498 idpf_vc_xn_lock(xn);499 goto release_and_unlock;500 }501 502 if (params->async)503 return 0;504 505 wait_for_completion_timeout(&xn->completed,506 msecs_to_jiffies(params->timeout_ms));507 508 /* No need to check the return value; we check the final state of the509 * transaction below. It's possible the transaction actually gets more510 * timeout than specified if we get preempted here but after511 * wait_for_completion_timeout returns. This should be non-issue512 * however.513 */514 idpf_vc_xn_lock(xn);515 switch (xn->state) {516 case IDPF_VC_XN_SHUTDOWN:517 retval = -ENXIO;518 goto only_unlock;519 case IDPF_VC_XN_WAITING:520 dev_notice_ratelimited(&adapter->pdev->dev, "Transaction timed-out (op %d, %dms)\n",521 params->vc_op, params->timeout_ms);522 retval = -ETIME;523 break;524 case IDPF_VC_XN_COMPLETED_SUCCESS:525 retval = xn->reply_sz;526 break;527 case IDPF_VC_XN_COMPLETED_FAILED:528 dev_notice_ratelimited(&adapter->pdev->dev, "Transaction failed (op %d)\n",529 params->vc_op);530 retval = -EIO;531 break;532 default:533 /* Invalid state. */534 WARN_ON_ONCE(1);535 retval = -EIO;536 break;537 }538 539release_and_unlock:540 idpf_vc_xn_push_free(adapter->vcxn_mngr, xn);541 /* If we receive a VC reply after here, it will be dropped. */542only_unlock:543 idpf_vc_xn_unlock(xn);544 545 return retval;546}547 548/**549 * idpf_vc_xn_forward_async - Handle async reply receives550 * @adapter: private data struct551 * @xn: transaction to handle552 * @ctlq_msg: corresponding ctlq_msg553 *554 * For async sends we're going to lose the caller's context so, if an555 * async_handler was provided, it can deal with the reply, otherwise we'll just556 * check and report if there is an error.557 */558static int559idpf_vc_xn_forward_async(struct idpf_adapter *adapter, struct idpf_vc_xn *xn,560 const struct idpf_ctlq_msg *ctlq_msg)561{562 int err = 0;563 564 if (ctlq_msg->cookie.mbx.chnl_opcode != xn->vc_op) {565 dev_err_ratelimited(&adapter->pdev->dev, "Async message opcode does not match transaction opcode (msg: %d) (xn: %d)\n",566 ctlq_msg->cookie.mbx.chnl_opcode, xn->vc_op);567 xn->reply_sz = 0;568 err = -EINVAL;569 goto release_bufs;570 }571 572 if (xn->async_handler) {573 err = xn->async_handler(adapter, xn, ctlq_msg);574 goto release_bufs;575 }576 577 if (ctlq_msg->cookie.mbx.chnl_retval) {578 xn->reply_sz = 0;579 dev_err_ratelimited(&adapter->pdev->dev, "Async message failure (op %d)\n",580 ctlq_msg->cookie.mbx.chnl_opcode);581 err = -EINVAL;582 }583 584release_bufs:585 idpf_vc_xn_push_free(adapter->vcxn_mngr, xn);586 587 return err;588}589 590/**591 * idpf_vc_xn_forward_reply - copy a reply back to receiving thread592 * @adapter: driver specific private structure with vcxn_mngr593 * @ctlq_msg: controlq message to send back to receiving thread594 */595static int596idpf_vc_xn_forward_reply(struct idpf_adapter *adapter,597 const struct idpf_ctlq_msg *ctlq_msg)598{599 const void *payload = NULL;600 size_t payload_size = 0;601 struct idpf_vc_xn *xn;602 u16 msg_info;603 int err = 0;604 u16 xn_idx;605 u16 salt;606 607 msg_info = ctlq_msg->ctx.sw_cookie.data;608 xn_idx = FIELD_GET(IDPF_VC_XN_IDX_M, msg_info);609 if (xn_idx >= ARRAY_SIZE(adapter->vcxn_mngr->ring)) {610 dev_err_ratelimited(&adapter->pdev->dev, "Out of bounds cookie received: %02x\n",611 xn_idx);612 return -EINVAL;613 }614 xn = &adapter->vcxn_mngr->ring[xn_idx];615 salt = FIELD_GET(IDPF_VC_XN_SALT_M, msg_info);616 if (xn->salt != salt) {617 dev_err_ratelimited(&adapter->pdev->dev, "Transaction salt does not match (%02x != %02x)\n",618 xn->salt, salt);619 return -EINVAL;620 }621 622 idpf_vc_xn_lock(xn);623 switch (xn->state) {624 case IDPF_VC_XN_WAITING:625 /* success */626 break;627 case IDPF_VC_XN_IDLE:628 dev_err_ratelimited(&adapter->pdev->dev, "Unexpected or belated VC reply (op %d)\n",629 ctlq_msg->cookie.mbx.chnl_opcode);630 err = -EINVAL;631 goto out_unlock;632 case IDPF_VC_XN_SHUTDOWN:633 /* ENXIO is a bit special here as the recv msg loop uses that634 * know if it should stop trying to clean the ring if we lost635 * the virtchnl. We need to stop playing with registers and636 * yield.637 */638 err = -ENXIO;639 goto out_unlock;640 case IDPF_VC_XN_ASYNC:641 err = idpf_vc_xn_forward_async(adapter, xn, ctlq_msg);642 idpf_vc_xn_unlock(xn);643 return err;644 default:645 dev_err_ratelimited(&adapter->pdev->dev, "Overwriting VC reply (op %d)\n",646 ctlq_msg->cookie.mbx.chnl_opcode);647 err = -EBUSY;648 goto out_unlock;649 }650 651 if (ctlq_msg->cookie.mbx.chnl_opcode != xn->vc_op) {652 dev_err_ratelimited(&adapter->pdev->dev, "Message opcode does not match transaction opcode (msg: %d) (xn: %d)\n",653 ctlq_msg->cookie.mbx.chnl_opcode, xn->vc_op);654 xn->reply_sz = 0;655 xn->state = IDPF_VC_XN_COMPLETED_FAILED;656 err = -EINVAL;657 goto out_unlock;658 }659 660 if (ctlq_msg->cookie.mbx.chnl_retval) {661 xn->reply_sz = 0;662 xn->state = IDPF_VC_XN_COMPLETED_FAILED;663 err = -EINVAL;664 goto out_unlock;665 }666 667 if (ctlq_msg->data_len) {668 payload = ctlq_msg->ctx.indirect.payload->va;669 payload_size = ctlq_msg->data_len;670 }671 672 xn->reply_sz = payload_size;673 xn->state = IDPF_VC_XN_COMPLETED_SUCCESS;674 675 if (xn->reply.iov_base && xn->reply.iov_len && payload_size)676 memcpy(xn->reply.iov_base, payload,677 min_t(size_t, xn->reply.iov_len, payload_size));678 679out_unlock:680 idpf_vc_xn_unlock(xn);681 /* we _cannot_ hold lock while calling complete */682 complete(&xn->completed);683 684 return err;685}686 687/**688 * idpf_recv_mb_msg - Receive message over mailbox689 * @adapter: Driver specific private structure690 *691 * Will receive control queue message and posts the receive buffer. Returns 0692 * on success and negative on failure.693 */694int idpf_recv_mb_msg(struct idpf_adapter *adapter)695{696 struct idpf_ctlq_msg ctlq_msg;697 struct idpf_dma_mem *dma_mem;698 int post_err, err;699 u16 num_recv;700 701 while (1) {702 /* This will get <= num_recv messages and output how many703 * actually received on num_recv.704 */705 num_recv = 1;706 err = idpf_ctlq_recv(adapter->hw.arq, &num_recv, &ctlq_msg);707 if (err || !num_recv)708 break;709 710 if (ctlq_msg.data_len) {711 dma_mem = ctlq_msg.ctx.indirect.payload;712 } else {713 dma_mem = NULL;714 num_recv = 0;715 }716 717 if (ctlq_msg.cookie.mbx.chnl_opcode == VIRTCHNL2_OP_EVENT)718 idpf_recv_event_msg(adapter, &ctlq_msg);719 else720 err = idpf_vc_xn_forward_reply(adapter, &ctlq_msg);721 722 post_err = idpf_ctlq_post_rx_buffs(&adapter->hw,723 adapter->hw.arq,724 &num_recv, &dma_mem);725 726 /* If post failed clear the only buffer we supplied */727 if (post_err) {728 if (dma_mem)729 dmam_free_coherent(&adapter->pdev->dev,730 dma_mem->size, dma_mem->va,731 dma_mem->pa);732 break;733 }734 735 /* virtchnl trying to shutdown, stop cleaning */736 if (err == -ENXIO)737 break;738 }739 740 return err;741}742 743/**744 * idpf_wait_for_marker_event - wait for software marker response745 * @vport: virtual port data structure746 *747 * Returns 0 success, negative on failure.748 **/749static int idpf_wait_for_marker_event(struct idpf_vport *vport)750{751 int event;752 int i;753 754 for (i = 0; i < vport->num_txq; i++)755 idpf_queue_set(SW_MARKER, vport->txqs[i]);756 757 event = wait_event_timeout(vport->sw_marker_wq,758 test_and_clear_bit(IDPF_VPORT_SW_MARKER,759 vport->flags),760 msecs_to_jiffies(500));761 762 for (i = 0; i < vport->num_txq; i++)763 idpf_queue_clear(POLL_MODE, vport->txqs[i]);764 765 if (event)766 return 0;767 768 dev_warn(&vport->adapter->pdev->dev, "Failed to receive marker packets\n");769 770 return -ETIMEDOUT;771}772 773/**774 * idpf_send_ver_msg - send virtchnl version message775 * @adapter: Driver specific private structure776 *777 * Send virtchnl version message. Returns 0 on success, negative on failure.778 */779static int idpf_send_ver_msg(struct idpf_adapter *adapter)780{781 struct idpf_vc_xn_params xn_params = {};782 struct virtchnl2_version_info vvi;783 ssize_t reply_sz;784 u32 major, minor;785 int err = 0;786 787 if (adapter->virt_ver_maj) {788 vvi.major = cpu_to_le32(adapter->virt_ver_maj);789 vvi.minor = cpu_to_le32(adapter->virt_ver_min);790 } else {791 vvi.major = cpu_to_le32(IDPF_VIRTCHNL_VERSION_MAJOR);792 vvi.minor = cpu_to_le32(IDPF_VIRTCHNL_VERSION_MINOR);793 }794 795 xn_params.vc_op = VIRTCHNL2_OP_VERSION;796 xn_params.send_buf.iov_base = &vvi;797 xn_params.send_buf.iov_len = sizeof(vvi);798 xn_params.recv_buf = xn_params.send_buf;799 xn_params.timeout_ms = IDPF_VC_XN_DEFAULT_TIMEOUT_MSEC;800 801 reply_sz = idpf_vc_xn_exec(adapter, &xn_params);802 if (reply_sz < 0)803 return reply_sz;804 if (reply_sz < sizeof(vvi))805 return -EIO;806 807 major = le32_to_cpu(vvi.major);808 minor = le32_to_cpu(vvi.minor);809 810 if (major > IDPF_VIRTCHNL_VERSION_MAJOR) {811 dev_warn(&adapter->pdev->dev, "Virtchnl major version greater than supported\n");812 return -EINVAL;813 }814 815 if (major == IDPF_VIRTCHNL_VERSION_MAJOR &&816 minor > IDPF_VIRTCHNL_VERSION_MINOR)817 dev_warn(&adapter->pdev->dev, "Virtchnl minor version didn't match\n");818 819 /* If we have a mismatch, resend version to update receiver on what820 * version we will use.821 */822 if (!adapter->virt_ver_maj &&823 major != IDPF_VIRTCHNL_VERSION_MAJOR &&824 minor != IDPF_VIRTCHNL_VERSION_MINOR)825 err = -EAGAIN;826 827 adapter->virt_ver_maj = major;828 adapter->virt_ver_min = minor;829 830 return err;831}832 833/**834 * idpf_send_get_caps_msg - Send virtchnl get capabilities message835 * @adapter: Driver specific private structure836 *837 * Send virtchl get capabilities message. Returns 0 on success, negative on838 * failure.839 */840static int idpf_send_get_caps_msg(struct idpf_adapter *adapter)841{842 struct virtchnl2_get_capabilities caps = {};843 struct idpf_vc_xn_params xn_params = {};844 ssize_t reply_sz;845 846 caps.csum_caps =847 cpu_to_le32(VIRTCHNL2_CAP_TX_CSUM_L3_IPV4 |848 VIRTCHNL2_CAP_TX_CSUM_L4_IPV4_TCP |849 VIRTCHNL2_CAP_TX_CSUM_L4_IPV4_UDP |850 VIRTCHNL2_CAP_TX_CSUM_L4_IPV4_SCTP |851 VIRTCHNL2_CAP_TX_CSUM_L4_IPV6_TCP |852 VIRTCHNL2_CAP_TX_CSUM_L4_IPV6_UDP |853 VIRTCHNL2_CAP_TX_CSUM_L4_IPV6_SCTP |854 VIRTCHNL2_CAP_RX_CSUM_L3_IPV4 |855 VIRTCHNL2_CAP_RX_CSUM_L4_IPV4_TCP |856 VIRTCHNL2_CAP_RX_CSUM_L4_IPV4_UDP |857 VIRTCHNL2_CAP_RX_CSUM_L4_IPV4_SCTP |858 VIRTCHNL2_CAP_RX_CSUM_L4_IPV6_TCP |859 VIRTCHNL2_CAP_RX_CSUM_L4_IPV6_UDP |860 VIRTCHNL2_CAP_RX_CSUM_L4_IPV6_SCTP |861 VIRTCHNL2_CAP_TX_CSUM_L3_SINGLE_TUNNEL |862 VIRTCHNL2_CAP_RX_CSUM_L3_SINGLE_TUNNEL |863 VIRTCHNL2_CAP_TX_CSUM_L4_SINGLE_TUNNEL |864 VIRTCHNL2_CAP_RX_CSUM_L4_SINGLE_TUNNEL |865 VIRTCHNL2_CAP_RX_CSUM_GENERIC);866 867 caps.seg_caps =868 cpu_to_le32(VIRTCHNL2_CAP_SEG_IPV4_TCP |869 VIRTCHNL2_CAP_SEG_IPV4_UDP |870 VIRTCHNL2_CAP_SEG_IPV4_SCTP |871 VIRTCHNL2_CAP_SEG_IPV6_TCP |872 VIRTCHNL2_CAP_SEG_IPV6_UDP |873 VIRTCHNL2_CAP_SEG_IPV6_SCTP |874 VIRTCHNL2_CAP_SEG_TX_SINGLE_TUNNEL);875 876 caps.rss_caps =877 cpu_to_le64(VIRTCHNL2_CAP_RSS_IPV4_TCP |878 VIRTCHNL2_CAP_RSS_IPV4_UDP |879 VIRTCHNL2_CAP_RSS_IPV4_SCTP |880 VIRTCHNL2_CAP_RSS_IPV4_OTHER |881 VIRTCHNL2_CAP_RSS_IPV6_TCP |882 VIRTCHNL2_CAP_RSS_IPV6_UDP |883 VIRTCHNL2_CAP_RSS_IPV6_SCTP |884 VIRTCHNL2_CAP_RSS_IPV6_OTHER);885 886 caps.hsplit_caps =887 cpu_to_le32(VIRTCHNL2_CAP_RX_HSPLIT_AT_L4V4 |888 VIRTCHNL2_CAP_RX_HSPLIT_AT_L4V6);889 890 caps.rsc_caps =891 cpu_to_le32(VIRTCHNL2_CAP_RSC_IPV4_TCP |892 VIRTCHNL2_CAP_RSC_IPV6_TCP);893 894 caps.other_caps =895 cpu_to_le64(VIRTCHNL2_CAP_SRIOV |896 VIRTCHNL2_CAP_MACFILTER |897 VIRTCHNL2_CAP_SPLITQ_QSCHED |898 VIRTCHNL2_CAP_PROMISC |899 VIRTCHNL2_CAP_LOOPBACK);900 901 xn_params.vc_op = VIRTCHNL2_OP_GET_CAPS;902 xn_params.send_buf.iov_base = ∩︀903 xn_params.send_buf.iov_len = sizeof(caps);904 xn_params.recv_buf.iov_base = &adapter->caps;905 xn_params.recv_buf.iov_len = sizeof(adapter->caps);906 xn_params.timeout_ms = IDPF_VC_XN_DEFAULT_TIMEOUT_MSEC;907 908 reply_sz = idpf_vc_xn_exec(adapter, &xn_params);909 if (reply_sz < 0)910 return reply_sz;911 if (reply_sz < sizeof(adapter->caps))912 return -EIO;913 914 return 0;915}916 917/**918 * idpf_vport_alloc_max_qs - Allocate max queues for a vport919 * @adapter: Driver specific private structure920 * @max_q: vport max queue structure921 */922int idpf_vport_alloc_max_qs(struct idpf_adapter *adapter,923 struct idpf_vport_max_q *max_q)924{925 struct idpf_avail_queue_info *avail_queues = &adapter->avail_queues;926 struct virtchnl2_get_capabilities *caps = &adapter->caps;927 u16 default_vports = idpf_get_default_vports(adapter);928 int max_rx_q, max_tx_q;929 930 mutex_lock(&adapter->queue_lock);931 932 max_rx_q = le16_to_cpu(caps->max_rx_q) / default_vports;933 max_tx_q = le16_to_cpu(caps->max_tx_q) / default_vports;934 if (adapter->num_alloc_vports < default_vports) {935 max_q->max_rxq = min_t(u16, max_rx_q, IDPF_MAX_Q);936 max_q->max_txq = min_t(u16, max_tx_q, IDPF_MAX_Q);937 } else {938 max_q->max_rxq = IDPF_MIN_Q;939 max_q->max_txq = IDPF_MIN_Q;940 }941 max_q->max_bufq = max_q->max_rxq * IDPF_MAX_BUFQS_PER_RXQ_GRP;942 max_q->max_complq = max_q->max_txq;943 944 if (avail_queues->avail_rxq < max_q->max_rxq ||945 avail_queues->avail_txq < max_q->max_txq ||946 avail_queues->avail_bufq < max_q->max_bufq ||947 avail_queues->avail_complq < max_q->max_complq) {948 mutex_unlock(&adapter->queue_lock);949 950 return -EINVAL;951 }952 953 avail_queues->avail_rxq -= max_q->max_rxq;954 avail_queues->avail_txq -= max_q->max_txq;955 avail_queues->avail_bufq -= max_q->max_bufq;956 avail_queues->avail_complq -= max_q->max_complq;957 958 mutex_unlock(&adapter->queue_lock);959 960 return 0;961}962 963/**964 * idpf_vport_dealloc_max_qs - Deallocate max queues of a vport965 * @adapter: Driver specific private structure966 * @max_q: vport max queue structure967 */968void idpf_vport_dealloc_max_qs(struct idpf_adapter *adapter,969 struct idpf_vport_max_q *max_q)970{971 struct idpf_avail_queue_info *avail_queues;972 973 mutex_lock(&adapter->queue_lock);974 avail_queues = &adapter->avail_queues;975 976 avail_queues->avail_rxq += max_q->max_rxq;977 avail_queues->avail_txq += max_q->max_txq;978 avail_queues->avail_bufq += max_q->max_bufq;979 avail_queues->avail_complq += max_q->max_complq;980 981 mutex_unlock(&adapter->queue_lock);982}983 984/**985 * idpf_init_avail_queues - Initialize available queues on the device986 * @adapter: Driver specific private structure987 */988static void idpf_init_avail_queues(struct idpf_adapter *adapter)989{990 struct idpf_avail_queue_info *avail_queues = &adapter->avail_queues;991 struct virtchnl2_get_capabilities *caps = &adapter->caps;992 993 avail_queues->avail_rxq = le16_to_cpu(caps->max_rx_q);994 avail_queues->avail_txq = le16_to_cpu(caps->max_tx_q);995 avail_queues->avail_bufq = le16_to_cpu(caps->max_rx_bufq);996 avail_queues->avail_complq = le16_to_cpu(caps->max_tx_complq);997}998 999/**1000 * idpf_get_reg_intr_vecs - Get vector queue register offset1001 * @vport: virtual port structure1002 * @reg_vals: Register offsets to store in1003 *1004 * Returns number of registers that got populated1005 */1006int idpf_get_reg_intr_vecs(struct idpf_vport *vport,1007 struct idpf_vec_regs *reg_vals)1008{1009 struct virtchnl2_vector_chunks *chunks;1010 struct idpf_vec_regs reg_val;1011 u16 num_vchunks, num_vec;1012 int num_regs = 0, i, j;1013 1014 chunks = &vport->adapter->req_vec_chunks->vchunks;1015 num_vchunks = le16_to_cpu(chunks->num_vchunks);1016 1017 for (j = 0; j < num_vchunks; j++) {1018 struct virtchnl2_vector_chunk *chunk;1019 u32 dynctl_reg_spacing;1020 u32 itrn_reg_spacing;1021 1022 chunk = &chunks->vchunks[j];1023 num_vec = le16_to_cpu(chunk->num_vectors);1024 reg_val.dyn_ctl_reg = le32_to_cpu(chunk->dynctl_reg_start);1025 reg_val.itrn_reg = le32_to_cpu(chunk->itrn_reg_start);1026 reg_val.itrn_index_spacing = le32_to_cpu(chunk->itrn_index_spacing);1027 1028 dynctl_reg_spacing = le32_to_cpu(chunk->dynctl_reg_spacing);1029 itrn_reg_spacing = le32_to_cpu(chunk->itrn_reg_spacing);1030 1031 for (i = 0; i < num_vec; i++) {1032 reg_vals[num_regs].dyn_ctl_reg = reg_val.dyn_ctl_reg;1033 reg_vals[num_regs].itrn_reg = reg_val.itrn_reg;1034 reg_vals[num_regs].itrn_index_spacing =1035 reg_val.itrn_index_spacing;1036 1037 reg_val.dyn_ctl_reg += dynctl_reg_spacing;1038 reg_val.itrn_reg += itrn_reg_spacing;1039 num_regs++;1040 }1041 }1042 1043 return num_regs;1044}1045 1046/**1047 * idpf_vport_get_q_reg - Get the queue registers for the vport1048 * @reg_vals: register values needing to be set1049 * @num_regs: amount we expect to fill1050 * @q_type: queue model1051 * @chunks: queue regs received over mailbox1052 *1053 * This function parses the queue register offsets from the queue register1054 * chunk information, with a specific queue type and stores it into the array1055 * passed as an argument. It returns the actual number of queue registers that1056 * are filled.1057 */1058static int idpf_vport_get_q_reg(u32 *reg_vals, int num_regs, u32 q_type,1059 struct virtchnl2_queue_reg_chunks *chunks)1060{1061 u16 num_chunks = le16_to_cpu(chunks->num_chunks);1062 int reg_filled = 0, i;1063 u32 reg_val;1064 1065 while (num_chunks--) {1066 struct virtchnl2_queue_reg_chunk *chunk;1067 u16 num_q;1068 1069 chunk = &chunks->chunks[num_chunks];1070 if (le32_to_cpu(chunk->type) != q_type)1071 continue;1072 1073 num_q = le32_to_cpu(chunk->num_queues);1074 reg_val = le64_to_cpu(chunk->qtail_reg_start);1075 for (i = 0; i < num_q && reg_filled < num_regs ; i++) {1076 reg_vals[reg_filled++] = reg_val;1077 reg_val += le32_to_cpu(chunk->qtail_reg_spacing);1078 }1079 }1080 1081 return reg_filled;1082}1083 1084/**1085 * __idpf_queue_reg_init - initialize queue registers1086 * @vport: virtual port structure1087 * @reg_vals: registers we are initializing1088 * @num_regs: how many registers there are in total1089 * @q_type: queue model1090 *1091 * Return number of queues that are initialized1092 */1093static int __idpf_queue_reg_init(struct idpf_vport *vport, u32 *reg_vals,1094 int num_regs, u32 q_type)1095{1096 struct idpf_adapter *adapter = vport->adapter;1097 int i, j, k = 0;1098 1099 switch (q_type) {1100 case VIRTCHNL2_QUEUE_TYPE_TX:1101 for (i = 0; i < vport->num_txq_grp; i++) {1102 struct idpf_txq_group *tx_qgrp = &vport->txq_grps[i];1103 1104 for (j = 0; j < tx_qgrp->num_txq && k < num_regs; j++, k++)1105 tx_qgrp->txqs[j]->tail =1106 idpf_get_reg_addr(adapter, reg_vals[k]);1107 }1108 break;1109 case VIRTCHNL2_QUEUE_TYPE_RX:1110 for (i = 0; i < vport->num_rxq_grp; i++) {1111 struct idpf_rxq_group *rx_qgrp = &vport->rxq_grps[i];1112 u16 num_rxq = rx_qgrp->singleq.num_rxq;1113 1114 for (j = 0; j < num_rxq && k < num_regs; j++, k++) {1115 struct idpf_rx_queue *q;1116 1117 q = rx_qgrp->singleq.rxqs[j];1118 q->tail = idpf_get_reg_addr(adapter,1119 reg_vals[k]);1120 }1121 }1122 break;1123 case VIRTCHNL2_QUEUE_TYPE_RX_BUFFER:1124 for (i = 0; i < vport->num_rxq_grp; i++) {1125 struct idpf_rxq_group *rx_qgrp = &vport->rxq_grps[i];1126 u8 num_bufqs = vport->num_bufqs_per_qgrp;1127 1128 for (j = 0; j < num_bufqs && k < num_regs; j++, k++) {1129 struct idpf_buf_queue *q;1130 1131 q = &rx_qgrp->splitq.bufq_sets[j].bufq;1132 q->tail = idpf_get_reg_addr(adapter,1133 reg_vals[k]);1134 }1135 }1136 break;1137 default:1138 break;1139 }1140 1141 return k;1142}1143 1144/**1145 * idpf_queue_reg_init - initialize queue registers1146 * @vport: virtual port structure1147 *1148 * Return 0 on success, negative on failure1149 */1150int idpf_queue_reg_init(struct idpf_vport *vport)1151{1152 struct virtchnl2_create_vport *vport_params;1153 struct virtchnl2_queue_reg_chunks *chunks;1154 struct idpf_vport_config *vport_config;1155 u16 vport_idx = vport->idx;1156 int num_regs, ret = 0;1157 u32 *reg_vals;1158 1159 /* We may never deal with more than 256 same type of queues */1160 reg_vals = kzalloc(sizeof(void *) * IDPF_LARGE_MAX_Q, GFP_KERNEL);1161 if (!reg_vals)1162 return -ENOMEM;1163 1164 vport_config = vport->adapter->vport_config[vport_idx];1165 if (vport_config->req_qs_chunks) {1166 struct virtchnl2_add_queues *vc_aq =1167 (struct virtchnl2_add_queues *)vport_config->req_qs_chunks;1168 chunks = &vc_aq->chunks;1169 } else {1170 vport_params = vport->adapter->vport_params_recvd[vport_idx];1171 chunks = &vport_params->chunks;1172 }1173 1174 /* Initialize Tx queue tail register address */1175 num_regs = idpf_vport_get_q_reg(reg_vals, IDPF_LARGE_MAX_Q,1176 VIRTCHNL2_QUEUE_TYPE_TX,1177 chunks);1178 if (num_regs < vport->num_txq) {1179 ret = -EINVAL;1180 goto free_reg_vals;1181 }1182 1183 num_regs = __idpf_queue_reg_init(vport, reg_vals, num_regs,1184 VIRTCHNL2_QUEUE_TYPE_TX);1185 if (num_regs < vport->num_txq) {1186 ret = -EINVAL;1187 goto free_reg_vals;1188 }1189 1190 /* Initialize Rx/buffer queue tail register address based on Rx queue1191 * model1192 */1193 if (idpf_is_queue_model_split(vport->rxq_model)) {1194 num_regs = idpf_vport_get_q_reg(reg_vals, IDPF_LARGE_MAX_Q,1195 VIRTCHNL2_QUEUE_TYPE_RX_BUFFER,1196 chunks);1197 if (num_regs < vport->num_bufq) {1198 ret = -EINVAL;1199 goto free_reg_vals;1200 }1201 1202 num_regs = __idpf_queue_reg_init(vport, reg_vals, num_regs,1203 VIRTCHNL2_QUEUE_TYPE_RX_BUFFER);1204 if (num_regs < vport->num_bufq) {1205 ret = -EINVAL;1206 goto free_reg_vals;1207 }1208 } else {1209 num_regs = idpf_vport_get_q_reg(reg_vals, IDPF_LARGE_MAX_Q,1210 VIRTCHNL2_QUEUE_TYPE_RX,1211 chunks);1212 if (num_regs < vport->num_rxq) {1213 ret = -EINVAL;1214 goto free_reg_vals;1215 }1216 1217 num_regs = __idpf_queue_reg_init(vport, reg_vals, num_regs,1218 VIRTCHNL2_QUEUE_TYPE_RX);1219 if (num_regs < vport->num_rxq) {1220 ret = -EINVAL;1221 goto free_reg_vals;1222 }1223 }1224 1225free_reg_vals:1226 kfree(reg_vals);1227 1228 return ret;1229}1230 1231/**1232 * idpf_send_create_vport_msg - Send virtchnl create vport message1233 * @adapter: Driver specific private structure1234 * @max_q: vport max queue info1235 *1236 * send virtchnl creae vport message1237 *1238 * Returns 0 on success, negative on failure1239 */1240int idpf_send_create_vport_msg(struct idpf_adapter *adapter,1241 struct idpf_vport_max_q *max_q)1242{1243 struct virtchnl2_create_vport *vport_msg;1244 struct idpf_vc_xn_params xn_params = {};1245 u16 idx = adapter->next_vport;1246 int err, buf_size;1247 ssize_t reply_sz;1248 1249 buf_size = sizeof(struct virtchnl2_create_vport);1250 if (!adapter->vport_params_reqd[idx]) {1251 adapter->vport_params_reqd[idx] = kzalloc(buf_size,1252 GFP_KERNEL);1253 if (!adapter->vport_params_reqd[idx])1254 return -ENOMEM;1255 }1256 1257 vport_msg = adapter->vport_params_reqd[idx];1258 vport_msg->vport_type = cpu_to_le16(VIRTCHNL2_VPORT_TYPE_DEFAULT);1259 vport_msg->vport_index = cpu_to_le16(idx);1260 1261 if (adapter->req_tx_splitq || !IS_ENABLED(CONFIG_IDPF_SINGLEQ))1262 vport_msg->txq_model = cpu_to_le16(VIRTCHNL2_QUEUE_MODEL_SPLIT);1263 else1264 vport_msg->txq_model = cpu_to_le16(VIRTCHNL2_QUEUE_MODEL_SINGLE);1265 1266 if (adapter->req_rx_splitq || !IS_ENABLED(CONFIG_IDPF_SINGLEQ))1267 vport_msg->rxq_model = cpu_to_le16(VIRTCHNL2_QUEUE_MODEL_SPLIT);1268 else1269 vport_msg->rxq_model = cpu_to_le16(VIRTCHNL2_QUEUE_MODEL_SINGLE);1270 1271 err = idpf_vport_calc_total_qs(adapter, idx, vport_msg, max_q);1272 if (err) {1273 dev_err(&adapter->pdev->dev, "Enough queues are not available");1274 1275 return err;1276 }1277 1278 if (!adapter->vport_params_recvd[idx]) {1279 adapter->vport_params_recvd[idx] = kzalloc(IDPF_CTLQ_MAX_BUF_LEN,1280 GFP_KERNEL);1281 if (!adapter->vport_params_recvd[idx]) {1282 err = -ENOMEM;1283 goto free_vport_params;1284 }1285 }1286 1287 xn_params.vc_op = VIRTCHNL2_OP_CREATE_VPORT;1288 xn_params.send_buf.iov_base = vport_msg;1289 xn_params.send_buf.iov_len = buf_size;1290 xn_params.recv_buf.iov_base = adapter->vport_params_recvd[idx];1291 xn_params.recv_buf.iov_len = IDPF_CTLQ_MAX_BUF_LEN;1292 xn_params.timeout_ms = IDPF_VC_XN_DEFAULT_TIMEOUT_MSEC;1293 reply_sz = idpf_vc_xn_exec(adapter, &xn_params);1294 if (reply_sz < 0) {1295 err = reply_sz;1296 goto free_vport_params;1297 }1298 1299 return 0;1300 1301free_vport_params:1302 kfree(adapter->vport_params_recvd[idx]);1303 adapter->vport_params_recvd[idx] = NULL;1304 kfree(adapter->vport_params_reqd[idx]);1305 adapter->vport_params_reqd[idx] = NULL;1306 1307 return err;1308}1309 1310/**1311 * idpf_check_supported_desc_ids - Verify we have required descriptor support1312 * @vport: virtual port structure1313 *1314 * Return 0 on success, error on failure1315 */1316int idpf_check_supported_desc_ids(struct idpf_vport *vport)1317{1318 struct idpf_adapter *adapter = vport->adapter;1319 struct virtchnl2_create_vport *vport_msg;1320 u64 rx_desc_ids, tx_desc_ids;1321 1322 vport_msg = adapter->vport_params_recvd[vport->idx];1323 1324 if (!IS_ENABLED(CONFIG_IDPF_SINGLEQ) &&1325 (vport_msg->rxq_model == VIRTCHNL2_QUEUE_MODEL_SINGLE ||1326 vport_msg->txq_model == VIRTCHNL2_QUEUE_MODEL_SINGLE)) {1327 pci_err(adapter->pdev, "singleq mode requested, but not compiled-in\n");1328 return -EOPNOTSUPP;1329 }1330 1331 rx_desc_ids = le64_to_cpu(vport_msg->rx_desc_ids);1332 tx_desc_ids = le64_to_cpu(vport_msg->tx_desc_ids);1333 1334 if (idpf_is_queue_model_split(vport->rxq_model)) {1335 if (!(rx_desc_ids & VIRTCHNL2_RXDID_2_FLEX_SPLITQ_M)) {1336 dev_info(&adapter->pdev->dev, "Minimum RX descriptor support not provided, using the default\n");1337 vport_msg->rx_desc_ids = cpu_to_le64(VIRTCHNL2_RXDID_2_FLEX_SPLITQ_M);1338 }1339 } else {1340 if (!(rx_desc_ids & VIRTCHNL2_RXDID_2_FLEX_SQ_NIC_M))1341 vport->base_rxd = true;1342 }1343 1344 if (!idpf_is_queue_model_split(vport->txq_model))1345 return 0;1346 1347 if ((tx_desc_ids & MIN_SUPPORT_TXDID) != MIN_SUPPORT_TXDID) {1348 dev_info(&adapter->pdev->dev, "Minimum TX descriptor support not provided, using the default\n");1349 vport_msg->tx_desc_ids = cpu_to_le64(MIN_SUPPORT_TXDID);1350 }1351 1352 return 0;1353}1354 1355/**1356 * idpf_send_destroy_vport_msg - Send virtchnl destroy vport message1357 * @vport: virtual port data structure1358 *1359 * Send virtchnl destroy vport message. Returns 0 on success, negative on1360 * failure.1361 */1362int idpf_send_destroy_vport_msg(struct idpf_vport *vport)1363{1364 struct idpf_vc_xn_params xn_params = {};1365 struct virtchnl2_vport v_id;1366 ssize_t reply_sz;1367 1368 v_id.vport_id = cpu_to_le32(vport->vport_id);1369 1370 xn_params.vc_op = VIRTCHNL2_OP_DESTROY_VPORT;1371 xn_params.send_buf.iov_base = &v_id;1372 xn_params.send_buf.iov_len = sizeof(v_id);1373 xn_params.timeout_ms = IDPF_VC_XN_MIN_TIMEOUT_MSEC;1374 reply_sz = idpf_vc_xn_exec(vport->adapter, &xn_params);1375 1376 return reply_sz < 0 ? reply_sz : 0;1377}1378 1379/**1380 * idpf_send_enable_vport_msg - Send virtchnl enable vport message1381 * @vport: virtual port data structure1382 *1383 * Send enable vport virtchnl message. Returns 0 on success, negative on1384 * failure.1385 */1386int idpf_send_enable_vport_msg(struct idpf_vport *vport)1387{1388 struct idpf_vc_xn_params xn_params = {};1389 struct virtchnl2_vport v_id;1390 ssize_t reply_sz;1391 1392 v_id.vport_id = cpu_to_le32(vport->vport_id);1393 1394 xn_params.vc_op = VIRTCHNL2_OP_ENABLE_VPORT;1395 xn_params.send_buf.iov_base = &v_id;1396 xn_params.send_buf.iov_len = sizeof(v_id);1397 xn_params.timeout_ms = IDPF_VC_XN_DEFAULT_TIMEOUT_MSEC;1398 reply_sz = idpf_vc_xn_exec(vport->adapter, &xn_params);1399 1400 return reply_sz < 0 ? reply_sz : 0;1401}1402 1403/**1404 * idpf_send_disable_vport_msg - Send virtchnl disable vport message1405 * @vport: virtual port data structure1406 *1407 * Send disable vport virtchnl message. Returns 0 on success, negative on1408 * failure.1409 */1410int idpf_send_disable_vport_msg(struct idpf_vport *vport)1411{1412 struct idpf_vc_xn_params xn_params = {};1413 struct virtchnl2_vport v_id;1414 ssize_t reply_sz;1415 1416 v_id.vport_id = cpu_to_le32(vport->vport_id);1417 1418 xn_params.vc_op = VIRTCHNL2_OP_DISABLE_VPORT;1419 xn_params.send_buf.iov_base = &v_id;1420 xn_params.send_buf.iov_len = sizeof(v_id);1421 xn_params.timeout_ms = IDPF_VC_XN_MIN_TIMEOUT_MSEC;1422 reply_sz = idpf_vc_xn_exec(vport->adapter, &xn_params);1423 1424 return reply_sz < 0 ? reply_sz : 0;1425}1426 1427/**1428 * idpf_send_config_tx_queues_msg - Send virtchnl config tx queues message1429 * @vport: virtual port data structure1430 *1431 * Send config tx queues virtchnl message. Returns 0 on success, negative on1432 * failure.1433 */1434static int idpf_send_config_tx_queues_msg(struct idpf_vport *vport)1435{1436 struct virtchnl2_config_tx_queues *ctq __free(kfree) = NULL;1437 struct virtchnl2_txq_info *qi __free(kfree) = NULL;1438 struct idpf_vc_xn_params xn_params = {};1439 u32 config_sz, chunk_sz, buf_sz;1440 int totqs, num_msgs, num_chunks;1441 ssize_t reply_sz;1442 int i, k = 0;1443 1444 totqs = vport->num_txq + vport->num_complq;1445 qi = kcalloc(totqs, sizeof(struct virtchnl2_txq_info), GFP_KERNEL);1446 if (!qi)1447 return -ENOMEM;1448 1449 /* Populate the queue info buffer with all queue context info */1450 for (i = 0; i < vport->num_txq_grp; i++) {1451 struct idpf_txq_group *tx_qgrp = &vport->txq_grps[i];1452 int j, sched_mode;1453 1454 for (j = 0; j < tx_qgrp->num_txq; j++, k++) {1455 qi[k].queue_id =1456 cpu_to_le32(tx_qgrp->txqs[j]->q_id);1457 qi[k].model =1458 cpu_to_le16(vport->txq_model);1459 qi[k].type =1460 cpu_to_le32(VIRTCHNL2_QUEUE_TYPE_TX);1461 qi[k].ring_len =1462 cpu_to_le16(tx_qgrp->txqs[j]->desc_count);1463 qi[k].dma_ring_addr =1464 cpu_to_le64(tx_qgrp->txqs[j]->dma);1465 if (idpf_is_queue_model_split(vport->txq_model)) {1466 struct idpf_tx_queue *q = tx_qgrp->txqs[j];1467 1468 qi[k].tx_compl_queue_id =1469 cpu_to_le16(tx_qgrp->complq->q_id);1470 qi[k].relative_queue_id = cpu_to_le16(j);1471 1472 if (idpf_queue_has(FLOW_SCH_EN, q))1473 qi[k].sched_mode =1474 cpu_to_le16(VIRTCHNL2_TXQ_SCHED_MODE_FLOW);1475 else1476 qi[k].sched_mode =1477 cpu_to_le16(VIRTCHNL2_TXQ_SCHED_MODE_QUEUE);1478 } else {1479 qi[k].sched_mode =1480 cpu_to_le16(VIRTCHNL2_TXQ_SCHED_MODE_QUEUE);1481 }1482 }1483 1484 if (!idpf_is_queue_model_split(vport->txq_model))1485 continue;1486 1487 qi[k].queue_id = cpu_to_le32(tx_qgrp->complq->q_id);1488 qi[k].model = cpu_to_le16(vport->txq_model);1489 qi[k].type = cpu_to_le32(VIRTCHNL2_QUEUE_TYPE_TX_COMPLETION);1490 qi[k].ring_len = cpu_to_le16(tx_qgrp->complq->desc_count);1491 qi[k].dma_ring_addr = cpu_to_le64(tx_qgrp->complq->dma);1492 1493 if (idpf_queue_has(FLOW_SCH_EN, tx_qgrp->complq))1494 sched_mode = VIRTCHNL2_TXQ_SCHED_MODE_FLOW;1495 else1496 sched_mode = VIRTCHNL2_TXQ_SCHED_MODE_QUEUE;1497 qi[k].sched_mode = cpu_to_le16(sched_mode);1498 1499 k++;1500 }1501 1502 /* Make sure accounting agrees */1503 if (k != totqs)1504 return -EINVAL;1505 1506 /* Chunk up the queue contexts into multiple messages to avoid1507 * sending a control queue message buffer that is too large1508 */1509 config_sz = sizeof(struct virtchnl2_config_tx_queues);1510 chunk_sz = sizeof(struct virtchnl2_txq_info);1511 1512 num_chunks = min_t(u32, IDPF_NUM_CHUNKS_PER_MSG(config_sz, chunk_sz),1513 totqs);1514 num_msgs = DIV_ROUND_UP(totqs, num_chunks);1515 1516 buf_sz = struct_size(ctq, qinfo, num_chunks);1517 ctq = kzalloc(buf_sz, GFP_KERNEL);1518 if (!ctq)1519 return -ENOMEM;1520 1521 xn_params.vc_op = VIRTCHNL2_OP_CONFIG_TX_QUEUES;1522 xn_params.timeout_ms = IDPF_VC_XN_DEFAULT_TIMEOUT_MSEC;1523 1524 for (i = 0, k = 0; i < num_msgs; i++) {1525 memset(ctq, 0, buf_sz);1526 ctq->vport_id = cpu_to_le32(vport->vport_id);1527 ctq->num_qinfo = cpu_to_le16(num_chunks);1528 memcpy(ctq->qinfo, &qi[k], chunk_sz * num_chunks);1529 1530 xn_params.send_buf.iov_base = ctq;1531 xn_params.send_buf.iov_len = buf_sz;1532 reply_sz = idpf_vc_xn_exec(vport->adapter, &xn_params);1533 if (reply_sz < 0)1534 return reply_sz;1535 1536 k += num_chunks;1537 totqs -= num_chunks;1538 num_chunks = min(num_chunks, totqs);1539 /* Recalculate buffer size */1540 buf_sz = struct_size(ctq, qinfo, num_chunks);1541 }1542 1543 return 0;1544}1545 1546/**1547 * idpf_send_config_rx_queues_msg - Send virtchnl config rx queues message1548 * @vport: virtual port data structure1549 *1550 * Send config rx queues virtchnl message. Returns 0 on success, negative on1551 * failure.1552 */1553static int idpf_send_config_rx_queues_msg(struct idpf_vport *vport)1554{1555 struct virtchnl2_config_rx_queues *crq __free(kfree) = NULL;1556 struct virtchnl2_rxq_info *qi __free(kfree) = NULL;1557 struct idpf_vc_xn_params xn_params = {};1558 u32 config_sz, chunk_sz, buf_sz;1559 int totqs, num_msgs, num_chunks;1560 ssize_t reply_sz;1561 int i, k = 0;1562 1563 totqs = vport->num_rxq + vport->num_bufq;1564 qi = kcalloc(totqs, sizeof(struct virtchnl2_rxq_info), GFP_KERNEL);1565 if (!qi)1566 return -ENOMEM;1567 1568 /* Populate the queue info buffer with all queue context info */1569 for (i = 0; i < vport->num_rxq_grp; i++) {1570 struct idpf_rxq_group *rx_qgrp = &vport->rxq_grps[i];1571 u16 num_rxq;1572 int j;1573 1574 if (!idpf_is_queue_model_split(vport->rxq_model))1575 goto setup_rxqs;1576 1577 for (j = 0; j < vport->num_bufqs_per_qgrp; j++, k++) {1578 struct idpf_buf_queue *bufq =1579 &rx_qgrp->splitq.bufq_sets[j].bufq;1580 1581 qi[k].queue_id = cpu_to_le32(bufq->q_id);1582 qi[k].model = cpu_to_le16(vport->rxq_model);1583 qi[k].type =1584 cpu_to_le32(VIRTCHNL2_QUEUE_TYPE_RX_BUFFER);1585 qi[k].desc_ids = cpu_to_le64(VIRTCHNL2_RXDID_2_FLEX_SPLITQ_M);1586 qi[k].ring_len = cpu_to_le16(bufq->desc_count);1587 qi[k].dma_ring_addr = cpu_to_le64(bufq->dma);1588 qi[k].data_buffer_size = cpu_to_le32(bufq->rx_buf_size);1589 qi[k].buffer_notif_stride = IDPF_RX_BUF_STRIDE;1590 qi[k].rx_buffer_low_watermark =1591 cpu_to_le16(bufq->rx_buffer_low_watermark);1592 if (idpf_is_feature_ena(vport, NETIF_F_GRO_HW))1593 qi[k].qflags |= cpu_to_le16(VIRTCHNL2_RXQ_RSC);1594 }1595 1596setup_rxqs:1597 if (idpf_is_queue_model_split(vport->rxq_model))1598 num_rxq = rx_qgrp->splitq.num_rxq_sets;1599 else1600 num_rxq = rx_qgrp->singleq.num_rxq;1601 1602 for (j = 0; j < num_rxq; j++, k++) {1603 const struct idpf_bufq_set *sets;1604 struct idpf_rx_queue *rxq;1605 1606 if (!idpf_is_queue_model_split(vport->rxq_model)) {1607 rxq = rx_qgrp->singleq.rxqs[j];1608 goto common_qi_fields;1609 }1610 1611 rxq = &rx_qgrp->splitq.rxq_sets[j]->rxq;1612 sets = rxq->bufq_sets;1613 1614 /* In splitq mode, RXQ buffer size should be1615 * set to that of the first buffer queue1616 * associated with this RXQ.1617 */1618 rxq->rx_buf_size = sets[0].bufq.rx_buf_size;1619 1620 qi[k].rx_bufq1_id = cpu_to_le16(sets[0].bufq.q_id);1621 if (vport->num_bufqs_per_qgrp > IDPF_SINGLE_BUFQ_PER_RXQ_GRP) {1622 qi[k].bufq2_ena = IDPF_BUFQ2_ENA;1623 qi[k].rx_bufq2_id =1624 cpu_to_le16(sets[1].bufq.q_id);1625 }1626 qi[k].rx_buffer_low_watermark =1627 cpu_to_le16(rxq->rx_buffer_low_watermark);1628 if (idpf_is_feature_ena(vport, NETIF_F_GRO_HW))1629 qi[k].qflags |= cpu_to_le16(VIRTCHNL2_RXQ_RSC);1630 1631 rxq->rx_hbuf_size = sets[0].bufq.rx_hbuf_size;1632 1633 if (idpf_queue_has(HSPLIT_EN, rxq)) {1634 qi[k].qflags |=1635 cpu_to_le16(VIRTCHNL2_RXQ_HDR_SPLIT);1636 qi[k].hdr_buffer_size =1637 cpu_to_le16(rxq->rx_hbuf_size);1638 }1639 1640common_qi_fields:1641 qi[k].queue_id = cpu_to_le32(rxq->q_id);1642 qi[k].model = cpu_to_le16(vport->rxq_model);1643 qi[k].type = cpu_to_le32(VIRTCHNL2_QUEUE_TYPE_RX);1644 qi[k].ring_len = cpu_to_le16(rxq->desc_count);1645 qi[k].dma_ring_addr = cpu_to_le64(rxq->dma);1646 qi[k].max_pkt_size = cpu_to_le32(rxq->rx_max_pkt_size);1647 qi[k].data_buffer_size = cpu_to_le32(rxq->rx_buf_size);1648 qi[k].qflags |=1649 cpu_to_le16(VIRTCHNL2_RX_DESC_SIZE_32BYTE);1650 qi[k].desc_ids = cpu_to_le64(rxq->rxdids);1651 }1652 }1653 1654 /* Make sure accounting agrees */1655 if (k != totqs)1656 return -EINVAL;1657 1658 /* Chunk up the queue contexts into multiple messages to avoid1659 * sending a control queue message buffer that is too large1660 */1661 config_sz = sizeof(struct virtchnl2_config_rx_queues);1662 chunk_sz = sizeof(struct virtchnl2_rxq_info);1663 1664 num_chunks = min_t(u32, IDPF_NUM_CHUNKS_PER_MSG(config_sz, chunk_sz),1665 totqs);1666 num_msgs = DIV_ROUND_UP(totqs, num_chunks);1667 1668 buf_sz = struct_size(crq, qinfo, num_chunks);1669 crq = kzalloc(buf_sz, GFP_KERNEL);1670 if (!crq)1671 return -ENOMEM;1672 1673 xn_params.vc_op = VIRTCHNL2_OP_CONFIG_RX_QUEUES;1674 xn_params.timeout_ms = IDPF_VC_XN_DEFAULT_TIMEOUT_MSEC;1675 1676 for (i = 0, k = 0; i < num_msgs; i++) {1677 memset(crq, 0, buf_sz);1678 crq->vport_id = cpu_to_le32(vport->vport_id);1679 crq->num_qinfo = cpu_to_le16(num_chunks);1680 memcpy(crq->qinfo, &qi[k], chunk_sz * num_chunks);1681 1682 xn_params.send_buf.iov_base = crq;1683 xn_params.send_buf.iov_len = buf_sz;1684 reply_sz = idpf_vc_xn_exec(vport->adapter, &xn_params);1685 if (reply_sz < 0)1686 return reply_sz;1687 1688 k += num_chunks;1689 totqs -= num_chunks;1690 num_chunks = min(num_chunks, totqs);1691 /* Recalculate buffer size */1692 buf_sz = struct_size(crq, qinfo, num_chunks);1693 }1694 1695 return 0;1696}1697 1698/**1699 * idpf_send_ena_dis_queues_msg - Send virtchnl enable or disable1700 * queues message1701 * @vport: virtual port data structure1702 * @ena: if true enable, false disable1703 *1704 * Send enable or disable queues virtchnl message. Returns 0 on success,1705 * negative on failure.1706 */1707static int idpf_send_ena_dis_queues_msg(struct idpf_vport *vport, bool ena)1708{1709 struct virtchnl2_del_ena_dis_queues *eq __free(kfree) = NULL;1710 struct virtchnl2_queue_chunk *qc __free(kfree) = NULL;1711 u32 num_msgs, num_chunks, num_txq, num_rxq, num_q;1712 struct idpf_vc_xn_params xn_params = {};1713 struct virtchnl2_queue_chunks *qcs;1714 u32 config_sz, chunk_sz, buf_sz;1715 ssize_t reply_sz;1716 int i, j, k = 0;1717 1718 num_txq = vport->num_txq + vport->num_complq;1719 num_rxq = vport->num_rxq + vport->num_bufq;1720 num_q = num_txq + num_rxq;1721 buf_sz = sizeof(struct virtchnl2_queue_chunk) * num_q;1722 qc = kzalloc(buf_sz, GFP_KERNEL);1723 if (!qc)1724 return -ENOMEM;1725 1726 for (i = 0; i < vport->num_txq_grp; i++) {1727 struct idpf_txq_group *tx_qgrp = &vport->txq_grps[i];1728 1729 for (j = 0; j < tx_qgrp->num_txq; j++, k++) {1730 qc[k].type = cpu_to_le32(VIRTCHNL2_QUEUE_TYPE_TX);1731 qc[k].start_queue_id = cpu_to_le32(tx_qgrp->txqs[j]->q_id);1732 qc[k].num_queues = cpu_to_le32(IDPF_NUMQ_PER_CHUNK);1733 }1734 }1735 if (vport->num_txq != k)1736 return -EINVAL;1737 1738 if (!idpf_is_queue_model_split(vport->txq_model))1739 goto setup_rx;1740 1741 for (i = 0; i < vport->num_txq_grp; i++, k++) {1742 struct idpf_txq_group *tx_qgrp = &vport->txq_grps[i];1743 1744 qc[k].type = cpu_to_le32(VIRTCHNL2_QUEUE_TYPE_TX_COMPLETION);1745 qc[k].start_queue_id = cpu_to_le32(tx_qgrp->complq->q_id);1746 qc[k].num_queues = cpu_to_le32(IDPF_NUMQ_PER_CHUNK);1747 }1748 if (vport->num_complq != (k - vport->num_txq))1749 return -EINVAL;1750 1751setup_rx:1752 for (i = 0; i < vport->num_rxq_grp; i++) {1753 struct idpf_rxq_group *rx_qgrp = &vport->rxq_grps[i];1754 1755 if (idpf_is_queue_model_split(vport->rxq_model))1756 num_rxq = rx_qgrp->splitq.num_rxq_sets;1757 else1758 num_rxq = rx_qgrp->singleq.num_rxq;1759 1760 for (j = 0; j < num_rxq; j++, k++) {1761 if (idpf_is_queue_model_split(vport->rxq_model)) {1762 qc[k].start_queue_id =1763 cpu_to_le32(rx_qgrp->splitq.rxq_sets[j]->rxq.q_id);1764 qc[k].type =1765 cpu_to_le32(VIRTCHNL2_QUEUE_TYPE_RX);1766 } else {1767 qc[k].start_queue_id =1768 cpu_to_le32(rx_qgrp->singleq.rxqs[j]->q_id);1769 qc[k].type =1770 cpu_to_le32(VIRTCHNL2_QUEUE_TYPE_RX);1771 }1772 qc[k].num_queues = cpu_to_le32(IDPF_NUMQ_PER_CHUNK);1773 }1774 }1775 if (vport->num_rxq != k - (vport->num_txq + vport->num_complq))1776 return -EINVAL;1777 1778 if (!idpf_is_queue_model_split(vport->rxq_model))1779 goto send_msg;1780 1781 for (i = 0; i < vport->num_rxq_grp; i++) {1782 struct idpf_rxq_group *rx_qgrp = &vport->rxq_grps[i];1783 1784 for (j = 0; j < vport->num_bufqs_per_qgrp; j++, k++) {1785 const struct idpf_buf_queue *q;1786 1787 q = &rx_qgrp->splitq.bufq_sets[j].bufq;1788 qc[k].type =1789 cpu_to_le32(VIRTCHNL2_QUEUE_TYPE_RX_BUFFER);1790 qc[k].start_queue_id = cpu_to_le32(q->q_id);1791 qc[k].num_queues = cpu_to_le32(IDPF_NUMQ_PER_CHUNK);1792 }1793 }1794 if (vport->num_bufq != k - (vport->num_txq +1795 vport->num_complq +1796 vport->num_rxq))1797 return -EINVAL;1798 1799send_msg:1800 /* Chunk up the queue info into multiple messages */1801 config_sz = sizeof(struct virtchnl2_del_ena_dis_queues);1802 chunk_sz = sizeof(struct virtchnl2_queue_chunk);1803 1804 num_chunks = min_t(u32, IDPF_NUM_CHUNKS_PER_MSG(config_sz, chunk_sz),1805 num_q);1806 num_msgs = DIV_ROUND_UP(num_q, num_chunks);1807 1808 buf_sz = struct_size(eq, chunks.chunks, num_chunks);1809 eq = kzalloc(buf_sz, GFP_KERNEL);1810 if (!eq)1811 return -ENOMEM;1812 1813 if (ena) {1814 xn_params.vc_op = VIRTCHNL2_OP_ENABLE_QUEUES;1815 xn_params.timeout_ms = IDPF_VC_XN_DEFAULT_TIMEOUT_MSEC;1816 } else {1817 xn_params.vc_op = VIRTCHNL2_OP_DISABLE_QUEUES;1818 xn_params.timeout_ms = IDPF_VC_XN_MIN_TIMEOUT_MSEC;1819 }1820 1821 for (i = 0, k = 0; i < num_msgs; i++) {1822 memset(eq, 0, buf_sz);1823 eq->vport_id = cpu_to_le32(vport->vport_id);1824 eq->chunks.num_chunks = cpu_to_le16(num_chunks);1825 qcs = &eq->chunks;1826 memcpy(qcs->chunks, &qc[k], chunk_sz * num_chunks);1827 1828 xn_params.send_buf.iov_base = eq;1829 xn_params.send_buf.iov_len = buf_sz;1830 reply_sz = idpf_vc_xn_exec(vport->adapter, &xn_params);1831 if (reply_sz < 0)1832 return reply_sz;1833 1834 k += num_chunks;1835 num_q -= num_chunks;1836 num_chunks = min(num_chunks, num_q);1837 /* Recalculate buffer size */1838 buf_sz = struct_size(eq, chunks.chunks, num_chunks);1839 }1840 1841 return 0;1842}1843 1844/**1845 * idpf_send_map_unmap_queue_vector_msg - Send virtchnl map or unmap queue1846 * vector message1847 * @vport: virtual port data structure1848 * @map: true for map and false for unmap1849 *1850 * Send map or unmap queue vector virtchnl message. Returns 0 on success,1851 * negative on failure.1852 */1853int idpf_send_map_unmap_queue_vector_msg(struct idpf_vport *vport, bool map)1854{1855 struct virtchnl2_queue_vector_maps *vqvm __free(kfree) = NULL;1856 struct virtchnl2_queue_vector *vqv __free(kfree) = NULL;1857 struct idpf_vc_xn_params xn_params = {};1858 u32 config_sz, chunk_sz, buf_sz;1859 u32 num_msgs, num_chunks, num_q;1860 ssize_t reply_sz;1861 int i, j, k = 0;1862 1863 num_q = vport->num_txq + vport->num_rxq;1864 1865 buf_sz = sizeof(struct virtchnl2_queue_vector) * num_q;1866 vqv = kzalloc(buf_sz, GFP_KERNEL);1867 if (!vqv)1868 return -ENOMEM;1869 1870 for (i = 0; i < vport->num_txq_grp; i++) {1871 struct idpf_txq_group *tx_qgrp = &vport->txq_grps[i];1872 1873 for (j = 0; j < tx_qgrp->num_txq; j++, k++) {1874 vqv[k].queue_type =1875 cpu_to_le32(VIRTCHNL2_QUEUE_TYPE_TX);1876 vqv[k].queue_id = cpu_to_le32(tx_qgrp->txqs[j]->q_id);1877 1878 if (idpf_is_queue_model_split(vport->txq_model)) {1879 vqv[k].vector_id =1880 cpu_to_le16(tx_qgrp->complq->q_vector->v_idx);1881 vqv[k].itr_idx =1882 cpu_to_le32(tx_qgrp->complq->q_vector->tx_itr_idx);1883 } else {1884 vqv[k].vector_id =1885 cpu_to_le16(tx_qgrp->txqs[j]->q_vector->v_idx);1886 vqv[k].itr_idx =1887 cpu_to_le32(tx_qgrp->txqs[j]->q_vector->tx_itr_idx);1888 }1889 }1890 }1891 1892 if (vport->num_txq != k)1893 return -EINVAL;1894 1895 for (i = 0; i < vport->num_rxq_grp; i++) {1896 struct idpf_rxq_group *rx_qgrp = &vport->rxq_grps[i];1897 u16 num_rxq;1898 1899 if (idpf_is_queue_model_split(vport->rxq_model))1900 num_rxq = rx_qgrp->splitq.num_rxq_sets;1901 else1902 num_rxq = rx_qgrp->singleq.num_rxq;1903 1904 for (j = 0; j < num_rxq; j++, k++) {1905 struct idpf_rx_queue *rxq;1906 1907 if (idpf_is_queue_model_split(vport->rxq_model))1908 rxq = &rx_qgrp->splitq.rxq_sets[j]->rxq;1909 else1910 rxq = rx_qgrp->singleq.rxqs[j];1911 1912 vqv[k].queue_type =1913 cpu_to_le32(VIRTCHNL2_QUEUE_TYPE_RX);1914 vqv[k].queue_id = cpu_to_le32(rxq->q_id);1915 vqv[k].vector_id = cpu_to_le16(rxq->q_vector->v_idx);1916 vqv[k].itr_idx = cpu_to_le32(rxq->q_vector->rx_itr_idx);1917 }1918 }1919 1920 if (idpf_is_queue_model_split(vport->txq_model)) {1921 if (vport->num_rxq != k - vport->num_complq)1922 return -EINVAL;1923 } else {1924 if (vport->num_rxq != k - vport->num_txq)1925 return -EINVAL;1926 }1927 1928 /* Chunk up the vector info into multiple messages */1929 config_sz = sizeof(struct virtchnl2_queue_vector_maps);1930 chunk_sz = sizeof(struct virtchnl2_queue_vector);1931 1932 num_chunks = min_t(u32, IDPF_NUM_CHUNKS_PER_MSG(config_sz, chunk_sz),1933 num_q);1934 num_msgs = DIV_ROUND_UP(num_q, num_chunks);1935 1936 buf_sz = struct_size(vqvm, qv_maps, num_chunks);1937 vqvm = kzalloc(buf_sz, GFP_KERNEL);1938 if (!vqvm)1939 return -ENOMEM;1940 1941 if (map) {1942 xn_params.vc_op = VIRTCHNL2_OP_MAP_QUEUE_VECTOR;1943 xn_params.timeout_ms = IDPF_VC_XN_DEFAULT_TIMEOUT_MSEC;1944 } else {1945 xn_params.vc_op = VIRTCHNL2_OP_UNMAP_QUEUE_VECTOR;1946 xn_params.timeout_ms = IDPF_VC_XN_MIN_TIMEOUT_MSEC;1947 }1948 1949 for (i = 0, k = 0; i < num_msgs; i++) {1950 memset(vqvm, 0, buf_sz);1951 xn_params.send_buf.iov_base = vqvm;1952 xn_params.send_buf.iov_len = buf_sz;1953 vqvm->vport_id = cpu_to_le32(vport->vport_id);1954 vqvm->num_qv_maps = cpu_to_le16(num_chunks);1955 memcpy(vqvm->qv_maps, &vqv[k], chunk_sz * num_chunks);1956 1957 reply_sz = idpf_vc_xn_exec(vport->adapter, &xn_params);1958 if (reply_sz < 0)1959 return reply_sz;1960 1961 k += num_chunks;1962 num_q -= num_chunks;1963 num_chunks = min(num_chunks, num_q);1964 /* Recalculate buffer size */1965 buf_sz = struct_size(vqvm, qv_maps, num_chunks);1966 }1967 1968 return 0;1969}1970 1971/**1972 * idpf_send_enable_queues_msg - send enable queues virtchnl message1973 * @vport: Virtual port private data structure1974 *1975 * Will send enable queues virtchnl message. Returns 0 on success, negative on1976 * failure.1977 */1978int idpf_send_enable_queues_msg(struct idpf_vport *vport)1979{1980 return idpf_send_ena_dis_queues_msg(vport, true);1981}1982 1983/**1984 * idpf_send_disable_queues_msg - send disable queues virtchnl message1985 * @vport: Virtual port private data structure1986 *1987 * Will send disable queues virtchnl message. Returns 0 on success, negative1988 * on failure.1989 */1990int idpf_send_disable_queues_msg(struct idpf_vport *vport)1991{1992 int err, i;1993 1994 err = idpf_send_ena_dis_queues_msg(vport, false);1995 if (err)1996 return err;1997 1998 /* switch to poll mode as interrupts will be disabled after disable1999 * queues virtchnl message is sent2000 */2001 for (i = 0; i < vport->num_txq; i++)2002 idpf_queue_set(POLL_MODE, vport->txqs[i]);2003 2004 /* schedule the napi to receive all the marker packets */2005 local_bh_disable();2006 for (i = 0; i < vport->num_q_vectors; i++)2007 napi_schedule(&vport->q_vectors[i].napi);2008 local_bh_enable();2009 2010 return idpf_wait_for_marker_event(vport);2011}2012 2013/**2014 * idpf_convert_reg_to_queue_chunks - Copy queue chunk information to the right2015 * structure2016 * @dchunks: Destination chunks to store data to2017 * @schunks: Source chunks to copy data from2018 * @num_chunks: number of chunks to copy2019 */2020static void idpf_convert_reg_to_queue_chunks(struct virtchnl2_queue_chunk *dchunks,2021 struct virtchnl2_queue_reg_chunk *schunks,2022 u16 num_chunks)2023{2024 u16 i;2025 2026 for (i = 0; i < num_chunks; i++) {2027 dchunks[i].type = schunks[i].type;2028 dchunks[i].start_queue_id = schunks[i].start_queue_id;2029 dchunks[i].num_queues = schunks[i].num_queues;2030 }2031}2032 2033/**2034 * idpf_send_delete_queues_msg - send delete queues virtchnl message2035 * @vport: Virtual port private data structure2036 *2037 * Will send delete queues virtchnl message. Return 0 on success, negative on2038 * failure.2039 */2040int idpf_send_delete_queues_msg(struct idpf_vport *vport)2041{2042 struct virtchnl2_del_ena_dis_queues *eq __free(kfree) = NULL;2043 struct virtchnl2_create_vport *vport_params;2044 struct virtchnl2_queue_reg_chunks *chunks;2045 struct idpf_vc_xn_params xn_params = {};2046 struct idpf_vport_config *vport_config;2047 u16 vport_idx = vport->idx;2048 ssize_t reply_sz;2049 u16 num_chunks;2050 int buf_size;2051 2052 vport_config = vport->adapter->vport_config[vport_idx];2053 if (vport_config->req_qs_chunks) {2054 chunks = &vport_config->req_qs_chunks->chunks;2055 } else {2056 vport_params = vport->adapter->vport_params_recvd[vport_idx];2057 chunks = &vport_params->chunks;2058 }2059 2060 num_chunks = le16_to_cpu(chunks->num_chunks);2061 buf_size = struct_size(eq, chunks.chunks, num_chunks);2062 2063 eq = kzalloc(buf_size, GFP_KERNEL);2064 if (!eq)2065 return -ENOMEM;2066 2067 eq->vport_id = cpu_to_le32(vport->vport_id);2068 eq->chunks.num_chunks = cpu_to_le16(num_chunks);2069 2070 idpf_convert_reg_to_queue_chunks(eq->chunks.chunks, chunks->chunks,2071 num_chunks);2072 2073 xn_params.vc_op = VIRTCHNL2_OP_DEL_QUEUES;2074 xn_params.timeout_ms = IDPF_VC_XN_MIN_TIMEOUT_MSEC;2075 xn_params.send_buf.iov_base = eq;2076 xn_params.send_buf.iov_len = buf_size;2077 reply_sz = idpf_vc_xn_exec(vport->adapter, &xn_params);2078 2079 return reply_sz < 0 ? reply_sz : 0;2080}2081 2082/**2083 * idpf_send_config_queues_msg - Send config queues virtchnl message2084 * @vport: Virtual port private data structure2085 *2086 * Will send config queues virtchnl message. Returns 0 on success, negative on2087 * failure.2088 */2089int idpf_send_config_queues_msg(struct idpf_vport *vport)2090{2091 int err;2092 2093 err = idpf_send_config_tx_queues_msg(vport);2094 if (err)2095 return err;2096 2097 return idpf_send_config_rx_queues_msg(vport);2098}2099 2100/**2101 * idpf_send_add_queues_msg - Send virtchnl add queues message2102 * @vport: Virtual port private data structure2103 * @num_tx_q: number of transmit queues2104 * @num_complq: number of transmit completion queues2105 * @num_rx_q: number of receive queues2106 * @num_rx_bufq: number of receive buffer queues2107 *2108 * Returns 0 on success, negative on failure. vport _MUST_ be const here as2109 * we should not change any fields within vport itself in this function.2110 */2111int idpf_send_add_queues_msg(const struct idpf_vport *vport, u16 num_tx_q,2112 u16 num_complq, u16 num_rx_q, u16 num_rx_bufq)2113{2114 struct virtchnl2_add_queues *vc_msg __free(kfree) = NULL;2115 struct idpf_vc_xn_params xn_params = {};2116 struct idpf_vport_config *vport_config;2117 struct virtchnl2_add_queues aq = {};2118 u16 vport_idx = vport->idx;2119 ssize_t reply_sz;2120 int size;2121 2122 vc_msg = kzalloc(IDPF_CTLQ_MAX_BUF_LEN, GFP_KERNEL);2123 if (!vc_msg)2124 return -ENOMEM;2125 2126 vport_config = vport->adapter->vport_config[vport_idx];2127 kfree(vport_config->req_qs_chunks);2128 vport_config->req_qs_chunks = NULL;2129 2130 aq.vport_id = cpu_to_le32(vport->vport_id);2131 aq.num_tx_q = cpu_to_le16(num_tx_q);2132 aq.num_tx_complq = cpu_to_le16(num_complq);2133 aq.num_rx_q = cpu_to_le16(num_rx_q);2134 aq.num_rx_bufq = cpu_to_le16(num_rx_bufq);2135 2136 xn_params.vc_op = VIRTCHNL2_OP_ADD_QUEUES;2137 xn_params.timeout_ms = IDPF_VC_XN_DEFAULT_TIMEOUT_MSEC;2138 xn_params.send_buf.iov_base = &aq;2139 xn_params.send_buf.iov_len = sizeof(aq);2140 xn_params.recv_buf.iov_base = vc_msg;2141 xn_params.recv_buf.iov_len = IDPF_CTLQ_MAX_BUF_LEN;2142 reply_sz = idpf_vc_xn_exec(vport->adapter, &xn_params);2143 if (reply_sz < 0)2144 return reply_sz;2145 2146 /* compare vc_msg num queues with vport num queues */2147 if (le16_to_cpu(vc_msg->num_tx_q) != num_tx_q ||2148 le16_to_cpu(vc_msg->num_rx_q) != num_rx_q ||2149 le16_to_cpu(vc_msg->num_tx_complq) != num_complq ||2150 le16_to_cpu(vc_msg->num_rx_bufq) != num_rx_bufq)2151 return -EINVAL;2152 2153 size = struct_size(vc_msg, chunks.chunks,2154 le16_to_cpu(vc_msg->chunks.num_chunks));2155 if (reply_sz < size)2156 return -EIO;2157 2158 vport_config->req_qs_chunks = kmemdup(vc_msg, size, GFP_KERNEL);2159 if (!vport_config->req_qs_chunks)2160 return -ENOMEM;2161 2162 return 0;2163}2164 2165/**2166 * idpf_send_alloc_vectors_msg - Send virtchnl alloc vectors message2167 * @adapter: Driver specific private structure2168 * @num_vectors: number of vectors to be allocated2169 *2170 * Returns 0 on success, negative on failure.2171 */2172int idpf_send_alloc_vectors_msg(struct idpf_adapter *adapter, u16 num_vectors)2173{2174 struct virtchnl2_alloc_vectors *rcvd_vec __free(kfree) = NULL;2175 struct idpf_vc_xn_params xn_params = {};2176 struct virtchnl2_alloc_vectors ac = {};2177 ssize_t reply_sz;2178 u16 num_vchunks;2179 int size;2180 2181 ac.num_vectors = cpu_to_le16(num_vectors);2182 2183 rcvd_vec = kzalloc(IDPF_CTLQ_MAX_BUF_LEN, GFP_KERNEL);2184 if (!rcvd_vec)2185 return -ENOMEM;2186 2187 xn_params.vc_op = VIRTCHNL2_OP_ALLOC_VECTORS;2188 xn_params.send_buf.iov_base = ∾2189 xn_params.send_buf.iov_len = sizeof(ac);2190 xn_params.recv_buf.iov_base = rcvd_vec;2191 xn_params.recv_buf.iov_len = IDPF_CTLQ_MAX_BUF_LEN;2192 xn_params.timeout_ms = IDPF_VC_XN_DEFAULT_TIMEOUT_MSEC;2193 reply_sz = idpf_vc_xn_exec(adapter, &xn_params);2194 if (reply_sz < 0)2195 return reply_sz;2196 2197 num_vchunks = le16_to_cpu(rcvd_vec->vchunks.num_vchunks);2198 size = struct_size(rcvd_vec, vchunks.vchunks, num_vchunks);2199 if (reply_sz < size)2200 return -EIO;2201 2202 if (size > IDPF_CTLQ_MAX_BUF_LEN)2203 return -EINVAL;2204 2205 kfree(adapter->req_vec_chunks);2206 adapter->req_vec_chunks = kmemdup(rcvd_vec, size, GFP_KERNEL);2207 if (!adapter->req_vec_chunks)2208 return -ENOMEM;2209 2210 if (le16_to_cpu(adapter->req_vec_chunks->num_vectors) < num_vectors) {2211 kfree(adapter->req_vec_chunks);2212 adapter->req_vec_chunks = NULL;2213 return -EINVAL;2214 }2215 2216 return 0;2217}2218 2219/**2220 * idpf_send_dealloc_vectors_msg - Send virtchnl de allocate vectors message2221 * @adapter: Driver specific private structure2222 *2223 * Returns 0 on success, negative on failure.2224 */2225int idpf_send_dealloc_vectors_msg(struct idpf_adapter *adapter)2226{2227 struct virtchnl2_alloc_vectors *ac = adapter->req_vec_chunks;2228 struct virtchnl2_vector_chunks *vcs = &ac->vchunks;2229 struct idpf_vc_xn_params xn_params = {};2230 ssize_t reply_sz;2231 int buf_size;2232 2233 buf_size = struct_size(vcs, vchunks, le16_to_cpu(vcs->num_vchunks));2234 2235 xn_params.vc_op = VIRTCHNL2_OP_DEALLOC_VECTORS;2236 xn_params.send_buf.iov_base = vcs;2237 xn_params.send_buf.iov_len = buf_size;2238 xn_params.timeout_ms = IDPF_VC_XN_MIN_TIMEOUT_MSEC;2239 reply_sz = idpf_vc_xn_exec(adapter, &xn_params);2240 if (reply_sz < 0)2241 return reply_sz;2242 2243 kfree(adapter->req_vec_chunks);2244 adapter->req_vec_chunks = NULL;2245 2246 return 0;2247}2248 2249/**2250 * idpf_get_max_vfs - Get max number of vfs supported2251 * @adapter: Driver specific private structure2252 *2253 * Returns max number of VFs2254 */2255static int idpf_get_max_vfs(struct idpf_adapter *adapter)2256{2257 return le16_to_cpu(adapter->caps.max_sriov_vfs);2258}2259 2260/**2261 * idpf_send_set_sriov_vfs_msg - Send virtchnl set sriov vfs message2262 * @adapter: Driver specific private structure2263 * @num_vfs: number of virtual functions to be created2264 *2265 * Returns 0 on success, negative on failure.2266 */2267int idpf_send_set_sriov_vfs_msg(struct idpf_adapter *adapter, u16 num_vfs)2268{2269 struct virtchnl2_sriov_vfs_info svi = {};2270 struct idpf_vc_xn_params xn_params = {};2271 ssize_t reply_sz;2272 2273 svi.num_vfs = cpu_to_le16(num_vfs);2274 xn_params.vc_op = VIRTCHNL2_OP_SET_SRIOV_VFS;2275 xn_params.timeout_ms = IDPF_VC_XN_DEFAULT_TIMEOUT_MSEC;2276 xn_params.send_buf.iov_base = &svi;2277 xn_params.send_buf.iov_len = sizeof(svi);2278 reply_sz = idpf_vc_xn_exec(adapter, &xn_params);2279 2280 return reply_sz < 0 ? reply_sz : 0;2281}2282 2283/**2284 * idpf_send_get_stats_msg - Send virtchnl get statistics message2285 * @vport: vport to get stats for2286 *2287 * Returns 0 on success, negative on failure.2288 */2289int idpf_send_get_stats_msg(struct idpf_vport *vport)2290{2291 struct idpf_netdev_priv *np = netdev_priv(vport->netdev);2292 struct rtnl_link_stats64 *netstats = &np->netstats;2293 struct virtchnl2_vport_stats stats_msg = {};2294 struct idpf_vc_xn_params xn_params = {};2295 ssize_t reply_sz;2296 2297 2298 /* Don't send get_stats message if the link is down */2299 if (np->state <= __IDPF_VPORT_DOWN)2300 return 0;2301 2302 stats_msg.vport_id = cpu_to_le32(vport->vport_id);2303 2304 xn_params.vc_op = VIRTCHNL2_OP_GET_STATS;2305 xn_params.send_buf.iov_base = &stats_msg;2306 xn_params.send_buf.iov_len = sizeof(stats_msg);2307 xn_params.recv_buf = xn_params.send_buf;2308 xn_params.timeout_ms = IDPF_VC_XN_DEFAULT_TIMEOUT_MSEC;2309 2310 reply_sz = idpf_vc_xn_exec(vport->adapter, &xn_params);2311 if (reply_sz < 0)2312 return reply_sz;2313 if (reply_sz < sizeof(stats_msg))2314 return -EIO;2315 2316 spin_lock_bh(&np->stats_lock);2317 2318 netstats->rx_packets = le64_to_cpu(stats_msg.rx_unicast) +2319 le64_to_cpu(stats_msg.rx_multicast) +2320 le64_to_cpu(stats_msg.rx_broadcast);2321 netstats->tx_packets = le64_to_cpu(stats_msg.tx_unicast) +2322 le64_to_cpu(stats_msg.tx_multicast) +2323 le64_to_cpu(stats_msg.tx_broadcast);2324 netstats->rx_bytes = le64_to_cpu(stats_msg.rx_bytes);2325 netstats->tx_bytes = le64_to_cpu(stats_msg.tx_bytes);2326 netstats->rx_errors = le64_to_cpu(stats_msg.rx_errors);2327 netstats->tx_errors = le64_to_cpu(stats_msg.tx_errors);2328 netstats->rx_dropped = le64_to_cpu(stats_msg.rx_discards);2329 netstats->tx_dropped = le64_to_cpu(stats_msg.tx_discards);2330 2331 vport->port_stats.vport_stats = stats_msg;2332 2333 spin_unlock_bh(&np->stats_lock);2334 2335 return 0;2336}2337 2338/**2339 * idpf_send_get_set_rss_lut_msg - Send virtchnl get or set rss lut message2340 * @vport: virtual port data structure2341 * @get: flag to set or get rss look up table2342 *2343 * Returns 0 on success, negative on failure.2344 */2345int idpf_send_get_set_rss_lut_msg(struct idpf_vport *vport, bool get)2346{2347 struct virtchnl2_rss_lut *recv_rl __free(kfree) = NULL;2348 struct virtchnl2_rss_lut *rl __free(kfree) = NULL;2349 struct idpf_vc_xn_params xn_params = {};2350 struct idpf_rss_data *rss_data;2351 int buf_size, lut_buf_size;2352 ssize_t reply_sz;2353 int i;2354 2355 rss_data =2356 &vport->adapter->vport_config[vport->idx]->user_config.rss_data;2357 buf_size = struct_size(rl, lut, rss_data->rss_lut_size);2358 rl = kzalloc(buf_size, GFP_KERNEL);2359 if (!rl)2360 return -ENOMEM;2361 2362 rl->vport_id = cpu_to_le32(vport->vport_id);2363 2364 xn_params.timeout_ms = IDPF_VC_XN_DEFAULT_TIMEOUT_MSEC;2365 xn_params.send_buf.iov_base = rl;2366 xn_params.send_buf.iov_len = buf_size;2367 2368 if (get) {2369 recv_rl = kzalloc(IDPF_CTLQ_MAX_BUF_LEN, GFP_KERNEL);2370 if (!recv_rl)2371 return -ENOMEM;2372 xn_params.vc_op = VIRTCHNL2_OP_GET_RSS_LUT;2373 xn_params.recv_buf.iov_base = recv_rl;2374 xn_params.recv_buf.iov_len = IDPF_CTLQ_MAX_BUF_LEN;2375 } else {2376 rl->lut_entries = cpu_to_le16(rss_data->rss_lut_size);2377 for (i = 0; i < rss_data->rss_lut_size; i++)2378 rl->lut[i] = cpu_to_le32(rss_data->rss_lut[i]);2379 2380 xn_params.vc_op = VIRTCHNL2_OP_SET_RSS_LUT;2381 }2382 reply_sz = idpf_vc_xn_exec(vport->adapter, &xn_params);2383 if (reply_sz < 0)2384 return reply_sz;2385 if (!get)2386 return 0;2387 if (reply_sz < sizeof(struct virtchnl2_rss_lut))2388 return -EIO;2389 2390 lut_buf_size = le16_to_cpu(recv_rl->lut_entries) * sizeof(u32);2391 if (reply_sz < lut_buf_size)2392 return -EIO;2393 2394 /* size didn't change, we can reuse existing lut buf */2395 if (rss_data->rss_lut_size == le16_to_cpu(recv_rl->lut_entries))2396 goto do_memcpy;2397 2398 rss_data->rss_lut_size = le16_to_cpu(recv_rl->lut_entries);2399 kfree(rss_data->rss_lut);2400 2401 rss_data->rss_lut = kzalloc(lut_buf_size, GFP_KERNEL);2402 if (!rss_data->rss_lut) {2403 rss_data->rss_lut_size = 0;2404 return -ENOMEM;2405 }2406 2407do_memcpy:2408 memcpy(rss_data->rss_lut, recv_rl->lut, rss_data->rss_lut_size);2409 2410 return 0;2411}2412 2413/**2414 * idpf_send_get_set_rss_key_msg - Send virtchnl get or set rss key message2415 * @vport: virtual port data structure2416 * @get: flag to set or get rss look up table2417 *2418 * Returns 0 on success, negative on failure2419 */2420int idpf_send_get_set_rss_key_msg(struct idpf_vport *vport, bool get)2421{2422 struct virtchnl2_rss_key *recv_rk __free(kfree) = NULL;2423 struct virtchnl2_rss_key *rk __free(kfree) = NULL;2424 struct idpf_vc_xn_params xn_params = {};2425 struct idpf_rss_data *rss_data;2426 ssize_t reply_sz;2427 int i, buf_size;2428 u16 key_size;2429 2430 rss_data =2431 &vport->adapter->vport_config[vport->idx]->user_config.rss_data;2432 buf_size = struct_size(rk, key_flex, rss_data->rss_key_size);2433 rk = kzalloc(buf_size, GFP_KERNEL);2434 if (!rk)2435 return -ENOMEM;2436 2437 rk->vport_id = cpu_to_le32(vport->vport_id);2438 xn_params.send_buf.iov_base = rk;2439 xn_params.send_buf.iov_len = buf_size;2440 xn_params.timeout_ms = IDPF_VC_XN_DEFAULT_TIMEOUT_MSEC;2441 if (get) {2442 recv_rk = kzalloc(IDPF_CTLQ_MAX_BUF_LEN, GFP_KERNEL);2443 if (!recv_rk)2444 return -ENOMEM;2445 2446 xn_params.vc_op = VIRTCHNL2_OP_GET_RSS_KEY;2447 xn_params.recv_buf.iov_base = recv_rk;2448 xn_params.recv_buf.iov_len = IDPF_CTLQ_MAX_BUF_LEN;2449 } else {2450 rk->key_len = cpu_to_le16(rss_data->rss_key_size);2451 for (i = 0; i < rss_data->rss_key_size; i++)2452 rk->key_flex[i] = rss_data->rss_key[i];2453 2454 xn_params.vc_op = VIRTCHNL2_OP_SET_RSS_KEY;2455 }2456 2457 reply_sz = idpf_vc_xn_exec(vport->adapter, &xn_params);2458 if (reply_sz < 0)2459 return reply_sz;2460 if (!get)2461 return 0;2462 if (reply_sz < sizeof(struct virtchnl2_rss_key))2463 return -EIO;2464 2465 key_size = min_t(u16, NETDEV_RSS_KEY_LEN,2466 le16_to_cpu(recv_rk->key_len));2467 if (reply_sz < key_size)2468 return -EIO;2469 2470 /* key len didn't change, reuse existing buf */2471 if (rss_data->rss_key_size == key_size)2472 goto do_memcpy;2473 2474 rss_data->rss_key_size = key_size;2475 kfree(rss_data->rss_key);2476 rss_data->rss_key = kzalloc(key_size, GFP_KERNEL);2477 if (!rss_data->rss_key) {2478 rss_data->rss_key_size = 0;2479 return -ENOMEM;2480 }2481 2482do_memcpy:2483 memcpy(rss_data->rss_key, recv_rk->key_flex, rss_data->rss_key_size);2484 2485 return 0;2486}2487 2488/**2489 * idpf_fill_ptype_lookup - Fill L3 specific fields in ptype lookup table2490 * @ptype: ptype lookup table2491 * @pstate: state machine for ptype lookup table2492 * @ipv4: ipv4 or ipv62493 * @frag: fragmentation allowed2494 *2495 */2496static void idpf_fill_ptype_lookup(struct libeth_rx_pt *ptype,2497 struct idpf_ptype_state *pstate,2498 bool ipv4, bool frag)2499{2500 if (!pstate->outer_ip || !pstate->outer_frag) {2501 pstate->outer_ip = true;2502 2503 if (ipv4)2504 ptype->outer_ip = LIBETH_RX_PT_OUTER_IPV4;2505 else2506 ptype->outer_ip = LIBETH_RX_PT_OUTER_IPV6;2507 2508 if (frag) {2509 ptype->outer_frag = LIBETH_RX_PT_FRAG;2510 pstate->outer_frag = true;2511 }2512 } else {2513 ptype->tunnel_type = LIBETH_RX_PT_TUNNEL_IP_IP;2514 pstate->tunnel_state = IDPF_PTYPE_TUNNEL_IP;2515 2516 if (ipv4)2517 ptype->tunnel_end_prot = LIBETH_RX_PT_TUNNEL_END_IPV4;2518 else2519 ptype->tunnel_end_prot = LIBETH_RX_PT_TUNNEL_END_IPV6;2520 2521 if (frag)2522 ptype->tunnel_end_frag = LIBETH_RX_PT_FRAG;2523 }2524}2525 2526static void idpf_finalize_ptype_lookup(struct libeth_rx_pt *ptype)2527{2528 if (ptype->payload_layer == LIBETH_RX_PT_PAYLOAD_L2 &&2529 ptype->inner_prot)2530 ptype->payload_layer = LIBETH_RX_PT_PAYLOAD_L4;2531 else if (ptype->payload_layer == LIBETH_RX_PT_PAYLOAD_L2 &&2532 ptype->outer_ip)2533 ptype->payload_layer = LIBETH_RX_PT_PAYLOAD_L3;2534 else if (ptype->outer_ip == LIBETH_RX_PT_OUTER_L2)2535 ptype->payload_layer = LIBETH_RX_PT_PAYLOAD_L2;2536 else2537 ptype->payload_layer = LIBETH_RX_PT_PAYLOAD_NONE;2538 2539 libeth_rx_pt_gen_hash_type(ptype);2540}2541 2542/**2543 * idpf_send_get_rx_ptype_msg - Send virtchnl for ptype info2544 * @vport: virtual port data structure2545 *2546 * Returns 0 on success, negative on failure.2547 */2548int idpf_send_get_rx_ptype_msg(struct idpf_vport *vport)2549{2550 struct virtchnl2_get_ptype_info *get_ptype_info __free(kfree) = NULL;2551 struct virtchnl2_get_ptype_info *ptype_info __free(kfree) = NULL;2552 struct libeth_rx_pt *ptype_lkup __free(kfree) = NULL;2553 int max_ptype, ptypes_recvd = 0, ptype_offset;2554 struct idpf_adapter *adapter = vport->adapter;2555 struct idpf_vc_xn_params xn_params = {};2556 u16 next_ptype_id = 0;2557 ssize_t reply_sz;2558 int i, j, k;2559 2560 if (vport->rx_ptype_lkup)2561 return 0;2562 2563 if (idpf_is_queue_model_split(vport->rxq_model))2564 max_ptype = IDPF_RX_MAX_PTYPE;2565 else2566 max_ptype = IDPF_RX_MAX_BASE_PTYPE;2567 2568 ptype_lkup = kcalloc(max_ptype, sizeof(*ptype_lkup), GFP_KERNEL);2569 if (!ptype_lkup)2570 return -ENOMEM;2571 2572 get_ptype_info = kzalloc(sizeof(*get_ptype_info), GFP_KERNEL);2573 if (!get_ptype_info)2574 return -ENOMEM;2575 2576 ptype_info = kzalloc(IDPF_CTLQ_MAX_BUF_LEN, GFP_KERNEL);2577 if (!ptype_info)2578 return -ENOMEM;2579 2580 xn_params.vc_op = VIRTCHNL2_OP_GET_PTYPE_INFO;2581 xn_params.send_buf.iov_base = get_ptype_info;2582 xn_params.send_buf.iov_len = sizeof(*get_ptype_info);2583 xn_params.recv_buf.iov_base = ptype_info;2584 xn_params.recv_buf.iov_len = IDPF_CTLQ_MAX_BUF_LEN;2585 xn_params.timeout_ms = IDPF_VC_XN_DEFAULT_TIMEOUT_MSEC;2586 2587 while (next_ptype_id < max_ptype) {2588 get_ptype_info->start_ptype_id = cpu_to_le16(next_ptype_id);2589 2590 if ((next_ptype_id + IDPF_RX_MAX_PTYPES_PER_BUF) > max_ptype)2591 get_ptype_info->num_ptypes =2592 cpu_to_le16(max_ptype - next_ptype_id);2593 else2594 get_ptype_info->num_ptypes =2595 cpu_to_le16(IDPF_RX_MAX_PTYPES_PER_BUF);2596 2597 reply_sz = idpf_vc_xn_exec(adapter, &xn_params);2598 if (reply_sz < 0)2599 return reply_sz;2600 2601 ptypes_recvd += le16_to_cpu(ptype_info->num_ptypes);2602 if (ptypes_recvd > max_ptype)2603 return -EINVAL;2604 2605 next_ptype_id = le16_to_cpu(get_ptype_info->start_ptype_id) +2606 le16_to_cpu(get_ptype_info->num_ptypes);2607 2608 ptype_offset = IDPF_RX_PTYPE_HDR_SZ;2609 2610 for (i = 0; i < le16_to_cpu(ptype_info->num_ptypes); i++) {2611 struct idpf_ptype_state pstate = { };2612 struct virtchnl2_ptype *ptype;2613 u16 id;2614 2615 ptype = (struct virtchnl2_ptype *)2616 ((u8 *)ptype_info + ptype_offset);2617 2618 ptype_offset += IDPF_GET_PTYPE_SIZE(ptype);2619 if (ptype_offset > IDPF_CTLQ_MAX_BUF_LEN)2620 return -EINVAL;2621 2622 /* 0xFFFF indicates end of ptypes */2623 if (le16_to_cpu(ptype->ptype_id_10) ==2624 IDPF_INVALID_PTYPE_ID)2625 goto out;2626 2627 if (idpf_is_queue_model_split(vport->rxq_model))2628 k = le16_to_cpu(ptype->ptype_id_10);2629 else2630 k = ptype->ptype_id_8;2631 2632 for (j = 0; j < ptype->proto_id_count; j++) {2633 id = le16_to_cpu(ptype->proto_id[j]);2634 switch (id) {2635 case VIRTCHNL2_PROTO_HDR_GRE:2636 if (pstate.tunnel_state ==2637 IDPF_PTYPE_TUNNEL_IP) {2638 ptype_lkup[k].tunnel_type =2639 LIBETH_RX_PT_TUNNEL_IP_GRENAT;2640 pstate.tunnel_state |=2641 IDPF_PTYPE_TUNNEL_IP_GRENAT;2642 }2643 break;2644 case VIRTCHNL2_PROTO_HDR_MAC:2645 ptype_lkup[k].outer_ip =2646 LIBETH_RX_PT_OUTER_L2;2647 if (pstate.tunnel_state ==2648 IDPF_TUN_IP_GRE) {2649 ptype_lkup[k].tunnel_type =2650 LIBETH_RX_PT_TUNNEL_IP_GRENAT_MAC;2651 pstate.tunnel_state |=2652 IDPF_PTYPE_TUNNEL_IP_GRENAT_MAC;2653 }2654 break;2655 case VIRTCHNL2_PROTO_HDR_IPV4:2656 idpf_fill_ptype_lookup(&ptype_lkup[k],2657 &pstate, true,2658 false);2659 break;2660 case VIRTCHNL2_PROTO_HDR_IPV6:2661 idpf_fill_ptype_lookup(&ptype_lkup[k],2662 &pstate, false,2663 false);2664 break;2665 case VIRTCHNL2_PROTO_HDR_IPV4_FRAG:2666 idpf_fill_ptype_lookup(&ptype_lkup[k],2667 &pstate, true,2668 true);2669 break;2670 case VIRTCHNL2_PROTO_HDR_IPV6_FRAG:2671 idpf_fill_ptype_lookup(&ptype_lkup[k],2672 &pstate, false,2673 true);2674 break;2675 case VIRTCHNL2_PROTO_HDR_UDP:2676 ptype_lkup[k].inner_prot =2677 LIBETH_RX_PT_INNER_UDP;2678 break;2679 case VIRTCHNL2_PROTO_HDR_TCP:2680 ptype_lkup[k].inner_prot =2681 LIBETH_RX_PT_INNER_TCP;2682 break;2683 case VIRTCHNL2_PROTO_HDR_SCTP:2684 ptype_lkup[k].inner_prot =2685 LIBETH_RX_PT_INNER_SCTP;2686 break;2687 case VIRTCHNL2_PROTO_HDR_ICMP:2688 ptype_lkup[k].inner_prot =2689 LIBETH_RX_PT_INNER_ICMP;2690 break;2691 case VIRTCHNL2_PROTO_HDR_PAY:2692 ptype_lkup[k].payload_layer =2693 LIBETH_RX_PT_PAYLOAD_L2;2694 break;2695 case VIRTCHNL2_PROTO_HDR_ICMPV6:2696 case VIRTCHNL2_PROTO_HDR_IPV6_EH:2697 case VIRTCHNL2_PROTO_HDR_PRE_MAC:2698 case VIRTCHNL2_PROTO_HDR_POST_MAC:2699 case VIRTCHNL2_PROTO_HDR_ETHERTYPE:2700 case VIRTCHNL2_PROTO_HDR_SVLAN:2701 case VIRTCHNL2_PROTO_HDR_CVLAN:2702 case VIRTCHNL2_PROTO_HDR_MPLS:2703 case VIRTCHNL2_PROTO_HDR_MMPLS:2704 case VIRTCHNL2_PROTO_HDR_PTP:2705 case VIRTCHNL2_PROTO_HDR_CTRL:2706 case VIRTCHNL2_PROTO_HDR_LLDP:2707 case VIRTCHNL2_PROTO_HDR_ARP:2708 case VIRTCHNL2_PROTO_HDR_ECP:2709 case VIRTCHNL2_PROTO_HDR_EAPOL:2710 case VIRTCHNL2_PROTO_HDR_PPPOD:2711 case VIRTCHNL2_PROTO_HDR_PPPOE:2712 case VIRTCHNL2_PROTO_HDR_IGMP:2713 case VIRTCHNL2_PROTO_HDR_AH:2714 case VIRTCHNL2_PROTO_HDR_ESP:2715 case VIRTCHNL2_PROTO_HDR_IKE:2716 case VIRTCHNL2_PROTO_HDR_NATT_KEEP:2717 case VIRTCHNL2_PROTO_HDR_L2TPV2:2718 case VIRTCHNL2_PROTO_HDR_L2TPV2_CONTROL:2719 case VIRTCHNL2_PROTO_HDR_L2TPV3:2720 case VIRTCHNL2_PROTO_HDR_GTP:2721 case VIRTCHNL2_PROTO_HDR_GTP_EH:2722 case VIRTCHNL2_PROTO_HDR_GTPCV2:2723 case VIRTCHNL2_PROTO_HDR_GTPC_TEID:2724 case VIRTCHNL2_PROTO_HDR_GTPU:2725 case VIRTCHNL2_PROTO_HDR_GTPU_UL:2726 case VIRTCHNL2_PROTO_HDR_GTPU_DL:2727 case VIRTCHNL2_PROTO_HDR_ECPRI:2728 case VIRTCHNL2_PROTO_HDR_VRRP:2729 case VIRTCHNL2_PROTO_HDR_OSPF:2730 case VIRTCHNL2_PROTO_HDR_TUN:2731 case VIRTCHNL2_PROTO_HDR_NVGRE:2732 case VIRTCHNL2_PROTO_HDR_VXLAN:2733 case VIRTCHNL2_PROTO_HDR_VXLAN_GPE:2734 case VIRTCHNL2_PROTO_HDR_GENEVE:2735 case VIRTCHNL2_PROTO_HDR_NSH:2736 case VIRTCHNL2_PROTO_HDR_QUIC:2737 case VIRTCHNL2_PROTO_HDR_PFCP:2738 case VIRTCHNL2_PROTO_HDR_PFCP_NODE:2739 case VIRTCHNL2_PROTO_HDR_PFCP_SESSION:2740 case VIRTCHNL2_PROTO_HDR_RTP:2741 case VIRTCHNL2_PROTO_HDR_NO_PROTO:2742 break;2743 default:2744 break;2745 }2746 }2747 2748 idpf_finalize_ptype_lookup(&ptype_lkup[k]);2749 }2750 }2751 2752out:2753 vport->rx_ptype_lkup = no_free_ptr(ptype_lkup);2754 2755 return 0;2756}2757 2758/**2759 * idpf_send_ena_dis_loopback_msg - Send virtchnl enable/disable loopback2760 * message2761 * @vport: virtual port data structure2762 *2763 * Returns 0 on success, negative on failure.2764 */2765int idpf_send_ena_dis_loopback_msg(struct idpf_vport *vport)2766{2767 struct idpf_vc_xn_params xn_params = {};2768 struct virtchnl2_loopback loopback;2769 ssize_t reply_sz;2770 2771 loopback.vport_id = cpu_to_le32(vport->vport_id);2772 loopback.enable = idpf_is_feature_ena(vport, NETIF_F_LOOPBACK);2773 2774 xn_params.vc_op = VIRTCHNL2_OP_LOOPBACK;2775 xn_params.timeout_ms = IDPF_VC_XN_DEFAULT_TIMEOUT_MSEC;2776 xn_params.send_buf.iov_base = &loopback;2777 xn_params.send_buf.iov_len = sizeof(loopback);2778 reply_sz = idpf_vc_xn_exec(vport->adapter, &xn_params);2779 2780 return reply_sz < 0 ? reply_sz : 0;2781}2782 2783/**2784 * idpf_find_ctlq - Given a type and id, find ctlq info2785 * @hw: hardware struct2786 * @type: type of ctrlq to find2787 * @id: ctlq id to find2788 *2789 * Returns pointer to found ctlq info struct, NULL otherwise.2790 */2791static struct idpf_ctlq_info *idpf_find_ctlq(struct idpf_hw *hw,2792 enum idpf_ctlq_type type, int id)2793{2794 struct idpf_ctlq_info *cq, *tmp;2795 2796 list_for_each_entry_safe(cq, tmp, &hw->cq_list_head, cq_list)2797 if (cq->q_id == id && cq->cq_type == type)2798 return cq;2799 2800 return NULL;2801}2802 2803/**2804 * idpf_init_dflt_mbx - Setup default mailbox parameters and make request2805 * @adapter: adapter info struct2806 *2807 * Returns 0 on success, negative otherwise2808 */2809int idpf_init_dflt_mbx(struct idpf_adapter *adapter)2810{2811 struct idpf_ctlq_create_info ctlq_info[] = {2812 {2813 .type = IDPF_CTLQ_TYPE_MAILBOX_TX,2814 .id = IDPF_DFLT_MBX_ID,2815 .len = IDPF_DFLT_MBX_Q_LEN,2816 .buf_size = IDPF_CTLQ_MAX_BUF_LEN2817 },2818 {2819 .type = IDPF_CTLQ_TYPE_MAILBOX_RX,2820 .id = IDPF_DFLT_MBX_ID,2821 .len = IDPF_DFLT_MBX_Q_LEN,2822 .buf_size = IDPF_CTLQ_MAX_BUF_LEN2823 }2824 };2825 struct idpf_hw *hw = &adapter->hw;2826 int err;2827 2828 adapter->dev_ops.reg_ops.ctlq_reg_init(ctlq_info);2829 2830 err = idpf_ctlq_init(hw, IDPF_NUM_DFLT_MBX_Q, ctlq_info);2831 if (err)2832 return err;2833 2834 hw->asq = idpf_find_ctlq(hw, IDPF_CTLQ_TYPE_MAILBOX_TX,2835 IDPF_DFLT_MBX_ID);2836 hw->arq = idpf_find_ctlq(hw, IDPF_CTLQ_TYPE_MAILBOX_RX,2837 IDPF_DFLT_MBX_ID);2838 2839 if (!hw->asq || !hw->arq) {2840 idpf_ctlq_deinit(hw);2841 2842 return -ENOENT;2843 }2844 2845 adapter->state = __IDPF_VER_CHECK;2846 2847 return 0;2848}2849 2850/**2851 * idpf_deinit_dflt_mbx - Free up ctlqs setup2852 * @adapter: Driver specific private data structure2853 */2854void idpf_deinit_dflt_mbx(struct idpf_adapter *adapter)2855{2856 if (adapter->hw.arq && adapter->hw.asq) {2857 idpf_mb_clean(adapter);2858 idpf_ctlq_deinit(&adapter->hw);2859 }2860 adapter->hw.arq = NULL;2861 adapter->hw.asq = NULL;2862}2863 2864/**2865 * idpf_vport_params_buf_rel - Release memory for MailBox resources2866 * @adapter: Driver specific private data structure2867 *2868 * Will release memory to hold the vport parameters received on MailBox2869 */2870static void idpf_vport_params_buf_rel(struct idpf_adapter *adapter)2871{2872 kfree(adapter->vport_params_recvd);2873 adapter->vport_params_recvd = NULL;2874 kfree(adapter->vport_params_reqd);2875 adapter->vport_params_reqd = NULL;2876 kfree(adapter->vport_ids);2877 adapter->vport_ids = NULL;2878}2879 2880/**2881 * idpf_vport_params_buf_alloc - Allocate memory for MailBox resources2882 * @adapter: Driver specific private data structure2883 *2884 * Will alloc memory to hold the vport parameters received on MailBox2885 */2886static int idpf_vport_params_buf_alloc(struct idpf_adapter *adapter)2887{2888 u16 num_max_vports = idpf_get_max_vports(adapter);2889 2890 adapter->vport_params_reqd = kcalloc(num_max_vports,2891 sizeof(*adapter->vport_params_reqd),2892 GFP_KERNEL);2893 if (!adapter->vport_params_reqd)2894 return -ENOMEM;2895 2896 adapter->vport_params_recvd = kcalloc(num_max_vports,2897 sizeof(*adapter->vport_params_recvd),2898 GFP_KERNEL);2899 if (!adapter->vport_params_recvd)2900 goto err_mem;2901 2902 adapter->vport_ids = kcalloc(num_max_vports, sizeof(u32), GFP_KERNEL);2903 if (!adapter->vport_ids)2904 goto err_mem;2905 2906 if (adapter->vport_config)2907 return 0;2908 2909 adapter->vport_config = kcalloc(num_max_vports,2910 sizeof(*adapter->vport_config),2911 GFP_KERNEL);2912 if (!adapter->vport_config)2913 goto err_mem;2914 2915 return 0;2916 2917err_mem:2918 idpf_vport_params_buf_rel(adapter);2919 2920 return -ENOMEM;2921}2922 2923/**2924 * idpf_vc_core_init - Initialize state machine and get driver specific2925 * resources2926 * @adapter: Driver specific private structure2927 *2928 * This function will initialize the state machine and request all necessary2929 * resources required by the device driver. Once the state machine is2930 * initialized, allocate memory to store vport specific information and also2931 * requests required interrupts.2932 *2933 * Returns 0 on success, -EAGAIN function will get called again,2934 * otherwise negative on failure.2935 */2936int idpf_vc_core_init(struct idpf_adapter *adapter)2937{2938 int task_delay = 30;2939 u16 num_max_vports;2940 int err = 0;2941 2942 if (!adapter->vcxn_mngr) {2943 adapter->vcxn_mngr = kzalloc(sizeof(*adapter->vcxn_mngr), GFP_KERNEL);2944 if (!adapter->vcxn_mngr) {2945 err = -ENOMEM;2946 goto init_failed;2947 }2948 }2949 idpf_vc_xn_init(adapter->vcxn_mngr);2950 2951 while (adapter->state != __IDPF_INIT_SW) {2952 switch (adapter->state) {2953 case __IDPF_VER_CHECK:2954 err = idpf_send_ver_msg(adapter);2955 switch (err) {2956 case 0:2957 /* success, move state machine forward */2958 adapter->state = __IDPF_GET_CAPS;2959 fallthrough;2960 case -EAGAIN:2961 goto restart;2962 default:2963 /* Something bad happened, try again but only a2964 * few times.2965 */2966 goto init_failed;2967 }2968 case __IDPF_GET_CAPS:2969 err = idpf_send_get_caps_msg(adapter);2970 if (err)2971 goto init_failed;2972 adapter->state = __IDPF_INIT_SW;2973 break;2974 default:2975 dev_err(&adapter->pdev->dev, "Device is in bad state: %d\n",2976 adapter->state);2977 err = -EINVAL;2978 goto init_failed;2979 }2980 break;2981restart:2982 /* Give enough time before proceeding further with2983 * state machine2984 */2985 msleep(task_delay);2986 }2987 2988 pci_sriov_set_totalvfs(adapter->pdev, idpf_get_max_vfs(adapter));2989 num_max_vports = idpf_get_max_vports(adapter);2990 adapter->max_vports = num_max_vports;2991 adapter->vports = kcalloc(num_max_vports, sizeof(*adapter->vports),2992 GFP_KERNEL);2993 if (!adapter->vports)2994 return -ENOMEM;2995 2996 if (!adapter->netdevs) {2997 adapter->netdevs = kcalloc(num_max_vports,2998 sizeof(struct net_device *),2999 GFP_KERNEL);3000 if (!adapter->netdevs) {3001 err = -ENOMEM;3002 goto err_netdev_alloc;3003 }3004 }3005 3006 err = idpf_vport_params_buf_alloc(adapter);3007 if (err) {3008 dev_err(&adapter->pdev->dev, "Failed to alloc vport params buffer: %d\n",3009 err);3010 goto err_netdev_alloc;3011 }3012 3013 /* Start the mailbox task before requesting vectors. This will ensure3014 * vector information response from mailbox is handled3015 */3016 queue_delayed_work(adapter->mbx_wq, &adapter->mbx_task, 0);3017 3018 queue_delayed_work(adapter->serv_wq, &adapter->serv_task,3019 msecs_to_jiffies(5 * (adapter->pdev->devfn & 0x07)));3020 3021 err = idpf_intr_req(adapter);3022 if (err) {3023 dev_err(&adapter->pdev->dev, "failed to enable interrupt vectors: %d\n",3024 err);3025 goto err_intr_req;3026 }3027 3028 idpf_init_avail_queues(adapter);3029 3030 /* Skew the delay for init tasks for each function based on fn number3031 * to prevent every function from making the same call simultaneously.3032 */3033 queue_delayed_work(adapter->init_wq, &adapter->init_task,3034 msecs_to_jiffies(5 * (adapter->pdev->devfn & 0x07)));3035 3036 set_bit(IDPF_VC_CORE_INIT, adapter->flags);3037 3038 return 0;3039 3040err_intr_req:3041 cancel_delayed_work_sync(&adapter->serv_task);3042 cancel_delayed_work_sync(&adapter->mbx_task);3043 idpf_vport_params_buf_rel(adapter);3044err_netdev_alloc:3045 kfree(adapter->vports);3046 adapter->vports = NULL;3047 return err;3048 3049init_failed:3050 /* Don't retry if we're trying to go down, just bail. */3051 if (test_bit(IDPF_REMOVE_IN_PROG, adapter->flags))3052 return err;3053 3054 if (++adapter->mb_wait_count > IDPF_MB_MAX_ERR) {3055 dev_err(&adapter->pdev->dev, "Failed to establish mailbox communications with hardware\n");3056 3057 return -EFAULT;3058 }3059 /* If it reached here, it is possible that mailbox queue initialization3060 * register writes might not have taken effect. Retry to initialize3061 * the mailbox again3062 */3063 adapter->state = __IDPF_VER_CHECK;3064 if (adapter->vcxn_mngr)3065 idpf_vc_xn_shutdown(adapter->vcxn_mngr);3066 set_bit(IDPF_HR_DRV_LOAD, adapter->flags);3067 queue_delayed_work(adapter->vc_event_wq, &adapter->vc_event_task,3068 msecs_to_jiffies(task_delay));3069 3070 return -EAGAIN;3071}3072 3073/**3074 * idpf_vc_core_deinit - Device deinit routine3075 * @adapter: Driver specific private structure3076 *3077 */3078void idpf_vc_core_deinit(struct idpf_adapter *adapter)3079{3080 if (!test_bit(IDPF_VC_CORE_INIT, adapter->flags))3081 return;3082 3083 idpf_deinit_task(adapter);3084 idpf_intr_rel(adapter);3085 idpf_vc_xn_shutdown(adapter->vcxn_mngr);3086 3087 cancel_delayed_work_sync(&adapter->serv_task);3088 cancel_delayed_work_sync(&adapter->mbx_task);3089 3090 idpf_vport_params_buf_rel(adapter);3091 3092 kfree(adapter->vports);3093 adapter->vports = NULL;3094 3095 clear_bit(IDPF_VC_CORE_INIT, adapter->flags);3096}3097 3098/**3099 * idpf_vport_alloc_vec_indexes - Get relative vector indexes3100 * @vport: virtual port data struct3101 *3102 * This function requests the vector information required for the vport and3103 * stores the vector indexes received from the 'global vector distribution'3104 * in the vport's queue vectors array.3105 *3106 * Return 0 on success, error on failure3107 */3108int idpf_vport_alloc_vec_indexes(struct idpf_vport *vport)3109{3110 struct idpf_vector_info vec_info;3111 int num_alloc_vecs;3112 3113 vec_info.num_curr_vecs = vport->num_q_vectors;3114 vec_info.num_req_vecs = max(vport->num_txq, vport->num_rxq);3115 vec_info.default_vport = vport->default_vport;3116 vec_info.index = vport->idx;3117 3118 num_alloc_vecs = idpf_req_rel_vector_indexes(vport->adapter,3119 vport->q_vector_idxs,3120 &vec_info);3121 if (num_alloc_vecs <= 0) {3122 dev_err(&vport->adapter->pdev->dev, "Vector distribution failed: %d\n",3123 num_alloc_vecs);3124 return -EINVAL;3125 }3126 3127 vport->num_q_vectors = num_alloc_vecs;3128 3129 return 0;3130}3131 3132/**3133 * idpf_vport_init - Initialize virtual port3134 * @vport: virtual port to be initialized3135 * @max_q: vport max queue info3136 *3137 * Will initialize vport with the info received through MB earlier3138 */3139void idpf_vport_init(struct idpf_vport *vport, struct idpf_vport_max_q *max_q)3140{3141 struct idpf_adapter *adapter = vport->adapter;3142 struct virtchnl2_create_vport *vport_msg;3143 struct idpf_vport_config *vport_config;3144 u16 tx_itr[] = {2, 8, 64, 128, 256};3145 u16 rx_itr[] = {2, 8, 32, 96, 128};3146 struct idpf_rss_data *rss_data;3147 u16 idx = vport->idx;3148 3149 vport_config = adapter->vport_config[idx];3150 rss_data = &vport_config->user_config.rss_data;3151 vport_msg = adapter->vport_params_recvd[idx];3152 3153 vport_config->max_q.max_txq = max_q->max_txq;3154 vport_config->max_q.max_rxq = max_q->max_rxq;3155 vport_config->max_q.max_complq = max_q->max_complq;3156 vport_config->max_q.max_bufq = max_q->max_bufq;3157 3158 vport->txq_model = le16_to_cpu(vport_msg->txq_model);3159 vport->rxq_model = le16_to_cpu(vport_msg->rxq_model);3160 vport->vport_type = le16_to_cpu(vport_msg->vport_type);3161 vport->vport_id = le32_to_cpu(vport_msg->vport_id);3162 3163 rss_data->rss_key_size = min_t(u16, NETDEV_RSS_KEY_LEN,3164 le16_to_cpu(vport_msg->rss_key_size));3165 rss_data->rss_lut_size = le16_to_cpu(vport_msg->rss_lut_size);3166 3167 ether_addr_copy(vport->default_mac_addr, vport_msg->default_mac_addr);3168 vport->max_mtu = le16_to_cpu(vport_msg->max_mtu) - LIBETH_RX_LL_LEN;3169 3170 /* Initialize Tx and Rx profiles for Dynamic Interrupt Moderation */3171 memcpy(vport->rx_itr_profile, rx_itr, IDPF_DIM_PROFILE_SLOTS);3172 memcpy(vport->tx_itr_profile, tx_itr, IDPF_DIM_PROFILE_SLOTS);3173 3174 idpf_vport_set_hsplit(vport, ETHTOOL_TCP_DATA_SPLIT_ENABLED);3175 3176 idpf_vport_init_num_qs(vport, vport_msg);3177 idpf_vport_calc_num_q_desc(vport);3178 idpf_vport_calc_num_q_groups(vport);3179 idpf_vport_alloc_vec_indexes(vport);3180 3181 vport->crc_enable = adapter->crc_enable;3182}3183 3184/**3185 * idpf_get_vec_ids - Initialize vector id from Mailbox parameters3186 * @adapter: adapter structure to get the mailbox vector id3187 * @vecids: Array of vector ids3188 * @num_vecids: number of vector ids3189 * @chunks: vector ids received over mailbox3190 *3191 * Will initialize the mailbox vector id which is received from the3192 * get capabilities and data queue vector ids with ids received as3193 * mailbox parameters.3194 * Returns number of ids filled3195 */3196int idpf_get_vec_ids(struct idpf_adapter *adapter,3197 u16 *vecids, int num_vecids,3198 struct virtchnl2_vector_chunks *chunks)3199{3200 u16 num_chunks = le16_to_cpu(chunks->num_vchunks);3201 int num_vecid_filled = 0;3202 int i, j;3203 3204 vecids[num_vecid_filled] = adapter->mb_vector.v_idx;3205 num_vecid_filled++;3206 3207 for (j = 0; j < num_chunks; j++) {3208 struct virtchnl2_vector_chunk *chunk;3209 u16 start_vecid, num_vec;3210 3211 chunk = &chunks->vchunks[j];3212 num_vec = le16_to_cpu(chunk->num_vectors);3213 start_vecid = le16_to_cpu(chunk->start_vector_id);3214 3215 for (i = 0; i < num_vec; i++) {3216 if ((num_vecid_filled + i) < num_vecids) {3217 vecids[num_vecid_filled + i] = start_vecid;3218 start_vecid++;3219 } else {3220 break;3221 }3222 }3223 num_vecid_filled = num_vecid_filled + i;3224 }3225 3226 return num_vecid_filled;3227}3228 3229/**3230 * idpf_vport_get_queue_ids - Initialize queue id from Mailbox parameters3231 * @qids: Array of queue ids3232 * @num_qids: number of queue ids3233 * @q_type: queue model3234 * @chunks: queue ids received over mailbox3235 *3236 * Will initialize all queue ids with ids received as mailbox parameters3237 * Returns number of ids filled3238 */3239static int idpf_vport_get_queue_ids(u32 *qids, int num_qids, u16 q_type,3240 struct virtchnl2_queue_reg_chunks *chunks)3241{3242 u16 num_chunks = le16_to_cpu(chunks->num_chunks);3243 u32 num_q_id_filled = 0, i;3244 u32 start_q_id, num_q;3245 3246 while (num_chunks--) {3247 struct virtchnl2_queue_reg_chunk *chunk;3248 3249 chunk = &chunks->chunks[num_chunks];3250 if (le32_to_cpu(chunk->type) != q_type)3251 continue;3252 3253 num_q = le32_to_cpu(chunk->num_queues);3254 start_q_id = le32_to_cpu(chunk->start_queue_id);3255 3256 for (i = 0; i < num_q; i++) {3257 if ((num_q_id_filled + i) < num_qids) {3258 qids[num_q_id_filled + i] = start_q_id;3259 start_q_id++;3260 } else {3261 break;3262 }3263 }3264 num_q_id_filled = num_q_id_filled + i;3265 }3266 3267 return num_q_id_filled;3268}3269 3270/**3271 * __idpf_vport_queue_ids_init - Initialize queue ids from Mailbox parameters3272 * @vport: virtual port for which the queues ids are initialized3273 * @qids: queue ids3274 * @num_qids: number of queue ids3275 * @q_type: type of queue3276 *3277 * Will initialize all queue ids with ids received as mailbox3278 * parameters. Returns number of queue ids initialized.3279 */3280static int __idpf_vport_queue_ids_init(struct idpf_vport *vport,3281 const u32 *qids,3282 int num_qids,3283 u32 q_type)3284{3285 int i, j, k = 0;3286 3287 switch (q_type) {3288 case VIRTCHNL2_QUEUE_TYPE_TX:3289 for (i = 0; i < vport->num_txq_grp; i++) {3290 struct idpf_txq_group *tx_qgrp = &vport->txq_grps[i];3291 3292 for (j = 0; j < tx_qgrp->num_txq && k < num_qids; j++, k++)3293 tx_qgrp->txqs[j]->q_id = qids[k];3294 }3295 break;3296 case VIRTCHNL2_QUEUE_TYPE_RX:3297 for (i = 0; i < vport->num_rxq_grp; i++) {3298 struct idpf_rxq_group *rx_qgrp = &vport->rxq_grps[i];3299 u16 num_rxq;3300 3301 if (idpf_is_queue_model_split(vport->rxq_model))3302 num_rxq = rx_qgrp->splitq.num_rxq_sets;3303 else3304 num_rxq = rx_qgrp->singleq.num_rxq;3305 3306 for (j = 0; j < num_rxq && k < num_qids; j++, k++) {3307 struct idpf_rx_queue *q;3308 3309 if (idpf_is_queue_model_split(vport->rxq_model))3310 q = &rx_qgrp->splitq.rxq_sets[j]->rxq;3311 else3312 q = rx_qgrp->singleq.rxqs[j];3313 q->q_id = qids[k];3314 }3315 }3316 break;3317 case VIRTCHNL2_QUEUE_TYPE_TX_COMPLETION:3318 for (i = 0; i < vport->num_txq_grp && k < num_qids; i++, k++) {3319 struct idpf_txq_group *tx_qgrp = &vport->txq_grps[i];3320 3321 tx_qgrp->complq->q_id = qids[k];3322 }3323 break;3324 case VIRTCHNL2_QUEUE_TYPE_RX_BUFFER:3325 for (i = 0; i < vport->num_rxq_grp; i++) {3326 struct idpf_rxq_group *rx_qgrp = &vport->rxq_grps[i];3327 u8 num_bufqs = vport->num_bufqs_per_qgrp;3328 3329 for (j = 0; j < num_bufqs && k < num_qids; j++, k++) {3330 struct idpf_buf_queue *q;3331 3332 q = &rx_qgrp->splitq.bufq_sets[j].bufq;3333 q->q_id = qids[k];3334 }3335 }3336 break;3337 default:3338 break;3339 }3340 3341 return k;3342}3343 3344/**3345 * idpf_vport_queue_ids_init - Initialize queue ids from Mailbox parameters3346 * @vport: virtual port for which the queues ids are initialized3347 *3348 * Will initialize all queue ids with ids received as mailbox parameters.3349 * Returns 0 on success, negative if all the queues are not initialized.3350 */3351int idpf_vport_queue_ids_init(struct idpf_vport *vport)3352{3353 struct virtchnl2_create_vport *vport_params;3354 struct virtchnl2_queue_reg_chunks *chunks;3355 struct idpf_vport_config *vport_config;3356 u16 vport_idx = vport->idx;3357 int num_ids, err = 0;3358 u16 q_type;3359 u32 *qids;3360 3361 vport_config = vport->adapter->vport_config[vport_idx];3362 if (vport_config->req_qs_chunks) {3363 struct virtchnl2_add_queues *vc_aq =3364 (struct virtchnl2_add_queues *)vport_config->req_qs_chunks;3365 chunks = &vc_aq->chunks;3366 } else {3367 vport_params = vport->adapter->vport_params_recvd[vport_idx];3368 chunks = &vport_params->chunks;3369 }3370 3371 qids = kcalloc(IDPF_MAX_QIDS, sizeof(u32), GFP_KERNEL);3372 if (!qids)3373 return -ENOMEM;3374 3375 num_ids = idpf_vport_get_queue_ids(qids, IDPF_MAX_QIDS,3376 VIRTCHNL2_QUEUE_TYPE_TX,3377 chunks);3378 if (num_ids < vport->num_txq) {3379 err = -EINVAL;3380 goto mem_rel;3381 }3382 num_ids = __idpf_vport_queue_ids_init(vport, qids, num_ids,3383 VIRTCHNL2_QUEUE_TYPE_TX);3384 if (num_ids < vport->num_txq) {3385 err = -EINVAL;3386 goto mem_rel;3387 }3388 3389 num_ids = idpf_vport_get_queue_ids(qids, IDPF_MAX_QIDS,3390 VIRTCHNL2_QUEUE_TYPE_RX,3391 chunks);3392 if (num_ids < vport->num_rxq) {3393 err = -EINVAL;3394 goto mem_rel;3395 }3396 num_ids = __idpf_vport_queue_ids_init(vport, qids, num_ids,3397 VIRTCHNL2_QUEUE_TYPE_RX);3398 if (num_ids < vport->num_rxq) {3399 err = -EINVAL;3400 goto mem_rel;3401 }3402 3403 if (!idpf_is_queue_model_split(vport->txq_model))3404 goto check_rxq;3405 3406 q_type = VIRTCHNL2_QUEUE_TYPE_TX_COMPLETION;3407 num_ids = idpf_vport_get_queue_ids(qids, IDPF_MAX_QIDS, q_type, chunks);3408 if (num_ids < vport->num_complq) {3409 err = -EINVAL;3410 goto mem_rel;3411 }3412 num_ids = __idpf_vport_queue_ids_init(vport, qids, num_ids, q_type);3413 if (num_ids < vport->num_complq) {3414 err = -EINVAL;3415 goto mem_rel;3416 }3417 3418check_rxq:3419 if (!idpf_is_queue_model_split(vport->rxq_model))3420 goto mem_rel;3421 3422 q_type = VIRTCHNL2_QUEUE_TYPE_RX_BUFFER;3423 num_ids = idpf_vport_get_queue_ids(qids, IDPF_MAX_QIDS, q_type, chunks);3424 if (num_ids < vport->num_bufq) {3425 err = -EINVAL;3426 goto mem_rel;3427 }3428 num_ids = __idpf_vport_queue_ids_init(vport, qids, num_ids, q_type);3429 if (num_ids < vport->num_bufq)3430 err = -EINVAL;3431 3432mem_rel:3433 kfree(qids);3434 3435 return err;3436}3437 3438/**3439 * idpf_vport_adjust_qs - Adjust to new requested queues3440 * @vport: virtual port data struct3441 *3442 * Renegotiate queues. Returns 0 on success, negative on failure.3443 */3444int idpf_vport_adjust_qs(struct idpf_vport *vport)3445{3446 struct virtchnl2_create_vport vport_msg;3447 int err;3448 3449 vport_msg.txq_model = cpu_to_le16(vport->txq_model);3450 vport_msg.rxq_model = cpu_to_le16(vport->rxq_model);3451 err = idpf_vport_calc_total_qs(vport->adapter, vport->idx, &vport_msg,3452 NULL);3453 if (err)3454 return err;3455 3456 idpf_vport_init_num_qs(vport, &vport_msg);3457 idpf_vport_calc_num_q_groups(vport);3458 3459 return 0;3460}3461 3462/**3463 * idpf_is_capability_ena - Default implementation of capability checking3464 * @adapter: Private data struct3465 * @all: all or one flag3466 * @field: caps field to check for flags3467 * @flag: flag to check3468 *3469 * Return true if all capabilities are supported, false otherwise3470 */3471bool idpf_is_capability_ena(struct idpf_adapter *adapter, bool all,3472 enum idpf_cap_field field, u64 flag)3473{3474 u8 *caps = (u8 *)&adapter->caps;3475 u32 *cap_field;3476 3477 if (!caps)3478 return false;3479 3480 if (field == IDPF_BASE_CAPS)3481 return false;3482 3483 cap_field = (u32 *)(caps + field);3484 3485 if (all)3486 return (*cap_field & flag) == flag;3487 else3488 return !!(*cap_field & flag);3489}3490 3491/**3492 * idpf_get_vport_id: Get vport id3493 * @vport: virtual port structure3494 *3495 * Return vport id from the adapter persistent data3496 */3497u32 idpf_get_vport_id(struct idpf_vport *vport)3498{3499 struct virtchnl2_create_vport *vport_msg;3500 3501 vport_msg = vport->adapter->vport_params_recvd[vport->idx];3502 3503 return le32_to_cpu(vport_msg->vport_id);3504}3505 3506/**3507 * idpf_mac_filter_async_handler - Async callback for mac filters3508 * @adapter: private data struct3509 * @xn: transaction for message3510 * @ctlq_msg: received message3511 *3512 * In some scenarios driver can't sleep and wait for a reply (e.g.: stack is3513 * holding rtnl_lock) when adding a new mac filter. It puts us in a difficult3514 * situation to deal with errors returned on the reply. The best we can3515 * ultimately do is remove it from our list of mac filters and report the3516 * error.3517 */3518static int idpf_mac_filter_async_handler(struct idpf_adapter *adapter,3519 struct idpf_vc_xn *xn,3520 const struct idpf_ctlq_msg *ctlq_msg)3521{3522 struct virtchnl2_mac_addr_list *ma_list;3523 struct idpf_vport_config *vport_config;3524 struct virtchnl2_mac_addr *mac_addr;3525 struct idpf_mac_filter *f, *tmp;3526 struct list_head *ma_list_head;3527 struct idpf_vport *vport;3528 u16 num_entries;3529 int i;3530 3531 /* if success we're done, we're only here if something bad happened */3532 if (!ctlq_msg->cookie.mbx.chnl_retval)3533 return 0;3534 3535 /* make sure at least struct is there */3536 if (xn->reply_sz < sizeof(*ma_list))3537 goto invalid_payload;3538 3539 ma_list = ctlq_msg->ctx.indirect.payload->va;3540 mac_addr = ma_list->mac_addr_list;3541 num_entries = le16_to_cpu(ma_list->num_mac_addr);3542 /* we should have received a buffer at least this big */3543 if (xn->reply_sz < struct_size(ma_list, mac_addr_list, num_entries))3544 goto invalid_payload;3545 3546 vport = idpf_vid_to_vport(adapter, le32_to_cpu(ma_list->vport_id));3547 if (!vport)3548 goto invalid_payload;3549 3550 vport_config = adapter->vport_config[le32_to_cpu(ma_list->vport_id)];3551 ma_list_head = &vport_config->user_config.mac_filter_list;3552 3553 /* We can't do much to reconcile bad filters at this point, however we3554 * should at least remove them from our list one way or the other so we3555 * have some idea what good filters we have.3556 */3557 spin_lock_bh(&vport_config->mac_filter_list_lock);3558 list_for_each_entry_safe(f, tmp, ma_list_head, list)3559 for (i = 0; i < num_entries; i++)3560 if (ether_addr_equal(mac_addr[i].addr, f->macaddr))3561 list_del(&f->list);3562 spin_unlock_bh(&vport_config->mac_filter_list_lock);3563 dev_err_ratelimited(&adapter->pdev->dev, "Received error sending MAC filter request (op %d)\n",3564 xn->vc_op);3565 3566 return 0;3567 3568invalid_payload:3569 dev_err_ratelimited(&adapter->pdev->dev, "Received invalid MAC filter payload (op %d) (len %zd)\n",3570 xn->vc_op, xn->reply_sz);3571 3572 return -EINVAL;3573}3574 3575/**3576 * idpf_add_del_mac_filters - Add/del mac filters3577 * @vport: Virtual port data structure3578 * @np: Netdev private structure3579 * @add: Add or delete flag3580 * @async: Don't wait for return message3581 *3582 * Returns 0 on success, error on failure.3583 **/3584int idpf_add_del_mac_filters(struct idpf_vport *vport,3585 struct idpf_netdev_priv *np,3586 bool add, bool async)3587{3588 struct virtchnl2_mac_addr_list *ma_list __free(kfree) = NULL;3589 struct virtchnl2_mac_addr *mac_addr __free(kfree) = NULL;3590 struct idpf_adapter *adapter = np->adapter;3591 struct idpf_vc_xn_params xn_params = {};3592 struct idpf_vport_config *vport_config;3593 u32 num_msgs, total_filters = 0;3594 struct idpf_mac_filter *f;3595 ssize_t reply_sz;3596 int i = 0, k;3597 3598 xn_params.vc_op = add ? VIRTCHNL2_OP_ADD_MAC_ADDR :3599 VIRTCHNL2_OP_DEL_MAC_ADDR;3600 xn_params.timeout_ms = IDPF_VC_XN_DEFAULT_TIMEOUT_MSEC;3601 xn_params.async = async;3602 xn_params.async_handler = idpf_mac_filter_async_handler;3603 3604 vport_config = adapter->vport_config[np->vport_idx];3605 spin_lock_bh(&vport_config->mac_filter_list_lock);3606 3607 /* Find the number of newly added filters */3608 list_for_each_entry(f, &vport_config->user_config.mac_filter_list,3609 list) {3610 if (add && f->add)3611 total_filters++;3612 else if (!add && f->remove)3613 total_filters++;3614 }3615 3616 if (!total_filters) {3617 spin_unlock_bh(&vport_config->mac_filter_list_lock);3618 3619 return 0;3620 }3621 3622 /* Fill all the new filters into virtchannel message */3623 mac_addr = kcalloc(total_filters, sizeof(struct virtchnl2_mac_addr),3624 GFP_ATOMIC);3625 if (!mac_addr) {3626 spin_unlock_bh(&vport_config->mac_filter_list_lock);3627 3628 return -ENOMEM;3629 }3630 3631 list_for_each_entry(f, &vport_config->user_config.mac_filter_list,3632 list) {3633 if (add && f->add) {3634 ether_addr_copy(mac_addr[i].addr, f->macaddr);3635 i++;3636 f->add = false;3637 if (i == total_filters)3638 break;3639 }3640 if (!add && f->remove) {3641 ether_addr_copy(mac_addr[i].addr, f->macaddr);3642 i++;3643 f->remove = false;3644 if (i == total_filters)3645 break;3646 }3647 }3648 3649 spin_unlock_bh(&vport_config->mac_filter_list_lock);3650 3651 /* Chunk up the filters into multiple messages to avoid3652 * sending a control queue message buffer that is too large3653 */3654 num_msgs = DIV_ROUND_UP(total_filters, IDPF_NUM_FILTERS_PER_MSG);3655 3656 for (i = 0, k = 0; i < num_msgs; i++) {3657 u32 entries_size, buf_size, num_entries;3658 3659 num_entries = min_t(u32, total_filters,3660 IDPF_NUM_FILTERS_PER_MSG);3661 entries_size = sizeof(struct virtchnl2_mac_addr) * num_entries;3662 buf_size = struct_size(ma_list, mac_addr_list, num_entries);3663 3664 if (!ma_list || num_entries != IDPF_NUM_FILTERS_PER_MSG) {3665 kfree(ma_list);3666 ma_list = kzalloc(buf_size, GFP_ATOMIC);3667 if (!ma_list)3668 return -ENOMEM;3669 } else {3670 memset(ma_list, 0, buf_size);3671 }3672 3673 ma_list->vport_id = cpu_to_le32(np->vport_id);3674 ma_list->num_mac_addr = cpu_to_le16(num_entries);3675 memcpy(ma_list->mac_addr_list, &mac_addr[k], entries_size);3676 3677 xn_params.send_buf.iov_base = ma_list;3678 xn_params.send_buf.iov_len = buf_size;3679 reply_sz = idpf_vc_xn_exec(adapter, &xn_params);3680 if (reply_sz < 0)3681 return reply_sz;3682 3683 k += num_entries;3684 total_filters -= num_entries;3685 }3686 3687 return 0;3688}3689 3690/**3691 * idpf_set_promiscuous - set promiscuous and send message to mailbox3692 * @adapter: Driver specific private structure3693 * @config_data: Vport specific config data3694 * @vport_id: Vport identifier3695 *3696 * Request to enable promiscuous mode for the vport. Message is sent3697 * asynchronously and won't wait for response. Returns 0 on success, negative3698 * on failure;3699 */3700int idpf_set_promiscuous(struct idpf_adapter *adapter,3701 struct idpf_vport_user_config_data *config_data,3702 u32 vport_id)3703{3704 struct idpf_vc_xn_params xn_params = {};3705 struct virtchnl2_promisc_info vpi;3706 ssize_t reply_sz;3707 u16 flags = 0;3708 3709 if (test_bit(__IDPF_PROMISC_UC, config_data->user_flags))3710 flags |= VIRTCHNL2_UNICAST_PROMISC;3711 if (test_bit(__IDPF_PROMISC_MC, config_data->user_flags))3712 flags |= VIRTCHNL2_MULTICAST_PROMISC;3713 3714 vpi.vport_id = cpu_to_le32(vport_id);3715 vpi.flags = cpu_to_le16(flags);3716 3717 xn_params.vc_op = VIRTCHNL2_OP_CONFIG_PROMISCUOUS_MODE;3718 xn_params.timeout_ms = IDPF_VC_XN_DEFAULT_TIMEOUT_MSEC;3719 xn_params.send_buf.iov_base = &vpi;3720 xn_params.send_buf.iov_len = sizeof(vpi);3721 /* setting promiscuous is only ever done asynchronously */3722 xn_params.async = true;3723 reply_sz = idpf_vc_xn_exec(adapter, &xn_params);3724 3725 return reply_sz < 0 ? reply_sz : 0;3726}3727