Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) 2020 Marvell.
3 : : * All rights reserved.
4 : : * www.marvell.com
5 : : */
6 : :
7 : : #include <rte_alarm.h>
8 : :
9 : : #include "base/bcm_osal.h"
10 : : #include "base/ecore.h"
11 : : #include "base/ecore_sriov.h"
12 : : #include "base/ecore_mcp.h"
13 : : #include "base/ecore_vf.h"
14 : :
15 : : #include "qede_sriov.h"
16 : :
17 : : static void qed_sriov_enable_qid_config(struct ecore_hwfn *hwfn,
18 : : u16 vfid,
19 : : struct ecore_iov_vf_init_params *params)
20 : : {
21 : : u16 num_pf_l2_queues, base, i;
22 : :
23 : : /* Since we have an equal resource distribution per-VF, and we assume
24 : : * PF has acquired its first queues, we start setting sequentially from
25 : : * there.
26 : : */
27 : 0 : num_pf_l2_queues = (u16)FEAT_NUM(hwfn, ECORE_PF_L2_QUE);
28 : :
29 : 0 : base = num_pf_l2_queues + vfid * params->num_queues;
30 : 0 : params->rel_vf_id = vfid;
31 : :
32 [ # # ]: 0 : for (i = 0; i < params->num_queues; i++) {
33 : 0 : params->req_rx_queue[i] = base + i;
34 : 0 : params->req_tx_queue[i] = base + i;
35 : : }
36 : :
37 : : /* PF uses indices 0 for itself; Set vport/RSS afterwards */
38 : 0 : params->vport_id = vfid + 1;
39 : 0 : params->rss_eng_id = vfid + 1;
40 : : }
41 : :
42 : 0 : static void qed_sriov_enable(struct ecore_dev *edev, int num)
43 : : {
44 : : struct ecore_iov_vf_init_params params;
45 : : struct ecore_hwfn *p_hwfn;
46 : : struct ecore_ptt *p_ptt;
47 : : int i, j, rc;
48 : :
49 [ # # ]: 0 : if ((u32)num >= RESC_NUM(&edev->hwfns[0], ECORE_VPORT)) {
50 : 0 : DP_NOTICE(edev, false, "Can start at most %d VFs\n",
51 : : RESC_NUM(&edev->hwfns[0], ECORE_VPORT) - 1);
52 : 0 : return;
53 : : }
54 : :
55 : : OSAL_MEMSET(¶ms, 0, sizeof(struct ecore_iov_vf_init_params));
56 : :
57 [ # # ]: 0 : for_each_hwfn(edev, j) {
58 : : int feat_num;
59 : :
60 : 0 : p_hwfn = &edev->hwfns[j];
61 : 0 : p_ptt = ecore_ptt_acquire(p_hwfn);
62 : 0 : feat_num = FEAT_NUM(p_hwfn, ECORE_VF_L2_QUE) / num;
63 : :
64 : 0 : params.num_queues = OSAL_MIN_T(int, feat_num, 16);
65 : :
66 [ # # ]: 0 : for (i = 0; i < num; i++) {
67 [ # # ]: 0 : if (!ecore_iov_is_valid_vfid(p_hwfn, i, false, true))
68 : 0 : continue;
69 : :
70 : 0 : qed_sriov_enable_qid_config(p_hwfn, i, ¶ms);
71 : :
72 : 0 : rc = ecore_iov_init_hw_for_vf(p_hwfn, p_ptt, ¶ms);
73 [ # # ]: 0 : if (rc) {
74 : 0 : DP_ERR(edev, "Failed to enable VF[%d]\n", i);
75 : 0 : ecore_ptt_release(p_hwfn, p_ptt);
76 : 0 : return;
77 : : }
78 : : }
79 : :
80 : 0 : ecore_ptt_release(p_hwfn, p_ptt);
81 : : }
82 : : }
83 : :
84 : 0 : void qed_sriov_configure(struct ecore_dev *edev, int num_vfs_param)
85 : : {
86 [ # # ]: 0 : if (!IS_ECORE_SRIOV(edev)) {
87 [ # # ]: 0 : DP_VERBOSE(edev, ECORE_MSG_IOV, "SR-IOV is not supported\n");
88 : 0 : return;
89 : : }
90 : :
91 [ # # ]: 0 : if (num_vfs_param)
92 : 0 : qed_sriov_enable(edev, num_vfs_param);
93 : : }
94 : :
95 : 0 : static void qed_handle_vf_msg(struct ecore_hwfn *hwfn)
96 : : {
97 : : u64 events[ECORE_VF_ARRAY_LENGTH];
98 : : struct ecore_ptt *ptt;
99 : : int i;
100 : :
101 : 0 : ptt = ecore_ptt_acquire(hwfn);
102 [ # # ]: 0 : if (!ptt) {
103 : 0 : DP_NOTICE(hwfn, true, "PTT acquire failed\n");
104 : 0 : qed_schedule_iov(hwfn, QED_IOV_WQ_MSG_FLAG);
105 : 0 : return;
106 : : }
107 : :
108 : 0 : ecore_iov_pf_get_pending_events(hwfn, events);
109 : :
110 [ # # ]: 0 : ecore_for_each_vf(hwfn, i) {
111 : : /* Skip VFs with no pending messages */
112 [ # # ]: 0 : if (!ECORE_VF_ARRAY_GET_VFID(events, i))
113 : 0 : continue;
114 : :
115 [ # # ]: 0 : DP_VERBOSE(hwfn, ECORE_MSG_IOV,
116 : : "Handling VF message from VF 0x%02x [Abs 0x%02x]\n",
117 : : i, hwfn->p_dev->p_iov_info->first_vf_in_pf + i);
118 : :
119 : : /* Copy VF's message to PF's request buffer for that VF */
120 [ # # ]: 0 : if (ecore_iov_copy_vf_msg(hwfn, ptt, i))
121 : 0 : continue;
122 : :
123 : 0 : ecore_iov_process_mbx_req(hwfn, ptt, i);
124 : : }
125 : :
126 : 0 : ecore_ptt_release(hwfn, ptt);
127 : : }
128 : :
129 : 0 : static void qed_handle_bulletin_post(struct ecore_hwfn *hwfn)
130 : : {
131 : : struct ecore_ptt *ptt;
132 : : int i;
133 : :
134 : 0 : ptt = ecore_ptt_acquire(hwfn);
135 [ # # ]: 0 : if (!ptt) {
136 : 0 : DP_NOTICE(hwfn, true, "PTT acquire failed\n");
137 : 0 : qed_schedule_iov(hwfn, QED_IOV_WQ_BULLETIN_UPDATE_FLAG);
138 : 0 : return;
139 : : }
140 : :
141 : : /* TODO - at the moment update bulletin board of all VFs.
142 : : * if this proves to costly, we can mark VFs that need their
143 : : * bulletins updated.
144 : : */
145 [ # # ]: 0 : ecore_for_each_vf(hwfn, i)
146 : 0 : ecore_iov_post_vf_bulletin(hwfn, i, ptt);
147 : :
148 : 0 : ecore_ptt_release(hwfn, ptt);
149 : : }
150 : :
151 [ # # ]: 0 : void qed_iov_pf_task(void *arg)
152 : : {
153 : : struct ecore_hwfn *p_hwfn = arg;
154 : : int rc;
155 : :
156 [ # # ]: 0 : if (OSAL_GET_BIT(QED_IOV_WQ_MSG_FLAG, &p_hwfn->iov_task_flags)) {
157 : : OSAL_CLEAR_BIT(QED_IOV_WQ_MSG_FLAG, &p_hwfn->iov_task_flags);
158 : 0 : qed_handle_vf_msg(p_hwfn);
159 : : }
160 : :
161 [ # # ]: 0 : if (OSAL_GET_BIT(QED_IOV_WQ_BULLETIN_UPDATE_FLAG,
162 : : &p_hwfn->iov_task_flags)) {
163 : : OSAL_CLEAR_BIT(QED_IOV_WQ_BULLETIN_UPDATE_FLAG,
164 : : &p_hwfn->iov_task_flags);
165 : 0 : qed_handle_bulletin_post(p_hwfn);
166 : : }
167 : :
168 [ # # ]: 0 : if (OSAL_GET_BIT(QED_IOV_WQ_FLR_FLAG, &p_hwfn->iov_task_flags)) {
169 : 0 : struct ecore_ptt *p_ptt = ecore_ptt_acquire(p_hwfn);
170 : :
171 : : OSAL_CLEAR_BIT(QED_IOV_WQ_FLR_FLAG, &p_hwfn->iov_task_flags);
172 : :
173 [ # # ]: 0 : if (!p_ptt) {
174 : 0 : qed_schedule_iov(p_hwfn, QED_IOV_WQ_FLR_FLAG);
175 : 0 : return;
176 : : }
177 : :
178 : 0 : rc = ecore_iov_vf_flr_cleanup(p_hwfn, p_ptt);
179 [ # # ]: 0 : if (rc)
180 : 0 : qed_schedule_iov(p_hwfn, QED_IOV_WQ_FLR_FLAG);
181 : :
182 : 0 : ecore_ptt_release(p_hwfn, p_ptt);
183 : : }
184 : : }
185 : :
186 : 0 : int qed_schedule_iov(struct ecore_hwfn *p_hwfn, enum qed_iov_wq_flag flag)
187 : : {
188 [ # # ]: 0 : DP_VERBOSE(p_hwfn, ECORE_MSG_IOV, "Scheduling iov task [Flag: %d]\n",
189 : : flag);
190 : :
191 : : OSAL_SET_BIT(flag, &p_hwfn->iov_task_flags);
192 : 0 : return rte_eal_alarm_set(1, qed_iov_pf_task, p_hwfn);
193 : : }
194 : :
195 : 0 : void qed_inform_vf_link_state(struct ecore_hwfn *hwfn)
196 : : {
197 : 0 : struct ecore_hwfn *lead_hwfn = ECORE_LEADING_HWFN(hwfn->p_dev);
198 : : struct ecore_mcp_link_capabilities caps;
199 : : struct ecore_mcp_link_params params;
200 : : struct ecore_mcp_link_state link;
201 : : int i;
202 : :
203 [ # # ]: 0 : if (!hwfn->pf_iov_info)
204 : 0 : return;
205 : :
206 : 0 : memcpy(¶ms, ecore_mcp_get_link_params(lead_hwfn),
207 : : sizeof(params));
208 : 0 : memcpy(&link, ecore_mcp_get_link_state(lead_hwfn), sizeof(link));
209 : 0 : memcpy(&caps, ecore_mcp_get_link_capabilities(lead_hwfn),
210 : : sizeof(caps));
211 : :
212 : : /* Update bulletin of all future possible VFs with link configuration */
213 [ # # ]: 0 : for (i = 0; i < hwfn->p_dev->p_iov_info->total_vfs; i++) {
214 : 0 : ecore_iov_set_link(hwfn, i,
215 : : ¶ms, &link, &caps);
216 : : }
217 : :
218 : 0 : qed_schedule_iov(hwfn, QED_IOV_WQ_BULLETIN_UPDATE_FLAG);
219 : : }
|