Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d490d158 authored by Mark Rustad's avatar Mark Rustad Committed by Jeff Kirsher
Browse files

ixgbe: Check whether FDIRCMD writes actually complete



Wait up to about 100 us for FDIRCMD writes to complete and return
failure indications.

Signed-off-by: default avatarMark Rustad <mark.d.rustad@intel.com>
Tested-by: default avatarPhil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent b5529ef5
Loading
Loading
Loading
Loading
+39 −24
Original line number Diff line number Diff line
/*******************************************************************************

  Intel 10 Gigabit PCI Express Linux driver
  Copyright(c) 1999 - 2014 Intel Corporation.
  Copyright(c) 1999 - 2015 Intel Corporation.

  This program is free software; you can redistribute it and/or modify it
  under the terms and conditions of the GNU General Public License,
@@ -1241,6 +1241,25 @@ static s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
	return status;
}

/**
 * ixgbe_fdir_check_cmd_complete - poll to check whether FDIRCMD is complete
 * @hw: pointer to hardware structure
 * @fdircmd: current value of FDIRCMD register
 */
static s32 ixgbe_fdir_check_cmd_complete(struct ixgbe_hw *hw, u32 *fdircmd)
{
	int i;

	for (i = 0; i < IXGBE_FDIRCMD_CMD_POLL; i++) {
		*fdircmd = IXGBE_READ_REG(hw, IXGBE_FDIRCMD);
		if (!(*fdircmd & IXGBE_FDIRCMD_CMD_MASK))
			return 0;
		udelay(10);
	}

	return IXGBE_ERR_FDIR_CMD_INCOMPLETE;
}

/**
 *  ixgbe_reinit_fdir_tables_82599 - Reinitialize Flow Director tables.
 *  @hw: pointer to hardware structure
@@ -1249,6 +1268,8 @@ s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw)
{
	int i;
	u32 fdirctrl = IXGBE_READ_REG(hw, IXGBE_FDIRCTRL);
	u32 fdircmd;
	s32 err;

	fdirctrl &= ~IXGBE_FDIRCTRL_INIT_DONE;

@@ -1256,15 +1277,10 @@ s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw)
	 * Before starting reinitialization process,
	 * FDIRCMD.CMD must be zero.
	 */
	for (i = 0; i < IXGBE_FDIRCMD_CMD_POLL; i++) {
		if (!(IXGBE_READ_REG(hw, IXGBE_FDIRCMD) &
		      IXGBE_FDIRCMD_CMD_MASK))
			break;
		udelay(10);
	}
	if (i >= IXGBE_FDIRCMD_CMD_POLL) {
		hw_dbg(hw, "Flow Director previous command isn't complete, aborting table re-initialization.\n");
		return IXGBE_ERR_FDIR_REINIT_FAILED;
	err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd);
	if (err) {
		hw_dbg(hw, "Flow Director previous command did not complete, aborting table re-initialization.\n");
		return err;
	}

	IXGBE_WRITE_REG(hw, IXGBE_FDIRFREE, 0);
@@ -1754,6 +1770,7 @@ s32 ixgbe_fdir_write_perfect_filter_82599(struct ixgbe_hw *hw,
					  u16 soft_id, u8 queue)
{
	u32 fdirport, fdirvlan, fdirhash, fdircmd;
	s32 err;

	/* currently IPv6 is not supported, must be programmed with 0 */
	IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(0),
@@ -1802,6 +1819,11 @@ s32 ixgbe_fdir_write_perfect_filter_82599(struct ixgbe_hw *hw,
	fdircmd |= (u32)input->formatted.vm_pool << IXGBE_FDIRCMD_VT_POOL_SHIFT;

	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, fdircmd);
	err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd);
	if (err) {
		hw_dbg(hw, "Flow Director command did not complete!\n");
		return err;
	}

	return 0;
}
@@ -1811,9 +1833,8 @@ s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw,
					  u16 soft_id)
{
	u32 fdirhash;
	u32 fdircmd = 0;
	u32 retry_count;
	s32 err = 0;
	u32 fdircmd;
	s32 err;

	/* configure FDIRHASH register */
	fdirhash = input->formatted.bkt_hash;
@@ -1826,18 +1847,12 @@ s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw,
	/* Query if filter is present */
	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, IXGBE_FDIRCMD_CMD_QUERY_REM_FILT);

	for (retry_count = 10; retry_count; retry_count--) {
		/* allow 10us for query to process */
		udelay(10);
		/* verify query completed successfully */
		fdircmd = IXGBE_READ_REG(hw, IXGBE_FDIRCMD);
		if (!(fdircmd & IXGBE_FDIRCMD_CMD_MASK))
			break;
	err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd);
	if (err) {
		hw_dbg(hw, "Flow Director command did not complete!\n");
		return err;
	}

	if (!retry_count)
		err = IXGBE_ERR_FDIR_REINIT_FAILED;

	/* if filter exists in hardware then remove it */
	if (fdircmd & IXGBE_FDIRCMD_FILTER_VALID) {
		IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
@@ -1846,7 +1861,7 @@ s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw,
				IXGBE_FDIRCMD_CMD_REMOVE_FLOW);
	}

	return err;
	return 0;
}

/**
+1 −0
Original line number Diff line number Diff line
@@ -3460,6 +3460,7 @@ struct ixgbe_info {
#define IXGBE_ERR_PBA_SECTION                   -31
#define IXGBE_ERR_INVALID_ARGUMENT              -32
#define IXGBE_ERR_HOST_INTERFACE_COMMAND        -33
#define IXGBE_ERR_FDIR_CMD_INCOMPLETE		-38
#define IXGBE_NOT_IMPLEMENTED                   0x7FFFFFFF

#define IXGBE_KRM_PORT_CAR_GEN_CTRL(P)	((P) ? 0x8010 : 0x4010)