X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Ftxgbe%2Fbase%2Ftxgbe_vf.c;h=fb6d6d90ea922ba305e46439901db514ae640a2d;hb=1c9e61b3a45321b3cae742e8769b10c06c0324f0;hp=fadecaa11bd211384a8cda557a4bd0ed3a36cc2e;hpb=039b769f7c018351fbadf240f7dd692d3b02518f;p=dpdk.git diff --git a/drivers/net/txgbe/base/txgbe_vf.c b/drivers/net/txgbe/base/txgbe_vf.c index fadecaa11b..fb6d6d90ea 100644 --- a/drivers/net/txgbe/base/txgbe_vf.c +++ b/drivers/net/txgbe/base/txgbe_vf.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2015-2020 + * Copyright(c) 2015-2020 Beijing WangXun Technology Co., Ltd. + * Copyright(c) 2010-2017 Intel Corporation */ #include "txgbe_mbx.h" @@ -26,10 +27,17 @@ s32 txgbe_init_ops_vf(struct txgbe_hw *hw) mac->get_mac_addr = txgbe_get_mac_addr_vf; mac->stop_hw = txgbe_stop_hw_vf; mac->negotiate_api_version = txgbevf_negotiate_api_version; + mac->update_mc_addr_list = txgbe_update_mc_addr_list_vf; + + /* Link */ + mac->check_link = txgbe_check_mac_link_vf; /* RAR, Multicast, VLAN */ mac->set_rar = txgbe_set_rar_vf; mac->set_uc_addr = txgbevf_set_uc_addr_vf; + mac->update_xcast_mode = txgbevf_update_xcast_mode; + mac->set_vfta = txgbe_set_vfta_vf; + mac->set_rlpml = txgbevf_rlpml_set_vf; mac->max_tx_queues = 1; mac->max_rx_queues = 1; @@ -207,6 +215,39 @@ s32 txgbe_stop_hw_vf(struct txgbe_hw *hw) return 0; } +/** + * txgbe_mta_vector - Determines bit-vector in multicast table to set + * @hw: pointer to hardware structure + * @mc_addr: the multicast address + **/ +STATIC s32 txgbe_mta_vector(struct txgbe_hw *hw, u8 *mc_addr) +{ + u32 vector = 0; + + switch (hw->mac.mc_filter_type) { + case 0: /* use bits [47:36] of the address */ + vector = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4)); + break; + case 1: /* use bits [46:35] of the address */ + vector = ((mc_addr[4] >> 3) | (((u16)mc_addr[5]) << 5)); + break; + case 2: /* use bits [45:34] of the address */ + vector = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6)); + break; + case 3: /* use bits [43:32] of the address */ + vector = ((mc_addr[4]) | (((u16)mc_addr[5]) << 8)); + break; + default: /* Invalid mc_filter_type */ + DEBUGOUT("MC filter type param set incorrectly\n"); + ASSERT(0); + break; + } + + /* vector can only be 12-bits or boundary will be exceeded */ + vector &= 0xFFF; + return vector; +} + STATIC s32 txgbevf_write_msg_read_ack(struct txgbe_hw *hw, u32 *msg, u32 *retmsg, u16 size) { @@ -252,6 +293,121 @@ s32 txgbe_set_rar_vf(struct txgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, return ret_val; } +/** + * txgbe_update_mc_addr_list_vf - Update Multicast addresses + * @hw: pointer to the HW structure + * @mc_addr_list: array of multicast addresses to program + * @mc_addr_count: number of multicast addresses to program + * @next: caller supplied function to return next address in list + * @clear: unused + * + * Updates the Multicast Table Array. + **/ +s32 txgbe_update_mc_addr_list_vf(struct txgbe_hw *hw, u8 *mc_addr_list, + u32 mc_addr_count, txgbe_mc_addr_itr next, + bool clear) +{ + struct txgbe_mbx_info *mbx = &hw->mbx; + u32 msgbuf[TXGBE_P2VMBX_SIZE]; + u16 *vector_list = (u16 *)&msgbuf[1]; + u32 vector; + u32 cnt, i; + u32 vmdq; + + UNREFERENCED_PARAMETER(clear); + + DEBUGFUNC("txgbe_update_mc_addr_list_vf"); + + /* Each entry in the list uses 1 16 bit word. We have 30 + * 16 bit words available in our HW msg buffer (minus 1 for the + * msg type). That's 30 hash values if we pack 'em right. If + * there are more than 30 MC addresses to add then punt the + * extras for now and then add code to handle more than 30 later. + * It would be unusual for a server to request that many multi-cast + * addresses except for in large enterprise network environments. + */ + + DEBUGOUT("MC Addr Count = %d\n", mc_addr_count); + + cnt = (mc_addr_count > 30) ? 30 : mc_addr_count; + msgbuf[0] = TXGBE_VF_SET_MULTICAST; + msgbuf[0] |= cnt << TXGBE_VT_MSGINFO_SHIFT; + + for (i = 0; i < cnt; i++) { + vector = txgbe_mta_vector(hw, next(hw, &mc_addr_list, &vmdq)); + DEBUGOUT("Hash value = 0x%03X\n", vector); + vector_list[i] = (u16)vector; + } + + return mbx->write_posted(hw, msgbuf, TXGBE_P2VMBX_SIZE, 0); +} + +/** + * txgbevf_update_xcast_mode - Update Multicast mode + * @hw: pointer to the HW structure + * @xcast_mode: new multicast mode + * + * Updates the Multicast Mode of VF. + **/ +s32 txgbevf_update_xcast_mode(struct txgbe_hw *hw, int xcast_mode) +{ + u32 msgbuf[2]; + s32 err; + + switch (hw->api_version) { + case txgbe_mbox_api_12: + /* New modes were introduced in 1.3 version */ + if (xcast_mode > TXGBEVF_XCAST_MODE_ALLMULTI) + return TXGBE_ERR_FEATURE_NOT_SUPPORTED; + /* Fall through */ + case txgbe_mbox_api_13: + break; + default: + return TXGBE_ERR_FEATURE_NOT_SUPPORTED; + } + + msgbuf[0] = TXGBE_VF_UPDATE_XCAST_MODE; + msgbuf[1] = xcast_mode; + + err = txgbevf_write_msg_read_ack(hw, msgbuf, msgbuf, 2); + if (err) + return err; + + msgbuf[0] &= ~TXGBE_VT_MSGTYPE_CTS; + if (msgbuf[0] == (TXGBE_VF_UPDATE_XCAST_MODE | TXGBE_VT_MSGTYPE_NACK)) + return TXGBE_ERR_FEATURE_NOT_SUPPORTED; + return 0; +} + +/** + * txgbe_set_vfta_vf - Set/Unset vlan filter table address + * @hw: pointer to the HW structure + * @vlan: 12 bit VLAN ID + * @vind: unused by VF drivers + * @vlan_on: if true then set bit, else clear bit + * @vlvf_bypass: boolean flag indicating updating default pool is okay + * + * Turn on/off specified VLAN in the VLAN filter table. + **/ +s32 txgbe_set_vfta_vf(struct txgbe_hw *hw, u32 vlan, u32 vind, + bool vlan_on, bool vlvf_bypass) +{ + u32 msgbuf[2]; + s32 ret_val; + UNREFERENCED_PARAMETER(vind, vlvf_bypass); + + msgbuf[0] = TXGBE_VF_SET_VLAN; + msgbuf[1] = vlan; + /* Setting the 8 bit field MSG INFO to TRUE indicates "add" */ + msgbuf[0] |= vlan_on << TXGBE_VT_MSGINFO_SHIFT; + + ret_val = txgbevf_write_msg_read_ack(hw, msgbuf, msgbuf, 2); + if (!ret_val && (msgbuf[0] & TXGBE_VT_MSGTYPE_ACK)) + return 0; + + return ret_val | (msgbuf[0] & TXGBE_VT_MSGTYPE_NACK); +} + /** * txgbe_get_mac_addr_vf - Read device MAC address * @hw: pointer to the HW structure @@ -297,6 +453,125 @@ s32 txgbevf_set_uc_addr_vf(struct txgbe_hw *hw, u32 index, u8 *addr) return ret_val; } +/** + * txgbe_check_mac_link_vf - Get link/speed status + * @hw: pointer to hardware structure + * @speed: pointer to link speed + * @link_up: true is link is up, false otherwise + * @autoneg_wait_to_complete: true when waiting for completion is needed + * + * Reads the links register to determine if link is up and the current speed + **/ +s32 txgbe_check_mac_link_vf(struct txgbe_hw *hw, u32 *speed, + bool *link_up, bool wait_to_complete) +{ + /** + * for a quick link status checking, wait_to_compelet == 0, + * skip PF link status checking + */ + bool no_pflink_check = wait_to_complete == 0; + struct txgbe_mbx_info *mbx = &hw->mbx; + struct txgbe_mac_info *mac = &hw->mac; + s32 ret_val = 0; + u32 links_reg; + u32 in_msg = 0; + + /* If we were hit with a reset drop the link */ + if (!mbx->check_for_rst(hw, 0) || !mbx->timeout) + mac->get_link_status = true; + + if (!mac->get_link_status) + goto out; + + /* if link status is down no point in checking to see if pf is up */ + links_reg = rd32(hw, TXGBE_VFSTATUS); + if (!(links_reg & TXGBE_VFSTATUS_UP)) + goto out; + + /* for SFP+ modules and DA cables it can take up to 500usecs + * before the link status is correct + */ + if (mac->type == txgbe_mac_raptor_vf && wait_to_complete) { + if (po32m(hw, TXGBE_VFSTATUS, TXGBE_VFSTATUS_UP, + 0, NULL, 5, 100)) + goto out; + } + + switch (links_reg & TXGBE_VFSTATUS_BW_MASK) { + case TXGBE_VFSTATUS_BW_10G: + *speed = TXGBE_LINK_SPEED_10GB_FULL; + break; + case TXGBE_VFSTATUS_BW_1G: + *speed = TXGBE_LINK_SPEED_1GB_FULL; + break; + case TXGBE_VFSTATUS_BW_100M: + *speed = TXGBE_LINK_SPEED_100M_FULL; + break; + default: + *speed = TXGBE_LINK_SPEED_UNKNOWN; + } + + if (no_pflink_check) { + if (*speed == TXGBE_LINK_SPEED_UNKNOWN) + mac->get_link_status = true; + else + mac->get_link_status = false; + + goto out; + } + + /* if the read failed it could just be a mailbox collision, best wait + * until we are called again and don't report an error + */ + if (mbx->read(hw, &in_msg, 1, 0)) + goto out; + + if (!(in_msg & TXGBE_VT_MSGTYPE_CTS)) { + /* msg is not CTS and is NACK we must have lost CTS status */ + if (in_msg & TXGBE_VT_MSGTYPE_NACK) + ret_val = -1; + goto out; + } + + /* the pf is talking, if we timed out in the past we reinit */ + if (!mbx->timeout) { + ret_val = -1; + goto out; + } + + /* if we passed all the tests above then the link is up and we no + * longer need to check for link + */ + mac->get_link_status = false; + +out: + *link_up = !mac->get_link_status; + return ret_val; +} + +/** + * txgbevf_rlpml_set_vf - Set the maximum receive packet length + * @hw: pointer to the HW structure + * @max_size: value to assign to max frame size + **/ +s32 txgbevf_rlpml_set_vf(struct txgbe_hw *hw, u16 max_size) +{ + u32 msgbuf[2]; + s32 retval; + + msgbuf[0] = TXGBE_VF_SET_LPE; + msgbuf[1] = max_size; + + retval = txgbevf_write_msg_read_ack(hw, msgbuf, msgbuf, 2); + if (retval) + return retval; + if ((msgbuf[0] & TXGBE_VF_SET_LPE) && + (msgbuf[0] & TXGBE_VT_MSGTYPE_NACK)) + return TXGBE_ERR_MBX; + + return 0; +} + /** * txgbevf_negotiate_api_version - Negotiate supported API version * @hw: pointer to the HW structure