Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright(c) 2009 - 2018 Intel Corporation. */
0003 
0004 #include "mbx.h"
0005 
0006 /**
0007  *  e1000_poll_for_msg - Wait for message notification
0008  *  @hw: pointer to the HW structure
0009  *
0010  *  returns SUCCESS if it successfully received a message notification
0011  **/
0012 static s32 e1000_poll_for_msg(struct e1000_hw *hw)
0013 {
0014     struct e1000_mbx_info *mbx = &hw->mbx;
0015     int countdown = mbx->timeout;
0016 
0017     if (!mbx->ops.check_for_msg)
0018         goto out;
0019 
0020     while (countdown && mbx->ops.check_for_msg(hw)) {
0021         countdown--;
0022         udelay(mbx->usec_delay);
0023     }
0024 
0025     /* if we failed, all future posted messages fail until reset */
0026     if (!countdown)
0027         mbx->timeout = 0;
0028 out:
0029     return countdown ? E1000_SUCCESS : -E1000_ERR_MBX;
0030 }
0031 
0032 /**
0033  *  e1000_poll_for_ack - Wait for message acknowledgment
0034  *  @hw: pointer to the HW structure
0035  *
0036  *  returns SUCCESS if it successfully received a message acknowledgment
0037  **/
0038 static s32 e1000_poll_for_ack(struct e1000_hw *hw)
0039 {
0040     struct e1000_mbx_info *mbx = &hw->mbx;
0041     int countdown = mbx->timeout;
0042 
0043     if (!mbx->ops.check_for_ack)
0044         goto out;
0045 
0046     while (countdown && mbx->ops.check_for_ack(hw)) {
0047         countdown--;
0048         udelay(mbx->usec_delay);
0049     }
0050 
0051     /* if we failed, all future posted messages fail until reset */
0052     if (!countdown)
0053         mbx->timeout = 0;
0054 out:
0055     return countdown ? E1000_SUCCESS : -E1000_ERR_MBX;
0056 }
0057 
0058 /**
0059  *  e1000_read_posted_mbx - Wait for message notification and receive message
0060  *  @hw: pointer to the HW structure
0061  *  @msg: The message buffer
0062  *  @size: Length of buffer
0063  *
0064  *  returns SUCCESS if it successfully received a message notification and
0065  *  copied it into the receive buffer.
0066  **/
0067 static s32 e1000_read_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size)
0068 {
0069     struct e1000_mbx_info *mbx = &hw->mbx;
0070     s32 ret_val = -E1000_ERR_MBX;
0071 
0072     if (!mbx->ops.read)
0073         goto out;
0074 
0075     ret_val = e1000_poll_for_msg(hw);
0076 
0077     /* if ack received read message, otherwise we timed out */
0078     if (!ret_val)
0079         ret_val = mbx->ops.read(hw, msg, size);
0080 out:
0081     return ret_val;
0082 }
0083 
0084 /**
0085  *  e1000_write_posted_mbx - Write a message to the mailbox, wait for ack
0086  *  @hw: pointer to the HW structure
0087  *  @msg: The message buffer
0088  *  @size: Length of buffer
0089  *
0090  *  returns SUCCESS if it successfully copied message into the buffer and
0091  *  received an ack to that message within delay * timeout period
0092  **/
0093 static s32 e1000_write_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size)
0094 {
0095     struct e1000_mbx_info *mbx = &hw->mbx;
0096     s32 ret_val = -E1000_ERR_MBX;
0097 
0098     /* exit if we either can't write or there isn't a defined timeout */
0099     if (!mbx->ops.write || !mbx->timeout)
0100         goto out;
0101 
0102     /* send msg*/
0103     ret_val = mbx->ops.write(hw, msg, size);
0104 
0105     /* if msg sent wait until we receive an ack */
0106     if (!ret_val)
0107         ret_val = e1000_poll_for_ack(hw);
0108 out:
0109     return ret_val;
0110 }
0111 
0112 /**
0113  *  e1000_read_v2p_mailbox - read v2p mailbox
0114  *  @hw: pointer to the HW structure
0115  *
0116  *  This function is used to read the v2p mailbox without losing the read to
0117  *  clear status bits.
0118  **/
0119 static u32 e1000_read_v2p_mailbox(struct e1000_hw *hw)
0120 {
0121     u32 v2p_mailbox = er32(V2PMAILBOX(0));
0122 
0123     v2p_mailbox |= hw->dev_spec.vf.v2p_mailbox;
0124     hw->dev_spec.vf.v2p_mailbox |= v2p_mailbox & E1000_V2PMAILBOX_R2C_BITS;
0125 
0126     return v2p_mailbox;
0127 }
0128 
0129 /**
0130  *  e1000_check_for_bit_vf - Determine if a status bit was set
0131  *  @hw: pointer to the HW structure
0132  *  @mask: bitmask for bits to be tested and cleared
0133  *
0134  *  This function is used to check for the read to clear bits within
0135  *  the V2P mailbox.
0136  **/
0137 static s32 e1000_check_for_bit_vf(struct e1000_hw *hw, u32 mask)
0138 {
0139     u32 v2p_mailbox = e1000_read_v2p_mailbox(hw);
0140     s32 ret_val = -E1000_ERR_MBX;
0141 
0142     if (v2p_mailbox & mask)
0143         ret_val = E1000_SUCCESS;
0144 
0145     hw->dev_spec.vf.v2p_mailbox &= ~mask;
0146 
0147     return ret_val;
0148 }
0149 
0150 /**
0151  *  e1000_check_for_msg_vf - checks to see if the PF has sent mail
0152  *  @hw: pointer to the HW structure
0153  *
0154  *  returns SUCCESS if the PF has set the Status bit or else ERR_MBX
0155  **/
0156 static s32 e1000_check_for_msg_vf(struct e1000_hw *hw)
0157 {
0158     s32 ret_val = -E1000_ERR_MBX;
0159 
0160     if (!e1000_check_for_bit_vf(hw, E1000_V2PMAILBOX_PFSTS)) {
0161         ret_val = E1000_SUCCESS;
0162         hw->mbx.stats.reqs++;
0163     }
0164 
0165     return ret_val;
0166 }
0167 
0168 /**
0169  *  e1000_check_for_ack_vf - checks to see if the PF has ACK'd
0170  *  @hw: pointer to the HW structure
0171  *
0172  *  returns SUCCESS if the PF has set the ACK bit or else ERR_MBX
0173  **/
0174 static s32 e1000_check_for_ack_vf(struct e1000_hw *hw)
0175 {
0176     s32 ret_val = -E1000_ERR_MBX;
0177 
0178     if (!e1000_check_for_bit_vf(hw, E1000_V2PMAILBOX_PFACK)) {
0179         ret_val = E1000_SUCCESS;
0180         hw->mbx.stats.acks++;
0181     }
0182 
0183     return ret_val;
0184 }
0185 
0186 /**
0187  *  e1000_check_for_rst_vf - checks to see if the PF has reset
0188  *  @hw: pointer to the HW structure
0189  *
0190  *  returns true if the PF has set the reset done bit or else false
0191  **/
0192 static s32 e1000_check_for_rst_vf(struct e1000_hw *hw)
0193 {
0194     s32 ret_val = -E1000_ERR_MBX;
0195 
0196     if (!e1000_check_for_bit_vf(hw, (E1000_V2PMAILBOX_RSTD |
0197                      E1000_V2PMAILBOX_RSTI))) {
0198         ret_val = E1000_SUCCESS;
0199         hw->mbx.stats.rsts++;
0200     }
0201 
0202     return ret_val;
0203 }
0204 
0205 /**
0206  *  e1000_obtain_mbx_lock_vf - obtain mailbox lock
0207  *  @hw: pointer to the HW structure
0208  *
0209  *  return SUCCESS if we obtained the mailbox lock
0210  **/
0211 static s32 e1000_obtain_mbx_lock_vf(struct e1000_hw *hw)
0212 {
0213     s32 ret_val = -E1000_ERR_MBX;
0214     int count = 10;
0215 
0216     do {
0217         /* Take ownership of the buffer */
0218         ew32(V2PMAILBOX(0), E1000_V2PMAILBOX_VFU);
0219 
0220         /* reserve mailbox for VF use */
0221         if (e1000_read_v2p_mailbox(hw) & E1000_V2PMAILBOX_VFU) {
0222             ret_val = 0;
0223             break;
0224         }
0225         udelay(1000);
0226     } while (count-- > 0);
0227 
0228     return ret_val;
0229 }
0230 
0231 /**
0232  *  e1000_write_mbx_vf - Write a message to the mailbox
0233  *  @hw: pointer to the HW structure
0234  *  @msg: The message buffer
0235  *  @size: Length of buffer
0236  *
0237  *  returns SUCCESS if it successfully copied message into the buffer
0238  **/
0239 static s32 e1000_write_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size)
0240 {
0241     s32 err;
0242     u16 i;
0243 
0244     lockdep_assert_held(&hw->mbx_lock);
0245 
0246     /* lock the mailbox to prevent pf/vf race condition */
0247     err = e1000_obtain_mbx_lock_vf(hw);
0248     if (err)
0249         goto out_no_write;
0250 
0251     /* flush any ack or msg as we are going to overwrite mailbox */
0252     e1000_check_for_ack_vf(hw);
0253     e1000_check_for_msg_vf(hw);
0254 
0255     /* copy the caller specified message to the mailbox memory buffer */
0256     for (i = 0; i < size; i++)
0257         array_ew32(VMBMEM(0), i, msg[i]);
0258 
0259     /* update stats */
0260     hw->mbx.stats.msgs_tx++;
0261 
0262     /* Drop VFU and interrupt the PF to tell it a message has been sent */
0263     ew32(V2PMAILBOX(0), E1000_V2PMAILBOX_REQ);
0264 
0265 out_no_write:
0266     return err;
0267 }
0268 
0269 /**
0270  *  e1000_read_mbx_vf - Reads a message from the inbox intended for VF
0271  *  @hw: pointer to the HW structure
0272  *  @msg: The message buffer
0273  *  @size: Length of buffer
0274  *
0275  *  returns SUCCESS if it successfully read message from buffer
0276  **/
0277 static s32 e1000_read_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size)
0278 {
0279     s32 err;
0280     u16 i;
0281 
0282     lockdep_assert_held(&hw->mbx_lock);
0283 
0284     /* lock the mailbox to prevent pf/vf race condition */
0285     err = e1000_obtain_mbx_lock_vf(hw);
0286     if (err)
0287         goto out_no_read;
0288 
0289     /* copy the message from the mailbox memory buffer */
0290     for (i = 0; i < size; i++)
0291         msg[i] = array_er32(VMBMEM(0), i);
0292 
0293     /* Acknowledge receipt and release mailbox, then we're done */
0294     ew32(V2PMAILBOX(0), E1000_V2PMAILBOX_ACK);
0295 
0296     /* update stats */
0297     hw->mbx.stats.msgs_rx++;
0298 
0299 out_no_read:
0300     return err;
0301 }
0302 
0303 /**
0304  *  e1000_init_mbx_params_vf - set initial values for VF mailbox
0305  *  @hw: pointer to the HW structure
0306  *
0307  *  Initializes the hw->mbx struct to correct values for VF mailbox
0308  */
0309 s32 e1000_init_mbx_params_vf(struct e1000_hw *hw)
0310 {
0311     struct e1000_mbx_info *mbx = &hw->mbx;
0312 
0313     /* start mailbox as timed out and let the reset_hw call set the timeout
0314      * value to being communications
0315      */
0316     mbx->timeout = 0;
0317     mbx->usec_delay = E1000_VF_MBX_INIT_DELAY;
0318 
0319     mbx->size = E1000_VFMAILBOX_SIZE;
0320 
0321     mbx->ops.read = e1000_read_mbx_vf;
0322     mbx->ops.write = e1000_write_mbx_vf;
0323     mbx->ops.read_posted = e1000_read_posted_mbx;
0324     mbx->ops.write_posted = e1000_write_posted_mbx;
0325     mbx->ops.check_for_msg = e1000_check_for_msg_vf;
0326     mbx->ops.check_for_ack = e1000_check_for_ack_vf;
0327     mbx->ops.check_for_rst = e1000_check_for_rst_vf;
0328 
0329     mbx->stats.msgs_tx = 0;
0330     mbx->stats.msgs_rx = 0;
0331     mbx->stats.reqs = 0;
0332     mbx->stats.acks = 0;
0333     mbx->stats.rsts = 0;
0334 
0335     return E1000_SUCCESS;
0336 }