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

Commit c8c60d88 authored by Yuval Mintz's avatar Yuval Mintz Committed by David S. Miller
Browse files

bnx2x: Added EEE support



This patch adds energy efficient energy support (802.3az) to bnx2x
boards with 84833 phys (and sufficiently new BC and external FW).

Signed-off-by: default avatarYuval Mintz <yuvalmin@broadcom.com>
Signed-off-by: default avatarEilon Greenstein <eilong@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 80f12ecc
Loading
Loading
Loading
Loading
+60 −1
Original line number Diff line number Diff line
@@ -1067,8 +1067,18 @@ struct port_feat_cfg { /* port 0: 0x454 port 1: 0x4c8 */
	   uses the same defines as link_config */
	u32 mfw_wol_link_cfg2;				    /* 0x480 */

	u32 Reserved2[17];				    /* 0x484 */

	/*  EEE power saving mode */
	u32 eee_power_mode;                                 /* 0x484 */
	#define PORT_FEAT_CFG_EEE_POWER_MODE_MASK                     0x000000FF
	#define PORT_FEAT_CFG_EEE_POWER_MODE_SHIFT                    0
	#define PORT_FEAT_CFG_EEE_POWER_MODE_DISABLED                 0x00000000
	#define PORT_FEAT_CFG_EEE_POWER_MODE_BALANCED                 0x00000001
	#define PORT_FEAT_CFG_EEE_POWER_MODE_AGGRESSIVE               0x00000002
	#define PORT_FEAT_CFG_EEE_POWER_MODE_LOW_LATENCY              0x00000003


	u32 Reserved2[16];                                  /* 0x488 */
};


@@ -1255,6 +1265,8 @@ struct drv_func_mb {
	#define DRV_MSG_CODE_DRV_INFO_ACK               0xd8000000
	#define DRV_MSG_CODE_DRV_INFO_NACK              0xd9000000

	#define DRV_MSG_CODE_EEE_RESULTS_ACK            0xda000000

	#define DRV_MSG_CODE_SET_MF_BW                  0xe0000000
	#define REQ_BC_VER_4_SET_MF_BW                  0x00060202
	#define DRV_MSG_CODE_SET_MF_BW_ACK              0xe1000000
@@ -1320,6 +1332,8 @@ struct drv_func_mb {
	#define FW_MSG_CODE_DRV_INFO_ACK                0xd8100000
	#define FW_MSG_CODE_DRV_INFO_NACK               0xd9100000

	#define FW_MSG_CODE_EEE_RESULS_ACK              0xda100000

	#define FW_MSG_CODE_SET_MF_BW_SENT              0xe0000000
	#define FW_MSG_CODE_SET_MF_BW_DONE              0xe1000000

@@ -1383,6 +1397,8 @@ struct drv_func_mb {

	#define DRV_STATUS_DRV_INFO_REQ                 0x04000000

	#define DRV_STATUS_EEE_NEGOTIATION_RESULTS      0x08000000

	u32 virt_mac_upper;
	#define VIRT_MAC_SIGN_MASK                      0xffff0000
	#define VIRT_MAC_SIGNATURE                      0x564d0000
@@ -1613,6 +1629,11 @@ struct fw_flr_mb {
	struct fw_flr_ack ack;
};

struct eee_remote_vals {
	u32         tx_tw;
	u32         rx_tw;
};

/**** SUPPORT FOR SHMEM ARRRAYS ***
 * The SHMEM HSI is aligned on 32 bit boundaries which makes it difficult to
 * define arrays with storage types smaller then unsigned dwords.
@@ -2053,6 +2074,41 @@ struct shmem2_region {
#define DRV_INFO_CONTROL_OP_CODE_MASK      0x0000ff00
#define DRV_INFO_CONTROL_OP_CODE_SHIFT     8
	u32 ibft_host_addr; /* initialized by option ROM */
	struct eee_remote_vals eee_remote_vals[PORT_MAX];
	u32 reserved[E2_FUNC_MAX];


	/* the status of EEE auto-negotiation
	 * bits 15:0 the configured tx-lpi entry timer value. Depends on bit 31.
	 * bits 19:16 the supported modes for EEE.
	 * bits 23:20 the speeds advertised for EEE.
	 * bits 27:24 the speeds the Link partner advertised for EEE.
	 * The supported/adv. modes in bits 27:19 originate from the
	 * SHMEM_EEE_XXX_ADV definitions (where XXX is replaced by speed).
	 * bit 28 when 1'b1 EEE was requested.
	 * bit 29 when 1'b1 tx lpi was requested.
	 * bit 30 when 1'b1 EEE was negotiated. Tx lpi will be asserted iff
	 * 30:29 are 2'b11.
	 * bit 31 when 1'b0 bits 15:0 contain a PORT_FEAT_CFG_EEE_ define as
	 * value. When 1'b1 those bits contains a value times 16 microseconds.
	 */
	u32 eee_status[PORT_MAX];
	#define SHMEM_EEE_TIMER_MASK		   0x0000ffff
	#define SHMEM_EEE_SUPPORTED_MASK	   0x000f0000
	#define SHMEM_EEE_SUPPORTED_SHIFT	   16
	#define SHMEM_EEE_ADV_STATUS_MASK	   0x00f00000
		#define SHMEM_EEE_100M_ADV	   (1<<0)
		#define SHMEM_EEE_1G_ADV	   (1<<1)
		#define SHMEM_EEE_10G_ADV	   (1<<2)
	#define SHMEM_EEE_ADV_STATUS_SHIFT	   20
	#define	SHMEM_EEE_LP_ADV_STATUS_MASK	   0x0f000000
	#define SHMEM_EEE_LP_ADV_STATUS_SHIFT	   24
	#define SHMEM_EEE_REQUESTED_BIT		   0x10000000
	#define SHMEM_EEE_LPI_REQUESTED_BIT	   0x20000000
	#define SHMEM_EEE_ACTIVE_BIT		   0x40000000
	#define SHMEM_EEE_TIME_OUTPUT_BIT	   0x80000000

	u32 sizeof_port_stats;
};


@@ -2599,6 +2655,9 @@ struct host_port_stats {
	u32            pfc_frames_tx_lo;
	u32            pfc_frames_rx_hi;
	u32            pfc_frames_rx_lo;

	u32            eee_lpi_count_hi;
	u32            eee_lpi_count_lo;
};


+315 −8
Original line number Diff line number Diff line
@@ -1305,6 +1305,94 @@ int bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos)

	return 0;
}

/******************************************************************/
/*			EEE section				   */
/******************************************************************/
static u8 bnx2x_eee_has_cap(struct link_params *params)
{
	struct bnx2x *bp = params->bp;

	if (REG_RD(bp, params->shmem2_base) <=
		   offsetof(struct shmem2_region, eee_status[params->port]))
		return 0;

	return 1;
}

static int bnx2x_eee_nvram_to_time(u32 nvram_mode, u32 *idle_timer)
{
	switch (nvram_mode) {
	case PORT_FEAT_CFG_EEE_POWER_MODE_BALANCED:
		*idle_timer = EEE_MODE_NVRAM_BALANCED_TIME;
		break;
	case PORT_FEAT_CFG_EEE_POWER_MODE_AGGRESSIVE:
		*idle_timer = EEE_MODE_NVRAM_AGGRESSIVE_TIME;
		break;
	case PORT_FEAT_CFG_EEE_POWER_MODE_LOW_LATENCY:
		*idle_timer = EEE_MODE_NVRAM_LATENCY_TIME;
		break;
	default:
		*idle_timer = 0;
		break;
	}

	return 0;
}

static int bnx2x_eee_time_to_nvram(u32 idle_timer, u32 *nvram_mode)
{
	switch (idle_timer) {
	case EEE_MODE_NVRAM_BALANCED_TIME:
		*nvram_mode = PORT_FEAT_CFG_EEE_POWER_MODE_BALANCED;
		break;
	case EEE_MODE_NVRAM_AGGRESSIVE_TIME:
		*nvram_mode = PORT_FEAT_CFG_EEE_POWER_MODE_AGGRESSIVE;
		break;
	case EEE_MODE_NVRAM_LATENCY_TIME:
		*nvram_mode = PORT_FEAT_CFG_EEE_POWER_MODE_LOW_LATENCY;
		break;
	default:
		*nvram_mode = PORT_FEAT_CFG_EEE_POWER_MODE_DISABLED;
		break;
	}

	return 0;
}

static u32 bnx2x_eee_calc_timer(struct link_params *params)
{
	u32 eee_mode, eee_idle;
	struct bnx2x *bp = params->bp;

	if (params->eee_mode & EEE_MODE_OVERRIDE_NVRAM) {
		if (params->eee_mode & EEE_MODE_OUTPUT_TIME) {
			/* time value in eee_mode --> used directly*/
			eee_idle = params->eee_mode & EEE_MODE_TIMER_MASK;
		} else {
			/* hsi value in eee_mode --> time */
			if (bnx2x_eee_nvram_to_time(params->eee_mode &
						    EEE_MODE_NVRAM_MASK,
						    &eee_idle))
				return 0;
		}
	} else {
		/* hsi values in nvram --> time*/
		eee_mode = ((REG_RD(bp, params->shmem_base +
				    offsetof(struct shmem_region, dev_info.
				    port_feature_config[params->port].
				    eee_power_mode)) &
			     PORT_FEAT_CFG_EEE_POWER_MODE_MASK) >>
			    PORT_FEAT_CFG_EEE_POWER_MODE_SHIFT);

		if (bnx2x_eee_nvram_to_time(eee_mode, &eee_idle))
			return 0;
	}

	return eee_idle;
}


/******************************************************************/
/*			PFC section				  */
/******************************************************************/
@@ -1729,6 +1817,14 @@ static int bnx2x_xmac_enable(struct link_params *params,
	/* update PFC */
	bnx2x_update_pfc_xmac(params, vars, 0);

	if (vars->eee_status & SHMEM_EEE_ADV_STATUS_MASK) {
		DP(NETIF_MSG_LINK, "Setting XMAC for EEE\n");
		REG_WR(bp, xmac_base + XMAC_REG_EEE_TIMERS_HI, 0x1380008);
		REG_WR(bp, xmac_base + XMAC_REG_EEE_CTRL, 0x1);
	} else {
		REG_WR(bp, xmac_base + XMAC_REG_EEE_CTRL, 0x0);
	}

	/* Enable TX and RX */
	val = XMAC_CTRL_REG_TX_EN | XMAC_CTRL_REG_RX_EN;

@@ -2439,6 +2535,16 @@ static void bnx2x_update_mng(struct link_params *params, u32 link_status)
			port_mb[params->port].link_status), link_status);
}

static void bnx2x_update_mng_eee(struct link_params *params, u32 eee_status)
{
	struct bnx2x *bp = params->bp;

	if (bnx2x_eee_has_cap(params))
		REG_WR(bp, params->shmem2_base +
		       offsetof(struct shmem2_region,
				eee_status[params->port]), eee_status);
}

static void bnx2x_update_pfc_nig(struct link_params *params,
		struct link_vars *vars,
		struct bnx2x_nig_brb_pfc_port_params *nig_params)
@@ -3950,6 +4056,20 @@ static void bnx2x_warpcore_set_10G_XFI(struct bnx2x_phy *phy,
	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
			 MDIO_WC_REG_DIGITAL4_MISC3, val | 0x8080);

	/* Enable LPI pass through */
	if ((params->eee_mode & EEE_MODE_ADV_LPI) &&
	    (phy->flags & FLAGS_EEE_10GBT) &&
	    (!(params->eee_mode & EEE_MODE_ENABLE_LPI) ||
	      bnx2x_eee_calc_timer(params)) &&
	    (params->req_duplex[bnx2x_phy_selection(params)] == DUPLEX_FULL)) {
		DP(NETIF_MSG_LINK, "Configure WC for LPI pass through\n");
		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
				 MDIO_WC_REG_EEE_COMBO_CONTROL0,
				 0x7c);
		bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
					 MDIO_WC_REG_DIGITAL4_MISC5, 0xc000);
	}

	/* 10G XFI Full Duplex */
	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
			 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x100);
@@ -6462,6 +6582,15 @@ static int bnx2x_update_link_down(struct link_params *params,
	       (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
	}
	if (CHIP_IS_E3(bp)) {
		REG_WR(bp, MISC_REG_CPMU_LP_FW_ENABLE_P0 + (params->port << 2),
		       0);
		REG_WR(bp, MISC_REG_CPMU_LP_DR_ENABLE, 0);
		REG_WR(bp, MISC_REG_CPMU_LP_MASK_ENT_P0 + (params->port << 2),
		       0);
		vars->eee_status &= ~(SHMEM_EEE_LP_ADV_STATUS_MASK |
				      SHMEM_EEE_ACTIVE_BIT);

		bnx2x_update_mng_eee(params, vars->eee_status);
		bnx2x_xmac_disable(params);
		bnx2x_umac_disable(params);
	}
@@ -6501,6 +6630,16 @@ static int bnx2x_update_link_up(struct link_params *params,
			bnx2x_umac_enable(params, vars, 0);
		bnx2x_set_led(params, vars,
			      LED_MODE_OPER, vars->line_speed);

		if ((vars->eee_status & SHMEM_EEE_ACTIVE_BIT) &&
		    (vars->eee_status & SHMEM_EEE_LPI_REQUESTED_BIT)) {
			DP(NETIF_MSG_LINK, "Enabling LPI assertion\n");
			REG_WR(bp, MISC_REG_CPMU_LP_FW_ENABLE_P0 +
			       (params->port << 2), 1);
			REG_WR(bp, MISC_REG_CPMU_LP_DR_ENABLE, 1);
			REG_WR(bp, MISC_REG_CPMU_LP_MASK_ENT_P0 +
			       (params->port << 2), 0xfc20);
		}
	}
	if ((CHIP_IS_E1x(bp) ||
	     CHIP_IS_E2(bp))) {
@@ -6538,7 +6677,7 @@ static int bnx2x_update_link_up(struct link_params *params,

	/* update shared memory */
	bnx2x_update_mng(params, vars->link_status);

	bnx2x_update_mng_eee(params, vars->eee_status);
	/* Check remote fault */
	for (phy_idx = INT_PHY; phy_idx < MAX_PHYS; phy_idx++) {
		if (params->phy[phy_idx].flags & FLAGS_TX_ERROR_CHECK) {
@@ -6582,6 +6721,8 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars)
		phy_vars[phy_index].phy_link_up = 0;
		phy_vars[phy_index].link_up = 0;
		phy_vars[phy_index].fault_detected = 0;
		/* different consideration, since vars holds inner state */
		phy_vars[phy_index].eee_status = vars->eee_status;
	}

	if (USES_WARPCORE(bp))
@@ -6711,6 +6852,9 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars)
			vars->link_status |= LINK_STATUS_SERDES_LINK;
		else
			vars->link_status &= ~LINK_STATUS_SERDES_LINK;

		vars->eee_status = phy_vars[active_external_phy].eee_status;

		DP(NETIF_MSG_LINK, "Active external phy selected: %x\n",
			   active_external_phy);
	}
@@ -9579,9 +9723,9 @@ static int bnx2x_8481_config_init(struct bnx2x_phy *phy,
static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy,
				   struct link_params *params,
		   u16 fw_cmd,
		   u16 cmd_args[])
		   u16 cmd_args[], int argc)
{
	u32 idx;
	int idx;
	u16 val;
	struct bnx2x *bp = params->bp;
	/* Write CMD_OPEN_OVERRIDE to STATUS reg */
@@ -9601,7 +9745,7 @@ static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy,
	}

	/* Prepare argument(s) and issue command */
	for (idx = 0; idx < PHY84833_CMDHDLR_MAX_ARGS; idx++) {
	for (idx = 0; idx < argc; idx++) {
		bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
				MDIO_84833_CMD_HDLR_DATA1 + idx,
				cmd_args[idx]);
@@ -9622,7 +9766,7 @@ static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy,
		return -EINVAL;
	}
	/* Gather returning data */
	for (idx = 0; idx < PHY84833_CMDHDLR_MAX_ARGS; idx++) {
	for (idx = 0; idx < argc; idx++) {
		bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
				MDIO_84833_CMD_HDLR_DATA1 + idx,
				&cmd_args[idx]);
@@ -9656,7 +9800,7 @@ static int bnx2x_84833_pair_swap_cfg(struct bnx2x_phy *phy,
	data[1] = (u16)pair_swap;

	status = bnx2x_84833_cmd_hdlr(phy, params,
		PHY84833_CMD_SET_PAIR_SWAP, data);
		PHY84833_CMD_SET_PAIR_SWAP, data, PHY84833_CMDHDLR_MAX_ARGS);
	if (status == 0)
		DP(NETIF_MSG_LINK, "Pairswap OK, val=0x%x\n", data[1]);

@@ -9734,6 +9878,95 @@ static int bnx2x_84833_hw_reset_phy(struct bnx2x_phy *phy,
	return 0;
}

static int bnx2x_8483x_eee_timers(struct link_params *params,
				   struct link_vars *vars)
{
	u32 eee_idle = 0, eee_mode;
	struct bnx2x *bp = params->bp;

	eee_idle = bnx2x_eee_calc_timer(params);

	if (eee_idle) {
		REG_WR(bp, MISC_REG_CPMU_LP_IDLE_THR_P0 + (params->port << 2),
		       eee_idle);
	} else if ((params->eee_mode & EEE_MODE_ENABLE_LPI) &&
		   (params->eee_mode & EEE_MODE_OVERRIDE_NVRAM) &&
		   (params->eee_mode & EEE_MODE_OUTPUT_TIME)) {
		DP(NETIF_MSG_LINK, "Error: Tx LPI is enabled with timer 0\n");
		return -EINVAL;
	}

	vars->eee_status &= ~(SHMEM_EEE_TIMER_MASK | SHMEM_EEE_TIME_OUTPUT_BIT);
	if (params->eee_mode & EEE_MODE_OUTPUT_TIME) {
		/* eee_idle in 1u --> eee_status in 16u */
		eee_idle >>= 4;
		vars->eee_status |= (eee_idle & SHMEM_EEE_TIMER_MASK) |
				    SHMEM_EEE_TIME_OUTPUT_BIT;
	} else {
		if (bnx2x_eee_time_to_nvram(eee_idle, &eee_mode))
			return -EINVAL;
		vars->eee_status |= eee_mode;
	}

	return 0;
}

static int bnx2x_8483x_disable_eee(struct bnx2x_phy *phy,
				   struct link_params *params,
				   struct link_vars *vars)
{
	int rc;
	struct bnx2x *bp = params->bp;
	u16 cmd_args = 0;

	DP(NETIF_MSG_LINK, "Don't Advertise 10GBase-T EEE\n");

	/* Make Certain LPI is disabled */
	REG_WR(bp, MISC_REG_CPMU_LP_FW_ENABLE_P0 + (params->port << 2), 0);
	REG_WR(bp, MISC_REG_CPMU_LP_DR_ENABLE, 0);

	/* Prevent Phy from working in EEE and advertising it */
	rc = bnx2x_84833_cmd_hdlr(phy, params,
		PHY84833_CMD_SET_EEE_MODE, &cmd_args, 1);
	if (rc != 0) {
		DP(NETIF_MSG_LINK, "EEE disable failed.\n");
		return rc;
	}

	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_EEE_ADV, 0);
	vars->eee_status &= ~SHMEM_EEE_ADV_STATUS_MASK;

	return 0;
}

static int bnx2x_8483x_enable_eee(struct bnx2x_phy *phy,
				   struct link_params *params,
				   struct link_vars *vars)
{
	int rc;
	struct bnx2x *bp = params->bp;
	u16 cmd_args = 1;

	DP(NETIF_MSG_LINK, "Advertise 10GBase-T EEE\n");

	rc = bnx2x_84833_cmd_hdlr(phy, params,
		PHY84833_CMD_SET_EEE_MODE, &cmd_args, 1);
	if (rc != 0) {
		DP(NETIF_MSG_LINK, "EEE enable failed.\n");
		return rc;
	}

	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_EEE_ADV, 0x8);

	/* Mask events preventing LPI generation */
	REG_WR(bp, MISC_REG_CPMU_LP_MASK_EXT_P0 + (params->port << 2), 0xfc20);

	vars->eee_status &= ~SHMEM_EEE_ADV_STATUS_MASK;
	vars->eee_status |= (SHMEM_EEE_10G_ADV << SHMEM_EEE_ADV_STATUS_SHIFT);

	return 0;
}

#define PHY84833_CONSTANT_LATENCY 1193
static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
				   struct link_params *params,
@@ -9833,7 +10066,8 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
		cmd_args[2] = PHY84833_CONSTANT_LATENCY + 1;
		cmd_args[3] = PHY84833_CONSTANT_LATENCY;
		rc = bnx2x_84833_cmd_hdlr(phy, params,
			PHY84833_CMD_SET_EEE_MODE, cmd_args);
			PHY84833_CMD_SET_EEE_MODE, cmd_args,
			PHY84833_CMDHDLR_MAX_ARGS);
		if (rc != 0)
			DP(NETIF_MSG_LINK, "Cfg AutogrEEEn failed.\n");
	}
@@ -9858,6 +10092,48 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
				 MDIO_CTL_REG_84823_USER_CTRL_REG, val);
	}

	bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
			MDIO_84833_TOP_CFG_FW_REV, &val);

	/* Configure EEE support */
	if ((val >= MDIO_84833_TOP_CFG_FW_EEE) && bnx2x_eee_has_cap(params)) {
		phy->flags |= FLAGS_EEE_10GBT;
		vars->eee_status |= SHMEM_EEE_10G_ADV <<
				    SHMEM_EEE_SUPPORTED_SHIFT;
		/* Propogate params' bits --> vars (for migration exposure) */
		if (params->eee_mode & EEE_MODE_ENABLE_LPI)
			vars->eee_status |= SHMEM_EEE_LPI_REQUESTED_BIT;
		else
			vars->eee_status &= ~SHMEM_EEE_LPI_REQUESTED_BIT;

		if (params->eee_mode & EEE_MODE_ADV_LPI)
			vars->eee_status |= SHMEM_EEE_REQUESTED_BIT;
		else
			vars->eee_status &= ~SHMEM_EEE_REQUESTED_BIT;

		rc = bnx2x_8483x_eee_timers(params, vars);
		if (rc != 0) {
			DP(NETIF_MSG_LINK, "Failed to configure EEE timers\n");
			bnx2x_8483x_disable_eee(phy, params, vars);
			return rc;
		}

		if ((params->req_duplex[actual_phy_selection] == DUPLEX_FULL) &&
		    (params->eee_mode & EEE_MODE_ADV_LPI) &&
		    (bnx2x_eee_calc_timer(params) ||
		     !(params->eee_mode & EEE_MODE_ENABLE_LPI)))
			rc = bnx2x_8483x_enable_eee(phy, params, vars);
		else
			rc = bnx2x_8483x_disable_eee(phy, params, vars);
		if (rc != 0) {
			DP(NETIF_MSG_LINK, "Failed to set EEE advertisment\n");
			return rc;
		}
	} else {
		phy->flags &= ~FLAGS_EEE_10GBT;
		vars->eee_status &= ~SHMEM_EEE_SUPPORTED_MASK;
	}

	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
		/* Bring PHY out of super isolate mode as the final step. */
		bnx2x_cl45_read(bp, phy,
@@ -9989,6 +10265,31 @@ static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
		if (val & (1<<11))
			vars->link_status |=
				LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE;

		/* Determine if EEE was negotiated */
		if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
			u32 eee_shmem = 0;

			bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
					MDIO_AN_REG_EEE_ADV, &val1);
			bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
					MDIO_AN_REG_LP_EEE_ADV, &val2);
			if ((val1 & val2) & 0x8) {
				DP(NETIF_MSG_LINK, "EEE negotiated\n");
				vars->eee_status |= SHMEM_EEE_ACTIVE_BIT;
			}

			if (val2 & 0x12)
				eee_shmem |= SHMEM_EEE_100M_ADV;
			if (val2 & 0x4)
				eee_shmem |= SHMEM_EEE_1G_ADV;
			if (val2 & 0x68)
				eee_shmem |= SHMEM_EEE_10G_ADV;

			vars->eee_status &= ~SHMEM_EEE_LP_ADV_STATUS_MASK;
			vars->eee_status |= (eee_shmem <<
					     SHMEM_EEE_LP_ADV_STATUS_SHIFT);
		}
	}

	return link_up;
@@ -11243,7 +11544,8 @@ static struct bnx2x_phy phy_84833 = {
	.def_md_devad	= 0,
	.flags		= (FLAGS_FAN_FAILURE_DET_REQ |
			   FLAGS_REARM_LATCH_SIGNAL |
			   FLAGS_TX_ERROR_CHECK),
			   FLAGS_TX_ERROR_CHECK |
			   FLAGS_EEE_10GBT),
	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
	.mdio_ctrl	= 0,
@@ -12011,6 +12313,8 @@ int bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
		break;
	}
	bnx2x_update_mng(params, vars->link_status);

	bnx2x_update_mng_eee(params, vars->eee_status);
	return 0;
}

@@ -12023,6 +12327,9 @@ int bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
	/* disable attentions */
	vars->link_status = 0;
	bnx2x_update_mng(params, vars->link_status);
	vars->eee_status &= ~(SHMEM_EEE_LP_ADV_STATUS_MASK |
			      SHMEM_EEE_ACTIVE_BIT);
	bnx2x_update_mng_eee(params, vars->eee_status);
	bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
		       (NIG_MASK_XGXS0_LINK_STATUS |
			NIG_MASK_XGXS0_LINK10G |
+26 −0
Original line number Diff line number Diff line
@@ -149,6 +149,7 @@ struct bnx2x_phy {
#define FLAGS_DUMMY_READ		(1<<9)
#define FLAGS_MDC_MDIO_WA_B0		(1<<10)
#define FLAGS_TX_ERROR_CHECK		(1<<12)
#define FLAGS_EEE_10GBT			(1<<13)

	/* preemphasis values for the rx side */
	u16 rx_preemphasis[4];
@@ -265,6 +266,30 @@ struct link_params {
	u8 num_phys;

	u8 rsrv;

	/* Used to configure the EEE Tx LPI timer, has several modes of
	 * operation, according to bits 29:28 -
	 * 2'b00: Timer will be configured by nvram, output will be the value
	 *        from nvram.
	 * 2'b01: Timer will be configured by nvram, output will be in
	 *        microseconds.
	 * 2'b10: bits 1:0 contain an nvram value which will be used instead
	 *        of the one located in the nvram. Output will be that value.
	 * 2'b11: bits 19:0 contain the idle timer in microseconds; output
	 *        will be in microseconds.
	 * Bits 31:30 should be 2'b11 in order for EEE to be enabled.
	 */
	u32 eee_mode;
#define EEE_MODE_NVRAM_BALANCED_TIME		(0xa00)
#define EEE_MODE_NVRAM_AGGRESSIVE_TIME		(0x100)
#define EEE_MODE_NVRAM_LATENCY_TIME		(0x6000)
#define EEE_MODE_NVRAM_MASK		(0x3)
#define EEE_MODE_TIMER_MASK		(0xfffff)
#define EEE_MODE_OUTPUT_TIME		(1<<28)
#define EEE_MODE_OVERRIDE_NVRAM		(1<<29)
#define EEE_MODE_ENABLE_LPI		(1<<30)
#define EEE_MODE_ADV_LPI			(1<<31)

	u16 hw_led_mode; /* part of the hw_config read from the shmem */
	u32 multi_phy_config;

@@ -301,6 +326,7 @@ struct link_vars {

	/* The same definitions as the shmem parameter */
	u32 link_status;
	u32 eee_status;
	u8 fault_detected;
	u8 rsrv1;
	u16 periodic_flags;
+22 −1
Original line number Diff line number Diff line
@@ -3176,6 +3176,12 @@ static void bnx2x_set_mf_bw(struct bnx2x *bp)
	bnx2x_fw_command(bp, DRV_MSG_CODE_SET_MF_BW_ACK, 0);
}

static void bnx2x_handle_eee_event(struct bnx2x *bp)
{
	DP(BNX2X_MSG_MCP, "EEE - LLDP event\n");
	bnx2x_fw_command(bp, DRV_MSG_CODE_EEE_RESULTS_ACK, 0);
}

static void bnx2x_handle_drv_info_req(struct bnx2x *bp)
{
	enum drv_info_opcode op_code;
@@ -3742,6 +3748,8 @@ static void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn)
			if (val & DRV_STATUS_AFEX_EVENT_MASK)
				bnx2x_handle_afex_cmd(bp,
					val & DRV_STATUS_AFEX_EVENT_MASK);
			if (val & DRV_STATUS_EEE_NEGOTIATION_RESULTS)
				bnx2x_handle_eee_event(bp);
			if (bp->link_vars.periodic_flags &
			    PERIODIC_FLAGS_LINK_EVENT) {
				/*  sync with link */
@@ -10082,7 +10090,7 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
{
	int port = BP_PORT(bp);
	u32 config;
	u32 ext_phy_type, ext_phy_config;
	u32 ext_phy_type, ext_phy_config, eee_mode;

	bp->link_params.bp = bp;
	bp->link_params.port = port;
@@ -10149,6 +10157,19 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
		bp->port.need_hw_lock = bnx2x_hw_lock_required(bp,
							bp->common.shmem_base,
							bp->common.shmem2_base);

	/* Configure link feature according to nvram value */
	eee_mode = (((SHMEM_RD(bp, dev_info.
		      port_feature_config[port].eee_power_mode)) &
		     PORT_FEAT_CFG_EEE_POWER_MODE_MASK) >>
		    PORT_FEAT_CFG_EEE_POWER_MODE_SHIFT);
	if (eee_mode != PORT_FEAT_CFG_EEE_POWER_MODE_DISABLED) {
		bp->link_params.eee_mode = EEE_MODE_ADV_LPI |
					   EEE_MODE_ENABLE_LPI |
					   EEE_MODE_OUTPUT_TIME;
	} else {
		bp->link_params.eee_mode = 0;
	}
}

void bnx2x_get_iscsi_info(struct bnx2x *bp)
+123 −0

File changed.

Preview size limit exceeded, changes collapsed.

Loading