brintos

brintos / linux-shallow public Read only

0
0
Text · 10.5 KiB · d67d77e Raw
436 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright(c) 1999 - 2018 Intel Corporation. */3 4#include <linux/pci.h>5#include <linux/delay.h>6#include "ixgbe.h"7#include "ixgbe_mbx.h"8 9/**10 *  ixgbe_read_mbx - Reads a message from the mailbox11 *  @hw: pointer to the HW structure12 *  @msg: The message buffer13 *  @size: Length of buffer14 *  @mbx_id: id of mailbox to read15 *16 *  returns SUCCESS if it successfully read message from buffer17 **/18int ixgbe_read_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)19{20	struct ixgbe_mbx_info *mbx = &hw->mbx;21 22	/* limit read to size of mailbox */23	if (size > mbx->size)24		size = mbx->size;25 26	if (!mbx->ops)27		return -EIO;28 29	return mbx->ops->read(hw, msg, size, mbx_id);30}31 32/**33 *  ixgbe_write_mbx - Write a message to the mailbox34 *  @hw: pointer to the HW structure35 *  @msg: The message buffer36 *  @size: Length of buffer37 *  @mbx_id: id of mailbox to write38 *39 *  returns SUCCESS if it successfully copied message into the buffer40 **/41int ixgbe_write_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)42{43	struct ixgbe_mbx_info *mbx = &hw->mbx;44 45	if (size > mbx->size)46		return -EINVAL;47 48	if (!mbx->ops)49		return -EIO;50 51	return mbx->ops->write(hw, msg, size, mbx_id);52}53 54/**55 *  ixgbe_check_for_msg - checks to see if someone sent us mail56 *  @hw: pointer to the HW structure57 *  @mbx_id: id of mailbox to check58 *59 *  returns SUCCESS if the Status bit was found or else ERR_MBX60 **/61int ixgbe_check_for_msg(struct ixgbe_hw *hw, u16 mbx_id)62{63	struct ixgbe_mbx_info *mbx = &hw->mbx;64 65	if (!mbx->ops)66		return -EIO;67 68	return mbx->ops->check_for_msg(hw, mbx_id);69}70 71/**72 *  ixgbe_check_for_ack - checks to see if someone sent us ACK73 *  @hw: pointer to the HW structure74 *  @mbx_id: id of mailbox to check75 *76 *  returns SUCCESS if the Status bit was found or else ERR_MBX77 **/78int ixgbe_check_for_ack(struct ixgbe_hw *hw, u16 mbx_id)79{80	struct ixgbe_mbx_info *mbx = &hw->mbx;81 82	if (!mbx->ops)83		return -EIO;84 85	return mbx->ops->check_for_ack(hw, mbx_id);86}87 88/**89 *  ixgbe_check_for_rst - checks to see if other side has reset90 *  @hw: pointer to the HW structure91 *  @mbx_id: id of mailbox to check92 *93 *  returns SUCCESS if the Status bit was found or else ERR_MBX94 **/95int ixgbe_check_for_rst(struct ixgbe_hw *hw, u16 mbx_id)96{97	struct ixgbe_mbx_info *mbx = &hw->mbx;98 99	if (!mbx->ops)100		return -EIO;101 102	return mbx->ops->check_for_rst(hw, mbx_id);103}104 105/**106 *  ixgbe_poll_for_msg - Wait for message notification107 *  @hw: pointer to the HW structure108 *  @mbx_id: id of mailbox to write109 *110 *  returns SUCCESS if it successfully received a message notification111 **/112static int ixgbe_poll_for_msg(struct ixgbe_hw *hw, u16 mbx_id)113{114	struct ixgbe_mbx_info *mbx = &hw->mbx;115	int countdown = mbx->timeout;116 117	if (!countdown || !mbx->ops)118		return -EIO;119 120	while (mbx->ops->check_for_msg(hw, mbx_id)) {121		countdown--;122		if (!countdown)123			return -EIO;124		udelay(mbx->usec_delay);125	}126 127	return 0;128}129 130/**131 *  ixgbe_poll_for_ack - Wait for message acknowledgement132 *  @hw: pointer to the HW structure133 *  @mbx_id: id of mailbox to write134 *135 *  returns SUCCESS if it successfully received a message acknowledgement136 **/137static int ixgbe_poll_for_ack(struct ixgbe_hw *hw, u16 mbx_id)138{139	struct ixgbe_mbx_info *mbx = &hw->mbx;140	int countdown = mbx->timeout;141 142	if (!countdown || !mbx->ops)143		return -EIO;144 145	while (mbx->ops->check_for_ack(hw, mbx_id)) {146		countdown--;147		if (!countdown)148			return -EIO;149		udelay(mbx->usec_delay);150	}151 152	return 0;153}154 155/**156 *  ixgbe_read_posted_mbx - Wait for message notification and receive message157 *  @hw: pointer to the HW structure158 *  @msg: The message buffer159 *  @size: Length of buffer160 *  @mbx_id: id of mailbox to write161 *162 *  returns SUCCESS if it successfully received a message notification and163 *  copied it into the receive buffer.164 **/165static int ixgbe_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size,166				 u16 mbx_id)167{168	struct ixgbe_mbx_info *mbx = &hw->mbx;169	int ret_val;170 171	if (!mbx->ops)172		return -EIO;173 174	ret_val = ixgbe_poll_for_msg(hw, mbx_id);175	if (ret_val)176		return ret_val;177 178	/* if ack received read message */179	return mbx->ops->read(hw, msg, size, mbx_id);180}181 182/**183 *  ixgbe_write_posted_mbx - Write a message to the mailbox, wait for ack184 *  @hw: pointer to the HW structure185 *  @msg: The message buffer186 *  @size: Length of buffer187 *  @mbx_id: id of mailbox to write188 *189 *  returns SUCCESS if it successfully copied message into the buffer and190 *  received an ack to that message within delay * timeout period191 **/192static int ixgbe_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size,193				  u16 mbx_id)194{195	struct ixgbe_mbx_info *mbx = &hw->mbx;196	int ret_val;197 198	/* exit if either we can't write or there isn't a defined timeout */199	if (!mbx->ops || !mbx->timeout)200		return -EIO;201 202	/* send msg */203	ret_val = mbx->ops->write(hw, msg, size, mbx_id);204	if (ret_val)205		return ret_val;206 207	/* if msg sent wait until we receive an ack */208	return ixgbe_poll_for_ack(hw, mbx_id);209}210 211static int ixgbe_check_for_bit_pf(struct ixgbe_hw *hw, u32 mask, s32 index)212{213	u32 mbvficr = IXGBE_READ_REG(hw, IXGBE_MBVFICR(index));214 215	if (mbvficr & mask) {216		IXGBE_WRITE_REG(hw, IXGBE_MBVFICR(index), mask);217		return 0;218	}219 220	return -EIO;221}222 223/**224 *  ixgbe_check_for_msg_pf - checks to see if the VF has sent mail225 *  @hw: pointer to the HW structure226 *  @vf_number: the VF index227 *228 *  returns SUCCESS if the VF has set the Status bit or else ERR_MBX229 **/230static int ixgbe_check_for_msg_pf(struct ixgbe_hw *hw, u16 vf_number)231{232	int index = IXGBE_MBVFICR_INDEX(vf_number);233	u32 vf_bit = vf_number % 16;234 235	if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFREQ_VF1 << vf_bit,236				    index)) {237		hw->mbx.stats.reqs++;238		return 0;239	}240 241	return -EIO;242}243 244/**245 *  ixgbe_check_for_ack_pf - checks to see if the VF has ACKed246 *  @hw: pointer to the HW structure247 *  @vf_number: the VF index248 *249 *  returns SUCCESS if the VF has set the Status bit or else ERR_MBX250 **/251static int ixgbe_check_for_ack_pf(struct ixgbe_hw *hw, u16 vf_number)252{253	int index = IXGBE_MBVFICR_INDEX(vf_number);254	u32 vf_bit = vf_number % 16;255 256	if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFACK_VF1 << vf_bit,257				    index)) {258		hw->mbx.stats.acks++;259		return 0;260	}261 262	return -EIO;263}264 265/**266 *  ixgbe_check_for_rst_pf - checks to see if the VF has reset267 *  @hw: pointer to the HW structure268 *  @vf_number: the VF index269 *270 *  returns SUCCESS if the VF has set the Status bit or else ERR_MBX271 **/272static int ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, u16 vf_number)273{274	u32 reg_offset = (vf_number < 32) ? 0 : 1;275	u32 vf_shift = vf_number % 32;276	u32 vflre = 0;277 278	switch (hw->mac.type) {279	case ixgbe_mac_82599EB:280		vflre = IXGBE_READ_REG(hw, IXGBE_VFLRE(reg_offset));281		break;282	case ixgbe_mac_X540:283	case ixgbe_mac_X550:284	case ixgbe_mac_X550EM_x:285	case ixgbe_mac_x550em_a:286		vflre = IXGBE_READ_REG(hw, IXGBE_VFLREC(reg_offset));287		break;288	default:289		break;290	}291 292	if (vflre & BIT(vf_shift)) {293		IXGBE_WRITE_REG(hw, IXGBE_VFLREC(reg_offset), BIT(vf_shift));294		hw->mbx.stats.rsts++;295		return 0;296	}297 298	return -EIO;299}300 301/**302 *  ixgbe_obtain_mbx_lock_pf - obtain mailbox lock303 *  @hw: pointer to the HW structure304 *  @vf_number: the VF index305 *306 *  return SUCCESS if we obtained the mailbox lock307 **/308static int ixgbe_obtain_mbx_lock_pf(struct ixgbe_hw *hw, u16 vf_number)309{310	u32 p2v_mailbox;311 312	/* Take ownership of the buffer */313	IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_PFU);314 315	/* reserve mailbox for vf use */316	p2v_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_number));317	if (p2v_mailbox & IXGBE_PFMAILBOX_PFU)318		return 0;319 320	return -EIO;321}322 323/**324 *  ixgbe_write_mbx_pf - Places a message in the mailbox325 *  @hw: pointer to the HW structure326 *  @msg: The message buffer327 *  @size: Length of buffer328 *  @vf_number: the VF index329 *330 *  returns SUCCESS if it successfully copied message into the buffer331 **/332static int ixgbe_write_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size,333			      u16 vf_number)334{335	int ret_val;336	u16 i;337 338	/* lock the mailbox to prevent pf/vf race condition */339	ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number);340	if (ret_val)341		return ret_val;342 343	/* flush msg and acks as we are overwriting the message buffer */344	ixgbe_check_for_msg_pf(hw, vf_number);345	ixgbe_check_for_ack_pf(hw, vf_number);346 347	/* copy the caller specified message to the mailbox memory buffer */348	for (i = 0; i < size; i++)349		IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i, msg[i]);350 351	/* Interrupt VF to tell it a message has been sent and release buffer*/352	IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_STS);353 354	/* update stats */355	hw->mbx.stats.msgs_tx++;356 357	return 0;358}359 360/**361 *  ixgbe_read_mbx_pf - Read a message from the mailbox362 *  @hw: pointer to the HW structure363 *  @msg: The message buffer364 *  @size: Length of buffer365 *  @vf_number: the VF index366 *367 *  This function copies a message from the mailbox buffer to the caller's368 *  memory buffer.  The presumption is that the caller knows that there was369 *  a message due to a VF request so no polling for message is needed.370 **/371static int ixgbe_read_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size,372			     u16 vf_number)373{374	int ret_val;375	u16 i;376 377	/* lock the mailbox to prevent pf/vf race condition */378	ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number);379	if (ret_val)380		return ret_val;381 382	/* copy the message to the mailbox memory buffer */383	for (i = 0; i < size; i++)384		msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i);385 386	/* Acknowledge the message and release buffer */387	IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_ACK);388 389	/* update stats */390	hw->mbx.stats.msgs_rx++;391 392	return 0;393}394 395#ifdef CONFIG_PCI_IOV396/**397 *  ixgbe_init_mbx_params_pf - set initial values for pf mailbox398 *  @hw: pointer to the HW structure399 *400 *  Initializes the hw->mbx struct to correct values for pf mailbox401 */402void ixgbe_init_mbx_params_pf(struct ixgbe_hw *hw)403{404	struct ixgbe_mbx_info *mbx = &hw->mbx;405 406	if (hw->mac.type != ixgbe_mac_82599EB &&407	    hw->mac.type != ixgbe_mac_X550 &&408	    hw->mac.type != ixgbe_mac_X550EM_x &&409	    hw->mac.type != ixgbe_mac_x550em_a &&410	    hw->mac.type != ixgbe_mac_X540)411		return;412 413	mbx->timeout = 0;414	mbx->usec_delay = 0;415 416	mbx->stats.msgs_tx = 0;417	mbx->stats.msgs_rx = 0;418	mbx->stats.reqs = 0;419	mbx->stats.acks = 0;420	mbx->stats.rsts = 0;421 422	mbx->size = IXGBE_VFMAILBOX_SIZE;423}424#endif /* CONFIG_PCI_IOV */425 426const struct ixgbe_mbx_operations mbx_ops_generic = {427	.read                   = ixgbe_read_mbx_pf,428	.write                  = ixgbe_write_mbx_pf,429	.read_posted            = ixgbe_read_posted_mbx,430	.write_posted           = ixgbe_write_posted_mbx,431	.check_for_msg          = ixgbe_check_for_msg_pf,432	.check_for_ack          = ixgbe_check_for_ack_pf,433	.check_for_rst          = ixgbe_check_for_rst_pf,434};435 436