Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) 2023 Corigine, Inc.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "nfp_vdpa_core.h"
7 : :
8 : : #include <nfp_common.h>
9 : : #include <rte_vhost.h>
10 : :
11 : : #include "nfp_vdpa_log.h"
12 : :
13 : : /* Available and used descs are in same order */
14 : : #ifndef VIRTIO_F_IN_ORDER
15 : : #define VIRTIO_F_IN_ORDER 35
16 : : #endif
17 : :
18 : : #define NFP_QCP_NOTIFY_MAX_ADD 0x7f
19 : :
20 : : enum nfp_qcp_notify_ptr {
21 : : NFP_QCP_NOTIFY_WRITE_PTR = 0,
22 : : NFP_QCP_NOTIFY_READ_PTR
23 : : };
24 : :
25 : : /**
26 : : * Add the value to the selected pointer of a queue
27 : : *
28 : : * @param queue
29 : : * Base address for queue structure
30 : : * @param ptr
31 : : * Add to the Read or Write pointer
32 : : * @param val
33 : : * Value to add to the queue pointer
34 : : */
35 : : static inline void
36 : : nfp_qcp_notify_ptr_add(uint8_t *q,
37 : : enum nfp_qcp_notify_ptr ptr,
38 : : uint32_t val)
39 : : {
40 : : uint32_t off;
41 : :
42 : : if (ptr == NFP_QCP_NOTIFY_WRITE_PTR)
43 : : off = NFP_QCP_QUEUE_ADD_RPTR;
44 : : else
45 : : off = NFP_QCP_QUEUE_ADD_WPTR;
46 : :
47 [ # # ]: 0 : for (; val > NFP_QCP_NOTIFY_MAX_ADD; val -= NFP_QCP_NOTIFY_MAX_ADD)
48 : : nn_writel(rte_cpu_to_le_32(NFP_QCP_NOTIFY_MAX_ADD), q + off);
49 : :
50 : : nn_writel(rte_cpu_to_le_32(val), q + off);
51 : : }
52 : :
53 : : int
54 : 0 : nfp_vdpa_hw_init(struct nfp_vdpa_hw *vdpa_hw,
55 : : struct rte_pci_device *pci_dev)
56 : : {
57 : : uint32_t queue;
58 : : struct nfp_hw *hw;
59 : : uint8_t *notify_base;
60 : :
61 : : hw = &vdpa_hw->super;
62 : 0 : hw->ctrl_bar = pci_dev->mem_resource[0].addr;
63 [ # # ]: 0 : if (hw->ctrl_bar == NULL) {
64 : 0 : DRV_CORE_LOG(ERR, "hw->ctrl_bar is NULL. BAR0 not configured.");
65 : 0 : return -ENODEV;
66 : : }
67 : :
68 : 0 : notify_base = hw->ctrl_bar + NFP_VDPA_NOTIFY_ADDR_BASE;
69 [ # # ]: 0 : for (queue = 0; queue < NFP_VDPA_MAX_QUEUES; queue++) {
70 : : uint32_t idx = queue * 2;
71 : :
72 : : /* RX */
73 : 0 : vdpa_hw->notify_addr[idx] = notify_base;
74 : 0 : notify_base += NFP_VDPA_NOTIFY_ADDR_INTERVAL;
75 : : /* TX */
76 : 0 : vdpa_hw->notify_addr[idx + 1] = notify_base;
77 : 0 : notify_base += NFP_VDPA_NOTIFY_ADDR_INTERVAL;
78 : :
79 : 0 : vdpa_hw->notify_region = queue;
80 : 0 : DRV_CORE_LOG(DEBUG, "notify_addr[%d] at %p, notify_addr[%d] at %p",
81 : : idx, vdpa_hw->notify_addr[idx],
82 : : idx + 1, vdpa_hw->notify_addr[idx + 1]);
83 : : }
84 : :
85 : 0 : vdpa_hw->features = (1ULL << VIRTIO_F_VERSION_1) |
86 : : (1ULL << VIRTIO_F_IN_ORDER) |
87 : : (1ULL << VHOST_USER_F_PROTOCOL_FEATURES);
88 : :
89 : 0 : return 0;
90 : : }
91 : :
92 : : static uint32_t
93 : : nfp_vdpa_check_offloads(void)
94 : : {
95 : : return NFP_NET_CFG_CTRL_SCATTER |
96 : : NFP_NET_CFG_CTRL_IN_ORDER;
97 : : }
98 : :
99 : : int
100 : 0 : nfp_vdpa_hw_start(struct nfp_vdpa_hw *vdpa_hw,
101 : : int vid)
102 : : {
103 : : int ret;
104 : : uint32_t update;
105 : : uint32_t new_ctrl;
106 : : struct timespec wait_tst;
107 : 0 : struct nfp_hw *hw = &vdpa_hw->super;
108 : : uint8_t mac_addr[RTE_ETHER_ADDR_LEN];
109 : :
110 : 0 : nn_cfg_writeq(hw, NFP_NET_CFG_TXR_ADDR(0), vdpa_hw->vring[1].desc);
111 [ # # ]: 0 : nn_cfg_writeb(hw, NFP_NET_CFG_TXR_SZ(0), rte_log2_u32(vdpa_hw->vring[1].size));
112 : 0 : nn_cfg_writeq(hw, NFP_NET_CFG_TXR_ADDR(1), vdpa_hw->vring[1].avail);
113 : 0 : nn_cfg_writeq(hw, NFP_NET_CFG_TXR_ADDR(2), vdpa_hw->vring[1].used);
114 : :
115 : 0 : nn_cfg_writeq(hw, NFP_NET_CFG_RXR_ADDR(0), vdpa_hw->vring[0].desc);
116 [ # # ]: 0 : nn_cfg_writeb(hw, NFP_NET_CFG_RXR_SZ(0), rte_log2_u32(vdpa_hw->vring[0].size));
117 : 0 : nn_cfg_writeq(hw, NFP_NET_CFG_RXR_ADDR(1), vdpa_hw->vring[0].avail);
118 : 0 : nn_cfg_writeq(hw, NFP_NET_CFG_RXR_ADDR(2), vdpa_hw->vring[0].used);
119 : :
120 : : rte_wmb();
121 : :
122 : 0 : nfp_disable_queues(hw);
123 : 0 : nfp_enable_queues(hw, NFP_VDPA_MAX_QUEUES, NFP_VDPA_MAX_QUEUES);
124 : :
125 : : new_ctrl = nfp_vdpa_check_offloads();
126 : :
127 : : nn_cfg_writel(hw, NFP_NET_CFG_MTU, 9216);
128 : : nn_cfg_writel(hw, NFP_NET_CFG_FLBUFSZ, 10240);
129 : :
130 : : /* TODO: Temporary set MAC to fixed value fe:1b:ac:05:a5:22 */
131 : 0 : mac_addr[0] = 0xfe;
132 : 0 : mac_addr[1] = 0x1b;
133 : 0 : mac_addr[2] = 0xac;
134 : 0 : mac_addr[3] = 0x05;
135 : 0 : mac_addr[4] = 0xa5;
136 : 0 : mac_addr[5] = (0x22 + vid);
137 : :
138 : : /* Writing new MAC to the specific port BAR address */
139 : 0 : nfp_write_mac(hw, (uint8_t *)mac_addr);
140 : :
141 : : /* Enable device */
142 : : new_ctrl |= NFP_NET_CFG_CTRL_ENABLE;
143 : :
144 : : /* Signal the NIC about the change */
145 : : update = NFP_NET_CFG_UPDATE_MACADDR |
146 : : NFP_NET_CFG_UPDATE_GEN |
147 : : NFP_NET_CFG_UPDATE_RING;
148 : :
149 : 0 : ret = nfp_reconfig(hw, new_ctrl, update);
150 [ # # ]: 0 : if (ret < 0)
151 : : return -EIO;
152 : :
153 : 0 : hw->ctrl = new_ctrl;
154 : :
155 : 0 : DRV_CORE_LOG(DEBUG, "Enabling the device, sleep 1 seconds...");
156 : 0 : wait_tst.tv_sec = 1;
157 : 0 : wait_tst.tv_nsec = 0;
158 : 0 : nanosleep(&wait_tst, 0);
159 : :
160 : 0 : return 0;
161 : : }
162 : :
163 : : void
164 : 0 : nfp_vdpa_hw_stop(struct nfp_vdpa_hw *vdpa_hw)
165 : : {
166 : 0 : nfp_disable_queues(&vdpa_hw->super);
167 : 0 : }
168 : :
169 : : /*
170 : : * This offset is used for mmaping the notify area. It implies it needs
171 : : * to be a multiple of PAGE_SIZE.
172 : : * For debugging, using notify region 0 with an offset of 4K. This should
173 : : * point to the conf bar.
174 : : */
175 : : uint64_t
176 : 0 : nfp_vdpa_get_queue_notify_offset(struct nfp_vdpa_hw *vdpa_hw __rte_unused,
177 : : int qid)
178 : : {
179 : 0 : return NFP_VDPA_NOTIFY_ADDR_BASE + ((uint64_t)qid * NFP_VDPA_NOTIFY_ADDR_INTERVAL);
180 : : }
181 : :
182 : : /*
183 : : * With just one queue the increment is 0, which does not
184 : : * incremente the counter but will raise a queue event due
185 : : * to queue configured for watermark events.
186 : : */
187 : : void
188 : 0 : nfp_vdpa_notify_queue(struct nfp_vdpa_hw *vdpa_hw,
189 : : uint16_t qid)
190 : : {
191 : 0 : nfp_qcp_notify_ptr_add(vdpa_hw->notify_addr[qid],
192 : : NFP_QCP_NOTIFY_WRITE_PTR, qid);
193 : 0 : }
|