.. | .. |
---|
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)); |
---|