Module Name: src Committed By: martin Date: Mon Jan 31 17:38:36 UTC 2022
Modified Files: src/sys/dev/pci/ixgbe [netbsd-8]: if_sriov.c ixgbe.c ixgbe_82599.c ixgbe_mbx.c ixgbe_mbx.h ixgbe_type.h ixgbe_vf.c ixgbe_x540.c ixv.c Log Message: Pull up following revision(s) (requested by msaitoh in ticket #1730): sys/dev/pci/ixgbe/ixgbe_mbx.h: revision 1.19 sys/dev/pci/ixgbe/ixgbe_vf.c: revision 1.31 sys/dev/pci/ixgbe/ixgbe_x540.c: revision 1.23 sys/dev/pci/ixgbe/if_sriov.c: revision 1.17 sys/dev/pci/ixgbe/ixv.c: revision 1.172 sys/dev/pci/ixgbe/ixv.c: revision 1.173 sys/dev/pci/ixgbe/ixgbe.c: revision 1.301 sys/dev/pci/ixgbe/ixgbe_type.h: revision 1.55 sys/dev/pci/ixgbe/ixgbe_82599.c: revision 1.29 sys/dev/pci/ixgbe/ixgbe_mbx.c: revision 1.16 sys/dev/pci/ixgbe/ixgbe_mbx.c: revision 1.17 sys/dev/pci/ixgbe/ixgbe_mbx.c: revision 1.18 Add code to support API version 1.5. No functional change. - This change adds almost all code to support API 1.5 except real negotiation and upgrade mailbox functions. - From ix-3.3.18, ix-3.3.22 and ixv-1.5.24. Enable mailbox API 1.5 support. Tested on ESXi with ixgben 1.10.3.0. Don't clear mailbox related counters in ixgbe_upgrade_mbx_params_vf(). Don't clear mailbox related counters in ixgbe_upgrade_mbx_params_pf(). To generate a diff of this commit: cvs rdiff -u -r1.1.4.7 -r1.1.4.8 src/sys/dev/pci/ixgbe/if_sriov.c cvs rdiff -u -r1.88.2.47 -r1.88.2.48 src/sys/dev/pci/ixgbe/ixgbe.c cvs rdiff -u -r1.14.8.8 -r1.14.8.9 src/sys/dev/pci/ixgbe/ixgbe_82599.c cvs rdiff -u -r1.6.8.5 -r1.6.8.6 src/sys/dev/pci/ixgbe/ixgbe_mbx.c cvs rdiff -u -r1.10.8.4 -r1.10.8.5 src/sys/dev/pci/ixgbe/ixgbe_mbx.h cvs rdiff -u -r1.22.2.15 -r1.22.2.16 src/sys/dev/pci/ixgbe/ixgbe_type.h cvs rdiff -u -r1.12.8.8 -r1.12.8.9 src/sys/dev/pci/ixgbe/ixgbe_vf.c cvs rdiff -u -r1.9.6.7 -r1.9.6.8 src/sys/dev/pci/ixgbe/ixgbe_x540.c cvs rdiff -u -r1.56.2.35 -r1.56.2.36 src/sys/dev/pci/ixgbe/ixv.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/pci/ixgbe/if_sriov.c diff -u src/sys/dev/pci/ixgbe/if_sriov.c:1.1.4.7 src/sys/dev/pci/ixgbe/if_sriov.c:1.1.4.8 --- src/sys/dev/pci/ixgbe/if_sriov.c:1.1.4.7 Sun Jan 30 16:06:35 2022 +++ src/sys/dev/pci/ixgbe/if_sriov.c Mon Jan 31 17:38:36 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: if_sriov.c,v 1.1.4.7 2022/01/30 16:06:35 martin Exp $ */ +/* $NetBSD: if_sriov.c,v 1.1.4.8 2022/01/31 17:38:36 martin Exp $ */ /****************************************************************************** Copyright (c) 2001-2017, Intel Corporation @@ -34,7 +34,7 @@ /*$FreeBSD: head/sys/dev/ixgbe/if_sriov.c 327031 2017-12-20 18:15:06Z erj $*/ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_sriov.c,v 1.1.4.7 2022/01/30 16:06:35 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_sriov.c,v 1.1.4.8 2022/01/31 17:38:36 martin Exp $"); #include "ixgbe.h" #include "ixgbe_sriov.h" @@ -99,7 +99,7 @@ ixgbe_send_vf_msg(struct ixgbe_hw *hw, s if (vf->flags & IXGBE_VF_CTS) msg |= IXGBE_VT_MSGTYPE_CTS; - hw->mbx.ops.write(hw, &msg, 1, vf->pool); + hw->mbx.ops[vf->pool].write(hw, &msg, 1, vf->pool); } static inline void @@ -594,7 +594,8 @@ ixgbe_process_vf_msg(struct adapter *ada hw = &adapter->hw; - error = hw->mbx.ops.read(hw, msg, IXGBE_VFMAILBOX_SIZE, vf->pool); + error = hw->mbx.ops[vf->pool].read(hw, msg, IXGBE_VFMAILBOX_SIZE, + vf->pool); if (error != 0) return; @@ -654,16 +655,17 @@ ixgbe_handle_mbx(void *context) for (i = 0; i < adapter->num_vfs; i++) { vf = &adapter->vfs[i]; - if (vf->flags & IXGBE_VF_ACTIVE) { - if (hw->mbx.ops.check_for_rst(hw, vf->pool) == 0) - ixgbe_process_vf_reset(adapter, vf); - - if (hw->mbx.ops.check_for_msg(hw, vf->pool) == 0) - ixgbe_process_vf_msg(adapter, vf); - - if (hw->mbx.ops.check_for_ack(hw, vf->pool) == 0) - ixgbe_process_vf_ack(adapter, vf); - } + if ((vf->flags & IXGBE_VF_ACTIVE) == 0) + continue; + + if (hw->mbx.ops[vf->pool].check_for_rst(hw, vf->pool) == 0) + ixgbe_process_vf_reset(adapter, vf); + + if (hw->mbx.ops[vf->pool].check_for_msg(hw, vf->pool) == 0) + ixgbe_process_vf_msg(adapter, vf); + + if (hw->mbx.ops[vf->pool].check_for_ack(hw, vf->pool) == 0) + ixgbe_process_vf_ack(adapter, vf); } IXGBE_CORE_UNLOCK(adapter); } /* ixgbe_handle_mbx */ Index: src/sys/dev/pci/ixgbe/ixgbe.c diff -u src/sys/dev/pci/ixgbe/ixgbe.c:1.88.2.47 src/sys/dev/pci/ixgbe/ixgbe.c:1.88.2.48 --- src/sys/dev/pci/ixgbe/ixgbe.c:1.88.2.47 Sun Jan 30 16:06:35 2022 +++ src/sys/dev/pci/ixgbe/ixgbe.c Mon Jan 31 17:38:36 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: ixgbe.c,v 1.88.2.47 2022/01/30 16:06:35 martin Exp $ */ +/* $NetBSD: ixgbe.c,v 1.88.2.48 2022/01/31 17:38:36 martin Exp $ */ /****************************************************************************** @@ -64,7 +64,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ixgbe.c,v 1.88.2.47 2022/01/30 16:06:35 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ixgbe.c,v 1.88.2.48 2022/01/31 17:38:36 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -84,7 +84,7 @@ __KERNEL_RCSID(0, "$NetBSD: ixgbe.c,v 1. * Driver version ************************************************************************/ static const char ixgbe_driver_version[] = "4.0.1-k"; -/* XXX NetBSD: + 3.3.10 */ +/* XXX NetBSD: + 3.3.24 */ /************************************************************************ * PCI Device ID Table Index: src/sys/dev/pci/ixgbe/ixgbe_82599.c diff -u src/sys/dev/pci/ixgbe/ixgbe_82599.c:1.14.8.8 src/sys/dev/pci/ixgbe/ixgbe_82599.c:1.14.8.9 --- src/sys/dev/pci/ixgbe/ixgbe_82599.c:1.14.8.8 Sun Jan 30 16:06:35 2022 +++ src/sys/dev/pci/ixgbe/ixgbe_82599.c Mon Jan 31 17:38:36 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: ixgbe_82599.c,v 1.14.8.8 2022/01/30 16:06:35 martin Exp $ */ +/* $NetBSD: ixgbe_82599.c,v 1.14.8.9 2022/01/31 17:38:36 martin Exp $ */ /****************************************************************************** SPDX-License-Identifier: BSD-3-Clause @@ -36,7 +36,7 @@ /*$FreeBSD: head/sys/dev/ixgbe/ixgbe_82599.c 331224 2018-03-19 20:55:05Z erj $*/ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ixgbe_82599.c,v 1.14.8.8 2022/01/30 16:06:35 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ixgbe_82599.c,v 1.14.8.9 2022/01/31 17:38:36 martin Exp $"); #include "ixgbe_type.h" #include "ixgbe_82599.h" @@ -331,6 +331,7 @@ s32 ixgbe_init_ops_82599(struct ixgbe_hw struct ixgbe_phy_info *phy = &hw->phy; struct ixgbe_eeprom_info *eeprom = &hw->eeprom; s32 ret_val; + u16 i; DEBUGFUNC("ixgbe_init_ops_82599"); @@ -392,7 +393,8 @@ s32 ixgbe_init_ops_82599(struct ixgbe_hw mac->arc_subsystem_valid = !!(IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw)) & IXGBE_FWSM_MODE_MASK); - hw->mbx.ops.init_params = ixgbe_init_mbx_params_pf; + for (i = 0; i < 64; i++) + hw->mbx.ops[i].init_params = ixgbe_init_mbx_params_pf; /* EEPROM */ eeprom->ops.read = ixgbe_read_eeprom_82599; Index: src/sys/dev/pci/ixgbe/ixgbe_mbx.c diff -u src/sys/dev/pci/ixgbe/ixgbe_mbx.c:1.6.8.5 src/sys/dev/pci/ixgbe/ixgbe_mbx.c:1.6.8.6 --- src/sys/dev/pci/ixgbe/ixgbe_mbx.c:1.6.8.5 Sun Jan 30 16:06:35 2022 +++ src/sys/dev/pci/ixgbe/ixgbe_mbx.c Mon Jan 31 17:38:36 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: ixgbe_mbx.c,v 1.6.8.5 2022/01/30 16:06:35 martin Exp $ */ +/* $NetBSD: ixgbe_mbx.c,v 1.6.8.6 2022/01/31 17:38:36 martin Exp $ */ /****************************************************************************** SPDX-License-Identifier: BSD-3-Clause @@ -36,11 +36,14 @@ /*$FreeBSD: head/sys/dev/ixgbe/ixgbe_mbx.c 326022 2017-11-20 19:36:21Z pfg $*/ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ixgbe_mbx.c,v 1.6.8.5 2022/01/30 16:06:35 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ixgbe_mbx.c,v 1.6.8.6 2022/01/31 17:38:36 martin Exp $"); #include "ixgbe_type.h" #include "ixgbe_mbx.h" +static s32 ixgbe_poll_for_msg(struct ixgbe_hw *hw, u16 mbx_id); +static s32 ixgbe_poll_for_ack(struct ixgbe_hw *hw, u16 mbx_id); + /** * ixgbe_read_mbx - Reads a message from the mailbox * @hw: pointer to the HW structure @@ -53,42 +56,91 @@ __KERNEL_RCSID(0, "$NetBSD: ixgbe_mbx.c, s32 ixgbe_read_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) { struct ixgbe_mbx_info *mbx = &hw->mbx; - s32 ret_val = IXGBE_ERR_MBX; DEBUGFUNC("ixgbe_read_mbx"); /* limit read to size of mailbox */ - if (size > mbx->size) + if (size > mbx->size) { + ERROR_REPORT3(IXGBE_ERROR_ARGUMENT, + "Invalid mailbox message size %u, changing to %u", + size, mbx->size); size = mbx->size; + } + + if (mbx->ops[mbx_id].read) + return mbx->ops[mbx_id].read(hw, msg, size, mbx_id); + + return IXGBE_ERR_CONFIG; +} + +/** + * ixgbe_poll_mbx - Wait for message and read it from the mailbox + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @mbx_id: id of mailbox to read + * + * returns SUCCESS if it successfully read message from buffer + **/ +s32 ixgbe_poll_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) +{ + struct ixgbe_mbx_info *mbx = &hw->mbx; + s32 ret_val; + + DEBUGFUNC("ixgbe_poll_mbx"); - if (mbx->ops.read) - ret_val = mbx->ops.read(hw, msg, size, mbx_id); + if (!mbx->ops[mbx_id].read || !mbx->ops[mbx_id].check_for_msg || + !mbx->timeout) + return IXGBE_ERR_CONFIG; + + /* limit read to size of mailbox */ + if (size > mbx->size) { + ERROR_REPORT3(IXGBE_ERROR_ARGUMENT, + "Invalid mailbox message size %u, changing to %u", + size, mbx->size); + size = mbx->size; + } + + ret_val = ixgbe_poll_for_msg(hw, mbx_id); + /* if ack received read message, otherwise we timed out */ + if (!ret_val) + return mbx->ops[mbx_id].read(hw, msg, size, mbx_id); return ret_val; } /** - * ixgbe_write_mbx - Write a message to the mailbox + * ixgbe_write_mbx - Write a message to the mailbox and wait for ACK * @hw: pointer to the HW structure * @msg: The message buffer * @size: Length of buffer * @mbx_id: id of mailbox to write * - * returns SUCCESS if it successfully copied message into the buffer + * returns SUCCESS if it successfully copied message into the buffer and + * received an ACK to that message within specified period **/ s32 ixgbe_write_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) { struct ixgbe_mbx_info *mbx = &hw->mbx; - s32 ret_val = IXGBE_SUCCESS; + s32 ret_val = IXGBE_ERR_MBX; DEBUGFUNC("ixgbe_write_mbx"); + /* + * exit if either we can't write, release + * or there is no timeout defined + */ + if (!mbx->ops[mbx_id].write || !mbx->ops[mbx_id].check_for_ack || + !mbx->ops[mbx_id].release || !mbx->timeout) + return IXGBE_ERR_CONFIG; + if (size > mbx->size) { - ret_val = IXGBE_ERR_MBX; + ret_val = IXGBE_ERR_PARAM; ERROR_REPORT2(IXGBE_ERROR_ARGUMENT, - "Invalid mailbox message size %d", size); - } else if (mbx->ops.write) - ret_val = mbx->ops.write(hw, msg, size, mbx_id); + "Invalid mailbox message size %u", size); + } else { + ret_val = mbx->ops[mbx_id].write(hw, msg, size, mbx_id); + } return ret_val; } @@ -103,12 +155,12 @@ s32 ixgbe_write_mbx(struct ixgbe_hw *hw, s32 ixgbe_check_for_msg(struct ixgbe_hw *hw, u16 mbx_id) { struct ixgbe_mbx_info *mbx = &hw->mbx; - s32 ret_val = IXGBE_ERR_MBX; + s32 ret_val = IXGBE_ERR_CONFIG; DEBUGFUNC("ixgbe_check_for_msg"); - if (mbx->ops.check_for_msg) - ret_val = mbx->ops.check_for_msg(hw, mbx_id); + if (mbx->ops[mbx_id].check_for_msg) + ret_val = mbx->ops[mbx_id].check_for_msg(hw, mbx_id); return ret_val; } @@ -123,12 +175,12 @@ s32 ixgbe_check_for_msg(struct ixgbe_hw s32 ixgbe_check_for_ack(struct ixgbe_hw *hw, u16 mbx_id) { struct ixgbe_mbx_info *mbx = &hw->mbx; - s32 ret_val = IXGBE_ERR_MBX; + s32 ret_val = IXGBE_ERR_CONFIG; DEBUGFUNC("ixgbe_check_for_ack"); - if (mbx->ops.check_for_ack) - ret_val = mbx->ops.check_for_ack(hw, mbx_id); + if (mbx->ops[mbx_id].check_for_ack) + ret_val = mbx->ops[mbx_id].check_for_ack(hw, mbx_id); return ret_val; } @@ -143,12 +195,12 @@ s32 ixgbe_check_for_ack(struct ixgbe_hw s32 ixgbe_check_for_rst(struct ixgbe_hw *hw, u16 mbx_id) { struct ixgbe_mbx_info *mbx = &hw->mbx; - s32 ret_val = IXGBE_ERR_MBX; + s32 ret_val = IXGBE_ERR_CONFIG; DEBUGFUNC("ixgbe_check_for_rst"); - if (mbx->ops.check_for_rst) - ret_val = mbx->ops.check_for_rst(hw, mbx_id); + if (mbx->ops[mbx_id].check_for_rst) + ret_val = mbx->ops[mbx_id].check_for_rst(hw, mbx_id); return ret_val; } @@ -156,19 +208,19 @@ s32 ixgbe_check_for_rst(struct ixgbe_hw /** * ixgbe_clear_mbx - Clear Mailbox Memory * @hw: pointer to the HW structure - * @vf_number: id of mailbox to write + * @mbx_id: id of mailbox to write * * Set VFMBMEM of given VF to 0x0. **/ -s32 ixgbe_clear_mbx(struct ixgbe_hw *hw, u16 vf_number) +s32 ixgbe_clear_mbx(struct ixgbe_hw *hw, u16 mbx_id) { struct ixgbe_mbx_info *mbx = &hw->mbx; - s32 ret_val = IXGBE_SUCCESS; + s32 ret_val = IXGBE_ERR_CONFIG; DEBUGFUNC("ixgbe_clear_mbx"); - if (mbx->ops.clear) - ret_val = mbx->ops.clear(hw, vf_number); + if (mbx->ops[mbx_id].clear) + ret_val = mbx->ops[mbx_id].clear(hw, mbx_id); return ret_val; } @@ -187,22 +239,23 @@ static s32 ixgbe_poll_for_msg(struct ixg DEBUGFUNC("ixgbe_poll_for_msg"); - if (!countdown || !mbx->ops.check_for_msg) - goto out; + if (!countdown || !mbx->ops[mbx_id].check_for_msg) + return IXGBE_ERR_CONFIG; - while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) { + while (countdown && mbx->ops[mbx_id].check_for_msg(hw, mbx_id)) { countdown--; if (!countdown) break; usec_delay(mbx->usec_delay); } - if (countdown == 0) + if (countdown == 0) { ERROR_REPORT2(IXGBE_ERROR_POLLING, - "Polling for VF%d mailbox message timedout", mbx_id); + "Polling for VF%u mailbox message timedout", mbx_id); + return IXGBE_ERR_TIMEOUT; + } -out: - return countdown ? IXGBE_SUCCESS : IXGBE_ERR_MBX; + return IXGBE_SUCCESS; } /** @@ -219,114 +272,72 @@ static s32 ixgbe_poll_for_ack(struct ixg DEBUGFUNC("ixgbe_poll_for_ack"); - if (!countdown || !mbx->ops.check_for_ack) - goto out; + if (!countdown || !mbx->ops[mbx_id].check_for_ack) + return IXGBE_ERR_CONFIG; - while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) { + while (countdown && mbx->ops[mbx_id].check_for_ack(hw, mbx_id)) { countdown--; if (!countdown) break; usec_delay(mbx->usec_delay); } - if (countdown == 0) + if (countdown == 0) { ERROR_REPORT2(IXGBE_ERROR_POLLING, - "Polling for VF%d mailbox ack timedout", mbx_id); + "Polling for VF%u mailbox ack timedout", mbx_id); + return IXGBE_ERR_TIMEOUT; + } -out: - return countdown ? IXGBE_SUCCESS : IXGBE_ERR_MBX; + return IXGBE_SUCCESS; } + /** - * ixgbe_read_posted_mbx - Wait for message notification and receive message + * ixgbe_read_mailbox_vf - read VF's mailbox register * @hw: pointer to the HW structure - * @msg: The message buffer - * @size: Length of buffer - * @mbx_id: id of mailbox to write * - * returns SUCCESS if it successfully received a message notification and - * copied it into the receive buffer. + * This function is used to read the mailbox register dedicated for VF without + * losing the read to clear status bits. **/ -s32 ixgbe_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) +static u32 ixgbe_read_mailbox_vf(struct ixgbe_hw *hw) { - struct ixgbe_mbx_info *mbx = &hw->mbx; - s32 ret_val = IXGBE_ERR_MBX; - - DEBUGFUNC("ixgbe_read_posted_mbx"); + u32 vf_mailbox = IXGBE_READ_REG(hw, IXGBE_VFMAILBOX); - if (!mbx->ops.read) - goto out; - - ret_val = ixgbe_poll_for_msg(hw, mbx_id); + vf_mailbox |= hw->mbx.vf_mailbox; + hw->mbx.vf_mailbox |= vf_mailbox & IXGBE_VFMAILBOX_R2C_BITS; - /* if ack received read message, otherwise we timed out */ - if (!ret_val) - ret_val = mbx->ops.read(hw, msg, size, mbx_id); -out: - return ret_val; + return vf_mailbox; } -/** - * ixgbe_write_posted_mbx - Write a message to the mailbox, wait for ack - * @hw: pointer to the HW structure - * @msg: The message buffer - * @size: Length of buffer - * @mbx_id: id of mailbox to write - * - * returns SUCCESS if it successfully copied message into the buffer and - * received an ack to that message within delay * timeout period - **/ -s32 ixgbe_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, - u16 mbx_id) +static void ixgbe_clear_msg_vf(struct ixgbe_hw *hw) { - struct ixgbe_mbx_info *mbx = &hw->mbx; - s32 ret_val = IXGBE_ERR_MBX; - - DEBUGFUNC("ixgbe_write_posted_mbx"); + u32 vf_mailbox = ixgbe_read_mailbox_vf(hw); - /* exit if either we can't write or there isn't a defined timeout */ - if (!mbx->ops.write || !mbx->timeout) - goto out; - - /* send msg */ - ret_val = mbx->ops.write(hw, msg, size, mbx_id); - - /* if msg sent wait until we receive an ack */ - if (!ret_val) - ret_val = ixgbe_poll_for_ack(hw, mbx_id); -out: - return ret_val; + if (vf_mailbox & IXGBE_VFMAILBOX_PFSTS) { + hw->mbx.stats.reqs.ev_count++; + hw->mbx.vf_mailbox &= ~IXGBE_VFMAILBOX_PFSTS; + } } -/** - * ixgbe_init_mbx_ops_generic - Initialize MB function pointers - * @hw: pointer to the HW structure - * - * Setups up the mailbox read and write message function pointers - **/ -void ixgbe_init_mbx_ops_generic(struct ixgbe_hw *hw) +static void ixgbe_clear_ack_vf(struct ixgbe_hw *hw) { - struct ixgbe_mbx_info *mbx = &hw->mbx; + u32 vf_mailbox = ixgbe_read_mailbox_vf(hw); - mbx->ops.read_posted = ixgbe_read_posted_mbx; - mbx->ops.write_posted = ixgbe_write_posted_mbx; + if (vf_mailbox & IXGBE_VFMAILBOX_PFACK) { + hw->mbx.stats.acks.ev_count++; + hw->mbx.vf_mailbox &= ~IXGBE_VFMAILBOX_PFACK; + } } -/** - * ixgbe_read_v2p_mailbox - read v2p mailbox - * @hw: pointer to the HW structure - * - * This function is used to read the v2p mailbox without losing the read to - * clear status bits. - **/ -static u32 ixgbe_read_v2p_mailbox(struct ixgbe_hw *hw) +static void ixgbe_clear_rst_vf(struct ixgbe_hw *hw) { - u32 v2p_mailbox = IXGBE_READ_REG(hw, IXGBE_VFMAILBOX); - - v2p_mailbox |= hw->mbx.v2p_mailbox; - hw->mbx.v2p_mailbox |= v2p_mailbox & IXGBE_VFMAILBOX_R2C_BITS; + u32 vf_mailbox = ixgbe_read_mailbox_vf(hw); - return v2p_mailbox; + if (vf_mailbox & (IXGBE_VFMAILBOX_RSTI | IXGBE_VFMAILBOX_RSTD)) { + hw->mbx.stats.rsts.ev_count++; + hw->mbx.vf_mailbox &= ~(IXGBE_VFMAILBOX_RSTI | + IXGBE_VFMAILBOX_RSTD); + } } /** @@ -339,15 +350,12 @@ static u32 ixgbe_read_v2p_mailbox(struct **/ static s32 ixgbe_check_for_bit_vf(struct ixgbe_hw *hw, u32 mask) { - u32 v2p_mailbox = ixgbe_read_v2p_mailbox(hw); - s32 ret_val = IXGBE_ERR_MBX; - - if (v2p_mailbox & mask) - ret_val = IXGBE_SUCCESS; + u32 vf_mailbox = ixgbe_read_mailbox_vf(hw); - hw->mbx.v2p_mailbox &= ~mask; + if (vf_mailbox & mask) + return IXGBE_SUCCESS; - return ret_val; + return IXGBE_ERR_MBX; } /** @@ -359,17 +367,15 @@ static s32 ixgbe_check_for_bit_vf(struct **/ static s32 ixgbe_check_for_msg_vf(struct ixgbe_hw *hw, u16 mbx_id) { - s32 ret_val = IXGBE_ERR_MBX; - UNREFERENCED_1PARAMETER(mbx_id); DEBUGFUNC("ixgbe_check_for_msg_vf"); if (!ixgbe_check_for_bit_vf(hw, IXGBE_VFMAILBOX_PFSTS)) { - ret_val = IXGBE_SUCCESS; hw->mbx.stats.reqs.ev_count++; + return IXGBE_SUCCESS; } - return ret_val; + return IXGBE_ERR_MBX; } /** @@ -381,17 +387,17 @@ static s32 ixgbe_check_for_msg_vf(struct **/ static s32 ixgbe_check_for_ack_vf(struct ixgbe_hw *hw, u16 mbx_id) { - s32 ret_val = IXGBE_ERR_MBX; - UNREFERENCED_1PARAMETER(mbx_id); DEBUGFUNC("ixgbe_check_for_ack_vf"); if (!ixgbe_check_for_bit_vf(hw, IXGBE_VFMAILBOX_PFACK)) { - ret_val = IXGBE_SUCCESS; + /* TODO: should this be autocleared? */ + ixgbe_clear_ack_vf(hw); hw->mbx.stats.acks.ev_count++; + return IXGBE_SUCCESS; } - return ret_val; + return IXGBE_ERR_MBX; } /** @@ -403,18 +409,18 @@ static s32 ixgbe_check_for_ack_vf(struct **/ static s32 ixgbe_check_for_rst_vf(struct ixgbe_hw *hw, u16 mbx_id) { - s32 ret_val = IXGBE_ERR_MBX; - UNREFERENCED_1PARAMETER(mbx_id); DEBUGFUNC("ixgbe_check_for_rst_vf"); - if (!ixgbe_check_for_bit_vf(hw, (IXGBE_VFMAILBOX_RSTD | - IXGBE_VFMAILBOX_RSTI))) { - ret_val = IXGBE_SUCCESS; + if (!ixgbe_check_for_bit_vf(hw, IXGBE_VFMAILBOX_RSTI | + IXGBE_VFMAILBOX_RSTD)) { + /* TODO: should this be autocleared? */ + ixgbe_clear_rst_vf(hw); hw->mbx.stats.rsts.ev_count++; + return IXGBE_SUCCESS; } - return ret_val; + return IXGBE_ERR_MBX; } /** @@ -425,21 +431,115 @@ static s32 ixgbe_check_for_rst_vf(struct **/ static s32 ixgbe_obtain_mbx_lock_vf(struct ixgbe_hw *hw) { + struct ixgbe_mbx_info *mbx = &hw->mbx; + int countdown = mbx->timeout; s32 ret_val = IXGBE_ERR_MBX; + u32 vf_mailbox; DEBUGFUNC("ixgbe_obtain_mbx_lock_vf"); - /* Take ownership of the buffer */ - IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_VFU); + if (!mbx->timeout) + return IXGBE_ERR_CONFIG; - /* reserve mailbox for vf use */ - if (ixgbe_read_v2p_mailbox(hw) & IXGBE_VFMAILBOX_VFU) - ret_val = IXGBE_SUCCESS; + while (countdown--) { + /* Reserve mailbox for VF use */ + vf_mailbox = ixgbe_read_mailbox_vf(hw); + vf_mailbox |= IXGBE_VFMAILBOX_VFU; + IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, vf_mailbox); + + /* Verify that VF is the owner of the lock */ + if (ixgbe_read_mailbox_vf(hw) & IXGBE_VFMAILBOX_VFU) { + ret_val = IXGBE_SUCCESS; + break; + } + + /* Wait a bit before trying again */ + usec_delay(mbx->usec_delay); + } + + if (ret_val != IXGBE_SUCCESS) { + ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE, + "Failed to obtain mailbox lock"); + ret_val = IXGBE_ERR_TIMEOUT; + } return ret_val; } /** + * ixgbe_release_mbx_lock_dummy - release mailbox lock + * @hw: pointer to the HW structure + * @mbx_id: id of mailbox to read + **/ +static void ixgbe_release_mbx_lock_dummy(struct ixgbe_hw *hw, u16 mbx_id) +{ + UNREFERENCED_2PARAMETER(hw, mbx_id); + + DEBUGFUNC("ixgbe_release_mbx_lock_dummy"); +} + +/** + * ixgbe_release_mbx_lock_vf - release mailbox lock + * @hw: pointer to the HW structure + * @mbx_id: id of mailbox to read + **/ +static void ixgbe_release_mbx_lock_vf(struct ixgbe_hw *hw, u16 mbx_id) +{ + u32 vf_mailbox; + + UNREFERENCED_1PARAMETER(mbx_id); + + DEBUGFUNC("ixgbe_release_mbx_lock_vf"); + + /* Return ownership of the buffer */ + vf_mailbox = ixgbe_read_mailbox_vf(hw); + vf_mailbox &= ~IXGBE_VFMAILBOX_VFU; + IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, vf_mailbox); +} + +/** + * ixgbe_write_mbx_vf_legacy - Write a message to the mailbox + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @mbx_id: id of mailbox to write + * + * returns SUCCESS if it successfully copied message into the buffer + **/ +static s32 ixgbe_write_mbx_vf_legacy(struct ixgbe_hw *hw, u32 *msg, u16 size, + u16 mbx_id) +{ + s32 ret_val; + u16 i; + + UNREFERENCED_1PARAMETER(mbx_id); + DEBUGFUNC("ixgbe_write_mbx_vf_legacy"); + + /* lock the mailbox to prevent pf/vf race condition */ + ret_val = ixgbe_obtain_mbx_lock_vf(hw); + if (ret_val) + return ret_val; + + /* flush msg and acks as we are overwriting the message buffer */ + ixgbe_check_for_msg_vf(hw, 0); + ixgbe_clear_msg_vf(hw); + ixgbe_check_for_ack_vf(hw, 0); + ixgbe_clear_ack_vf(hw); + + /* copy the caller specified message to the mailbox memory buffer */ + for (i = 0; i < size; i++) + IXGBE_WRITE_REG_ARRAY(hw, IXGBE_VFMBMEM, i, msg[i]); + + /* update stats */ + hw->mbx.stats.msgs_tx.ev_count++; + + /* interrupt the PF to tell it a message has been sent */ + IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_REQ); + + return IXGBE_SUCCESS; +} + +/** * ixgbe_write_mbx_vf - Write a message to the mailbox * @hw: pointer to the HW structure * @msg: The message buffer @@ -451,6 +551,7 @@ static s32 ixgbe_obtain_mbx_lock_vf(stru static s32 ixgbe_write_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) { + u32 vf_mailbox; s32 ret_val; u16 i; @@ -461,11 +562,11 @@ static s32 ixgbe_write_mbx_vf(struct ixg /* lock the mailbox to prevent pf/vf race condition */ ret_val = ixgbe_obtain_mbx_lock_vf(hw); if (ret_val) - goto out_no_write; + goto out; /* flush msg and acks as we are overwriting the message buffer */ - ixgbe_check_for_msg_vf(hw, 0); - ixgbe_check_for_ack_vf(hw, 0); + ixgbe_clear_msg_vf(hw); + ixgbe_clear_ack_vf(hw); /* copy the caller specified message to the mailbox memory buffer */ for (i = 0; i < size; i++) @@ -474,15 +575,22 @@ static s32 ixgbe_write_mbx_vf(struct ixg /* update stats */ hw->mbx.stats.msgs_tx.ev_count++; - /* Drop VFU and interrupt the PF to tell it a message has been sent */ - IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_REQ); + /* interrupt the PF to tell it a message has been sent */ + vf_mailbox = ixgbe_read_mailbox_vf(hw); + vf_mailbox |= IXGBE_VFMAILBOX_REQ; + IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, vf_mailbox); + + /* if msg sent wait until we receive an ack */ + ixgbe_poll_for_ack(hw, mbx_id); + +out: + hw->mbx.ops[mbx_id].release(hw, mbx_id); -out_no_write: return ret_val; } /** - * ixgbe_read_mbx_vf - Reads a message from the inbox intended for vf + * ixgbe_read_mbx_vf_legacy - Reads a message from the inbox intended for vf * @hw: pointer to the HW structure * @msg: The message buffer * @size: Length of buffer @@ -490,19 +598,19 @@ out_no_write: * * returns SUCCESS if it successfully read message from buffer **/ -static s32 ixgbe_read_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size, - u16 mbx_id) +static s32 ixgbe_read_mbx_vf_legacy(struct ixgbe_hw *hw, u32 *msg, u16 size, + u16 mbx_id) { - s32 ret_val = IXGBE_SUCCESS; + s32 ret_val; u16 i; - DEBUGFUNC("ixgbe_read_mbx_vf"); + DEBUGFUNC("ixgbe_read_mbx_vf_legacy"); UNREFERENCED_1PARAMETER(mbx_id); /* lock the mailbox to prevent pf/vf race condition */ ret_val = ixgbe_obtain_mbx_lock_vf(hw); if (ret_val) - goto out_no_read; + return ret_val; /* copy the message from the mailbox memory buffer */ for (i = 0; i < size; i++) @@ -514,35 +622,74 @@ static s32 ixgbe_read_mbx_vf(struct ixgb /* update stats */ hw->mbx.stats.msgs_rx.ev_count++; -out_no_read: - return ret_val; + return IXGBE_SUCCESS; +} + +/** + * ixgbe_read_mbx_vf - Reads a message from the inbox intended for vf + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @mbx_id: id of mailbox to read + * + * returns SUCCESS if it successfully read message from buffer + **/ +static s32 ixgbe_read_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size, + u16 mbx_id) +{ + u32 vf_mailbox; + s32 ret_val; + u16 i; + + DEBUGFUNC("ixgbe_read_mbx_vf"); + UNREFERENCED_1PARAMETER(mbx_id); + + /* check if there is a message from PF */ + ret_val = ixgbe_check_for_msg_vf(hw, 0); + if (ret_val != IXGBE_SUCCESS) + return IXGBE_ERR_MBX_NOMSG; + + ixgbe_clear_msg_vf(hw); + + /* copy the message from the mailbox memory buffer */ + for (i = 0; i < size; i++) + msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_VFMBMEM, i); + + /* Acknowledge receipt */ + vf_mailbox = ixgbe_read_mailbox_vf(hw); + vf_mailbox |= IXGBE_VFMAILBOX_ACK; + IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, vf_mailbox); + + /* update stats */ + hw->mbx.stats.msgs_rx.ev_count++; + + return IXGBE_SUCCESS; } /** * ixgbe_init_mbx_params_vf - set initial values for vf mailbox * @hw: pointer to the HW structure * - * Initializes the hw->mbx struct to correct values for vf mailbox + * Initializes single set the hw->mbx struct to correct values for vf mailbox + * Set of legacy functions is being used here */ void ixgbe_init_mbx_params_vf(struct ixgbe_hw *hw) { struct ixgbe_mbx_info *mbx = &hw->mbx; - /* start mailbox as timed out and let the reset_hw call set the timeout - * value to begin communications */ - mbx->timeout = 0; + mbx->timeout = IXGBE_VF_MBX_INIT_TIMEOUT; mbx->usec_delay = IXGBE_VF_MBX_INIT_DELAY; mbx->size = IXGBE_VFMAILBOX_SIZE; - mbx->ops.read = ixgbe_read_mbx_vf; - mbx->ops.write = ixgbe_write_mbx_vf; - mbx->ops.read_posted = ixgbe_read_posted_mbx; - mbx->ops.write_posted = ixgbe_write_posted_mbx; - mbx->ops.check_for_msg = ixgbe_check_for_msg_vf; - mbx->ops.check_for_ack = ixgbe_check_for_ack_vf; - mbx->ops.check_for_rst = ixgbe_check_for_rst_vf; - mbx->ops.clear = NULL; + /* VF has only one mailbox connection, no need for more IDs */ + mbx->ops[0].release = ixgbe_release_mbx_lock_dummy; + mbx->ops[0].read = ixgbe_read_mbx_vf_legacy; + mbx->ops[0].write = ixgbe_write_mbx_vf_legacy; + mbx->ops[0].check_for_msg = ixgbe_check_for_msg_vf; + mbx->ops[0].check_for_ack = ixgbe_check_for_ack_vf; + mbx->ops[0].check_for_rst = ixgbe_check_for_rst_vf; + mbx->ops[0].clear = NULL; mbx->stats.msgs_tx.ev_count = 0; mbx->stats.msgs_rx.ev_count = 0; @@ -551,62 +698,112 @@ void ixgbe_init_mbx_params_vf(struct ixg mbx->stats.rsts.ev_count = 0; } +/** + * ixgbe_upgrade_mbx_params_vf - set initial values for vf mailbox + * @hw: pointer to the HW structure + * + * Initializes the hw->mbx struct to correct values for vf mailbox + */ +void ixgbe_upgrade_mbx_params_vf(struct ixgbe_hw *hw) +{ + struct ixgbe_mbx_info *mbx = &hw->mbx; + + mbx->timeout = IXGBE_VF_MBX_INIT_TIMEOUT; + mbx->usec_delay = IXGBE_VF_MBX_INIT_DELAY; + + mbx->size = IXGBE_VFMAILBOX_SIZE; + + /* VF has only one mailbox connection, no need for more IDs */ + mbx->ops[0].release = ixgbe_release_mbx_lock_vf; + mbx->ops[0].read = ixgbe_read_mbx_vf; + mbx->ops[0].write = ixgbe_write_mbx_vf; + mbx->ops[0].check_for_msg = ixgbe_check_for_msg_vf; + mbx->ops[0].check_for_ack = ixgbe_check_for_ack_vf; + mbx->ops[0].check_for_rst = ixgbe_check_for_rst_vf; + mbx->ops[0].clear = NULL; +} + +static void ixgbe_clear_msg_pf(struct ixgbe_hw *hw, u16 vf_id) +{ + u32 vf_shift = IXGBE_PFMBICR_SHIFT(vf_id); + s32 index = IXGBE_PFMBICR_INDEX(vf_id); + u32 pfmbicr; + + pfmbicr = IXGBE_READ_REG(hw, IXGBE_PFMBICR(index)); + + if (pfmbicr & (IXGBE_PFMBICR_VFREQ_VF1 << vf_shift)) + hw->mbx.stats.reqs.ev_count++; + + IXGBE_WRITE_REG(hw, IXGBE_PFMBICR(index), + IXGBE_PFMBICR_VFREQ_VF1 << vf_shift); +} + +static void ixgbe_clear_ack_pf(struct ixgbe_hw *hw, u16 vf_id) +{ + u32 vf_shift = IXGBE_PFMBICR_SHIFT(vf_id); + s32 index = IXGBE_PFMBICR_INDEX(vf_id); + u32 pfmbicr; + + pfmbicr = IXGBE_READ_REG(hw, IXGBE_PFMBICR(index)); + + if (pfmbicr & (IXGBE_PFMBICR_VFACK_VF1 << vf_shift)) + hw->mbx.stats.acks.ev_count++; + + IXGBE_WRITE_REG(hw, IXGBE_PFMBICR(index), + IXGBE_PFMBICR_VFACK_VF1 << vf_shift); +} + static s32 ixgbe_check_for_bit_pf(struct ixgbe_hw *hw, u32 mask, s32 index) { - u32 mbvficr = IXGBE_READ_REG(hw, IXGBE_MBVFICR(index)); - s32 ret_val = IXGBE_ERR_MBX; + u32 pfmbicr = IXGBE_READ_REG(hw, IXGBE_PFMBICR(index)); - if (mbvficr & mask) { - ret_val = IXGBE_SUCCESS; - IXGBE_WRITE_REG(hw, IXGBE_MBVFICR(index), mask); - } + if (pfmbicr & mask) + return IXGBE_SUCCESS; - return ret_val; + return IXGBE_ERR_MBX; } /** * ixgbe_check_for_msg_pf - checks to see if the VF has sent mail * @hw: pointer to the HW structure - * @vf_number: the VF index + * @vf_id: the VF index * * returns SUCCESS if the VF has set the Status bit or else ERR_MBX **/ -static s32 ixgbe_check_for_msg_pf(struct ixgbe_hw *hw, u16 vf_number) +static s32 ixgbe_check_for_msg_pf(struct ixgbe_hw *hw, u16 vf_id) { - s32 ret_val = IXGBE_ERR_MBX; - s32 index = IXGBE_MBVFICR_INDEX(vf_number); - u32 vf_bit = vf_number % 16; + u32 vf_shift = IXGBE_PFMBICR_SHIFT(vf_id); + s32 index = IXGBE_PFMBICR_INDEX(vf_id); DEBUGFUNC("ixgbe_check_for_msg_pf"); - if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFREQ_VF1 << vf_bit, - index)) { - ret_val = IXGBE_SUCCESS; - hw->mbx.stats.reqs.ev_count++; - } + if (!ixgbe_check_for_bit_pf(hw, IXGBE_PFMBICR_VFREQ_VF1 << vf_shift, + index)) + return IXGBE_SUCCESS; - return ret_val; + return IXGBE_ERR_MBX; } /** * ixgbe_check_for_ack_pf - checks to see if the VF has ACKed * @hw: pointer to the HW structure - * @vf_number: the VF index + * @vf_id: the VF index * * returns SUCCESS if the VF has set the Status bit or else ERR_MBX **/ -static s32 ixgbe_check_for_ack_pf(struct ixgbe_hw *hw, u16 vf_number) +static s32 ixgbe_check_for_ack_pf(struct ixgbe_hw *hw, u16 vf_id) { + u32 vf_shift = IXGBE_PFMBICR_SHIFT(vf_id); + s32 index = IXGBE_PFMBICR_INDEX(vf_id); s32 ret_val = IXGBE_ERR_MBX; - s32 index = IXGBE_MBVFICR_INDEX(vf_number); - u32 vf_bit = vf_number % 16; DEBUGFUNC("ixgbe_check_for_ack_pf"); - if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFACK_VF1 << vf_bit, + if (!ixgbe_check_for_bit_pf(hw, IXGBE_PFMBICR_VFACK_VF1 << vf_shift, index)) { ret_val = IXGBE_SUCCESS; - hw->mbx.stats.acks.ev_count++; + /* TODO: should this be autocleared? */ + ixgbe_clear_ack_pf(hw, vf_id); } return ret_val; @@ -615,28 +812,28 @@ static s32 ixgbe_check_for_ack_pf(struct /** * ixgbe_check_for_rst_pf - checks to see if the VF has reset * @hw: pointer to the HW structure - * @vf_number: the VF index + * @vf_id: the VF index * * returns SUCCESS if the VF has set the Status bit or else ERR_MBX **/ -static s32 ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, u16 vf_number) +static s32 ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, u16 vf_id) { - u32 reg_offset = (vf_number < 32) ? 0 : 1; - u32 vf_shift = vf_number % 32; - u32 vflre = 0; + u32 vf_shift = IXGBE_PFVFLRE_SHIFT(vf_id); + u32 index = IXGBE_PFVFLRE_INDEX(vf_id); s32 ret_val = IXGBE_ERR_MBX; + u32 vflre = 0; DEBUGFUNC("ixgbe_check_for_rst_pf"); switch (hw->mac.type) { case ixgbe_mac_82599EB: - vflre = IXGBE_READ_REG(hw, IXGBE_VFLRE(reg_offset)); + vflre = IXGBE_READ_REG(hw, IXGBE_PFVFLRE(index)); break; case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: case ixgbe_mac_X550EM_a: case ixgbe_mac_X540: - vflre = IXGBE_READ_REG(hw, IXGBE_VFLREC(reg_offset)); + vflre = IXGBE_READ_REG(hw, IXGBE_PFVFLREC(index)); break; default: break; @@ -644,7 +841,7 @@ static s32 ixgbe_check_for_rst_pf(struct if (vflre & (1 << vf_shift)) { ret_val = IXGBE_SUCCESS; - IXGBE_WRITE_REG(hw, IXGBE_VFLREC(reg_offset), (1 << vf_shift)); + IXGBE_WRITE_REG(hw, IXGBE_PFVFLREC(index), (1 << vf_shift)); hw->mbx.stats.rsts.ev_count++; } @@ -654,142 +851,290 @@ static s32 ixgbe_check_for_rst_pf(struct /** * ixgbe_obtain_mbx_lock_pf - obtain mailbox lock * @hw: pointer to the HW structure - * @vf_number: the VF index + * @vf_id: the VF index * * return SUCCESS if we obtained the mailbox lock **/ -static s32 ixgbe_obtain_mbx_lock_pf(struct ixgbe_hw *hw, u16 vf_number) +static s32 ixgbe_obtain_mbx_lock_pf(struct ixgbe_hw *hw, u16 vf_id) { + struct ixgbe_mbx_info *mbx = &hw->mbx; + int countdown = mbx->timeout; s32 ret_val = IXGBE_ERR_MBX; - u32 p2v_mailbox; + u32 pf_mailbox; DEBUGFUNC("ixgbe_obtain_mbx_lock_pf"); - /* Take ownership of the buffer */ - IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_PFU); + if (!mbx->timeout) + return IXGBE_ERR_CONFIG; - /* reserve mailbox for vf use */ - p2v_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_number)); - if (p2v_mailbox & IXGBE_PFMAILBOX_PFU) - ret_val = IXGBE_SUCCESS; - else - ERROR_REPORT2(IXGBE_ERROR_POLLING, - "Failed to obtain mailbox lock for VF%d", vf_number); + while (countdown--) { + /* Reserve mailbox for PF use */ + pf_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_id)); + pf_mailbox |= IXGBE_PFMAILBOX_PFU; + IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_id), pf_mailbox); + + /* Verify that PF is the owner of the lock */ + pf_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_id)); + if (pf_mailbox & IXGBE_PFMAILBOX_PFU) { + ret_val = IXGBE_SUCCESS; + break; + } + /* Wait a bit before trying again */ + usec_delay(mbx->usec_delay); + } + + if (ret_val != IXGBE_SUCCESS) { + ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE, + "Failed to obtain mailbox lock"); + ret_val = IXGBE_ERR_TIMEOUT; + } return ret_val; } /** + * ixgbe_release_mbx_lock_pf - release mailbox lock + * @hw: pointer to the HW structure + * @vf_id: the VF index + **/ +static void ixgbe_release_mbx_lock_pf(struct ixgbe_hw *hw, u16 vf_id) +{ + u32 pf_mailbox; + + DEBUGFUNC("ixgbe_release_mbx_lock_pf"); + + /* Return ownership of the buffer */ + pf_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_id)); + pf_mailbox &= ~IXGBE_PFMAILBOX_PFU; + IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_id), pf_mailbox); +} + +/** + * ixgbe_write_mbx_pf_legacy - Places a message in the mailbox + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @vf_id: the VF index + * + * returns SUCCESS if it successfully copied message into the buffer + **/ +static s32 ixgbe_write_mbx_pf_legacy(struct ixgbe_hw *hw, u32 *msg, u16 size, + u16 vf_id) +{ + s32 ret_val; + u16 i; + + DEBUGFUNC("ixgbe_write_mbx_pf_legacy"); + + /* lock the mailbox to prevent pf/vf race condition */ + ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_id); + if (ret_val) + return ret_val; + + /* flush msg and acks as we are overwriting the message buffer */ + ixgbe_check_for_msg_pf(hw, vf_id); + ixgbe_clear_msg_pf(hw, vf_id); + ixgbe_check_for_ack_pf(hw, vf_id); + ixgbe_clear_ack_pf(hw, vf_id); + + /* copy the caller specified message to the mailbox memory buffer */ + for (i = 0; i < size; i++) + IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_id), i, msg[i]); + + /* Interrupt VF to tell it a message has been sent and release buffer*/ + IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_id), IXGBE_PFMAILBOX_STS); + + /* update stats */ + hw->mbx.stats.msgs_tx.ev_count++; + + return IXGBE_SUCCESS; +} + +/** * ixgbe_write_mbx_pf - Places a message in the mailbox * @hw: pointer to the HW structure * @msg: The message buffer * @size: Length of buffer - * @vf_number: the VF index + * @vf_id: the VF index * * returns SUCCESS if it successfully copied message into the buffer **/ static s32 ixgbe_write_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size, - u16 vf_number) + u16 vf_id) { + u32 pf_mailbox; s32 ret_val; u16 i; DEBUGFUNC("ixgbe_write_mbx_pf"); /* lock the mailbox to prevent pf/vf race condition */ - ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number); + ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_id); if (ret_val) - goto out_no_write; + goto out; /* flush msg and acks as we are overwriting the message buffer */ - ixgbe_check_for_msg_pf(hw, vf_number); - ixgbe_check_for_ack_pf(hw, vf_number); + ixgbe_clear_msg_pf(hw, vf_id); + ixgbe_clear_ack_pf(hw, vf_id); /* copy the caller specified message to the mailbox memory buffer */ for (i = 0; i < size; i++) - IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i, msg[i]); + IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_id), i, msg[i]); - /* Interrupt VF to tell it a message has been sent and release buffer*/ - IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_STS); + /* Interrupt VF to tell it a message has been sent */ + pf_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_id)); + pf_mailbox |= IXGBE_PFMAILBOX_STS; + IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_id), pf_mailbox); + + /* if msg sent wait until we receive an ack */ + ixgbe_poll_for_ack(hw, vf_id); /* update stats */ hw->mbx.stats.msgs_tx.ev_count++; -out_no_write: +out: + hw->mbx.ops[vf_id].release(hw, vf_id); + return ret_val; } /** + * ixgbe_read_mbx_pf_legacy - Read a message from the mailbox + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @vf_id: the VF index + * + * This function copies a message from the mailbox buffer to the caller's + * memory buffer. The presumption is that the caller knows that there was + * a message due to a VF request so no polling for message is needed. + **/ +static s32 ixgbe_read_mbx_pf_legacy(struct ixgbe_hw *hw, u32 *msg, u16 size, + u16 vf_id) +{ + s32 ret_val; + u16 i; + + DEBUGFUNC("ixgbe_read_mbx_pf_legacy"); + + /* lock the mailbox to prevent pf/vf race condition */ + ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_id); + if (ret_val != IXGBE_SUCCESS) + return ret_val; + + /* copy the message to the mailbox memory buffer */ + for (i = 0; i < size; i++) + msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_id), i); + + /* Acknowledge the message and release buffer */ + IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_id), IXGBE_PFMAILBOX_ACK); + + /* update stats */ + hw->mbx.stats.msgs_rx.ev_count++; + + return IXGBE_SUCCESS; +} + +/** * ixgbe_read_mbx_pf - Read a message from the mailbox * @hw: pointer to the HW structure * @msg: The message buffer * @size: Length of buffer - * @vf_number: the VF index + * @vf_id: the VF index * * This function copies a message from the mailbox buffer to the caller's * memory buffer. The presumption is that the caller knows that there was * a message due to a VF request so no polling for message is needed. **/ static s32 ixgbe_read_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size, - u16 vf_number) + u16 vf_id) { + u32 pf_mailbox; s32 ret_val; u16 i; DEBUGFUNC("ixgbe_read_mbx_pf"); - /* lock the mailbox to prevent pf/vf race condition */ - ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number); - if (ret_val) - goto out_no_read; + /* check if there is a message from VF */ + ret_val = ixgbe_check_for_msg_pf(hw, vf_id); + if (ret_val != IXGBE_SUCCESS) + return IXGBE_ERR_MBX_NOMSG; + + ixgbe_clear_msg_pf(hw, vf_id); /* copy the message to the mailbox memory buffer */ for (i = 0; i < size; i++) - msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i); + msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_id), i); /* Acknowledge the message and release buffer */ - IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_ACK); + pf_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_id)); + pf_mailbox |= IXGBE_PFMAILBOX_ACK; + IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_id), pf_mailbox); /* update stats */ hw->mbx.stats.msgs_rx.ev_count++; -out_no_read: - return ret_val; + return IXGBE_SUCCESS; } /** * ixgbe_clear_mbx_pf - Clear Mailbox Memory * @hw: pointer to the HW structure - * @vf_number: the VF index + * @vf_id: the VF index * * Set VFMBMEM of given VF to 0x0. **/ -static s32 ixgbe_clear_mbx_pf(struct ixgbe_hw *hw, u16 vf_number) +static s32 ixgbe_clear_mbx_pf(struct ixgbe_hw *hw, u16 vf_id) { u16 mbx_size = hw->mbx.size; u16 i; - if (vf_number > 63) + if (vf_id > 63) return IXGBE_ERR_PARAM; for (i = 0; i < mbx_size; ++i) - IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i, 0x0); + IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_id), i, 0x0); return IXGBE_SUCCESS; } /** + * ixgbe_init_mbx_params_pf_id - set initial values for pf mailbox + * @hw: pointer to the HW structure + * @vf_id: the VF index + * + * Initializes single set of the hw->mbx struct to correct values for pf mailbox + * Set of legacy functions is being used here + */ +void ixgbe_init_mbx_params_pf_id(struct ixgbe_hw *hw, u16 vf_id) +{ + struct ixgbe_mbx_info *mbx = &hw->mbx; + + mbx->ops[vf_id].release = ixgbe_release_mbx_lock_dummy; + mbx->ops[vf_id].read = ixgbe_read_mbx_pf_legacy; + mbx->ops[vf_id].write = ixgbe_write_mbx_pf_legacy; + mbx->ops[vf_id].check_for_msg = ixgbe_check_for_msg_pf; + mbx->ops[vf_id].check_for_ack = ixgbe_check_for_ack_pf; + mbx->ops[vf_id].check_for_rst = ixgbe_check_for_rst_pf; + mbx->ops[vf_id].clear = ixgbe_clear_mbx_pf; +} + +/** * ixgbe_init_mbx_params_pf - set initial values for pf mailbox * @hw: pointer to the HW structure * - * Initializes the hw->mbx struct to correct values for pf mailbox + * Initializes all sets of the hw->mbx struct to correct values for pf + * mailbox. One set corresponds to single VF. It also initializes counters + * and general variables. A set of legacy functions is used by default. */ void ixgbe_init_mbx_params_pf(struct ixgbe_hw *hw) { + u16 i; struct ixgbe_mbx_info *mbx = &hw->mbx; + /* Ensure we are not calling this function from VF */ if (hw->mac.type != ixgbe_mac_82599EB && hw->mac.type != ixgbe_mac_X550 && hw->mac.type != ixgbe_mac_X550EM_x && @@ -797,23 +1142,57 @@ void ixgbe_init_mbx_params_pf(struct ixg hw->mac.type != ixgbe_mac_X540) return; - mbx->timeout = 0; - mbx->usec_delay = 0; - + /* Initialize common mailbox settings */ + mbx->timeout = IXGBE_VF_MBX_INIT_TIMEOUT; + mbx->usec_delay = IXGBE_VF_MBX_INIT_DELAY; mbx->size = IXGBE_VFMAILBOX_SIZE; - mbx->ops.read = ixgbe_read_mbx_pf; - mbx->ops.write = ixgbe_write_mbx_pf; - mbx->ops.read_posted = ixgbe_read_posted_mbx; - mbx->ops.write_posted = ixgbe_write_posted_mbx; - mbx->ops.check_for_msg = ixgbe_check_for_msg_pf; - mbx->ops.check_for_ack = ixgbe_check_for_ack_pf; - mbx->ops.check_for_rst = ixgbe_check_for_rst_pf; - mbx->ops.clear = ixgbe_clear_mbx_pf; - + /* Initialize counters with zeroes */ mbx->stats.msgs_tx.ev_count = 0; mbx->stats.msgs_rx.ev_count = 0; mbx->stats.reqs.ev_count = 0; mbx->stats.acks.ev_count = 0; mbx->stats.rsts.ev_count = 0; + + /* No matter of VF number, we initialize params for all 64 VFs. */ + /* TODO: 1. Add a define for max VF and refactor SHARED to get rid + * of magic number for that (63 or 64 depending on use case.) + * 2. rewrite the code to dynamically allocate mbx->ops[vf_id] for + * certain number of VFs instead of default maximum value of 64 (0..63) + */ + for (i = 0; i < 64; i++) + ixgbe_init_mbx_params_pf_id(hw, i); +} + +/** + * ixgbe_upgrade_mbx_params_pf - Upgrade initial values for pf mailbox + * @hw: pointer to the HW structure + * @vf_id: the VF index + * + * Initializes the hw->mbx struct to new function set for improved + * stability and handling of messages. + */ +void ixgbe_upgrade_mbx_params_pf(struct ixgbe_hw *hw, u16 vf_id) +{ + struct ixgbe_mbx_info *mbx = &hw->mbx; + + /* Ensure we are not calling this function from VF */ + if (hw->mac.type != ixgbe_mac_82599EB && + hw->mac.type != ixgbe_mac_X550 && + hw->mac.type != ixgbe_mac_X550EM_x && + hw->mac.type != ixgbe_mac_X550EM_a && + hw->mac.type != ixgbe_mac_X540) + return; + + mbx->timeout = IXGBE_VF_MBX_INIT_TIMEOUT; + mbx->usec_delay = IXGBE_VF_MBX_INIT_DELAY; + mbx->size = IXGBE_VFMAILBOX_SIZE; + + mbx->ops[vf_id].release = ixgbe_release_mbx_lock_pf; + mbx->ops[vf_id].read = ixgbe_read_mbx_pf; + mbx->ops[vf_id].write = ixgbe_write_mbx_pf; + mbx->ops[vf_id].check_for_msg = ixgbe_check_for_msg_pf; + mbx->ops[vf_id].check_for_ack = ixgbe_check_for_ack_pf; + mbx->ops[vf_id].check_for_rst = ixgbe_check_for_rst_pf; + mbx->ops[vf_id].clear = ixgbe_clear_mbx_pf; } Index: src/sys/dev/pci/ixgbe/ixgbe_mbx.h diff -u src/sys/dev/pci/ixgbe/ixgbe_mbx.h:1.10.8.4 src/sys/dev/pci/ixgbe/ixgbe_mbx.h:1.10.8.5 --- src/sys/dev/pci/ixgbe/ixgbe_mbx.h:1.10.8.4 Sun Jan 30 16:06:35 2022 +++ src/sys/dev/pci/ixgbe/ixgbe_mbx.h Mon Jan 31 17:38:36 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: ixgbe_mbx.h,v 1.10.8.4 2022/01/30 16:06:35 martin Exp $ */ +/* $NetBSD: ixgbe_mbx.h,v 1.10.8.5 2022/01/31 17:38:36 martin Exp $ */ /****************************************************************************** SPDX-License-Identifier: BSD-3-Clause @@ -42,13 +42,12 @@ struct ixgbe_mbx_operations { void (*init_params)(struct ixgbe_hw *hw); - s32 (*read)(struct ixgbe_hw *, u32 *, u16, u16); - s32 (*write)(struct ixgbe_hw *, u32 *, u16, u16); - s32 (*read_posted)(struct ixgbe_hw *, u32 *, u16, u16); - s32 (*write_posted)(struct ixgbe_hw *, u32 *, u16, u16); - s32 (*check_for_msg)(struct ixgbe_hw *, u16); - s32 (*check_for_ack)(struct ixgbe_hw *, u16); - s32 (*check_for_rst)(struct ixgbe_hw *, u16); + void (*release)(struct ixgbe_hw *hw, u16 mbx_id); + s32 (*read)(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id); + s32 (*write)(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id); + s32 (*check_for_msg)(struct ixgbe_hw *hw, u16 vf_number); + s32 (*check_for_ack)(struct ixgbe_hw *hw, u16 vf_number); + s32 (*check_for_rst)(struct ixgbe_hw *hw, u16 vf_number); s32 (*clear)(struct ixgbe_hw *hw, u16 vf_number); }; @@ -62,11 +61,16 @@ struct ixgbe_mbx_stats { }; struct ixgbe_mbx_info { - struct ixgbe_mbx_operations ops; + /* + * PF: One set of operations for each VF to handle various API versions + * at the same time + * VF: Only the very first (0) set should be used + */ + struct ixgbe_mbx_operations ops[64]; struct ixgbe_mbx_stats stats; u32 timeout; u32 usec_delay; - u32 v2p_mailbox; + u32 vf_mailbox; u16 size; }; @@ -92,10 +96,10 @@ struct ixgbe_mbx_info { #define IXGBE_PFMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */ #define IXGBE_PFMAILBOX_RVFU 0x00000010 /* Reset VFU - used when VF stuck */ -#define IXGBE_MBVFICR_VFREQ_MASK 0x0000FFFF /* bits for VF messages */ -#define IXGBE_MBVFICR_VFREQ_VF1 0x00000001 /* bit for VF 1 message */ -#define IXGBE_MBVFICR_VFACK_MASK 0xFFFF0000 /* bits for VF acks */ -#define IXGBE_MBVFICR_VFACK_VF1 0x00010000 /* bit for VF 1 ack */ +#define IXGBE_PFMBICR_VFREQ_MASK 0x0000FFFF /* bits for VF messages */ +#define IXGBE_PFMBICR_VFREQ_VF1 0x00000001 /* bit for VF 1 message */ +#define IXGBE_PFMBICR_VFACK_MASK 0xFFFF0000 /* bits for VF acks */ +#define IXGBE_PFMBICR_VFACK_VF1 0x00010000 /* bit for VF 1 ack */ /* If it's a IXGBE_VF_* msg then it originates in the VF and is sent to the @@ -127,6 +131,9 @@ enum ixgbe_pfvf_api_rev { ixgbe_mbox_api_11, /* API version 1.1, linux/freebsd VF driver */ ixgbe_mbox_api_12, /* API version 1.2, linux/freebsd VF driver */ ixgbe_mbox_api_13, /* API version 1.3, linux/freebsd VF driver */ + /* API 1.4 is being used in the upstream for IPsec */ + ixgbe_mbox_api_14, /* API version 1.4, linux/freebsd VF driver */ + ixgbe_mbox_api_15, /* API version 1.5, linux/freebsd VF driver */ /* This value should always be last */ ixgbe_mbox_api_unknown, /* indicates that API version is not known */ }; @@ -187,16 +194,17 @@ enum ixgbevf_xcast_modes { #define IXGBE_VF_MBX_INIT_TIMEOUT 2000 /* number of retries on mailbox */ #define IXGBE_VF_MBX_INIT_DELAY 500 /* microseconds between retries */ -s32 ixgbe_read_mbx(struct ixgbe_hw *, u32 *, u16, u16); -s32 ixgbe_write_mbx(struct ixgbe_hw *, u32 *, u16, u16); -s32 ixgbe_read_posted_mbx(struct ixgbe_hw *, u32 *, u16, u16); -s32 ixgbe_write_posted_mbx(struct ixgbe_hw *, u32 *, u16, u16); -s32 ixgbe_check_for_msg(struct ixgbe_hw *, u16); -s32 ixgbe_check_for_ack(struct ixgbe_hw *, u16); -s32 ixgbe_check_for_rst(struct ixgbe_hw *, u16); +s32 ixgbe_read_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id); +s32 ixgbe_poll_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id); +s32 ixgbe_write_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id); +s32 ixgbe_check_for_msg(struct ixgbe_hw *hw, u16 mbx_id); +s32 ixgbe_check_for_ack(struct ixgbe_hw *hw, u16 mbx_id); +s32 ixgbe_check_for_rst(struct ixgbe_hw *hw, u16 mbx_id); s32 ixgbe_clear_mbx(struct ixgbe_hw *hw, u16 vf_number); -void ixgbe_init_mbx_ops_generic(struct ixgbe_hw *hw); void ixgbe_init_mbx_params_vf(struct ixgbe_hw *); -void ixgbe_init_mbx_params_pf(struct ixgbe_hw *); +void ixgbe_upgrade_mbx_params_vf(struct ixgbe_hw *hw); +void ixgbe_init_mbx_params_pf(struct ixgbe_hw *hw); +void ixgbe_init_mbx_params_pf_id(struct ixgbe_hw *hw, u16 vf_id); +void ixgbe_upgrade_mbx_params_pf(struct ixgbe_hw *hw, u16 vf_id); #endif /* _IXGBE_MBX_H_ */ Index: src/sys/dev/pci/ixgbe/ixgbe_type.h diff -u src/sys/dev/pci/ixgbe/ixgbe_type.h:1.22.2.15 src/sys/dev/pci/ixgbe/ixgbe_type.h:1.22.2.16 --- src/sys/dev/pci/ixgbe/ixgbe_type.h:1.22.2.15 Sun Jan 30 16:06:35 2022 +++ src/sys/dev/pci/ixgbe/ixgbe_type.h Mon Jan 31 17:38:36 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: ixgbe_type.h,v 1.22.2.15 2022/01/30 16:06:35 martin Exp $ */ +/* $NetBSD: ixgbe_type.h,v 1.22.2.16 2022/01/31 17:38:36 martin Exp $ */ /****************************************************************************** SPDX-License-Identifier: BSD-3-Clause @@ -480,8 +480,14 @@ struct ixgbe_nvm_version { #define IXGBE_PFMAILBOX(_i) (0x04B00 + (4 * (_i))) /* 64 total */ /* 64 Mailboxes, 16 DW each */ #define IXGBE_PFMBMEM(_i) (0x13000 + (64 * (_i))) +#define IXGBE_PFMBICR_INDEX(_i) ((_i) >> 4) +#define IXGBE_PFMBICR_SHIFT(_i) ((_i) % 16) #define IXGBE_PFMBICR(_i) (0x00710 + (4 * (_i))) /* 4 total */ #define IXGBE_PFMBIMR(_i) (0x00720 + (4 * (_i))) /* 4 total */ +#define IXGBE_PFVFLRE(_i) ((((_i) & 1) ? 0x001C0 : 0x00600)) +#define IXGBE_PFVFLREC(_i) (0x00700 + ((_i) * 4)) +#define IXGBE_PFVFLRE_INDEX(_i) ((_i) >> 5) +#define IXGBE_PFVFLRE_SHIFT(_i) ((_i) % 32) #define IXGBE_VFRE(_i) (0x051E0 + ((_i) * 4)) #define IXGBE_VFTE(_i) (0x08110 + ((_i) * 4)) #define IXGBE_VMECM(_i) (0x08790 + ((_i) * 4)) @@ -2411,6 +2417,7 @@ enum { #endif /* PREBOOT_SUPPORT || QV_RELEASE*/ + #define IXGBE_SAN_MAC_ADDR_PTR 0x28 #define IXGBE_NVM_MAP_VER 0x29 #define IXGBE_OEM_NVM_IMAGE_VER 0x2A @@ -2922,12 +2929,6 @@ enum { #define IXGBE_RX_DESC_SPECIAL_PRI_MASK 0xE000 /* Priority in upper 3 bits */ #define IXGBE_RX_DESC_SPECIAL_PRI_SHIFT 0x000D /* Priority in upper 3 of 16 */ #define IXGBE_TX_DESC_SPECIAL_PRI_SHIFT IXGBE_RX_DESC_SPECIAL_PRI_SHIFT - -/* SR-IOV specific macros */ -#define IXGBE_MBVFICR_INDEX(vf_number) (vf_number >> 4) -#define IXGBE_MBVFICR(_i) (0x00710 + ((_i) * 4)) -#define IXGBE_VFLRE(_i) (((_i & 1) ? 0x001C0 : 0x00600)) -#define IXGBE_VFLREC(_i) (0x00700 + ((_i) * 4)) /* Translated register #defines */ #define IXGBE_PVFCTRL(P) (0x00300 + (4 * (P))) #define IXGBE_PVFSTATUS(P) (0x00008 + (0 * (P))) @@ -4295,7 +4296,9 @@ struct ixgbe_hw { #define IXGBE_ERR_FDIR_CMD_INCOMPLETE -38 #define IXGBE_ERR_FW_RESP_INVALID -39 #define IXGBE_ERR_TOKEN_RETRY -40 -#define IXGBE_ERR_MBX -100 +#define IXGBE_ERR_MBX -41 +#define IXGBE_ERR_MBX_NOMSG -42 +#define IXGBE_ERR_TIMEOUT -43 #define IXGBE_ERR_NOT_TRUSTED -50 /* XXX NetBSD */ #define IXGBE_ERR_NOT_IN_PROMISC -51 /* XXX NetBSD */ Index: src/sys/dev/pci/ixgbe/ixgbe_vf.c diff -u src/sys/dev/pci/ixgbe/ixgbe_vf.c:1.12.8.8 src/sys/dev/pci/ixgbe/ixgbe_vf.c:1.12.8.9 --- src/sys/dev/pci/ixgbe/ixgbe_vf.c:1.12.8.8 Sun Jan 30 16:06:35 2022 +++ src/sys/dev/pci/ixgbe/ixgbe_vf.c Mon Jan 31 17:38:36 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: ixgbe_vf.c,v 1.12.8.8 2022/01/30 16:06:35 martin Exp $ */ +/* $NetBSD: ixgbe_vf.c,v 1.12.8.9 2022/01/31 17:38:36 martin Exp $ */ /****************************************************************************** SPDX-License-Identifier: BSD-3-Clause @@ -36,7 +36,7 @@ /*$FreeBSD: head/sys/dev/ixgbe/ixgbe_vf.c 331224 2018-03-19 20:55:05Z erj $*/ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ixgbe_vf.c,v 1.12.8.8 2022/01/30 16:06:35 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ixgbe_vf.c,v 1.12.8.9 2022/01/31 17:38:36 martin Exp $"); #include "ixgbe_api.h" #include "ixgbe_type.h" @@ -60,6 +60,8 @@ __KERNEL_RCSID(0, "$NetBSD: ixgbe_vf.c,v **/ s32 ixgbe_init_ops_vf(struct ixgbe_hw *hw) { + u16 i; + /* MAC */ hw->mac.ops.init_hw = ixgbe_init_hw_vf; hw->mac.ops.reset_hw = ixgbe_reset_hw_vf; @@ -92,7 +94,8 @@ s32 ixgbe_init_ops_vf(struct ixgbe_hw *h hw->mac.max_tx_queues = 1; hw->mac.max_rx_queues = 1; - hw->mbx.ops.init_params = ixgbe_init_mbx_params_vf; + for (i = 0; i < 64; i++) + hw->mbx.ops[i].init_params = ixgbe_init_mbx_params_vf; return IXGBE_SUCCESS; } @@ -196,6 +199,7 @@ s32 ixgbe_reset_hw_vf(struct ixgbe_hw *h /* reset the api version */ hw->api_version = ixgbe_mbox_api_10; + ixgbe_init_mbx_params_vf(hw); DEBUGOUT("Issuing a function level reset to MAC\n"); @@ -205,7 +209,7 @@ s32 ixgbe_reset_hw_vf(struct ixgbe_hw *h msec_delay(50); /* we cannot reset while the RSTI / RSTD bits are asserted */ - while (!mbx->ops.check_for_rst(hw, 0) && timeout) { + while (!mbx->ops[0].check_for_rst(hw, 0) && timeout) { timeout--; usec_delay(5); } @@ -220,7 +224,7 @@ s32 ixgbe_reset_hw_vf(struct ixgbe_hw *h mbx->timeout = IXGBE_VF_MBX_INIT_TIMEOUT; msgbuf[0] = IXGBE_VF_RESET; - mbx->ops.write_posted(hw, msgbuf, 1, 0); + ixgbe_write_mbx(hw, msgbuf, 1, 0); msec_delay(10); @@ -229,8 +233,8 @@ s32 ixgbe_reset_hw_vf(struct ixgbe_hw *h * also set up the mc_filter_type which is piggy backed * on the mac address in word 3 */ - ret_val = mbx->ops.read_posted(hw, msgbuf, - IXGBE_VF_PERMADDR_MSG_LEN, 0); + ret_val = ixgbe_poll_mbx(hw, msgbuf, + IXGBE_VF_PERMADDR_MSG_LEN, 0); if (ret_val) return ret_val; @@ -335,13 +339,12 @@ static s32 ixgbe_mta_vector(struct ixgbe static s32 ixgbevf_write_msg_read_ack(struct ixgbe_hw *hw, u32 *msg, u32 *retmsg, u16 size) { - struct ixgbe_mbx_info *mbx = &hw->mbx; - s32 retval = mbx->ops.write_posted(hw, msg, size, 0); + s32 retval = ixgbe_write_mbx(hw, msg, size, 0); if (retval) return retval; - return mbx->ops.read_posted(hw, retmsg, size, 0); + return ixgbe_poll_mbx(hw, retmsg, size, 0); } /** @@ -450,6 +453,7 @@ s32 ixgbevf_update_xcast_mode(struct ixg return IXGBE_ERR_FEATURE_NOT_SUPPORTED; /* Fall through */ case ixgbe_mbox_api_13: + case ixgbe_mbox_api_15: break; default: return IXGBE_ERR_FEATURE_NOT_SUPPORTED; @@ -621,11 +625,10 @@ s32 ixgbe_check_mac_link_vf(struct ixgbe struct ixgbe_mac_info *mac = &hw->mac; s32 ret_val = IXGBE_SUCCESS; u32 links_reg; - u32 in_msg = 0; UNREFERENCED_1PARAMETER(autoneg_wait_to_complete); /* If we were hit with a reset drop the link */ - if (!mbx->ops.check_for_rst(hw, 0) || !mbx->timeout) + if (!mbx->ops[0].check_for_rst(hw, 0) || !mbx->timeout) mac->get_link_status = TRUE; if (!mac->get_link_status) @@ -654,7 +657,7 @@ s32 ixgbe_check_mac_link_vf(struct ixgbe switch (links_reg & IXGBE_LINKS_SPEED_82599) { case IXGBE_LINKS_SPEED_10G_82599: *speed = IXGBE_LINK_SPEED_10GB_FULL; - if (hw->mac.type >= ixgbe_mac_X550) { + if (hw->mac.type >= ixgbe_mac_X550_vf) { if (links_reg & IXGBE_LINKS_SPEED_NON_STD) *speed = IXGBE_LINK_SPEED_2_5GB_FULL; } @@ -664,7 +667,7 @@ s32 ixgbe_check_mac_link_vf(struct ixgbe break; case IXGBE_LINKS_SPEED_100_82599: *speed = IXGBE_LINK_SPEED_100_FULL; - if (hw->mac.type >= ixgbe_mac_X550) { + if (hw->mac.type >= ixgbe_mac_X550_vf) { if (links_reg & IXGBE_LINKS_SPEED_NON_STD) *speed = IXGBE_LINK_SPEED_5GB_FULL; } @@ -672,30 +675,34 @@ s32 ixgbe_check_mac_link_vf(struct ixgbe case IXGBE_LINKS_SPEED_10_X550EM_A: *speed = IXGBE_LINK_SPEED_UNKNOWN; /* Since Reserved in older MAC's */ - if (hw->mac.type >= ixgbe_mac_X550) + if (hw->mac.type >= ixgbe_mac_X550_vf) *speed = IXGBE_LINK_SPEED_10_FULL; break; default: *speed = IXGBE_LINK_SPEED_UNKNOWN; } - /* 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->ops.read(hw, &in_msg, 1, 0)) - goto out; + if (hw->api_version < ixgbe_mbox_api_15) { + u32 in_msg = 0; - if (!(in_msg & IXGBE_VT_MSGTYPE_CTS)) { - /* msg is not CTS and is NACK we must have lost CTS status */ - if (in_msg & IXGBE_VT_MSGTYPE_FAILURE) - ret_val = -1; - 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 (ixgbe_read_mbx(hw, &in_msg, 1, 0)) + goto out; - /* the pf is talking, if we timed out in the past we reinit */ - if (!mbx->timeout) { - ret_val = -1; - goto out; + if (!(in_msg & IXGBE_VT_MSGTYPE_CTS)) { + /* msg is not CTS and is NACK we must have lost CTS status */ + if (in_msg & IXGBE_VT_MSGTYPE_FAILURE) + ret_val = IXGBE_ERR_MBX; + goto out; + } + + /* the pf is talking, if we timed out in the past we reinit */ + if (!mbx->timeout) { + ret_val = IXGBE_ERR_TIMEOUT; + goto out; + } } /* if we passed all the tests above then the link is up and we no @@ -773,6 +780,7 @@ int ixgbevf_get_queues(struct ixgbe_hw * case ixgbe_mbox_api_11: case ixgbe_mbox_api_12: case ixgbe_mbox_api_13: + case ixgbe_mbox_api_15: break; default: return 0; @@ -787,7 +795,7 @@ int ixgbevf_get_queues(struct ixgbe_hw * msg[0] &= ~IXGBE_VT_MSGTYPE_CTS; /* - * if we didn't get an ACK there must have been + * if we didn't get a SUCCESS there must have been * some sort of mailbox error so we should treat it * as such */ Index: src/sys/dev/pci/ixgbe/ixgbe_x540.c diff -u src/sys/dev/pci/ixgbe/ixgbe_x540.c:1.9.6.7 src/sys/dev/pci/ixgbe/ixgbe_x540.c:1.9.6.8 --- src/sys/dev/pci/ixgbe/ixgbe_x540.c:1.9.6.7 Sun Jan 30 16:06:35 2022 +++ src/sys/dev/pci/ixgbe/ixgbe_x540.c Mon Jan 31 17:38:36 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: ixgbe_x540.c,v 1.9.6.7 2022/01/30 16:06:35 martin Exp $ */ +/* $NetBSD: ixgbe_x540.c,v 1.9.6.8 2022/01/31 17:38:36 martin Exp $ */ /****************************************************************************** SPDX-License-Identifier: BSD-3-Clause @@ -36,7 +36,7 @@ /*$FreeBSD: head/sys/dev/ixgbe/ixgbe_x540.c 331224 2018-03-19 20:55:05Z erj $*/ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ixgbe_x540.c,v 1.9.6.7 2022/01/30 16:06:35 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ixgbe_x540.c,v 1.9.6.8 2022/01/31 17:38:36 martin Exp $"); #include "ixgbe_x540.h" #include "ixgbe_type.h" @@ -68,6 +68,7 @@ s32 ixgbe_init_ops_X540(struct ixgbe_hw struct ixgbe_phy_info *phy = &hw->phy; struct ixgbe_eeprom_info *eeprom = &hw->eeprom; s32 ret_val; + u16 i; DEBUGFUNC("ixgbe_init_ops_X540"); @@ -151,7 +152,8 @@ s32 ixgbe_init_ops_X540(struct ixgbe_hw mac->arc_subsystem_valid = !!(IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw)) & IXGBE_FWSM_MODE_MASK); - hw->mbx.ops.init_params = ixgbe_init_mbx_params_pf; + for (i = 0; i < 64; i++) + hw->mbx.ops[i].init_params = ixgbe_init_mbx_params_pf; /* LEDs */ mac->ops.blink_led_start = ixgbe_blink_led_start_X540; Index: src/sys/dev/pci/ixgbe/ixv.c diff -u src/sys/dev/pci/ixgbe/ixv.c:1.56.2.35 src/sys/dev/pci/ixgbe/ixv.c:1.56.2.36 --- src/sys/dev/pci/ixgbe/ixv.c:1.56.2.35 Sun Jan 30 16:06:35 2022 +++ src/sys/dev/pci/ixgbe/ixv.c Mon Jan 31 17:38:36 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: ixv.c,v 1.56.2.35 2022/01/30 16:06:35 martin Exp $ */ +/* $NetBSD: ixv.c,v 1.56.2.36 2022/01/31 17:38:36 martin Exp $ */ /****************************************************************************** @@ -35,7 +35,7 @@ /*$FreeBSD: head/sys/dev/ixgbe/if_ixv.c 331224 2018-03-19 20:55:05Z erj $*/ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ixv.c,v 1.56.2.35 2022/01/30 16:06:35 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ixv.c,v 1.56.2.36 2022/01/31 17:38:36 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -466,6 +466,12 @@ ixv_attach(device_t parent, device_t dev case ixgbe_mbox_api_13: apivstr = "1.3"; break; + case ixgbe_mbox_api_14: + apivstr = "1.4"; + break; + case ixgbe_mbox_api_15: + apivstr = "1.5"; + break; default: apivstr = "unknown"; break; @@ -1090,7 +1096,8 @@ static int ixv_negotiate_api(struct adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; - int mbx_api[] = { ixgbe_mbox_api_13, + int mbx_api[] = { ixgbe_mbox_api_15, + ixgbe_mbox_api_13, ixgbe_mbox_api_12, ixgbe_mbox_api_11, ixgbe_mbox_api_10, @@ -1098,8 +1105,11 @@ ixv_negotiate_api(struct adapter *adapte int i = 0; while (mbx_api[i] != ixgbe_mbox_api_unknown) { - if (ixgbevf_negotiate_api_version(hw, mbx_api[i]) == 0) + if (ixgbevf_negotiate_api_version(hw, mbx_api[i]) == 0) { + if (hw->api_version >= ixgbe_mbox_api_15) + ixgbe_upgrade_mbx_params_vf(hw); return (0); + } i++; }