hclgevf_mbx.c 9.9 KB
Newer Older
1 2 3 4 5 6 7
// SPDX-License-Identifier: GPL-2.0+
// Copyright (c) 2016-2017 Hisilicon Limited.

#include "hclge_mbx.h"
#include "hclgevf_main.h"
#include "hnae3.h"

8 9 10
#define CREATE_TRACE_POINTS
#include "hclgevf_trace.h"

11 12 13 14 15
static int hclgevf_resp_to_errno(u16 resp_code)
{
	return resp_code ? -resp_code : 0;
}

16
#define HCLGEVF_MBX_MATCH_ID_START	1
17 18 19 20 21 22 23 24
static void hclgevf_reset_mbx_resp_status(struct hclgevf_dev *hdev)
{
	/* this function should be called with mbx_resp.mbx_mutex held
	 * to prtect the received_response from race condition
	 */
	hdev->mbx_resp.received_resp  = false;
	hdev->mbx_resp.origin_mbx_msg = 0;
	hdev->mbx_resp.resp_status    = 0;
25 26 27 28
	hdev->mbx_resp.match_id++;
	/* Update match_id and ensure the value of match_id is not zero */
	if (hdev->mbx_resp.match_id == 0)
		hdev->mbx_resp.match_id = HCLGEVF_MBX_MATCH_ID_START;
29 30 31 32 33 34 35 36 37 38 39 40 41
	memset(hdev->mbx_resp.additional_info, 0, HCLGE_MBX_MAX_RESP_DATA_SIZE);
}

/* hclgevf_get_mbx_resp: used to get a response from PF after VF sends a mailbox
 * message to PF.
 * @hdev: pointer to struct hclgevf_dev
 * @resp_msg: pointer to store the original message type and response status
 * @len: the resp_msg data array length.
 */
static int hclgevf_get_mbx_resp(struct hclgevf_dev *hdev, u16 code0, u16 code1,
				u8 *resp_data, u16 resp_len)
{
#define HCLGEVF_MAX_TRY_TIMES	500
P
Peng Li 已提交
42
#define HCLGEVF_SLEEP_USECOND	1000
43 44 45 46 47 48
	struct hclgevf_mbx_resp_status *mbx_resp;
	u16 r_code0, r_code1;
	int i = 0;

	if (resp_len > HCLGE_MBX_MAX_RESP_DATA_SIZE) {
		dev_err(&hdev->pdev->dev,
49
			"VF mbx response len(=%u) exceeds maximum(=%u)\n",
50 51 52 53 54 55
			resp_len,
			HCLGE_MBX_MAX_RESP_DATA_SIZE);
		return -EINVAL;
	}

	while ((!hdev->mbx_resp.received_resp) && (i < HCLGEVF_MAX_TRY_TIMES)) {
56 57 58
		if (test_bit(HCLGEVF_STATE_CMD_DISABLE, &hdev->state))
			return -EIO;

P
Peng Li 已提交
59
		usleep_range(HCLGEVF_SLEEP_USECOND, HCLGEVF_SLEEP_USECOND * 2);
60 61 62 63 64
		i++;
	}

	if (i >= HCLGEVF_MAX_TRY_TIMES) {
		dev_err(&hdev->pdev->dev,
65
			"VF could not get mbx(%u,%u) resp(=%d) from PF in %d tries\n",
66
			code0, code1, hdev->mbx_resp.received_resp, i);
67 68 69 70 71 72
		return -EIO;
	}

	mbx_resp = &hdev->mbx_resp;
	r_code0 = (u16)(mbx_resp->origin_mbx_msg >> 16);
	r_code1 = (u16)(mbx_resp->origin_mbx_msg & 0xff);
73 74 75 76

	if (mbx_resp->resp_status)
		return mbx_resp->resp_status;

77 78 79 80 81 82 83
	if (resp_data)
		memcpy(resp_data, &mbx_resp->additional_info[0], resp_len);

	hclgevf_reset_mbx_resp_status(hdev);

	if (!(r_code0 == code0 && r_code1 == code1 && !mbx_resp->resp_status)) {
		dev_err(&hdev->pdev->dev,
84
			"VF could not match resp code(code0=%u,code1=%u), %d\n",
85
			code0, code1, mbx_resp->resp_status);
86
		dev_err(&hdev->pdev->dev,
87
			"VF could not match resp r_code(r_code0=%u,r_code1=%u)\n",
88
			r_code0, r_code1);
89 90 91 92 93 94
		return -EIO;
	}

	return 0;
}

95 96
int hclgevf_send_mbx_msg(struct hclgevf_dev *hdev,
			 struct hclge_vf_to_pf_msg *send_msg, bool need_resp,
97 98 99 100 101 102 103 104
			 u8 *resp_data, u16 resp_len)
{
	struct hclge_mbx_vf_to_pf_cmd *req;
	struct hclgevf_desc desc;
	int status;

	req = (struct hclge_mbx_vf_to_pf_cmd *)desc.data;

105
	if (!send_msg) {
106
		dev_err(&hdev->pdev->dev,
107
			"failed to send mbx, msg is NULL\n");
108 109 110 111
		return -EINVAL;
	}

	hclgevf_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_MBX_VF_TO_PF, false);
112 113 114
	if (need_resp)
		hnae3_set_bit(req->mbx_need_resp, HCLGE_MBX_NEED_RESP_B, 1);

115
	memcpy(&req->msg, send_msg, sizeof(struct hclge_vf_to_pf_msg));
116

117 118
	trace_hclge_vf_mbx_send(hdev, req);

119 120 121 122
	/* synchronous send */
	if (need_resp) {
		mutex_lock(&hdev->mbx_resp.mbx_mutex);
		hclgevf_reset_mbx_resp_status(hdev);
123
		req->match_id = hdev->mbx_resp.match_id;
124 125 126 127 128 129 130 131 132
		status = hclgevf_cmd_send(&hdev->hw, &desc, 1);
		if (status) {
			dev_err(&hdev->pdev->dev,
				"VF failed(=%d) to send mbx message to PF\n",
				status);
			mutex_unlock(&hdev->mbx_resp.mbx_mutex);
			return status;
		}

133 134
		status = hclgevf_get_mbx_resp(hdev, send_msg->code,
					      send_msg->subcode, resp_data,
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
					      resp_len);
		mutex_unlock(&hdev->mbx_resp.mbx_mutex);
	} else {
		/* asynchronous send */
		status = hclgevf_cmd_send(&hdev->hw, &desc, 1);
		if (status) {
			dev_err(&hdev->pdev->dev,
				"VF failed(=%d) to send mbx message to PF\n",
				status);
			return status;
		}
	}

	return status;
}

151 152 153 154 155 156 157
static bool hclgevf_cmd_crq_empty(struct hclgevf_hw *hw)
{
	u32 tail = hclgevf_read_dev(hw, HCLGEVF_NIC_CRQ_TAIL_REG);

	return tail == hw->cmq.crq.next_to_use;
}

158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
static void hclgevf_handle_mbx_response(struct hclgevf_dev *hdev,
					struct hclge_mbx_pf_to_vf_cmd *req)
{
	struct hclgevf_mbx_resp_status *resp = &hdev->mbx_resp;

	if (resp->received_resp)
		dev_warn(&hdev->pdev->dev,
			 "VF mbx resp flag not clear(%u)\n",
			 req->msg.vf_mbx_msg_code);

	resp->origin_mbx_msg =
			(req->msg.vf_mbx_msg_code << 16);
	resp->origin_mbx_msg |= req->msg.vf_mbx_msg_subcode;
	resp->resp_status =
		hclgevf_resp_to_errno(req->msg.resp_status);
	memcpy(resp->additional_info, req->msg.resp_data,
	       HCLGE_MBX_MAX_RESP_DATA_SIZE * sizeof(u8));
	if (req->match_id) {
		/* If match_id is not zero, it means PF support match_id.
		 * if the match_id is right, VF get the right response, or
		 * ignore the response. and driver will clear hdev->mbx_resp
		 * when send next message which need response.
		 */
		if (req->match_id == resp->match_id)
			resp->received_resp = true;
	} else {
		resp->received_resp = true;
	}
}

static void hclgevf_handle_mbx_msg(struct hclgevf_dev *hdev,
				   struct hclge_mbx_pf_to_vf_cmd *req)
{
	/* we will drop the async msg if we find ARQ as full
	 * and continue with next message
	 */
	if (atomic_read(&hdev->arq.count) >=
	    HCLGE_MBX_MAX_ARQ_MSG_NUM) {
		dev_warn(&hdev->pdev->dev,
			 "Async Q full, dropping msg(%u)\n",
			 req->msg.code);
		return;
	}

	/* tail the async message in arq */
	memcpy(hdev->arq.msg_q[hdev->arq.tail], &req->msg,
	       HCLGE_MBX_MAX_ARQ_MSG_SIZE * sizeof(u16));
	hclge_mbx_tail_ptr_move_arq(hdev->arq);
	atomic_inc(&hdev->arq.count);

	hclgevf_mbx_task_schedule(hdev);
}

211 212 213 214 215
void hclgevf_mbx_handler(struct hclgevf_dev *hdev)
{
	struct hclge_mbx_pf_to_vf_cmd *req;
	struct hclgevf_cmq_ring *crq;
	struct hclgevf_desc *desc;
216
	u16 flag;
217 218 219

	crq = &hdev->hw.cmq.crq;

220
	while (!hclgevf_cmd_crq_empty(&hdev->hw)) {
221 222 223 224 225
		if (test_bit(HCLGEVF_STATE_CMD_DISABLE, &hdev->state)) {
			dev_info(&hdev->pdev->dev, "vf crq need init\n");
			return;
		}

226 227 228
		desc = &crq->desc[crq->next_to_use];
		req = (struct hclge_mbx_pf_to_vf_cmd *)desc->data;

229
		flag = le16_to_cpu(crq->desc[crq->next_to_use].flag);
P
Peng Li 已提交
230
		if (unlikely(!hnae3_get_bit(flag, HCLGEVF_CMDQ_RX_OUTVLD_B))) {
231
			dev_warn(&hdev->pdev->dev,
232
				 "dropped invalid mailbox message, code = %u\n",
233
				 req->msg.code);
234 235 236 237 238 239 240

			/* dropping/not processing this invalid message */
			crq->desc[crq->next_to_use].flag = 0;
			hclge_mbx_ring_ptr_move_crq(crq);
			continue;
		}

241 242
		trace_hclge_vf_mbx_get(hdev, req);

243 244 245 246 247 248
		/* synchronous messages are time critical and need preferential
		 * treatment. Therefore, we need to acknowledge all the sync
		 * responses as quickly as possible so that waiting tasks do not
		 * timeout and simultaneously queue the async messages for later
		 * prcessing in context of mailbox task i.e. the slow path.
		 */
249
		switch (req->msg.code) {
250
		case HCLGE_MBX_PF_VF_RESP:
251
			hclgevf_handle_mbx_response(hdev, req);
252 253
			break;
		case HCLGE_MBX_LINK_STAT_CHANGE:
254
		case HCLGE_MBX_ASSERTING_RESET:
255
		case HCLGE_MBX_LINK_STAT_MODE:
256
		case HCLGE_MBX_PUSH_VLAN_INFO:
257
		case HCLGE_MBX_PUSH_PROMISC_INFO:
258
			hclgevf_handle_mbx_msg(hdev, req);
259 260 261
			break;
		default:
			dev_err(&hdev->pdev->dev,
262
				"VF received unsupported(%u) mbx msg from PF\n",
263
				req->msg.code);
264 265
			break;
		}
266
		crq->desc[crq->next_to_use].flag = 0;
267 268 269 270 271 272 273
		hclge_mbx_ring_ptr_move_crq(crq);
	}

	/* Write back CMDQ_RQ header pointer, M7 need this pointer */
	hclgevf_write_dev(&hdev->hw, HCLGEVF_NIC_CRQ_HEAD_REG,
			  crq->next_to_use);
}
274

275 276 277 278 279 280 281 282
static void hclgevf_parse_promisc_info(struct hclgevf_dev *hdev,
				       u16 promisc_info)
{
	if (!promisc_info)
		dev_info(&hdev->pdev->dev,
			 "Promisc mode is closed by host for being untrusted.\n");
}

283 284
void hclgevf_mbx_async_handler(struct hclgevf_dev *hdev)
{
285
	enum hnae3_reset_type reset_type;
286 287
	u16 link_status, state;
	u16 *msg_q, *vlan_info;
288 289 290
	u8 duplex;
	u32 speed;
	u32 tail;
291
	u8 flag;
292
	u8 idx;
293 294 295 296 297

	tail = hdev->arq.tail;

	/* process all the async queue messages */
	while (tail != hdev->arq.head) {
298 299 300 301 302 303
		if (test_bit(HCLGEVF_STATE_CMD_DISABLE, &hdev->state)) {
			dev_info(&hdev->pdev->dev,
				 "vf crq need init in async\n");
			return;
		}

304 305 306 307
		msg_q = hdev->arq.msg_q[hdev->arq.head];

		switch (msg_q[0]) {
		case HCLGE_MBX_LINK_STAT_CHANGE:
308
			link_status = msg_q[1];
309
			memcpy(&speed, &msg_q[2], sizeof(speed));
310
			duplex = (u8)msg_q[4];
311
			flag = (u8)msg_q[5];
312 313 314

			/* update upper layer with new link link status */
			hclgevf_update_speed_duplex(hdev, speed, duplex);
315
			hclgevf_update_link_status(hdev, link_status);
316

317 318 319 320
			if (flag & HCLGE_MBX_PUSH_LINK_STATUS_EN)
				set_bit(HCLGEVF_STATE_PF_PUSH_LINK_STATUS,
					&hdev->state);

321
			break;
322
		case HCLGE_MBX_LINK_STAT_MODE:
323
			idx = (u8)msg_q[1];
324 325 326 327 328 329 330
			if (idx)
				memcpy(&hdev->hw.mac.supported, &msg_q[2],
				       sizeof(unsigned long));
			else
				memcpy(&hdev->hw.mac.advertising, &msg_q[2],
				       sizeof(unsigned long));
			break;
331 332 333 334 335 336
		case HCLGE_MBX_ASSERTING_RESET:
			/* PF has asserted reset hence VF should go in pending
			 * state and poll for the hardware reset status till it
			 * has been completely reset. After this stack should
			 * eventually be re-initialized.
			 */
337
			reset_type = (enum hnae3_reset_type)msg_q[1];
338
			set_bit(reset_type, &hdev->reset_pending);
339 340 341
			set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state);
			hclgevf_reset_task_schedule(hdev);

342
			break;
343
		case HCLGE_MBX_PUSH_VLAN_INFO:
344
			state = msg_q[1];
345 346 347 348
			vlan_info = &msg_q[1];
			hclgevf_update_port_base_vlan_info(hdev, state,
							   (u8 *)vlan_info, 8);
			break;
349 350 351
		case HCLGE_MBX_PUSH_PROMISC_INFO:
			hclgevf_parse_promisc_info(hdev, msg_q[1]);
			break;
352 353
		default:
			dev_err(&hdev->pdev->dev,
354
				"fetched unsupported(%u) message from arq\n",
355 356 357 358 359
				msg_q[0]);
			break;
		}

		hclge_mbx_head_ptr_move_arq(hdev->arq);
360
		atomic_dec(&hdev->arq.count);
361 362 363
		msg_q = hdev->arq.msg_q[hdev->arq.head];
	}
}