qed: Add support for Unified Fabric Port.
This patch adds driver changes for supporting the Unified Fabric Port (UFP). This is a new paritioning mode wherein MFW provides the set of parameters to be used by the device such as traffic class, outer-vlan tag value, priority type etc. Drivers receives this info via notifications from mfw and configures the hardware accordingly. Signed-off-by: Sudarsana Reddy Kalluru <Sudarsana.Kalluru@cavium.com> Signed-off-by: Ariel Elior <ariel.elior@cavium.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									b51bdfb9cb
								
							
						
					
					
						commit
						cac6f69154
					
				| @ -474,6 +474,24 @@ enum qed_mf_mode_bit { | ||||
| 	QED_MF_DSCP_TO_TC_MAP, | ||||
| }; | ||||
| 
 | ||||
| enum qed_ufp_mode { | ||||
| 	QED_UFP_MODE_ETS, | ||||
| 	QED_UFP_MODE_VNIC_BW, | ||||
| 	QED_UFP_MODE_UNKNOWN | ||||
| }; | ||||
| 
 | ||||
| enum qed_ufp_pri_type { | ||||
| 	QED_UFP_PRI_OS, | ||||
| 	QED_UFP_PRI_VNIC, | ||||
| 	QED_UFP_PRI_UNKNOWN | ||||
| }; | ||||
| 
 | ||||
| struct qed_ufp_info { | ||||
| 	enum qed_ufp_pri_type pri_type; | ||||
| 	enum qed_ufp_mode mode; | ||||
| 	u8 tc; | ||||
| }; | ||||
| 
 | ||||
| enum BAR_ID { | ||||
| 	BAR_ID_0,		/* used for GRC */ | ||||
| 	BAR_ID_1		/* Used for doorbells */ | ||||
| @ -582,6 +600,8 @@ struct qed_hwfn { | ||||
| 
 | ||||
| 	struct qed_dcbx_info		*p_dcbx_info; | ||||
| 
 | ||||
| 	struct qed_ufp_info		ufp_info; | ||||
| 
 | ||||
| 	struct qed_dmae_info		dmae_info; | ||||
| 
 | ||||
| 	/* QM init */ | ||||
|  | ||||
| @ -274,8 +274,8 @@ qed_dcbx_process_tlv(struct qed_hwfn *p_hwfn, | ||||
| 		     u32 pri_tc_tbl, int count, u8 dcbx_version) | ||||
| { | ||||
| 	enum dcbx_protocol_type type; | ||||
| 	bool enable, ieee, eth_tlv; | ||||
| 	u8 tc, priority_map; | ||||
| 	bool enable, ieee; | ||||
| 	u16 protocol_id; | ||||
| 	int priority; | ||||
| 	int i; | ||||
| @ -283,6 +283,7 @@ qed_dcbx_process_tlv(struct qed_hwfn *p_hwfn, | ||||
| 	DP_VERBOSE(p_hwfn, QED_MSG_DCB, "Num APP entries = %d\n", count); | ||||
| 
 | ||||
| 	ieee = (dcbx_version == DCBX_CONFIG_VERSION_IEEE); | ||||
| 	eth_tlv = false; | ||||
| 	/* Parse APP TLV */ | ||||
| 	for (i = 0; i < count; i++) { | ||||
| 		protocol_id = QED_MFW_GET_FIELD(p_tbl[i].entry, | ||||
| @ -304,13 +305,22 @@ qed_dcbx_process_tlv(struct qed_hwfn *p_hwfn, | ||||
| 			 * indication, but we only got here if there was an | ||||
| 			 * app tlv for the protocol, so dcbx must be enabled. | ||||
| 			 */ | ||||
| 			enable = !(type == DCBX_PROTOCOL_ETH); | ||||
| 			if (type == DCBX_PROTOCOL_ETH) { | ||||
| 				enable = false; | ||||
| 				eth_tlv = true; | ||||
| 			} else { | ||||
| 				enable = true; | ||||
| 			} | ||||
| 
 | ||||
| 			qed_dcbx_update_app_info(p_data, p_hwfn, enable, | ||||
| 						 priority, tc, type); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/* If Eth TLV is not detected, use UFP TC as default TC */ | ||||
| 	if (test_bit(QED_MF_UFP_SPECIFIC, &p_hwfn->cdev->mf_bits) && !eth_tlv) | ||||
| 		p_data->arr[DCBX_PROTOCOL_ETH].tc = p_hwfn->ufp_info.tc; | ||||
| 
 | ||||
| 	/* Update ramrod protocol data and hw_info fields
 | ||||
| 	 * with default info when corresponding APP TLV's are not detected. | ||||
| 	 * The enabled field has a different logic for ethernet as only for | ||||
|  | ||||
| @ -1499,6 +1499,11 @@ static int qed_hw_init_pf(struct qed_hwfn *p_hwfn, | ||||
| 		STORE_RT_REG(p_hwfn, NIG_REG_LLH_FUNC_TAG_EN_RT_OFFSET, 1); | ||||
| 		STORE_RT_REG(p_hwfn, NIG_REG_LLH_FUNC_TAG_VALUE_RT_OFFSET, | ||||
| 			     p_hwfn->hw_info.ovlan); | ||||
| 
 | ||||
| 		DP_VERBOSE(p_hwfn, NETIF_MSG_HW, | ||||
| 			   "Configuring LLH_FUNC_FILTER_HDR_SEL\n"); | ||||
| 		STORE_RT_REG(p_hwfn, NIG_REG_LLH_FUNC_FILTER_HDR_SEL_RT_OFFSET, | ||||
| 			     1); | ||||
| 	} | ||||
| 
 | ||||
| 	/* Enable classification by MAC if needed */ | ||||
| @ -1635,6 +1640,7 @@ int qed_hw_init(struct qed_dev *cdev, struct qed_hw_init_params *p_params) | ||||
| 	bool b_default_mtu = true; | ||||
| 	struct qed_hwfn *p_hwfn; | ||||
| 	int rc = 0, mfw_rc, i; | ||||
| 	u16 ether_type; | ||||
| 
 | ||||
| 	if ((p_params->int_mode == QED_INT_MODE_MSI) && (cdev->num_hwfns > 1)) { | ||||
| 		DP_NOTICE(cdev, "MSI mode is not supported for CMT devices\n"); | ||||
| @ -1668,16 +1674,22 @@ int qed_hw_init(struct qed_dev *cdev, struct qed_hw_init_params *p_params) | ||||
| 		if (rc) | ||||
| 			return rc; | ||||
| 
 | ||||
| 		if (IS_PF(cdev) && test_bit(QED_MF_8021AD_TAGGING, | ||||
| 					    &cdev->mf_bits)) { | ||||
| 		if (IS_PF(cdev) && (test_bit(QED_MF_8021Q_TAGGING, | ||||
| 					     &cdev->mf_bits) || | ||||
| 				    test_bit(QED_MF_8021AD_TAGGING, | ||||
| 					     &cdev->mf_bits))) { | ||||
| 			if (test_bit(QED_MF_8021Q_TAGGING, &cdev->mf_bits)) | ||||
| 				ether_type = ETH_P_8021Q; | ||||
| 			else | ||||
| 				ether_type = ETH_P_8021AD; | ||||
| 			STORE_RT_REG(p_hwfn, PRS_REG_TAG_ETHERTYPE_0_RT_OFFSET, | ||||
| 				     ETH_P_8021AD); | ||||
| 				     ether_type); | ||||
| 			STORE_RT_REG(p_hwfn, NIG_REG_TAG_ETHERTYPE_0_RT_OFFSET, | ||||
| 				     ETH_P_8021AD); | ||||
| 				     ether_type); | ||||
| 			STORE_RT_REG(p_hwfn, PBF_REG_TAG_ETHERTYPE_0_RT_OFFSET, | ||||
| 				     ETH_P_8021AD); | ||||
| 				     ether_type); | ||||
| 			STORE_RT_REG(p_hwfn, DORQ_REG_TAG1_ETHERTYPE_RT_OFFSET, | ||||
| 				     ETH_P_8021AD); | ||||
| 				     ether_type); | ||||
| 		} | ||||
| 
 | ||||
| 		qed_fill_load_req_params(&load_req_params, | ||||
| @ -2659,6 +2671,12 @@ static int qed_hw_get_nvm_info(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) | ||||
| 		case NVM_CFG1_GLOB_MF_MODE_MF_ALLOWED: | ||||
| 			cdev->mf_bits = BIT(QED_MF_OVLAN_CLSS); | ||||
| 			break; | ||||
| 		case NVM_CFG1_GLOB_MF_MODE_UFP: | ||||
| 			cdev->mf_bits = BIT(QED_MF_OVLAN_CLSS) | | ||||
| 					BIT(QED_MF_LLH_PROTO_CLSS) | | ||||
| 					BIT(QED_MF_UFP_SPECIFIC) | | ||||
| 					BIT(QED_MF_8021Q_TAGGING); | ||||
| 			break; | ||||
| 		case NVM_CFG1_GLOB_MF_MODE_BD: | ||||
| 			cdev->mf_bits = BIT(QED_MF_OVLAN_CLSS) | | ||||
| 					BIT(QED_MF_LLH_PROTO_CLSS) | | ||||
| @ -2879,6 +2897,8 @@ qed_get_hw_info(struct qed_hwfn *p_hwfn, | ||||
| 		qed_mcp_cmd_port_init(p_hwfn, p_ptt); | ||||
| 
 | ||||
| 		qed_get_eee_caps(p_hwfn, p_ptt); | ||||
| 
 | ||||
| 		qed_mcp_read_ufp_config(p_hwfn, p_ptt); | ||||
| 	} | ||||
| 
 | ||||
| 	if (qed_mcp_is_init(p_hwfn)) { | ||||
|  | ||||
| @ -313,6 +313,9 @@ qed_sp_fcoe_conn_offload(struct qed_hwfn *p_hwfn, | ||||
| 	p_data->d_id.addr_mid = p_conn->d_id.addr_mid; | ||||
| 	p_data->d_id.addr_lo = p_conn->d_id.addr_lo; | ||||
| 	p_data->flags = p_conn->flags; | ||||
| 	if (test_bit(QED_MF_UFP_SPECIFIC, &p_hwfn->cdev->mf_bits)) | ||||
| 		SET_FIELD(p_data->flags, | ||||
| 			  FCOE_CONN_OFFLOAD_RAMROD_DATA_B_SINGLE_VLAN, 1); | ||||
| 	p_data->def_q_idx = p_conn->def_q_idx; | ||||
| 
 | ||||
| 	return qed_spq_post(p_hwfn, p_ent, NULL); | ||||
|  | ||||
| @ -11993,6 +11993,16 @@ struct public_port { | ||||
| #define EEE_REMOTE_TW_TX_OFFSET 0 | ||||
| #define EEE_REMOTE_TW_RX_MASK   0xffff0000 | ||||
| #define EEE_REMOTE_TW_RX_OFFSET 16 | ||||
| 
 | ||||
| 	u32 oem_cfg_port; | ||||
| #define OEM_CFG_CHANNEL_TYPE_MASK                       0x00000003 | ||||
| #define OEM_CFG_CHANNEL_TYPE_OFFSET                     0 | ||||
| #define OEM_CFG_CHANNEL_TYPE_VLAN_PARTITION             0x1 | ||||
| #define OEM_CFG_CHANNEL_TYPE_STAGGED                    0x2 | ||||
| #define OEM_CFG_SCHED_TYPE_MASK                         0x0000000C | ||||
| #define OEM_CFG_SCHED_TYPE_OFFSET                       2 | ||||
| #define OEM_CFG_SCHED_TYPE_ETS                          0x1 | ||||
| #define OEM_CFG_SCHED_TYPE_VNIC_BW                      0x2 | ||||
| }; | ||||
| 
 | ||||
| struct public_func { | ||||
| @ -12069,6 +12079,23 @@ struct public_func { | ||||
| #define DRV_ID_DRV_INIT_HW_MASK		0x80000000 | ||||
| #define DRV_ID_DRV_INIT_HW_SHIFT	31 | ||||
| #define DRV_ID_DRV_INIT_HW_FLAG		(1 << DRV_ID_DRV_INIT_HW_SHIFT) | ||||
| 
 | ||||
| 	u32 oem_cfg_func; | ||||
| #define OEM_CFG_FUNC_TC_MASK                    0x0000000F | ||||
| #define OEM_CFG_FUNC_TC_OFFSET                  0 | ||||
| #define OEM_CFG_FUNC_TC_0                       0x0 | ||||
| #define OEM_CFG_FUNC_TC_1                       0x1 | ||||
| #define OEM_CFG_FUNC_TC_2                       0x2 | ||||
| #define OEM_CFG_FUNC_TC_3                       0x3 | ||||
| #define OEM_CFG_FUNC_TC_4                       0x4 | ||||
| #define OEM_CFG_FUNC_TC_5                       0x5 | ||||
| #define OEM_CFG_FUNC_TC_6                       0x6 | ||||
| #define OEM_CFG_FUNC_TC_7                       0x7 | ||||
| 
 | ||||
| #define OEM_CFG_FUNC_HOST_PRI_CTRL_MASK         0x00000030 | ||||
| #define OEM_CFG_FUNC_HOST_PRI_CTRL_OFFSET       4 | ||||
| #define OEM_CFG_FUNC_HOST_PRI_CTRL_VNIC         0x1 | ||||
| #define OEM_CFG_FUNC_HOST_PRI_CTRL_OS           0x2 | ||||
| }; | ||||
| 
 | ||||
| struct mcp_mac { | ||||
| @ -12495,6 +12522,7 @@ enum MFW_DRV_MSG_TYPE { | ||||
| 	MFW_DRV_MSG_BW_UPDATE10, | ||||
| 	MFW_DRV_MSG_TRANSCEIVER_STATE_CHANGE, | ||||
| 	MFW_DRV_MSG_BW_UPDATE11, | ||||
| 	MFW_DRV_MSG_OEM_CFG_UPDATE, | ||||
| 	MFW_DRV_MSG_MAX | ||||
| }; | ||||
| 
 | ||||
|  | ||||
| @ -919,6 +919,10 @@ static int qed_sp_ll2_rx_queue_start(struct qed_hwfn *p_hwfn, | ||||
| 	p_ramrod->drop_ttl0_flg = p_ll2_conn->input.rx_drop_ttl0_flg; | ||||
| 	p_ramrod->inner_vlan_stripping_en = | ||||
| 		p_ll2_conn->input.rx_vlan_removal_en; | ||||
| 
 | ||||
| 	if (test_bit(QED_MF_UFP_SPECIFIC, &p_hwfn->cdev->mf_bits) && | ||||
| 	    p_ll2_conn->input.conn_type == QED_LL2_TYPE_FCOE) | ||||
| 		p_ramrod->report_outer_vlan = 1; | ||||
| 	p_ramrod->queue_id = p_ll2_conn->queue_id; | ||||
| 	p_ramrod->main_func_queue = p_ll2_conn->main_func_queue ? 1 : 0; | ||||
| 
 | ||||
| @ -1493,11 +1497,12 @@ int qed_ll2_establish_connection(void *cxt, u8 connection_handle) | ||||
| 	qed_ll2_establish_connection_ooo(p_hwfn, p_ll2_conn); | ||||
| 
 | ||||
| 	if (p_ll2_conn->input.conn_type == QED_LL2_TYPE_FCOE) { | ||||
| 		if (!test_bit(QED_MF_UFP_SPECIFIC, &p_hwfn->cdev->mf_bits)) | ||||
| 			qed_llh_add_protocol_filter(p_hwfn, p_ptt, | ||||
| 						    ETH_P_FCOE, 0, | ||||
| 						    QED_LLH_FILTER_ETHERTYPE); | ||||
| 		qed_llh_add_protocol_filter(p_hwfn, p_ptt, | ||||
| 					    0x8906, 0, | ||||
| 					    QED_LLH_FILTER_ETHERTYPE); | ||||
| 		qed_llh_add_protocol_filter(p_hwfn, p_ptt, | ||||
| 					    0x8914, 0, | ||||
| 					    ETH_P_FIP, 0, | ||||
| 					    QED_LLH_FILTER_ETHERTYPE); | ||||
| 	} | ||||
| 
 | ||||
| @ -1653,11 +1658,16 @@ qed_ll2_prepare_tx_packet_set_bd(struct qed_hwfn *p_hwfn, | ||||
| 
 | ||||
| 	start_bd = (struct core_tx_bd *)qed_chain_produce(p_tx_chain); | ||||
| 	if (QED_IS_IWARP_PERSONALITY(p_hwfn) && | ||||
| 	    p_ll2->input.conn_type == QED_LL2_TYPE_OOO) | ||||
| 	    p_ll2->input.conn_type == QED_LL2_TYPE_OOO) { | ||||
| 		start_bd->nw_vlan_or_lb_echo = | ||||
| 		    cpu_to_le16(IWARP_LL2_IN_ORDER_TX_QUEUE); | ||||
| 	else | ||||
| 	} else { | ||||
| 		start_bd->nw_vlan_or_lb_echo = cpu_to_le16(pkt->vlan); | ||||
| 		if (test_bit(QED_MF_UFP_SPECIFIC, &p_hwfn->cdev->mf_bits) && | ||||
| 		    p_ll2->input.conn_type == QED_LL2_TYPE_FCOE) | ||||
| 			pkt->remove_stag = true; | ||||
| 	} | ||||
| 
 | ||||
| 	SET_FIELD(start_bd->bitfield1, CORE_TX_BD_L4_HDR_OFFSET_W, | ||||
| 		  cpu_to_le16(pkt->l4_hdr_offset_w)); | ||||
| 	SET_FIELD(start_bd->bitfield1, CORE_TX_BD_TX_DST, tx_dest); | ||||
| @ -1668,6 +1678,9 @@ qed_ll2_prepare_tx_packet_set_bd(struct qed_hwfn *p_hwfn, | ||||
| 	SET_FIELD(bd_data, CORE_TX_BD_DATA_IP_CSUM, !!(pkt->enable_ip_cksum)); | ||||
| 	SET_FIELD(bd_data, CORE_TX_BD_DATA_L4_CSUM, !!(pkt->enable_l4_cksum)); | ||||
| 	SET_FIELD(bd_data, CORE_TX_BD_DATA_IP_LEN, !!(pkt->calc_ip_len)); | ||||
| 	SET_FIELD(bd_data, CORE_TX_BD_DATA_DISABLE_STAG_INSERTION, | ||||
| 		  !!(pkt->remove_stag)); | ||||
| 
 | ||||
| 	start_bd->bd_data.as_bitfield = cpu_to_le16(bd_data); | ||||
| 	DMA_REGPAIR_LE(start_bd->addr, pkt->first_frag); | ||||
| 	start_bd->nbytes = cpu_to_le16(pkt->first_frag_len); | ||||
| @ -1884,11 +1897,12 @@ int qed_ll2_terminate_connection(void *cxt, u8 connection_handle) | ||||
| 		qed_ooo_release_all_isles(p_hwfn, p_hwfn->p_ooo_info); | ||||
| 
 | ||||
| 	if (p_ll2_conn->input.conn_type == QED_LL2_TYPE_FCOE) { | ||||
| 		if (!test_bit(QED_MF_UFP_SPECIFIC, &p_hwfn->cdev->mf_bits)) | ||||
| 			qed_llh_remove_protocol_filter(p_hwfn, p_ptt, | ||||
| 						       ETH_P_FCOE, 0, | ||||
| 						      QED_LLH_FILTER_ETHERTYPE); | ||||
| 		qed_llh_remove_protocol_filter(p_hwfn, p_ptt, | ||||
| 					       0x8906, 0, | ||||
| 					       QED_LLH_FILTER_ETHERTYPE); | ||||
| 		qed_llh_remove_protocol_filter(p_hwfn, p_ptt, | ||||
| 					       0x8914, 0, | ||||
| 					       ETH_P_FIP, 0, | ||||
| 					       QED_LLH_FILTER_ETHERTYPE); | ||||
| 	} | ||||
| 
 | ||||
| @ -2360,7 +2374,8 @@ fail: | ||||
| 	return -EINVAL; | ||||
| } | ||||
| 
 | ||||
| static int qed_ll2_start_xmit(struct qed_dev *cdev, struct sk_buff *skb) | ||||
| static int qed_ll2_start_xmit(struct qed_dev *cdev, struct sk_buff *skb, | ||||
| 			      unsigned long xmit_flags) | ||||
| { | ||||
| 	struct qed_ll2_tx_pkt_info pkt; | ||||
| 	const skb_frag_t *frag; | ||||
| @ -2405,6 +2420,9 @@ static int qed_ll2_start_xmit(struct qed_dev *cdev, struct sk_buff *skb) | ||||
| 	pkt.first_frag = mapping; | ||||
| 	pkt.first_frag_len = skb->len; | ||||
| 	pkt.cookie = skb; | ||||
| 	if (test_bit(QED_MF_UFP_SPECIFIC, &cdev->mf_bits) && | ||||
| 	    test_bit(QED_LL2_XMIT_FLAGS_FIP_DISCOVERY, &xmit_flags)) | ||||
| 		pkt.remove_stag = true; | ||||
| 
 | ||||
| 	rc = qed_ll2_prepare_tx_packet(&cdev->hwfns[0], cdev->ll2->handle, | ||||
| 				       &pkt, 1); | ||||
|  | ||||
| @ -40,6 +40,7 @@ | ||||
| #include <linux/string.h> | ||||
| #include <linux/etherdevice.h> | ||||
| #include "qed.h" | ||||
| #include "qed_cxt.h" | ||||
| #include "qed_dcbx.h" | ||||
| #include "qed_hsi.h" | ||||
| #include "qed_hw.h" | ||||
| @ -1486,6 +1487,80 @@ static void qed_mcp_update_stag(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) | ||||
| 		    &resp, ¶m); | ||||
| } | ||||
| 
 | ||||
| void qed_mcp_read_ufp_config(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) | ||||
| { | ||||
| 	struct public_func shmem_info; | ||||
| 	u32 port_cfg, val; | ||||
| 
 | ||||
| 	if (!test_bit(QED_MF_UFP_SPECIFIC, &p_hwfn->cdev->mf_bits)) | ||||
| 		return; | ||||
| 
 | ||||
| 	memset(&p_hwfn->ufp_info, 0, sizeof(p_hwfn->ufp_info)); | ||||
| 	port_cfg = qed_rd(p_hwfn, p_ptt, p_hwfn->mcp_info->port_addr + | ||||
| 			  offsetof(struct public_port, oem_cfg_port)); | ||||
| 	val = (port_cfg & OEM_CFG_CHANNEL_TYPE_MASK) >> | ||||
| 		OEM_CFG_CHANNEL_TYPE_OFFSET; | ||||
| 	if (val != OEM_CFG_CHANNEL_TYPE_STAGGED) | ||||
| 		DP_NOTICE(p_hwfn, "Incorrect UFP Channel type  %d\n", val); | ||||
| 
 | ||||
| 	val = (port_cfg & OEM_CFG_SCHED_TYPE_MASK) >> OEM_CFG_SCHED_TYPE_OFFSET; | ||||
| 	if (val == OEM_CFG_SCHED_TYPE_ETS) { | ||||
| 		p_hwfn->ufp_info.mode = QED_UFP_MODE_ETS; | ||||
| 	} else if (val == OEM_CFG_SCHED_TYPE_VNIC_BW) { | ||||
| 		p_hwfn->ufp_info.mode = QED_UFP_MODE_VNIC_BW; | ||||
| 	} else { | ||||
| 		p_hwfn->ufp_info.mode = QED_UFP_MODE_UNKNOWN; | ||||
| 		DP_NOTICE(p_hwfn, "Unknown UFP scheduling mode %d\n", val); | ||||
| 	} | ||||
| 
 | ||||
| 	qed_mcp_get_shmem_func(p_hwfn, p_ptt, &shmem_info, MCP_PF_ID(p_hwfn)); | ||||
| 	val = (port_cfg & OEM_CFG_FUNC_TC_MASK) >> OEM_CFG_FUNC_TC_OFFSET; | ||||
| 	p_hwfn->ufp_info.tc = (u8)val; | ||||
| 	val = (port_cfg & OEM_CFG_FUNC_HOST_PRI_CTRL_MASK) >> | ||||
| 		OEM_CFG_FUNC_HOST_PRI_CTRL_OFFSET; | ||||
| 	if (val == OEM_CFG_FUNC_HOST_PRI_CTRL_VNIC) { | ||||
| 		p_hwfn->ufp_info.pri_type = QED_UFP_PRI_VNIC; | ||||
| 	} else if (val == OEM_CFG_FUNC_HOST_PRI_CTRL_OS) { | ||||
| 		p_hwfn->ufp_info.pri_type = QED_UFP_PRI_OS; | ||||
| 	} else { | ||||
| 		p_hwfn->ufp_info.pri_type = QED_UFP_PRI_UNKNOWN; | ||||
| 		DP_NOTICE(p_hwfn, "Unknown Host priority control %d\n", val); | ||||
| 	} | ||||
| 
 | ||||
| 	DP_NOTICE(p_hwfn, | ||||
| 		  "UFP shmem config: mode = %d tc = %d pri_type = %d\n", | ||||
| 		  p_hwfn->ufp_info.mode, | ||||
| 		  p_hwfn->ufp_info.tc, p_hwfn->ufp_info.pri_type); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| qed_mcp_handle_ufp_event(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) | ||||
| { | ||||
| 	qed_mcp_read_ufp_config(p_hwfn, p_ptt); | ||||
| 
 | ||||
| 	if (p_hwfn->ufp_info.mode == QED_UFP_MODE_VNIC_BW) { | ||||
| 		p_hwfn->qm_info.ooo_tc = p_hwfn->ufp_info.tc; | ||||
| 		p_hwfn->hw_info.offload_tc = p_hwfn->ufp_info.tc; | ||||
| 
 | ||||
| 		qed_qm_reconf(p_hwfn, p_ptt); | ||||
| 	} else if (p_hwfn->ufp_info.mode == QED_UFP_MODE_ETS) { | ||||
| 		/* Merge UFP TC with the dcbx TC data */ | ||||
| 		qed_dcbx_mib_update_event(p_hwfn, p_ptt, | ||||
| 					  QED_DCBX_OPERATIONAL_MIB); | ||||
| 	} else { | ||||
| 		DP_ERR(p_hwfn, "Invalid sched type, discard the UFP config\n"); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	/* update storm FW with negotiation results */ | ||||
| 	qed_sp_pf_update_ufp(p_hwfn); | ||||
| 
 | ||||
| 	/* update stag pcp value */ | ||||
| 	qed_sp_pf_update_stag(p_hwfn); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int qed_mcp_handle_events(struct qed_hwfn *p_hwfn, | ||||
| 			  struct qed_ptt *p_ptt) | ||||
| { | ||||
| @ -1529,6 +1604,9 @@ int qed_mcp_handle_events(struct qed_hwfn *p_hwfn, | ||||
| 			qed_dcbx_mib_update_event(p_hwfn, p_ptt, | ||||
| 						  QED_DCBX_OPERATIONAL_MIB); | ||||
| 			break; | ||||
| 		case MFW_DRV_MSG_OEM_CFG_UPDATE: | ||||
| 			qed_mcp_handle_ufp_event(p_hwfn, p_ptt); | ||||
| 			break; | ||||
| 		case MFW_DRV_MSG_TRANSCEIVER_STATE_CHANGE: | ||||
| 			qed_mcp_handle_transceiver_change(p_hwfn, p_ptt); | ||||
| 			break; | ||||
|  | ||||
| @ -1004,6 +1004,14 @@ int qed_mcp_get_capabilities(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt); | ||||
|  */ | ||||
| int qed_mcp_set_capabilities(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt); | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief Read ufp config from the shared memory. | ||||
|  * | ||||
|  * @param p_hwfn | ||||
|  * @param p_ptt | ||||
|  */ | ||||
| void qed_mcp_read_ufp_config(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt); | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief Populate the nvm info shadow in the given hardware function | ||||
|  * | ||||
|  | ||||
| @ -462,6 +462,15 @@ int qed_sp_pf_update_stag(struct qed_hwfn *p_hwfn); | ||||
|  * @return int | ||||
|  */ | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief qed_sp_pf_update_ufp - PF ufp update Ramrod | ||||
|  * | ||||
|  * @param p_hwfn | ||||
|  * | ||||
|  * @return int | ||||
|  */ | ||||
| int qed_sp_pf_update_ufp(struct qed_hwfn *p_hwfn); | ||||
| 
 | ||||
| int qed_sp_pf_stop(struct qed_hwfn *p_hwfn); | ||||
| 
 | ||||
| int qed_sp_pf_update_tunn_cfg(struct qed_hwfn *p_hwfn, | ||||
|  | ||||
| @ -314,7 +314,7 @@ int qed_sp_pf_start(struct qed_hwfn *p_hwfn, | ||||
| 	struct qed_spq_entry *p_ent = NULL; | ||||
| 	struct qed_sp_init_data init_data; | ||||
| 	int rc = -EINVAL; | ||||
| 	u8 page_cnt; | ||||
| 	u8 page_cnt, i; | ||||
| 
 | ||||
| 	/* update initial eq producer */ | ||||
| 	qed_eq_prod_update(p_hwfn, | ||||
| @ -345,12 +345,30 @@ int qed_sp_pf_start(struct qed_hwfn *p_hwfn, | ||||
| 		p_ramrod->mf_mode = MF_NPAR; | ||||
| 
 | ||||
| 	p_ramrod->outer_tag_config.outer_tag.tci = | ||||
| 		cpu_to_le16(p_hwfn->hw_info.ovlan); | ||||
| 	if (test_bit(QED_MF_8021AD_TAGGING, &p_hwfn->cdev->mf_bits)) { | ||||
| 				cpu_to_le16(p_hwfn->hw_info.ovlan); | ||||
| 	if (test_bit(QED_MF_8021Q_TAGGING, &p_hwfn->cdev->mf_bits)) { | ||||
| 		p_ramrod->outer_tag_config.outer_tag.tpid = ETH_P_8021Q; | ||||
| 	} else if (test_bit(QED_MF_8021AD_TAGGING, &p_hwfn->cdev->mf_bits)) { | ||||
| 		p_ramrod->outer_tag_config.outer_tag.tpid = ETH_P_8021AD; | ||||
| 		p_ramrod->outer_tag_config.enable_stag_pri_change = 1; | ||||
| 	} | ||||
| 
 | ||||
| 	p_ramrod->outer_tag_config.pri_map_valid = 1; | ||||
| 	for (i = 0; i < QED_MAX_PFC_PRIORITIES; i++) | ||||
| 		p_ramrod->outer_tag_config.inner_to_outer_pri_map[i] = i; | ||||
| 
 | ||||
| 	/* enable_stag_pri_change should be set if port is in BD mode or,
 | ||||
| 	 * UFP with Host Control mode. | ||||
| 	 */ | ||||
| 	if (test_bit(QED_MF_UFP_SPECIFIC, &p_hwfn->cdev->mf_bits)) { | ||||
| 		if (p_hwfn->ufp_info.pri_type == QED_UFP_PRI_OS) | ||||
| 			p_ramrod->outer_tag_config.enable_stag_pri_change = 1; | ||||
| 		else | ||||
| 			p_ramrod->outer_tag_config.enable_stag_pri_change = 0; | ||||
| 
 | ||||
| 		p_ramrod->outer_tag_config.outer_tag.tci |= | ||||
| 		    cpu_to_le16(((u16)p_hwfn->ufp_info.tc << 13)); | ||||
| 	} | ||||
| 
 | ||||
| 	/* Place EQ address in RAMROD */ | ||||
| 	DMA_REGPAIR_LE(p_ramrod->event_ring_pbl_addr, | ||||
| @ -431,6 +449,39 @@ int qed_sp_pf_update(struct qed_hwfn *p_hwfn) | ||||
| 	return qed_spq_post(p_hwfn, p_ent, NULL); | ||||
| } | ||||
| 
 | ||||
| int qed_sp_pf_update_ufp(struct qed_hwfn *p_hwfn) | ||||
| { | ||||
| 	struct qed_spq_entry *p_ent = NULL; | ||||
| 	struct qed_sp_init_data init_data; | ||||
| 	int rc = -EOPNOTSUPP; | ||||
| 
 | ||||
| 	if (p_hwfn->ufp_info.pri_type == QED_UFP_PRI_UNKNOWN) { | ||||
| 		DP_INFO(p_hwfn, "Invalid priority type %d\n", | ||||
| 			p_hwfn->ufp_info.pri_type); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Get SPQ entry */ | ||||
| 	memset(&init_data, 0, sizeof(init_data)); | ||||
| 	init_data.cid = qed_spq_get_cid(p_hwfn); | ||||
| 	init_data.opaque_fid = p_hwfn->hw_info.opaque_fid; | ||||
| 	init_data.comp_mode = QED_SPQ_MODE_CB; | ||||
| 
 | ||||
| 	rc = qed_sp_init_request(p_hwfn, &p_ent, | ||||
| 				 COMMON_RAMROD_PF_UPDATE, PROTOCOLID_COMMON, | ||||
| 				 &init_data); | ||||
| 	if (rc) | ||||
| 		return rc; | ||||
| 
 | ||||
| 	p_ent->ramrod.pf_update.update_enable_stag_pri_change = true; | ||||
| 	if (p_hwfn->ufp_info.pri_type == QED_UFP_PRI_OS) | ||||
| 		p_ent->ramrod.pf_update.enable_stag_pri_change = 1; | ||||
| 	else | ||||
| 		p_ent->ramrod.pf_update.enable_stag_pri_change = 0; | ||||
| 
 | ||||
| 	return qed_spq_post(p_hwfn, p_ent, NULL); | ||||
| } | ||||
| 
 | ||||
| /* Set pf update ramrod command params */ | ||||
| int qed_sp_pf_update_tunn_cfg(struct qed_hwfn *p_hwfn, | ||||
| 			      struct qed_ptt *p_ptt, | ||||
|  | ||||
| @ -23,6 +23,7 @@ void qedf_fcoe_send_vlan_req(struct qedf_ctx *qedf) | ||||
| 	struct fip_vlan *vlan; | ||||
| #define MY_FIP_ALL_FCF_MACS        ((__u8[6]) { 1, 0x10, 0x18, 1, 0, 2 }) | ||||
| 	static u8 my_fcoe_all_fcfs[ETH_ALEN] = MY_FIP_ALL_FCF_MACS; | ||||
| 	unsigned long flags = 0; | ||||
| 
 | ||||
| 	skb = dev_alloc_skb(sizeof(struct fip_vlan)); | ||||
| 	if (!skb) | ||||
| @ -65,7 +66,9 @@ void qedf_fcoe_send_vlan_req(struct qedf_ctx *qedf) | ||||
| 		kfree_skb(skb); | ||||
| 		return; | ||||
| 	} | ||||
| 	qed_ops->ll2->start_xmit(qedf->cdev, skb); | ||||
| 
 | ||||
| 	set_bit(QED_LL2_XMIT_FLAGS_FIP_DISCOVERY, &flags); | ||||
| 	qed_ops->ll2->start_xmit(qedf->cdev, skb, flags); | ||||
| } | ||||
| 
 | ||||
| static void qedf_fcoe_process_vlan_resp(struct qedf_ctx *qedf, | ||||
| @ -139,7 +142,7 @@ void qedf_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb) | ||||
| 		print_hex_dump(KERN_WARNING, "fip ", DUMP_PREFIX_OFFSET, 16, 1, | ||||
| 		    skb->data, skb->len, false); | ||||
| 
 | ||||
| 	qed_ops->ll2->start_xmit(qedf->cdev, skb); | ||||
| 	qed_ops->ll2->start_xmit(qedf->cdev, skb, 0); | ||||
| } | ||||
| 
 | ||||
| /* Process incoming FIP frames. */ | ||||
|  | ||||
| @ -994,7 +994,7 @@ static int qedf_xmit(struct fc_lport *lport, struct fc_frame *fp) | ||||
| 	if (qedf_dump_frames) | ||||
| 		print_hex_dump(KERN_WARNING, "fcoe: ", DUMP_PREFIX_OFFSET, 16, | ||||
| 		    1, skb->data, skb->len, false); | ||||
| 	qed_ops->ll2->start_xmit(qedf->cdev, skb); | ||||
| 	qed_ops->ll2->start_xmit(qedf->cdev, skb, 0); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @ -1150,7 +1150,7 @@ static int qedi_data_avail(struct qedi_ctx *qedi, u16 vlanid) | ||||
| 	if (vlanid) | ||||
| 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlanid); | ||||
| 
 | ||||
| 	rc = qedi_ops->ll2->start_xmit(cdev, skb); | ||||
| 	rc = qedi_ops->ll2->start_xmit(cdev, skb, 0); | ||||
| 	if (rc) { | ||||
| 		QEDI_ERR(&qedi->dbg_ctx, "ll2 start_xmit returned %d\n", | ||||
| 			 rc); | ||||
|  | ||||
| @ -202,6 +202,7 @@ struct qed_ll2_tx_pkt_info { | ||||
| 	bool enable_ip_cksum; | ||||
| 	bool enable_l4_cksum; | ||||
| 	bool calc_ip_len; | ||||
| 	bool remove_stag; | ||||
| }; | ||||
| 
 | ||||
| #define QED_LL2_UNUSED_HANDLE   (0xff) | ||||
| @ -220,6 +221,11 @@ struct qed_ll2_params { | ||||
| 	u8 ll2_mac_address[ETH_ALEN]; | ||||
| }; | ||||
| 
 | ||||
| enum qed_ll2_xmit_flags { | ||||
| 	/* FIP discovery packet */ | ||||
| 	QED_LL2_XMIT_FLAGS_FIP_DISCOVERY | ||||
| }; | ||||
| 
 | ||||
| struct qed_ll2_ops { | ||||
| /**
 | ||||
|  * @brief start - initializes ll2 | ||||
| @ -245,10 +251,12 @@ struct qed_ll2_ops { | ||||
|  * | ||||
|  * @param cdev | ||||
|  * @param skb | ||||
|  * @param xmit_flags - Transmit options defined by the enum qed_ll2_xmit_flags. | ||||
|  * | ||||
|  * @return 0 on success, otherwise error value. | ||||
|  */ | ||||
| 	int (*start_xmit)(struct qed_dev *cdev, struct sk_buff *skb); | ||||
| 	int (*start_xmit)(struct qed_dev *cdev, struct sk_buff *skb, | ||||
| 			  unsigned long xmit_flags); | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief register_cb_ops - protocol driver register the callback for Rx/Tx | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user