| .. | .. |
|---|
| 25 | 25 | #include "octeon_nic.h" |
|---|
| 26 | 26 | #include "octeon_main.h" |
|---|
| 27 | 27 | #include "octeon_network.h" |
|---|
| 28 | | -#include <net/switchdev.h> |
|---|
| 29 | 28 | #include "lio_vf_rep.h" |
|---|
| 30 | | -#include "octeon_network.h" |
|---|
| 31 | 29 | |
|---|
| 32 | 30 | static int lio_vf_rep_open(struct net_device *ndev); |
|---|
| 33 | 31 | static int lio_vf_rep_stop(struct net_device *ndev); |
|---|
| 34 | 32 | static netdev_tx_t lio_vf_rep_pkt_xmit(struct sk_buff *skb, |
|---|
| 35 | 33 | struct net_device *ndev); |
|---|
| 36 | | -static void lio_vf_rep_tx_timeout(struct net_device *netdev); |
|---|
| 34 | +static void lio_vf_rep_tx_timeout(struct net_device *netdev, unsigned int txqueue); |
|---|
| 37 | 35 | static int lio_vf_rep_phys_port_name(struct net_device *dev, |
|---|
| 38 | 36 | char *buf, size_t len); |
|---|
| 39 | 37 | static void lio_vf_rep_get_stats64(struct net_device *dev, |
|---|
| 40 | 38 | struct rtnl_link_stats64 *stats64); |
|---|
| 41 | 39 | static int lio_vf_rep_change_mtu(struct net_device *ndev, int new_mtu); |
|---|
| 40 | +static int lio_vf_get_port_parent_id(struct net_device *dev, |
|---|
| 41 | + struct netdev_phys_item_id *ppid); |
|---|
| 42 | 42 | |
|---|
| 43 | 43 | static const struct net_device_ops lio_vf_rep_ndev_ops = { |
|---|
| 44 | 44 | .ndo_open = lio_vf_rep_open, |
|---|
| .. | .. |
|---|
| 48 | 48 | .ndo_get_phys_port_name = lio_vf_rep_phys_port_name, |
|---|
| 49 | 49 | .ndo_get_stats64 = lio_vf_rep_get_stats64, |
|---|
| 50 | 50 | .ndo_change_mtu = lio_vf_rep_change_mtu, |
|---|
| 51 | + .ndo_get_port_parent_id = lio_vf_get_port_parent_id, |
|---|
| 51 | 52 | }; |
|---|
| 52 | | - |
|---|
| 53 | | -static void |
|---|
| 54 | | -lio_vf_rep_send_sc_complete(struct octeon_device *oct, |
|---|
| 55 | | - u32 status, void *ptr) |
|---|
| 56 | | -{ |
|---|
| 57 | | - struct octeon_soft_command *sc = (struct octeon_soft_command *)ptr; |
|---|
| 58 | | - struct lio_vf_rep_sc_ctx *ctx = |
|---|
| 59 | | - (struct lio_vf_rep_sc_ctx *)sc->ctxptr; |
|---|
| 60 | | - struct lio_vf_rep_resp *resp = |
|---|
| 61 | | - (struct lio_vf_rep_resp *)sc->virtrptr; |
|---|
| 62 | | - |
|---|
| 63 | | - if (status != OCTEON_REQUEST_TIMEOUT && READ_ONCE(resp->status)) |
|---|
| 64 | | - WRITE_ONCE(resp->status, 0); |
|---|
| 65 | | - |
|---|
| 66 | | - complete(&ctx->complete); |
|---|
| 67 | | -} |
|---|
| 68 | 53 | |
|---|
| 69 | 54 | static int |
|---|
| 70 | 55 | lio_vf_rep_send_soft_command(struct octeon_device *oct, |
|---|
| .. | .. |
|---|
| 72 | 57 | void *resp, int resp_size) |
|---|
| 73 | 58 | { |
|---|
| 74 | 59 | int tot_resp_size = sizeof(struct lio_vf_rep_resp) + resp_size; |
|---|
| 75 | | - int ctx_size = sizeof(struct lio_vf_rep_sc_ctx); |
|---|
| 76 | 60 | struct octeon_soft_command *sc = NULL; |
|---|
| 77 | 61 | struct lio_vf_rep_resp *rep_resp; |
|---|
| 78 | | - struct lio_vf_rep_sc_ctx *ctx; |
|---|
| 79 | 62 | void *sc_req; |
|---|
| 80 | 63 | int err; |
|---|
| 81 | 64 | |
|---|
| 82 | 65 | sc = (struct octeon_soft_command *) |
|---|
| 83 | 66 | octeon_alloc_soft_command(oct, req_size, |
|---|
| 84 | | - tot_resp_size, ctx_size); |
|---|
| 67 | + tot_resp_size, 0); |
|---|
| 85 | 68 | if (!sc) |
|---|
| 86 | 69 | return -ENOMEM; |
|---|
| 87 | 70 | |
|---|
| 88 | | - ctx = (struct lio_vf_rep_sc_ctx *)sc->ctxptr; |
|---|
| 89 | | - memset(ctx, 0, ctx_size); |
|---|
| 90 | | - init_completion(&ctx->complete); |
|---|
| 71 | + init_completion(&sc->complete); |
|---|
| 72 | + sc->sc_status = OCTEON_REQUEST_PENDING; |
|---|
| 91 | 73 | |
|---|
| 92 | 74 | sc_req = (struct lio_vf_rep_req *)sc->virtdptr; |
|---|
| 93 | 75 | memcpy(sc_req, req, req_size); |
|---|
| .. | .. |
|---|
| 99 | 81 | sc->iq_no = 0; |
|---|
| 100 | 82 | octeon_prepare_soft_command(oct, sc, OPCODE_NIC, |
|---|
| 101 | 83 | OPCODE_NIC_VF_REP_CMD, 0, 0, 0); |
|---|
| 102 | | - sc->callback = lio_vf_rep_send_sc_complete; |
|---|
| 103 | | - sc->callback_arg = sc; |
|---|
| 104 | | - sc->wait_time = LIO_VF_REP_REQ_TMO_MS; |
|---|
| 105 | 84 | |
|---|
| 106 | 85 | err = octeon_send_soft_command(oct, sc); |
|---|
| 107 | 86 | if (err == IQ_SEND_FAILED) |
|---|
| 108 | 87 | goto free_buff; |
|---|
| 109 | 88 | |
|---|
| 110 | | - wait_for_completion_timeout(&ctx->complete, |
|---|
| 111 | | - msecs_to_jiffies |
|---|
| 112 | | - (2 * LIO_VF_REP_REQ_TMO_MS)); |
|---|
| 89 | + err = wait_for_sc_completion_timeout(oct, sc, 0); |
|---|
| 90 | + if (err) |
|---|
| 91 | + return err; |
|---|
| 92 | + |
|---|
| 113 | 93 | err = READ_ONCE(rep_resp->status) ? -EBUSY : 0; |
|---|
| 114 | 94 | if (err) |
|---|
| 115 | 95 | dev_err(&oct->pci_dev->dev, "VF rep send config failed\n"); |
|---|
| 116 | | - |
|---|
| 117 | | - if (resp) |
|---|
| 96 | + else if (resp) |
|---|
| 118 | 97 | memcpy(resp, (rep_resp + 1), resp_size); |
|---|
| 98 | + |
|---|
| 99 | + WRITE_ONCE(sc->caller_is_done, true); |
|---|
| 100 | + return err; |
|---|
| 101 | + |
|---|
| 119 | 102 | free_buff: |
|---|
| 120 | 103 | octeon_free_soft_command(oct, sc); |
|---|
| 121 | 104 | |
|---|
| .. | .. |
|---|
| 189 | 172 | } |
|---|
| 190 | 173 | |
|---|
| 191 | 174 | static void |
|---|
| 192 | | -lio_vf_rep_tx_timeout(struct net_device *ndev) |
|---|
| 175 | +lio_vf_rep_tx_timeout(struct net_device *ndev, unsigned int txqueue) |
|---|
| 193 | 176 | { |
|---|
| 194 | 177 | netif_trans_update(ndev); |
|---|
| 195 | 178 | |
|---|
| .. | .. |
|---|
| 407 | 390 | } |
|---|
| 408 | 391 | |
|---|
| 409 | 392 | sc = (struct octeon_soft_command *) |
|---|
| 410 | | - octeon_alloc_soft_command(oct, 0, 0, 0); |
|---|
| 393 | + octeon_alloc_soft_command(oct, 0, 16, 0); |
|---|
| 411 | 394 | if (!sc) { |
|---|
| 412 | 395 | dev_err(&oct->pci_dev->dev, "VF rep: Soft command alloc failed\n"); |
|---|
| 413 | 396 | goto xmit_failed; |
|---|
| .. | .. |
|---|
| 416 | 399 | /* Multiple buffers are not used for vf_rep packets. */ |
|---|
| 417 | 400 | if (skb_shinfo(skb)->nr_frags != 0) { |
|---|
| 418 | 401 | dev_err(&oct->pci_dev->dev, "VF rep: nr_frags != 0. Dropping packet\n"); |
|---|
| 402 | + octeon_free_soft_command(oct, sc); |
|---|
| 419 | 403 | goto xmit_failed; |
|---|
| 420 | 404 | } |
|---|
| 421 | 405 | |
|---|
| .. | .. |
|---|
| 423 | 407 | skb->data, skb->len, DMA_TO_DEVICE); |
|---|
| 424 | 408 | if (dma_mapping_error(&oct->pci_dev->dev, sc->dmadptr)) { |
|---|
| 425 | 409 | dev_err(&oct->pci_dev->dev, "VF rep: DMA mapping failed\n"); |
|---|
| 410 | + octeon_free_soft_command(oct, sc); |
|---|
| 426 | 411 | goto xmit_failed; |
|---|
| 427 | 412 | } |
|---|
| 428 | 413 | |
|---|
| .. | .. |
|---|
| 443 | 428 | if (status == IQ_SEND_FAILED) { |
|---|
| 444 | 429 | dma_unmap_single(&oct->pci_dev->dev, sc->dmadptr, |
|---|
| 445 | 430 | sc->datasize, DMA_TO_DEVICE); |
|---|
| 431 | + octeon_free_soft_command(oct, sc); |
|---|
| 446 | 432 | goto xmit_failed; |
|---|
| 447 | 433 | } |
|---|
| 448 | 434 | |
|---|
| .. | .. |
|---|
| 459 | 445 | return NETDEV_TX_OK; |
|---|
| 460 | 446 | } |
|---|
| 461 | 447 | |
|---|
| 462 | | -static int |
|---|
| 463 | | -lio_vf_rep_attr_get(struct net_device *dev, struct switchdev_attr *attr) |
|---|
| 448 | +static int lio_vf_get_port_parent_id(struct net_device *dev, |
|---|
| 449 | + struct netdev_phys_item_id *ppid) |
|---|
| 464 | 450 | { |
|---|
| 465 | 451 | struct lio_vf_rep_desc *vf_rep = netdev_priv(dev); |
|---|
| 466 | 452 | struct net_device *parent_ndev = vf_rep->parent_ndev; |
|---|
| 467 | 453 | struct lio *lio = GET_LIO(parent_ndev); |
|---|
| 468 | 454 | |
|---|
| 469 | | - switch (attr->id) { |
|---|
| 470 | | - case SWITCHDEV_ATTR_ID_PORT_PARENT_ID: |
|---|
| 471 | | - attr->u.ppid.id_len = ETH_ALEN; |
|---|
| 472 | | - ether_addr_copy(attr->u.ppid.id, |
|---|
| 473 | | - (void *)&lio->linfo.hw_addr + 2); |
|---|
| 474 | | - break; |
|---|
| 475 | | - |
|---|
| 476 | | - default: |
|---|
| 477 | | - return -EOPNOTSUPP; |
|---|
| 478 | | - } |
|---|
| 455 | + ppid->id_len = ETH_ALEN; |
|---|
| 456 | + ether_addr_copy(ppid->id, (void *)&lio->linfo.hw_addr + 2); |
|---|
| 479 | 457 | |
|---|
| 480 | 458 | return 0; |
|---|
| 481 | 459 | } |
|---|
| 482 | | - |
|---|
| 483 | | -static const struct switchdev_ops lio_vf_rep_switchdev_ops = { |
|---|
| 484 | | - .switchdev_port_attr_get = lio_vf_rep_attr_get, |
|---|
| 485 | | -}; |
|---|
| 486 | 460 | |
|---|
| 487 | 461 | static void |
|---|
| 488 | 462 | lio_vf_rep_fetch_stats(struct work_struct *work) |
|---|
| .. | .. |
|---|
| 540 | 514 | ndev->min_mtu = LIO_MIN_MTU_SIZE; |
|---|
| 541 | 515 | ndev->max_mtu = LIO_MAX_MTU_SIZE; |
|---|
| 542 | 516 | ndev->netdev_ops = &lio_vf_rep_ndev_ops; |
|---|
| 543 | | - SWITCHDEV_SET_OPS(ndev, &lio_vf_rep_switchdev_ops); |
|---|
| 544 | 517 | |
|---|
| 545 | 518 | vf_rep = netdev_priv(ndev); |
|---|
| 546 | 519 | memset(vf_rep, 0, sizeof(*vf_rep)); |
|---|