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

Commit eb385146 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'qed-Align-PTT-and-add-various-link-modes'



Rahul Verma says:

====================
Align PTT and add various link modes.

This series aligns the ptt propagation as local ptt or global ptt.
Adds new transceiver modes, speed capabilities and board config,
which is utilized to display the enhanced link modes, media types
and speed. Enhances the link with detailed information.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 0ba4ad32 1c90eabc
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -915,7 +915,7 @@ u16 qed_get_cm_pq_idx_llt_mtc(struct qed_hwfn *p_hwfn, u8 tc);
/* Prototypes */
int qed_fill_dev_info(struct qed_dev *cdev,
		      struct qed_dev_info *dev_info);
void qed_link_update(struct qed_hwfn *hwfn);
void qed_link_update(struct qed_hwfn *hwfn, struct qed_ptt *ptt);
u32 qed_unzip_data(struct qed_hwfn *p_hwfn,
		   u32 input_len, u8 *input_buf,
		   u32 max_size, u8 *unzip_buf);
+53 −1
Original line number Diff line number Diff line
@@ -12207,11 +12207,56 @@ struct public_port {
	u32 transceiver_data;
#define ETH_TRANSCEIVER_STATE_MASK	0x000000FF
#define ETH_TRANSCEIVER_STATE_SHIFT	0x00000000
#define ETH_TRANSCEIVER_STATE_OFFSET	0x00000000
#define ETH_TRANSCEIVER_STATE_UNPLUGGED	0x00000000
#define ETH_TRANSCEIVER_STATE_PRESENT	0x00000001
#define ETH_TRANSCEIVER_STATE_VALID	0x00000003
#define ETH_TRANSCEIVER_STATE_UPDATING	0x00000008

#define ETH_TRANSCEIVER_TYPE_MASK       0x0000FF00
#define ETH_TRANSCEIVER_TYPE_OFFSET     0x8
#define ETH_TRANSCEIVER_TYPE_NONE                       0x00
#define ETH_TRANSCEIVER_TYPE_UNKNOWN                    0xFF
#define ETH_TRANSCEIVER_TYPE_1G_PCC                     0x01
#define ETH_TRANSCEIVER_TYPE_1G_ACC                     0x02
#define ETH_TRANSCEIVER_TYPE_1G_LX                      0x03
#define ETH_TRANSCEIVER_TYPE_1G_SX                      0x04
#define ETH_TRANSCEIVER_TYPE_10G_SR                     0x05
#define ETH_TRANSCEIVER_TYPE_10G_LR                     0x06
#define ETH_TRANSCEIVER_TYPE_10G_LRM                    0x07
#define ETH_TRANSCEIVER_TYPE_10G_ER                     0x08
#define ETH_TRANSCEIVER_TYPE_10G_PCC                    0x09
#define ETH_TRANSCEIVER_TYPE_10G_ACC                    0x0a
#define ETH_TRANSCEIVER_TYPE_XLPPI                      0x0b
#define ETH_TRANSCEIVER_TYPE_40G_LR4                    0x0c
#define ETH_TRANSCEIVER_TYPE_40G_SR4                    0x0d
#define ETH_TRANSCEIVER_TYPE_40G_CR4                    0x0e
#define ETH_TRANSCEIVER_TYPE_100G_AOC                   0x0f
#define ETH_TRANSCEIVER_TYPE_100G_SR4                   0x10
#define ETH_TRANSCEIVER_TYPE_100G_LR4                   0x11
#define ETH_TRANSCEIVER_TYPE_100G_ER4                   0x12
#define ETH_TRANSCEIVER_TYPE_100G_ACC                   0x13
#define ETH_TRANSCEIVER_TYPE_100G_CR4                   0x14
#define ETH_TRANSCEIVER_TYPE_4x10G_SR                   0x15
#define ETH_TRANSCEIVER_TYPE_25G_CA_N                   0x16
#define ETH_TRANSCEIVER_TYPE_25G_ACC_S                  0x17
#define ETH_TRANSCEIVER_TYPE_25G_CA_S                   0x18
#define ETH_TRANSCEIVER_TYPE_25G_ACC_M                  0x19
#define ETH_TRANSCEIVER_TYPE_25G_CA_L                   0x1a
#define ETH_TRANSCEIVER_TYPE_25G_ACC_L                  0x1b
#define ETH_TRANSCEIVER_TYPE_25G_SR                     0x1c
#define ETH_TRANSCEIVER_TYPE_25G_LR                     0x1d
#define ETH_TRANSCEIVER_TYPE_25G_AOC                    0x1e
#define ETH_TRANSCEIVER_TYPE_4x10G                      0x1f
#define ETH_TRANSCEIVER_TYPE_4x25G_CR                   0x20
#define ETH_TRANSCEIVER_TYPE_1000BASET                  0x21
#define ETH_TRANSCEIVER_TYPE_10G_BASET                  0x22
#define ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_SR      0x30
#define ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_CR      0x31
#define ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_LR      0x32
#define ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_SR     0x33
#define ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_CR     0x34
#define ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_LR     0x35
#define ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_AOC    0x36
	u32 wol_info;
	u32 wol_pkt_len;
	u32 wol_pkt_details;
@@ -13199,6 +13244,13 @@ struct nvm_cfg1_port {
	u32 transceiver_00;
	u32 device_ids;
	u32 board_cfg;
#define NVM_CFG1_PORT_PORT_TYPE_MASK                            0x000000FF
#define NVM_CFG1_PORT_PORT_TYPE_OFFSET                          0
#define NVM_CFG1_PORT_PORT_TYPE_UNDEFINED                       0x0
#define NVM_CFG1_PORT_PORT_TYPE_MODULE                          0x1
#define NVM_CFG1_PORT_PORT_TYPE_BACKPLANE                       0x2
#define NVM_CFG1_PORT_PORT_TYPE_EXT_PHY                         0x3
#define NVM_CFG1_PORT_PORT_TYPE_MODULE_SLAVE                    0x4
	u32 mnm_10g_cap;
	u32 mnm_10g_ctrl;
	u32 mnm_10g_misc;
+198 −61
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@
#include "qed_iscsi.h"

#include "qed_mcp.h"
#include "qed_reg_addr.h"
#include "qed_hw.h"
#include "qed_selftest.h"
#include "qed_debug.h"
@@ -1304,6 +1305,7 @@ static int qed_set_link(struct qed_dev *cdev, struct qed_link_params *params)
	struct qed_hwfn *hwfn;
	struct qed_mcp_link_params *link_params;
	struct qed_ptt *ptt;
	u32 sup_caps;
	int rc;

	if (!cdev)
@@ -1330,26 +1332,50 @@ static int qed_set_link(struct qed_dev *cdev, struct qed_link_params *params)
		link_params->speed.autoneg = params->autoneg;
	if (params->override_flags & QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS) {
		link_params->speed.advertised_speeds = 0;
		if ((params->adv_speeds & QED_LM_1000baseT_Half_BIT) ||
		    (params->adv_speeds & QED_LM_1000baseT_Full_BIT))
		sup_caps = QED_LM_1000baseT_Full_BIT |
			   QED_LM_1000baseKX_Full_BIT |
			   QED_LM_1000baseX_Full_BIT;
		if (params->adv_speeds & sup_caps)
			link_params->speed.advertised_speeds |=
			    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
		if (params->adv_speeds & QED_LM_10000baseKR_Full_BIT)
		sup_caps = QED_LM_10000baseT_Full_BIT |
			   QED_LM_10000baseKR_Full_BIT |
			   QED_LM_10000baseKX4_Full_BIT |
			   QED_LM_10000baseR_FEC_BIT |
			   QED_LM_10000baseCR_Full_BIT |
			   QED_LM_10000baseSR_Full_BIT |
			   QED_LM_10000baseLR_Full_BIT |
			   QED_LM_10000baseLRM_Full_BIT;
		if (params->adv_speeds & sup_caps)
			link_params->speed.advertised_speeds |=
			    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G;
		if (params->adv_speeds & QED_LM_20000baseKR2_Full_BIT)
			link_params->speed.advertised_speeds |=
				NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G;
		if (params->adv_speeds & QED_LM_25000baseKR_Full_BIT)
		sup_caps = QED_LM_25000baseKR_Full_BIT |
			   QED_LM_25000baseCR_Full_BIT |
			   QED_LM_25000baseSR_Full_BIT;
		if (params->adv_speeds & sup_caps)
			link_params->speed.advertised_speeds |=
			    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G;
		if (params->adv_speeds & QED_LM_40000baseLR4_Full_BIT)
		sup_caps = QED_LM_40000baseLR4_Full_BIT |
			   QED_LM_40000baseKR4_Full_BIT |
			   QED_LM_40000baseCR4_Full_BIT |
			   QED_LM_40000baseSR4_Full_BIT;
		if (params->adv_speeds & sup_caps)
			link_params->speed.advertised_speeds |=
				NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G;
		if (params->adv_speeds & QED_LM_50000baseKR2_Full_BIT)
		sup_caps = QED_LM_50000baseKR2_Full_BIT |
			   QED_LM_50000baseCR2_Full_BIT |
			   QED_LM_50000baseSR2_Full_BIT;
		if (params->adv_speeds & sup_caps)
			link_params->speed.advertised_speeds |=
			    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G;
		if (params->adv_speeds & QED_LM_100000baseKR4_Full_BIT)
		sup_caps = QED_LM_100000baseKR4_Full_BIT |
			   QED_LM_100000baseSR4_Full_BIT |
			   QED_LM_100000baseCR4_Full_BIT |
			   QED_LM_100000baseLR4_ER4_Full_BIT;
		if (params->adv_speeds & sup_caps)
			link_params->speed.advertised_speeds |=
			    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G;
	}
@@ -1462,12 +1488,149 @@ static int qed_get_link_data(struct qed_hwfn *hwfn,
	return 0;
}

static void qed_fill_link_capability(struct qed_hwfn *hwfn,
				     struct qed_ptt *ptt, u32 capability,
				     u32 *if_capability)
{
	u32 media_type, tcvr_state, tcvr_type;
	u32 speed_mask, board_cfg;

	if (qed_mcp_get_media_type(hwfn, ptt, &media_type))
		media_type = MEDIA_UNSPECIFIED;

	if (qed_mcp_get_transceiver_data(hwfn, ptt, &tcvr_state, &tcvr_type))
		tcvr_type = ETH_TRANSCEIVER_STATE_UNPLUGGED;

	if (qed_mcp_trans_speed_mask(hwfn, ptt, &speed_mask))
		speed_mask = 0xFFFFFFFF;

	if (qed_mcp_get_board_config(hwfn, ptt, &board_cfg))
		board_cfg = NVM_CFG1_PORT_PORT_TYPE_UNDEFINED;

	DP_VERBOSE(hwfn->cdev, NETIF_MSG_DRV,
		   "Media_type = 0x%x tcvr_state = 0x%x tcvr_type = 0x%x speed_mask = 0x%x board_cfg = 0x%x\n",
		   media_type, tcvr_state, tcvr_type, speed_mask, board_cfg);

	switch (media_type) {
	case MEDIA_DA_TWINAX:
		if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G)
			*if_capability |= QED_LM_20000baseKR2_Full_BIT;
		/* For DAC media multiple speed capabilities are supported*/
		capability = capability & speed_mask;
		if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G)
			*if_capability |= QED_LM_1000baseKX_Full_BIT;
		if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G)
			*if_capability |= QED_LM_10000baseCR_Full_BIT;
		if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G)
			*if_capability |= QED_LM_40000baseCR4_Full_BIT;
		if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G)
			*if_capability |= QED_LM_25000baseCR_Full_BIT;
		if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G)
			*if_capability |= QED_LM_50000baseCR2_Full_BIT;
		if (capability &
			NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G)
			*if_capability |= QED_LM_100000baseCR4_Full_BIT;
		break;
	case MEDIA_BASE_T:
		if (board_cfg & NVM_CFG1_PORT_PORT_TYPE_EXT_PHY) {
			if (capability &
			    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G) {
				*if_capability |= QED_LM_1000baseT_Full_BIT;
			}
			if (capability &
			    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G) {
				*if_capability |= QED_LM_10000baseT_Full_BIT;
			}
		}
		if (board_cfg & NVM_CFG1_PORT_PORT_TYPE_MODULE) {
			if (tcvr_type == ETH_TRANSCEIVER_TYPE_1000BASET)
				*if_capability |= QED_LM_1000baseT_Full_BIT;
			if (tcvr_type == ETH_TRANSCEIVER_TYPE_10G_BASET)
				*if_capability |= QED_LM_10000baseT_Full_BIT;
		}
		break;
	case MEDIA_SFP_1G_FIBER:
	case MEDIA_SFPP_10G_FIBER:
	case MEDIA_XFP_FIBER:
	case MEDIA_MODULE_FIBER:
		if (capability &
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G) {
			if ((tcvr_type == ETH_TRANSCEIVER_TYPE_1G_LX) ||
			    (tcvr_type == ETH_TRANSCEIVER_TYPE_1G_SX))
				*if_capability |= QED_LM_1000baseKX_Full_BIT;
		}
		if (capability &
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G) {
			if (tcvr_type == ETH_TRANSCEIVER_TYPE_10G_SR)
				*if_capability |= QED_LM_10000baseSR_Full_BIT;
			if (tcvr_type == ETH_TRANSCEIVER_TYPE_10G_LR)
				*if_capability |= QED_LM_10000baseLR_Full_BIT;
			if (tcvr_type == ETH_TRANSCEIVER_TYPE_10G_LRM)
				*if_capability |= QED_LM_10000baseLRM_Full_BIT;
			if (tcvr_type == ETH_TRANSCEIVER_TYPE_10G_ER)
				*if_capability |= QED_LM_10000baseR_FEC_BIT;
		}
		if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G)
			*if_capability |= QED_LM_20000baseKR2_Full_BIT;
		if (capability &
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G) {
			if (tcvr_type == ETH_TRANSCEIVER_TYPE_25G_SR)
				*if_capability |= QED_LM_25000baseSR_Full_BIT;
		}
		if (capability &
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G) {
			if (tcvr_type == ETH_TRANSCEIVER_TYPE_40G_LR4)
				*if_capability |= QED_LM_40000baseLR4_Full_BIT;
			if (tcvr_type == ETH_TRANSCEIVER_TYPE_40G_SR4)
				*if_capability |= QED_LM_40000baseSR4_Full_BIT;
		}
		if (capability &
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G)
			*if_capability |= QED_LM_50000baseKR2_Full_BIT;
		if (capability &
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G) {
			if (tcvr_type == ETH_TRANSCEIVER_TYPE_100G_SR4)
				*if_capability |= QED_LM_100000baseSR4_Full_BIT;
		}

		break;
	case MEDIA_KR:
		if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G)
			*if_capability |= QED_LM_20000baseKR2_Full_BIT;
		if (capability &
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G)
			*if_capability |= QED_LM_1000baseKX_Full_BIT;
		if (capability &
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G)
			*if_capability |= QED_LM_10000baseKR_Full_BIT;
		if (capability &
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G)
			*if_capability |= QED_LM_25000baseKR_Full_BIT;
		if (capability &
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G)
			*if_capability |= QED_LM_40000baseKR4_Full_BIT;
		if (capability &
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G)
			*if_capability |= QED_LM_50000baseKR2_Full_BIT;
		if (capability &
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G)
			*if_capability |= QED_LM_100000baseKR4_Full_BIT;
		break;
	case MEDIA_UNSPECIFIED:
	case MEDIA_NOT_PRESENT:
		DP_VERBOSE(hwfn->cdev, QED_MSG_DEBUG,
			   "Unknown media and transceiver type;\n");
		break;
	}
}

static void qed_fill_link(struct qed_hwfn *hwfn,
			  struct qed_ptt *ptt,
			  struct qed_link_output *if_link)
{
	struct qed_mcp_link_capabilities link_caps;
	struct qed_mcp_link_params params;
	struct qed_mcp_link_state link;
	struct qed_mcp_link_capabilities link_caps;
	u32 media_type;

	memset(if_link, 0, sizeof(*if_link));
@@ -1498,58 +1661,20 @@ static void qed_fill_link(struct qed_hwfn *hwfn,
		if_link->advertised_caps |= QED_LM_Autoneg_BIT;
	else
		if_link->advertised_caps &= ~QED_LM_Autoneg_BIT;
	if (params.speed.advertised_speeds &
	    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G)
		if_link->advertised_caps |= QED_LM_1000baseT_Half_BIT |
		    QED_LM_1000baseT_Full_BIT;
	if (params.speed.advertised_speeds &
	    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G)
		if_link->advertised_caps |= QED_LM_10000baseKR_Full_BIT;
	if (params.speed.advertised_speeds &
	    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G)
		if_link->advertised_caps |= QED_LM_20000baseKR2_Full_BIT;
	if (params.speed.advertised_speeds &
	    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G)
		if_link->advertised_caps |= QED_LM_25000baseKR_Full_BIT;
	if (params.speed.advertised_speeds &
	    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G)
		if_link->advertised_caps |= QED_LM_40000baseLR4_Full_BIT;
	if (params.speed.advertised_speeds &
	    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G)
		if_link->advertised_caps |= QED_LM_50000baseKR2_Full_BIT;
	if (params.speed.advertised_speeds &
	    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G)
		if_link->advertised_caps |= QED_LM_100000baseKR4_Full_BIT;

	if (link_caps.speed_capabilities &
	    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G)
		if_link->supported_caps |= QED_LM_1000baseT_Half_BIT |
		    QED_LM_1000baseT_Full_BIT;
	if (link_caps.speed_capabilities &
	    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G)
		if_link->supported_caps |= QED_LM_10000baseKR_Full_BIT;
	if (link_caps.speed_capabilities &
	    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G)
		if_link->supported_caps |= QED_LM_20000baseKR2_Full_BIT;
	if (link_caps.speed_capabilities &
	    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G)
		if_link->supported_caps |= QED_LM_25000baseKR_Full_BIT;
	if (link_caps.speed_capabilities &
	    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G)
		if_link->supported_caps |= QED_LM_40000baseLR4_Full_BIT;
	if (link_caps.speed_capabilities &
	    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G)
		if_link->supported_caps |= QED_LM_50000baseKR2_Full_BIT;
	if (link_caps.speed_capabilities &
	    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G)
		if_link->supported_caps |= QED_LM_100000baseKR4_Full_BIT;
	/* Fill link advertised capability*/
	qed_fill_link_capability(hwfn, ptt, params.speed.advertised_speeds,
				 &if_link->advertised_caps);
	/* Fill link supported capability*/
	qed_fill_link_capability(hwfn, ptt, link_caps.speed_capabilities,
				 &if_link->supported_caps);

	if (link.link_up)
		if_link->speed = link.speed;

	/* TODO - fill duplex properly */
	if_link->duplex = DUPLEX_FULL;
	qed_mcp_get_media_type(hwfn->cdev, &media_type);
	qed_mcp_get_media_type(hwfn, ptt, &media_type);
	if_link->port = qed_get_port_type(media_type);

	if_link->autoneg = params.speed.autoneg;
@@ -1562,9 +1687,8 @@ static void qed_fill_link(struct qed_hwfn *hwfn,
		if_link->pause_config |= QED_LINK_PAUSE_TX_ENABLE;

	/* Link partner capabilities */
	if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_1G_HD)
		if_link->lp_caps |= QED_LM_1000baseT_Half_BIT;
	if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_1G_FD)
	if (link.partner_adv_speed &
	    QED_LINK_PARTNER_SPEED_1G_FD)
		if_link->lp_caps |= QED_LM_1000baseT_Full_BIT;
	if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_10G)
		if_link->lp_caps |= QED_LM_10000baseKR_Full_BIT;
@@ -1607,21 +1731,34 @@ static void qed_fill_link(struct qed_hwfn *hwfn,
static void qed_get_current_link(struct qed_dev *cdev,
				 struct qed_link_output *if_link)
{
	struct qed_hwfn *hwfn;
	struct qed_ptt *ptt;
	int i;

	qed_fill_link(&cdev->hwfns[0], if_link);
	hwfn = &cdev->hwfns[0];
	if (IS_PF(cdev)) {
		ptt = qed_ptt_acquire(hwfn);
		if (ptt) {
			qed_fill_link(hwfn, ptt, if_link);
			qed_ptt_release(hwfn, ptt);
		} else {
			DP_NOTICE(hwfn, "Failed to fill link; No PTT\n");
		}
	} else {
		qed_fill_link(hwfn, NULL, if_link);
	}

	for_each_hwfn(cdev, i)
		qed_inform_vf_link_state(&cdev->hwfns[i]);
}

void qed_link_update(struct qed_hwfn *hwfn)
void qed_link_update(struct qed_hwfn *hwfn, struct qed_ptt *ptt)
{
	void *cookie = hwfn->cdev->ops_cookie;
	struct qed_common_cb_ops *op = hwfn->cdev->protocol_ops.common;
	struct qed_link_output if_link;

	qed_fill_link(hwfn, &if_link);
	qed_fill_link(hwfn, ptt, &if_link);
	qed_inform_vf_link_state(hwfn);

	if (IS_LEAD_HWFN(hwfn) && cookie)
+190 −11
Original line number Diff line number Diff line
@@ -1447,7 +1447,7 @@ static void qed_mcp_handle_link_change(struct qed_hwfn *p_hwfn,
	if (p_hwfn->mcp_info->capabilities & FW_MB_PARAM_FEATURE_SUPPORT_EEE)
		qed_mcp_read_eee_config(p_hwfn, p_ptt, p_link);

	qed_link_update(p_hwfn);
	qed_link_update(p_hwfn, p_ptt);
out:
	spin_unlock_bh(&p_hwfn->mcp_info->link_lock);
}
@@ -1867,12 +1867,12 @@ int qed_mcp_get_mbi_ver(struct qed_hwfn *p_hwfn,
	return 0;
}

int qed_mcp_get_media_type(struct qed_dev *cdev, u32 *p_media_type)
int qed_mcp_get_media_type(struct qed_hwfn *p_hwfn,
			   struct qed_ptt *p_ptt, u32 *p_media_type)
{
	struct qed_hwfn *p_hwfn = &cdev->hwfns[0];
	struct qed_ptt  *p_ptt;
	*p_media_type = MEDIA_UNSPECIFIED;

	if (IS_VF(cdev))
	if (IS_VF(p_hwfn->cdev))
		return -EINVAL;

	if (!qed_mcp_is_init(p_hwfn)) {
@@ -1880,16 +1880,195 @@ int qed_mcp_get_media_type(struct qed_dev *cdev, u32 *p_media_type)
		return -EBUSY;
	}

	if (!p_ptt) {
		*p_media_type = MEDIA_UNSPECIFIED;
		return -EINVAL;
	}

	p_ptt = qed_ptt_acquire(p_hwfn);
	if (!p_ptt)
	*p_media_type = qed_rd(p_hwfn, p_ptt,
			       p_hwfn->mcp_info->port_addr +
			       offsetof(struct public_port,
					media_type));

	return 0;
}

int qed_mcp_get_transceiver_data(struct qed_hwfn *p_hwfn,
				 struct qed_ptt *p_ptt,
				 u32 *p_transceiver_state,
				 u32 *p_transceiver_type)
{
	u32 transceiver_info;

	if (IS_VF(p_hwfn->cdev))
		return -EINVAL;

	if (!qed_mcp_is_init(p_hwfn)) {
		DP_NOTICE(p_hwfn, "MFW is not initialized!\n");
		return -EBUSY;
	}

	*p_media_type = qed_rd(p_hwfn, p_ptt, p_hwfn->mcp_info->port_addr +
			       offsetof(struct public_port, media_type));
	*p_transceiver_type = ETH_TRANSCEIVER_TYPE_NONE;
	*p_transceiver_state = ETH_TRANSCEIVER_STATE_UPDATING;

	qed_ptt_release(p_hwfn, p_ptt);
	transceiver_info = qed_rd(p_hwfn, p_ptt,
				  p_hwfn->mcp_info->port_addr +
				  offsetof(struct public_port,
					   transceiver_data));

	*p_transceiver_state = (transceiver_info &
				ETH_TRANSCEIVER_STATE_MASK) >>
				ETH_TRANSCEIVER_STATE_OFFSET;

	if (*p_transceiver_state == ETH_TRANSCEIVER_STATE_PRESENT)
		*p_transceiver_type = (transceiver_info &
				       ETH_TRANSCEIVER_TYPE_MASK) >>
				       ETH_TRANSCEIVER_TYPE_OFFSET;
	else
		*p_transceiver_type = ETH_TRANSCEIVER_TYPE_UNKNOWN;

	return 0;
}
static bool qed_is_transceiver_ready(u32 transceiver_state,
				     u32 transceiver_type)
{
	if ((transceiver_state & ETH_TRANSCEIVER_STATE_PRESENT) &&
	    ((transceiver_state & ETH_TRANSCEIVER_STATE_UPDATING) == 0x0) &&
	    (transceiver_type != ETH_TRANSCEIVER_TYPE_NONE))
		return true;

	return false;
}

int qed_mcp_trans_speed_mask(struct qed_hwfn *p_hwfn,
			     struct qed_ptt *p_ptt, u32 *p_speed_mask)
{
	u32 transceiver_type, transceiver_state;

	qed_mcp_get_transceiver_data(p_hwfn, p_ptt, &transceiver_state,
				     &transceiver_type);

	if (qed_is_transceiver_ready(transceiver_state, transceiver_type) ==
				     false)
		return -EINVAL;

	switch (transceiver_type) {
	case ETH_TRANSCEIVER_TYPE_1G_LX:
	case ETH_TRANSCEIVER_TYPE_1G_SX:
	case ETH_TRANSCEIVER_TYPE_1G_PCC:
	case ETH_TRANSCEIVER_TYPE_1G_ACC:
	case ETH_TRANSCEIVER_TYPE_1000BASET:
		*p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
		break;
	case ETH_TRANSCEIVER_TYPE_10G_SR:
	case ETH_TRANSCEIVER_TYPE_10G_LR:
	case ETH_TRANSCEIVER_TYPE_10G_LRM:
	case ETH_TRANSCEIVER_TYPE_10G_ER:
	case ETH_TRANSCEIVER_TYPE_10G_PCC:
	case ETH_TRANSCEIVER_TYPE_10G_ACC:
	case ETH_TRANSCEIVER_TYPE_4x10G:
		*p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G;
		break;
	case ETH_TRANSCEIVER_TYPE_40G_LR4:
	case ETH_TRANSCEIVER_TYPE_40G_SR4:
	case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_SR:
	case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_LR:
		*p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G |
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G;
		break;
	case ETH_TRANSCEIVER_TYPE_100G_AOC:
	case ETH_TRANSCEIVER_TYPE_100G_SR4:
	case ETH_TRANSCEIVER_TYPE_100G_LR4:
	case ETH_TRANSCEIVER_TYPE_100G_ER4:
	case ETH_TRANSCEIVER_TYPE_100G_ACC:
		*p_speed_mask =
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G |
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G;
		break;
	case ETH_TRANSCEIVER_TYPE_25G_SR:
	case ETH_TRANSCEIVER_TYPE_25G_LR:
	case ETH_TRANSCEIVER_TYPE_25G_AOC:
	case ETH_TRANSCEIVER_TYPE_25G_ACC_S:
	case ETH_TRANSCEIVER_TYPE_25G_ACC_M:
	case ETH_TRANSCEIVER_TYPE_25G_ACC_L:
		*p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G;
		break;
	case ETH_TRANSCEIVER_TYPE_25G_CA_N:
	case ETH_TRANSCEIVER_TYPE_25G_CA_S:
	case ETH_TRANSCEIVER_TYPE_25G_CA_L:
	case ETH_TRANSCEIVER_TYPE_4x25G_CR:
		*p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G |
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G |
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
		break;
	case ETH_TRANSCEIVER_TYPE_40G_CR4:
	case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_CR:
		*p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G |
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G |
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
		break;
	case ETH_TRANSCEIVER_TYPE_100G_CR4:
	case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_CR:
		*p_speed_mask =
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G |
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G |
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G |
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G |
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G |
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G |
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
		break;
	case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_SR:
	case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_LR:
	case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_AOC:
		*p_speed_mask =
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G |
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G |
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G |
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G;
		break;
	case ETH_TRANSCEIVER_TYPE_XLPPI:
		*p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G;
		break;
	case ETH_TRANSCEIVER_TYPE_10G_BASET:
		*p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G |
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
		break;
	default:
		DP_INFO(p_hwfn, "Unknown transcevier type 0x%x\n",
			transceiver_type);
		*p_speed_mask = 0xff;
		break;
	}

	return 0;
}

int qed_mcp_get_board_config(struct qed_hwfn *p_hwfn,
			     struct qed_ptt *p_ptt, u32 *p_board_config)
{
	u32 nvm_cfg_addr, nvm_cfg1_offset, port_cfg_addr;

	if (IS_VF(p_hwfn->cdev))
		return -EINVAL;

	if (!qed_mcp_is_init(p_hwfn)) {
		DP_NOTICE(p_hwfn, "MFW is not initialized!\n");
		return -EBUSY;
	}
	if (!p_ptt) {
		*p_board_config = NVM_CFG1_PORT_PORT_TYPE_UNDEFINED;
		return -EINVAL;
	}

	nvm_cfg_addr = qed_rd(p_hwfn, p_ptt, MISC_REG_GEN_PURP_CR0);
	nvm_cfg1_offset = qed_rd(p_hwfn, p_ptt, nvm_cfg_addr + 4);
	port_cfg_addr = MCP_REG_SCRATCH + nvm_cfg1_offset +
			offsetof(struct nvm_cfg1, port[MFW_PORT(p_hwfn)]);
	*p_board_config = qed_rd(p_hwfn, p_ptt,
				 port_cfg_addr +
				 offsetof(struct nvm_cfg1_port,
					  board_cfg));

	return 0;
}
+49 −2
Original line number Diff line number Diff line
@@ -322,14 +322,61 @@ int qed_mcp_get_mbi_ver(struct qed_hwfn *p_hwfn,
 * @brief Get media type value of the port.
 *
 * @param cdev      - qed dev pointer
 * @param p_ptt
 * @param mfw_ver    - media type value
 *
 * @return int -
 *      0 - Operation was successul.
 *      -EBUSY - Operation failed
 */
int qed_mcp_get_media_type(struct qed_dev      *cdev,
			   u32                  *media_type);
int qed_mcp_get_media_type(struct qed_hwfn *p_hwfn,
			   struct qed_ptt *p_ptt, u32 *media_type);

/**
 * @brief Get transceiver data of the port.
 *
 * @param cdev      - qed dev pointer
 * @param p_ptt
 * @param p_transceiver_state - transceiver state.
 * @param p_transceiver_type - media type value
 *
 * @return int -
 *      0 - Operation was successful.
 *      -EBUSY - Operation failed
 */
int qed_mcp_get_transceiver_data(struct qed_hwfn *p_hwfn,
				 struct qed_ptt *p_ptt,
				 u32 *p_transceiver_state,
				 u32 *p_tranceiver_type);

/**
 * @brief Get transceiver supported speed mask.
 *
 * @param cdev      - qed dev pointer
 * @param p_ptt
 * @param p_speed_mask - Bit mask of all supported speeds.
 *
 * @return int -
 *      0 - Operation was successful.
 *      -EBUSY - Operation failed
 */

int qed_mcp_trans_speed_mask(struct qed_hwfn *p_hwfn,
			     struct qed_ptt *p_ptt, u32 *p_speed_mask);

/**
 * @brief Get board configuration.
 *
 * @param cdev      - qed dev pointer
 * @param p_ptt
 * @param p_board_config - Board config.
 *
 * @return int -
 *      0 - Operation was successful.
 *      -EBUSY - Operation failed
 */
int qed_mcp_get_board_config(struct qed_hwfn *p_hwfn,
			     struct qed_ptt *p_ptt, u32 *p_board_config);

/**
 * @brief General function for sending commands to the MCP
Loading