cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mbx.c (8162B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* Copyright(c) 2009 - 2018 Intel Corporation. */
      3
      4#include "mbx.h"
      5
      6/**
      7 *  e1000_poll_for_msg - Wait for message notification
      8 *  @hw: pointer to the HW structure
      9 *
     10 *  returns SUCCESS if it successfully received a message notification
     11 **/
     12static s32 e1000_poll_for_msg(struct e1000_hw *hw)
     13{
     14	struct e1000_mbx_info *mbx = &hw->mbx;
     15	int countdown = mbx->timeout;
     16
     17	if (!mbx->ops.check_for_msg)
     18		goto out;
     19
     20	while (countdown && mbx->ops.check_for_msg(hw)) {
     21		countdown--;
     22		udelay(mbx->usec_delay);
     23	}
     24
     25	/* if we failed, all future posted messages fail until reset */
     26	if (!countdown)
     27		mbx->timeout = 0;
     28out:
     29	return countdown ? E1000_SUCCESS : -E1000_ERR_MBX;
     30}
     31
     32/**
     33 *  e1000_poll_for_ack - Wait for message acknowledgment
     34 *  @hw: pointer to the HW structure
     35 *
     36 *  returns SUCCESS if it successfully received a message acknowledgment
     37 **/
     38static s32 e1000_poll_for_ack(struct e1000_hw *hw)
     39{
     40	struct e1000_mbx_info *mbx = &hw->mbx;
     41	int countdown = mbx->timeout;
     42
     43	if (!mbx->ops.check_for_ack)
     44		goto out;
     45
     46	while (countdown && mbx->ops.check_for_ack(hw)) {
     47		countdown--;
     48		udelay(mbx->usec_delay);
     49	}
     50
     51	/* if we failed, all future posted messages fail until reset */
     52	if (!countdown)
     53		mbx->timeout = 0;
     54out:
     55	return countdown ? E1000_SUCCESS : -E1000_ERR_MBX;
     56}
     57
     58/**
     59 *  e1000_read_posted_mbx - Wait for message notification and receive message
     60 *  @hw: pointer to the HW structure
     61 *  @msg: The message buffer
     62 *  @size: Length of buffer
     63 *
     64 *  returns SUCCESS if it successfully received a message notification and
     65 *  copied it into the receive buffer.
     66 **/
     67static s32 e1000_read_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size)
     68{
     69	struct e1000_mbx_info *mbx = &hw->mbx;
     70	s32 ret_val = -E1000_ERR_MBX;
     71
     72	if (!mbx->ops.read)
     73		goto out;
     74
     75	ret_val = e1000_poll_for_msg(hw);
     76
     77	/* if ack received read message, otherwise we timed out */
     78	if (!ret_val)
     79		ret_val = mbx->ops.read(hw, msg, size);
     80out:
     81	return ret_val;
     82}
     83
     84/**
     85 *  e1000_write_posted_mbx - Write a message to the mailbox, wait for ack
     86 *  @hw: pointer to the HW structure
     87 *  @msg: The message buffer
     88 *  @size: Length of buffer
     89 *
     90 *  returns SUCCESS if it successfully copied message into the buffer and
     91 *  received an ack to that message within delay * timeout period
     92 **/
     93static s32 e1000_write_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size)
     94{
     95	struct e1000_mbx_info *mbx = &hw->mbx;
     96	s32 ret_val = -E1000_ERR_MBX;
     97
     98	/* exit if we either can't write or there isn't a defined timeout */
     99	if (!mbx->ops.write || !mbx->timeout)
    100		goto out;
    101
    102	/* send msg*/
    103	ret_val = mbx->ops.write(hw, msg, size);
    104
    105	/* if msg sent wait until we receive an ack */
    106	if (!ret_val)
    107		ret_val = e1000_poll_for_ack(hw);
    108out:
    109	return ret_val;
    110}
    111
    112/**
    113 *  e1000_read_v2p_mailbox - read v2p mailbox
    114 *  @hw: pointer to the HW structure
    115 *
    116 *  This function is used to read the v2p mailbox without losing the read to
    117 *  clear status bits.
    118 **/
    119static u32 e1000_read_v2p_mailbox(struct e1000_hw *hw)
    120{
    121	u32 v2p_mailbox = er32(V2PMAILBOX(0));
    122
    123	v2p_mailbox |= hw->dev_spec.vf.v2p_mailbox;
    124	hw->dev_spec.vf.v2p_mailbox |= v2p_mailbox & E1000_V2PMAILBOX_R2C_BITS;
    125
    126	return v2p_mailbox;
    127}
    128
    129/**
    130 *  e1000_check_for_bit_vf - Determine if a status bit was set
    131 *  @hw: pointer to the HW structure
    132 *  @mask: bitmask for bits to be tested and cleared
    133 *
    134 *  This function is used to check for the read to clear bits within
    135 *  the V2P mailbox.
    136 **/
    137static s32 e1000_check_for_bit_vf(struct e1000_hw *hw, u32 mask)
    138{
    139	u32 v2p_mailbox = e1000_read_v2p_mailbox(hw);
    140	s32 ret_val = -E1000_ERR_MBX;
    141
    142	if (v2p_mailbox & mask)
    143		ret_val = E1000_SUCCESS;
    144
    145	hw->dev_spec.vf.v2p_mailbox &= ~mask;
    146
    147	return ret_val;
    148}
    149
    150/**
    151 *  e1000_check_for_msg_vf - checks to see if the PF has sent mail
    152 *  @hw: pointer to the HW structure
    153 *
    154 *  returns SUCCESS if the PF has set the Status bit or else ERR_MBX
    155 **/
    156static s32 e1000_check_for_msg_vf(struct e1000_hw *hw)
    157{
    158	s32 ret_val = -E1000_ERR_MBX;
    159
    160	if (!e1000_check_for_bit_vf(hw, E1000_V2PMAILBOX_PFSTS)) {
    161		ret_val = E1000_SUCCESS;
    162		hw->mbx.stats.reqs++;
    163	}
    164
    165	return ret_val;
    166}
    167
    168/**
    169 *  e1000_check_for_ack_vf - checks to see if the PF has ACK'd
    170 *  @hw: pointer to the HW structure
    171 *
    172 *  returns SUCCESS if the PF has set the ACK bit or else ERR_MBX
    173 **/
    174static s32 e1000_check_for_ack_vf(struct e1000_hw *hw)
    175{
    176	s32 ret_val = -E1000_ERR_MBX;
    177
    178	if (!e1000_check_for_bit_vf(hw, E1000_V2PMAILBOX_PFACK)) {
    179		ret_val = E1000_SUCCESS;
    180		hw->mbx.stats.acks++;
    181	}
    182
    183	return ret_val;
    184}
    185
    186/**
    187 *  e1000_check_for_rst_vf - checks to see if the PF has reset
    188 *  @hw: pointer to the HW structure
    189 *
    190 *  returns true if the PF has set the reset done bit or else false
    191 **/
    192static s32 e1000_check_for_rst_vf(struct e1000_hw *hw)
    193{
    194	s32 ret_val = -E1000_ERR_MBX;
    195
    196	if (!e1000_check_for_bit_vf(hw, (E1000_V2PMAILBOX_RSTD |
    197					 E1000_V2PMAILBOX_RSTI))) {
    198		ret_val = E1000_SUCCESS;
    199		hw->mbx.stats.rsts++;
    200	}
    201
    202	return ret_val;
    203}
    204
    205/**
    206 *  e1000_obtain_mbx_lock_vf - obtain mailbox lock
    207 *  @hw: pointer to the HW structure
    208 *
    209 *  return SUCCESS if we obtained the mailbox lock
    210 **/
    211static s32 e1000_obtain_mbx_lock_vf(struct e1000_hw *hw)
    212{
    213	s32 ret_val = -E1000_ERR_MBX;
    214	int count = 10;
    215
    216	do {
    217		/* Take ownership of the buffer */
    218		ew32(V2PMAILBOX(0), E1000_V2PMAILBOX_VFU);
    219
    220		/* reserve mailbox for VF use */
    221		if (e1000_read_v2p_mailbox(hw) & E1000_V2PMAILBOX_VFU) {
    222			ret_val = 0;
    223			break;
    224		}
    225		udelay(1000);
    226	} while (count-- > 0);
    227
    228	return ret_val;
    229}
    230
    231/**
    232 *  e1000_write_mbx_vf - Write a message to the mailbox
    233 *  @hw: pointer to the HW structure
    234 *  @msg: The message buffer
    235 *  @size: Length of buffer
    236 *
    237 *  returns SUCCESS if it successfully copied message into the buffer
    238 **/
    239static s32 e1000_write_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size)
    240{
    241	s32 err;
    242	u16 i;
    243
    244	lockdep_assert_held(&hw->mbx_lock);
    245
    246	/* lock the mailbox to prevent pf/vf race condition */
    247	err = e1000_obtain_mbx_lock_vf(hw);
    248	if (err)
    249		goto out_no_write;
    250
    251	/* flush any ack or msg as we are going to overwrite mailbox */
    252	e1000_check_for_ack_vf(hw);
    253	e1000_check_for_msg_vf(hw);
    254
    255	/* copy the caller specified message to the mailbox memory buffer */
    256	for (i = 0; i < size; i++)
    257		array_ew32(VMBMEM(0), i, msg[i]);
    258
    259	/* update stats */
    260	hw->mbx.stats.msgs_tx++;
    261
    262	/* Drop VFU and interrupt the PF to tell it a message has been sent */
    263	ew32(V2PMAILBOX(0), E1000_V2PMAILBOX_REQ);
    264
    265out_no_write:
    266	return err;
    267}
    268
    269/**
    270 *  e1000_read_mbx_vf - Reads a message from the inbox intended for VF
    271 *  @hw: pointer to the HW structure
    272 *  @msg: The message buffer
    273 *  @size: Length of buffer
    274 *
    275 *  returns SUCCESS if it successfully read message from buffer
    276 **/
    277static s32 e1000_read_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size)
    278{
    279	s32 err;
    280	u16 i;
    281
    282	lockdep_assert_held(&hw->mbx_lock);
    283
    284	/* lock the mailbox to prevent pf/vf race condition */
    285	err = e1000_obtain_mbx_lock_vf(hw);
    286	if (err)
    287		goto out_no_read;
    288
    289	/* copy the message from the mailbox memory buffer */
    290	for (i = 0; i < size; i++)
    291		msg[i] = array_er32(VMBMEM(0), i);
    292
    293	/* Acknowledge receipt and release mailbox, then we're done */
    294	ew32(V2PMAILBOX(0), E1000_V2PMAILBOX_ACK);
    295
    296	/* update stats */
    297	hw->mbx.stats.msgs_rx++;
    298
    299out_no_read:
    300	return err;
    301}
    302
    303/**
    304 *  e1000_init_mbx_params_vf - set initial values for VF mailbox
    305 *  @hw: pointer to the HW structure
    306 *
    307 *  Initializes the hw->mbx struct to correct values for VF mailbox
    308 */
    309s32 e1000_init_mbx_params_vf(struct e1000_hw *hw)
    310{
    311	struct e1000_mbx_info *mbx = &hw->mbx;
    312
    313	/* start mailbox as timed out and let the reset_hw call set the timeout
    314	 * value to being communications
    315	 */
    316	mbx->timeout = 0;
    317	mbx->usec_delay = E1000_VF_MBX_INIT_DELAY;
    318
    319	mbx->size = E1000_VFMAILBOX_SIZE;
    320
    321	mbx->ops.read = e1000_read_mbx_vf;
    322	mbx->ops.write = e1000_write_mbx_vf;
    323	mbx->ops.read_posted = e1000_read_posted_mbx;
    324	mbx->ops.write_posted = e1000_write_posted_mbx;
    325	mbx->ops.check_for_msg = e1000_check_for_msg_vf;
    326	mbx->ops.check_for_ack = e1000_check_for_ack_vf;
    327	mbx->ops.check_for_rst = e1000_check_for_rst_vf;
    328
    329	mbx->stats.msgs_tx = 0;
    330	mbx->stats.msgs_rx = 0;
    331	mbx->stats.reqs = 0;
    332	mbx->stats.acks = 0;
    333	mbx->stats.rsts = 0;
    334
    335	return E1000_SUCCESS;
    336}