qed: Add Light L2 support
Other protocols beside the networking driver need the ability of passing some L2 traffic, usually [although not limited] for the purpose of some management traffic. Signed-off-by: Yuval Mintz <Yuval.Mintz@caviumnetworks.com> Signed-off-by: Ram Amrani <Ram.Amrani@caviumnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									b9118b7221
								
							
						
					
					
						commit
						0a7fb11c23
					
				| @ -88,6 +88,14 @@ config QED | |||||||
| 	---help--- | 	---help--- | ||||||
| 	  This enables the support for ... | 	  This enables the support for ... | ||||||
| 
 | 
 | ||||||
|  | config QED_LL2 | ||||||
|  | 	bool "Qlogic QED Light L2 interface" | ||||||
|  | 	default n | ||||||
|  | 	depends on QED | ||||||
|  | 	---help--- | ||||||
|  | 	This enables support for Light L2 interface which is required | ||||||
|  | 	by all qed protocol drivers other than qede. | ||||||
|  | 
 | ||||||
| config QED_SRIOV | config QED_SRIOV | ||||||
| 	bool "QLogic QED 25/40/100Gb SR-IOV support" | 	bool "QLogic QED 25/40/100Gb SR-IOV support" | ||||||
| 	depends on QED && PCI_IOV | 	depends on QED && PCI_IOV | ||||||
|  | |||||||
| @ -4,3 +4,4 @@ qed-y := qed_cxt.o qed_dev.o qed_hw.o qed_init_fw_funcs.o qed_init_ops.o \ | |||||||
| 	 qed_int.o qed_main.o qed_mcp.o qed_sp_commands.o qed_spq.o qed_l2.o \
 | 	 qed_int.o qed_main.o qed_mcp.o qed_sp_commands.o qed_spq.o qed_l2.o \
 | ||||||
| 	 qed_selftest.o qed_dcbx.o qed_debug.o | 	 qed_selftest.o qed_dcbx.o qed_debug.o | ||||||
| qed-$(CONFIG_QED_SRIOV) += qed_sriov.o qed_vf.o | qed-$(CONFIG_QED_SRIOV) += qed_sriov.o qed_vf.o | ||||||
|  | qed-$(CONFIG_QED_LL2) += qed_ll2.o | ||||||
|  | |||||||
| @ -72,6 +72,7 @@ struct qed_sb_info; | |||||||
| struct qed_sb_attn_info; | struct qed_sb_attn_info; | ||||||
| struct qed_cxt_mngr; | struct qed_cxt_mngr; | ||||||
| struct qed_sb_sp_info; | struct qed_sb_sp_info; | ||||||
|  | struct qed_ll2_info; | ||||||
| struct qed_mcp_info; | struct qed_mcp_info; | ||||||
| 
 | 
 | ||||||
| struct qed_rt_data { | struct qed_rt_data { | ||||||
| @ -152,6 +153,7 @@ enum QED_RESOURCES { | |||||||
| 	QED_MAC, | 	QED_MAC, | ||||||
| 	QED_VLAN, | 	QED_VLAN, | ||||||
| 	QED_ILT, | 	QED_ILT, | ||||||
|  | 	QED_LL2_QUEUE, | ||||||
| 	QED_MAX_RESC, | 	QED_MAX_RESC, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -360,6 +362,8 @@ struct qed_hwfn { | |||||||
| 	struct qed_sb_attn_info		*p_sb_attn; | 	struct qed_sb_attn_info		*p_sb_attn; | ||||||
| 
 | 
 | ||||||
| 	/* Protocol related */ | 	/* Protocol related */ | ||||||
|  | 	bool				using_ll2; | ||||||
|  | 	struct qed_ll2_info		*p_ll2_info; | ||||||
| 	struct qed_pf_params		pf_params; | 	struct qed_pf_params		pf_params; | ||||||
| 
 | 
 | ||||||
| 	bool b_rdma_enabled_in_prs; | 	bool b_rdma_enabled_in_prs; | ||||||
| @ -564,6 +568,11 @@ struct qed_dev { | |||||||
| 
 | 
 | ||||||
| 	struct qed_dbg_params		dbg_params; | 	struct qed_dbg_params		dbg_params; | ||||||
| 
 | 
 | ||||||
|  | #ifdef CONFIG_QED_LL2 | ||||||
|  | 	struct qed_cb_ll2_info		*ll2; | ||||||
|  | 	u8				ll2_mac_address[ETH_ALEN]; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| 	const struct firmware		*firmware; | 	const struct firmware		*firmware; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1839,6 +1839,8 @@ int qed_cxt_set_pf_params(struct qed_hwfn *p_hwfn) | |||||||
| 	/* Set the number of required CORE connections */ | 	/* Set the number of required CORE connections */ | ||||||
| 	u32 core_cids = 1; /* SPQ */ | 	u32 core_cids = 1; /* SPQ */ | ||||||
| 
 | 
 | ||||||
|  | 	if (p_hwfn->using_ll2) | ||||||
|  | 		core_cids += 4; | ||||||
| 	qed_cxt_set_proto_cid_count(p_hwfn, PROTOCOLID_CORE, core_cids, 0); | 	qed_cxt_set_proto_cid_count(p_hwfn, PROTOCOLID_CORE, core_cids, 0); | ||||||
| 
 | 
 | ||||||
| 	switch (p_hwfn->hw_info.personality) { | 	switch (p_hwfn->hw_info.personality) { | ||||||
|  | |||||||
| @ -29,6 +29,7 @@ | |||||||
| #include "qed_hw.h" | #include "qed_hw.h" | ||||||
| #include "qed_init_ops.h" | #include "qed_init_ops.h" | ||||||
| #include "qed_int.h" | #include "qed_int.h" | ||||||
|  | #include "qed_ll2.h" | ||||||
| #include "qed_mcp.h" | #include "qed_mcp.h" | ||||||
| #include "qed_reg_addr.h" | #include "qed_reg_addr.h" | ||||||
| #include "qed_sp.h" | #include "qed_sp.h" | ||||||
| @ -147,6 +148,9 @@ void qed_resc_free(struct qed_dev *cdev) | |||||||
| 		qed_eq_free(p_hwfn, p_hwfn->p_eq); | 		qed_eq_free(p_hwfn, p_hwfn->p_eq); | ||||||
| 		qed_consq_free(p_hwfn, p_hwfn->p_consq); | 		qed_consq_free(p_hwfn, p_hwfn->p_consq); | ||||||
| 		qed_int_free(p_hwfn); | 		qed_int_free(p_hwfn); | ||||||
|  | #ifdef CONFIG_QED_LL2 | ||||||
|  | 		qed_ll2_free(p_hwfn, p_hwfn->p_ll2_info); | ||||||
|  | #endif | ||||||
| 		qed_iov_free(p_hwfn); | 		qed_iov_free(p_hwfn); | ||||||
| 		qed_dmae_info_free(p_hwfn); | 		qed_dmae_info_free(p_hwfn); | ||||||
| 		qed_dcbx_info_free(p_hwfn, p_hwfn->p_dcbx_info); | 		qed_dcbx_info_free(p_hwfn, p_hwfn->p_dcbx_info); | ||||||
| @ -403,6 +407,9 @@ int qed_qm_reconf(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) | |||||||
| 
 | 
 | ||||||
| int qed_resc_alloc(struct qed_dev *cdev) | int qed_resc_alloc(struct qed_dev *cdev) | ||||||
| { | { | ||||||
|  | #ifdef CONFIG_QED_LL2 | ||||||
|  | 	struct qed_ll2_info *p_ll2_info; | ||||||
|  | #endif | ||||||
| 	struct qed_consq *p_consq; | 	struct qed_consq *p_consq; | ||||||
| 	struct qed_eq *p_eq; | 	struct qed_eq *p_eq; | ||||||
| 	int i, rc = 0; | 	int i, rc = 0; | ||||||
| @ -513,6 +520,15 @@ int qed_resc_alloc(struct qed_dev *cdev) | |||||||
| 			goto alloc_no_mem; | 			goto alloc_no_mem; | ||||||
| 		p_hwfn->p_consq = p_consq; | 		p_hwfn->p_consq = p_consq; | ||||||
| 
 | 
 | ||||||
|  | #ifdef CONFIG_QED_LL2 | ||||||
|  | 		if (p_hwfn->using_ll2) { | ||||||
|  | 			p_ll2_info = qed_ll2_alloc(p_hwfn); | ||||||
|  | 			if (!p_ll2_info) | ||||||
|  | 				goto alloc_no_mem; | ||||||
|  | 			p_hwfn->p_ll2_info = p_ll2_info; | ||||||
|  | 		} | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| 		/* DMA info initialization */ | 		/* DMA info initialization */ | ||||||
| 		rc = qed_dmae_info_alloc(p_hwfn); | 		rc = qed_dmae_info_alloc(p_hwfn); | ||||||
| 		if (rc) | 		if (rc) | ||||||
| @ -561,6 +577,10 @@ void qed_resc_setup(struct qed_dev *cdev) | |||||||
| 		qed_int_setup(p_hwfn, p_hwfn->p_main_ptt); | 		qed_int_setup(p_hwfn, p_hwfn->p_main_ptt); | ||||||
| 
 | 
 | ||||||
| 		qed_iov_setup(p_hwfn, p_hwfn->p_main_ptt); | 		qed_iov_setup(p_hwfn, p_hwfn->p_main_ptt); | ||||||
|  | #ifdef CONFIG_QED_LL2 | ||||||
|  | 		if (p_hwfn->using_ll2) | ||||||
|  | 			qed_ll2_setup(p_hwfn, p_hwfn->p_ll2_info); | ||||||
|  | #endif | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -1304,6 +1324,7 @@ static int qed_hw_get_resc(struct qed_hwfn *p_hwfn) | |||||||
| 	resc_num[QED_VLAN] = (ETH_NUM_VLAN_FILTERS - 1 /*For vlan0*/) / | 	resc_num[QED_VLAN] = (ETH_NUM_VLAN_FILTERS - 1 /*For vlan0*/) / | ||||||
| 			     num_funcs; | 			     num_funcs; | ||||||
| 	resc_num[QED_ILT] = PXP_NUM_ILT_RECORDS_BB / num_funcs; | 	resc_num[QED_ILT] = PXP_NUM_ILT_RECORDS_BB / num_funcs; | ||||||
|  | 	resc_num[QED_LL2_QUEUE] = MAX_NUM_LL2_RX_QUEUES / num_funcs; | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < QED_MAX_RESC; i++) | 	for (i = 0; i < QED_MAX_RESC; i++) | ||||||
| 		resc_start[i] = resc_num[i] * enabled_func_idx; | 		resc_start[i] = resc_num[i] * enabled_func_idx; | ||||||
| @ -1327,7 +1348,8 @@ static int qed_hw_get_resc(struct qed_hwfn *p_hwfn) | |||||||
| 		   "RL = %d start = %d\n" | 		   "RL = %d start = %d\n" | ||||||
| 		   "MAC = %d start = %d\n" | 		   "MAC = %d start = %d\n" | ||||||
| 		   "VLAN = %d start = %d\n" | 		   "VLAN = %d start = %d\n" | ||||||
| 		   "ILT = %d start = %d\n", | 		   "ILT = %d start = %d\n" | ||||||
|  | 		   "LL2_QUEUE = %d start = %d\n", | ||||||
| 		   p_hwfn->hw_info.resc_num[QED_SB], | 		   p_hwfn->hw_info.resc_num[QED_SB], | ||||||
| 		   p_hwfn->hw_info.resc_start[QED_SB], | 		   p_hwfn->hw_info.resc_start[QED_SB], | ||||||
| 		   p_hwfn->hw_info.resc_num[QED_L2_QUEUE], | 		   p_hwfn->hw_info.resc_num[QED_L2_QUEUE], | ||||||
| @ -1343,7 +1365,9 @@ static int qed_hw_get_resc(struct qed_hwfn *p_hwfn) | |||||||
| 		   p_hwfn->hw_info.resc_num[QED_VLAN], | 		   p_hwfn->hw_info.resc_num[QED_VLAN], | ||||||
| 		   p_hwfn->hw_info.resc_start[QED_VLAN], | 		   p_hwfn->hw_info.resc_start[QED_VLAN], | ||||||
| 		   p_hwfn->hw_info.resc_num[QED_ILT], | 		   p_hwfn->hw_info.resc_num[QED_ILT], | ||||||
| 		   p_hwfn->hw_info.resc_start[QED_ILT]); | 		   p_hwfn->hw_info.resc_start[QED_ILT], | ||||||
|  | 		   RESC_NUM(p_hwfn, QED_LL2_QUEUE), | ||||||
|  | 		   RESC_START(p_hwfn, QED_LL2_QUEUE)); | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| @ -2133,6 +2157,98 @@ int qed_fw_rss_eng(struct qed_hwfn *p_hwfn, u8 src_id, u8 *dst_id) | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static void qed_llh_mac_to_filter(u32 *p_high, u32 *p_low, | ||||||
|  | 				  u8 *p_filter) | ||||||
|  | { | ||||||
|  | 	*p_high = p_filter[1] | (p_filter[0] << 8); | ||||||
|  | 	*p_low = p_filter[5] | (p_filter[4] << 8) | | ||||||
|  | 		 (p_filter[3] << 16) | (p_filter[2] << 24); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int qed_llh_add_mac_filter(struct qed_hwfn *p_hwfn, | ||||||
|  | 			   struct qed_ptt *p_ptt, u8 *p_filter) | ||||||
|  | { | ||||||
|  | 	u32 high = 0, low = 0, en; | ||||||
|  | 	int i; | ||||||
|  | 
 | ||||||
|  | 	if (!(IS_MF_SI(p_hwfn) || IS_MF_DEFAULT(p_hwfn))) | ||||||
|  | 		return 0; | ||||||
|  | 
 | ||||||
|  | 	qed_llh_mac_to_filter(&high, &low, p_filter); | ||||||
|  | 
 | ||||||
|  | 	/* Find a free entry and utilize it */ | ||||||
|  | 	for (i = 0; i < NIG_REG_LLH_FUNC_FILTER_EN_SIZE; i++) { | ||||||
|  | 		en = qed_rd(p_hwfn, p_ptt, | ||||||
|  | 			    NIG_REG_LLH_FUNC_FILTER_EN + i * sizeof(u32)); | ||||||
|  | 		if (en) | ||||||
|  | 			continue; | ||||||
|  | 		qed_wr(p_hwfn, p_ptt, | ||||||
|  | 		       NIG_REG_LLH_FUNC_FILTER_VALUE + | ||||||
|  | 		       2 * i * sizeof(u32), low); | ||||||
|  | 		qed_wr(p_hwfn, p_ptt, | ||||||
|  | 		       NIG_REG_LLH_FUNC_FILTER_VALUE + | ||||||
|  | 		       (2 * i + 1) * sizeof(u32), high); | ||||||
|  | 		qed_wr(p_hwfn, p_ptt, | ||||||
|  | 		       NIG_REG_LLH_FUNC_FILTER_MODE + i * sizeof(u32), 0); | ||||||
|  | 		qed_wr(p_hwfn, p_ptt, | ||||||
|  | 		       NIG_REG_LLH_FUNC_FILTER_PROTOCOL_TYPE + | ||||||
|  | 		       i * sizeof(u32), 0); | ||||||
|  | 		qed_wr(p_hwfn, p_ptt, | ||||||
|  | 		       NIG_REG_LLH_FUNC_FILTER_EN + i * sizeof(u32), 1); | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 	if (i >= NIG_REG_LLH_FUNC_FILTER_EN_SIZE) { | ||||||
|  | 		DP_NOTICE(p_hwfn, | ||||||
|  | 			  "Failed to find an empty LLH filter to utilize\n"); | ||||||
|  | 		return -EINVAL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	DP_VERBOSE(p_hwfn, NETIF_MSG_HW, | ||||||
|  | 		   "mac: %pM is added at %d\n", | ||||||
|  | 		   p_filter, i); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void qed_llh_remove_mac_filter(struct qed_hwfn *p_hwfn, | ||||||
|  | 			       struct qed_ptt *p_ptt, u8 *p_filter) | ||||||
|  | { | ||||||
|  | 	u32 high = 0, low = 0; | ||||||
|  | 	int i; | ||||||
|  | 
 | ||||||
|  | 	if (!(IS_MF_SI(p_hwfn) || IS_MF_DEFAULT(p_hwfn))) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	qed_llh_mac_to_filter(&high, &low, p_filter); | ||||||
|  | 
 | ||||||
|  | 	/* Find the entry and clean it */ | ||||||
|  | 	for (i = 0; i < NIG_REG_LLH_FUNC_FILTER_EN_SIZE; i++) { | ||||||
|  | 		if (qed_rd(p_hwfn, p_ptt, | ||||||
|  | 			   NIG_REG_LLH_FUNC_FILTER_VALUE + | ||||||
|  | 			   2 * i * sizeof(u32)) != low) | ||||||
|  | 			continue; | ||||||
|  | 		if (qed_rd(p_hwfn, p_ptt, | ||||||
|  | 			   NIG_REG_LLH_FUNC_FILTER_VALUE + | ||||||
|  | 			   (2 * i + 1) * sizeof(u32)) != high) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		qed_wr(p_hwfn, p_ptt, | ||||||
|  | 		       NIG_REG_LLH_FUNC_FILTER_EN + i * sizeof(u32), 0); | ||||||
|  | 		qed_wr(p_hwfn, p_ptt, | ||||||
|  | 		       NIG_REG_LLH_FUNC_FILTER_VALUE + 2 * i * sizeof(u32), 0); | ||||||
|  | 		qed_wr(p_hwfn, p_ptt, | ||||||
|  | 		       NIG_REG_LLH_FUNC_FILTER_VALUE + | ||||||
|  | 		       (2 * i + 1) * sizeof(u32), 0); | ||||||
|  | 
 | ||||||
|  | 		DP_VERBOSE(p_hwfn, NETIF_MSG_HW, | ||||||
|  | 			   "mac: %pM is removed from %d\n", | ||||||
|  | 			   p_filter, i); | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 	if (i >= NIG_REG_LLH_FUNC_FILTER_EN_SIZE) | ||||||
|  | 		DP_NOTICE(p_hwfn, "Tried to remove a non-configured filter\n"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static int qed_set_coalesce(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, | static int qed_set_coalesce(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, | ||||||
| 			    u32 hw_addr, void *p_eth_qzone, | 			    u32 hw_addr, void *p_eth_qzone, | ||||||
| 			    size_t eth_qzone_size, u8 timeset) | 			    size_t eth_qzone_size, u8 timeset) | ||||||
|  | |||||||
| @ -309,6 +309,26 @@ int qed_fw_rss_eng(struct qed_hwfn *p_hwfn, | |||||||
| 		   u8 src_id, | 		   u8 src_id, | ||||||
| 		   u8 *dst_id); | 		   u8 *dst_id); | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief qed_llh_add_mac_filter - configures a MAC filter in llh | ||||||
|  |  * | ||||||
|  |  * @param p_hwfn | ||||||
|  |  * @param p_ptt | ||||||
|  |  * @param p_filter - MAC to add | ||||||
|  |  */ | ||||||
|  | int qed_llh_add_mac_filter(struct qed_hwfn *p_hwfn, | ||||||
|  | 			   struct qed_ptt *p_ptt, u8 *p_filter); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief qed_llh_remove_mac_filter - removes a MAC filter from llh | ||||||
|  |  * | ||||||
|  |  * @param p_hwfn | ||||||
|  |  * @param p_ptt | ||||||
|  |  * @param p_filter - MAC to remove | ||||||
|  |  */ | ||||||
|  | void qed_llh_remove_mac_filter(struct qed_hwfn *p_hwfn, | ||||||
|  | 			       struct qed_ptt *p_ptt, u8 *p_filter); | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * *@brief Cleanup of previous driver remains prior to load |  * *@brief Cleanup of previous driver remains prior to load | ||||||
|  * |  * | ||||||
|  | |||||||
							
								
								
									
										1699
									
								
								drivers/net/ethernet/qlogic/qed/qed_ll2.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1699
									
								
								drivers/net/ethernet/qlogic/qed/qed_ll2.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										289
									
								
								drivers/net/ethernet/qlogic/qed/qed_ll2.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										289
									
								
								drivers/net/ethernet/qlogic/qed/qed_ll2.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,289 @@ | |||||||
|  | /* QLogic qed NIC Driver
 | ||||||
|  |  * | ||||||
|  |  * Copyright (c) 2015 QLogic Corporation | ||||||
|  |  * | ||||||
|  |  * This software is available under the terms of the GNU General Public License | ||||||
|  |  * (GPL) Version 2, available from the file COPYING in the main directory of | ||||||
|  |  * this source tree. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #ifndef _QED_LL2_H | ||||||
|  | #define _QED_LL2_H | ||||||
|  | 
 | ||||||
|  | #include <linux/types.h> | ||||||
|  | #include <linux/kernel.h> | ||||||
|  | #include <linux/list.h> | ||||||
|  | #include <linux/mutex.h> | ||||||
|  | #include <linux/slab.h> | ||||||
|  | #include <linux/spinlock.h> | ||||||
|  | #include <linux/qed/qed_chain.h> | ||||||
|  | #include <linux/qed/qed_ll2_if.h> | ||||||
|  | #include "qed.h" | ||||||
|  | #include "qed_hsi.h" | ||||||
|  | #include "qed_sp.h" | ||||||
|  | 
 | ||||||
|  | #define QED_MAX_NUM_OF_LL2_CONNECTIONS                    (4) | ||||||
|  | 
 | ||||||
|  | enum qed_ll2_conn_type { | ||||||
|  | 	QED_LL2_TYPE_RESERVED, | ||||||
|  | 	QED_LL2_TYPE_ISCSI, | ||||||
|  | 	QED_LL2_TYPE_TEST, | ||||||
|  | 	QED_LL2_TYPE_ISCSI_OOO, | ||||||
|  | 	QED_LL2_TYPE_RESERVED2, | ||||||
|  | 	QED_LL2_TYPE_ROCE, | ||||||
|  | 	QED_LL2_TYPE_RESERVED3, | ||||||
|  | 	MAX_QED_LL2_RX_CONN_TYPE | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct qed_ll2_rx_packet { | ||||||
|  | 	struct list_head list_entry; | ||||||
|  | 	struct core_rx_bd_with_buff_len *rxq_bd; | ||||||
|  | 	dma_addr_t rx_buf_addr; | ||||||
|  | 	u16 buf_length; | ||||||
|  | 	void *cookie; | ||||||
|  | 	u8 placement_offset; | ||||||
|  | 	u16 parse_flags; | ||||||
|  | 	u16 packet_length; | ||||||
|  | 	u16 vlan; | ||||||
|  | 	u32 opaque_data[2]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct qed_ll2_tx_packet { | ||||||
|  | 	struct list_head list_entry; | ||||||
|  | 	u16 bd_used; | ||||||
|  | 	u16 vlan; | ||||||
|  | 	u16 l4_hdr_offset_w; | ||||||
|  | 	u8 bd_flags; | ||||||
|  | 	bool notify_fw; | ||||||
|  | 	void *cookie; | ||||||
|  | 
 | ||||||
|  | 	struct { | ||||||
|  | 		struct core_tx_bd *txq_bd; | ||||||
|  | 		dma_addr_t tx_frag; | ||||||
|  | 		u16 frag_len; | ||||||
|  | 	} bds_set[ETH_TX_MAX_BDS_PER_NON_LSO_PACKET]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct qed_ll2_rx_queue { | ||||||
|  | 	/* Lock protecting the Rx queue manipulation */ | ||||||
|  | 	spinlock_t lock; | ||||||
|  | 	struct qed_chain rxq_chain; | ||||||
|  | 	struct qed_chain rcq_chain; | ||||||
|  | 	u8 rx_sb_index; | ||||||
|  | 	bool b_cb_registred; | ||||||
|  | 	__le16 *p_fw_cons; | ||||||
|  | 	struct list_head active_descq; | ||||||
|  | 	struct list_head free_descq; | ||||||
|  | 	struct list_head posting_descq; | ||||||
|  | 	struct qed_ll2_rx_packet *descq_array; | ||||||
|  | 	void __iomem *set_prod_addr; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct qed_ll2_tx_queue { | ||||||
|  | 	/* Lock protecting the Tx queue manipulation */ | ||||||
|  | 	spinlock_t lock; | ||||||
|  | 	struct qed_chain txq_chain; | ||||||
|  | 	u8 tx_sb_index; | ||||||
|  | 	bool b_cb_registred; | ||||||
|  | 	__le16 *p_fw_cons; | ||||||
|  | 	struct list_head active_descq; | ||||||
|  | 	struct list_head free_descq; | ||||||
|  | 	struct list_head sending_descq; | ||||||
|  | 	struct qed_ll2_tx_packet *descq_array; | ||||||
|  | 	struct qed_ll2_tx_packet *cur_send_packet; | ||||||
|  | 	struct qed_ll2_tx_packet cur_completing_packet; | ||||||
|  | 	u16 cur_completing_bd_idx; | ||||||
|  | 	void __iomem *doorbell_addr; | ||||||
|  | 	u16 bds_idx; | ||||||
|  | 	u16 cur_send_frag_num; | ||||||
|  | 	u16 cur_completing_frag_num; | ||||||
|  | 	bool b_completing_packet; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct qed_ll2_info { | ||||||
|  | 	/* Lock protecting the state of LL2 */ | ||||||
|  | 	struct mutex mutex; | ||||||
|  | 	enum qed_ll2_conn_type conn_type; | ||||||
|  | 	u32 cid; | ||||||
|  | 	u8 my_id; | ||||||
|  | 	u8 queue_id; | ||||||
|  | 	u8 tx_stats_id; | ||||||
|  | 	bool b_active; | ||||||
|  | 	u16 mtu; | ||||||
|  | 	u8 rx_drop_ttl0_flg; | ||||||
|  | 	u8 rx_vlan_removal_en; | ||||||
|  | 	u8 tx_tc; | ||||||
|  | 	enum core_tx_dest tx_dest; | ||||||
|  | 	enum core_error_handle ai_err_packet_too_big; | ||||||
|  | 	enum core_error_handle ai_err_no_buf; | ||||||
|  | 	u8 tx_stats_en; | ||||||
|  | 	struct qed_ll2_rx_queue rx_queue; | ||||||
|  | 	struct qed_ll2_tx_queue tx_queue; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief qed_ll2_acquire_connection - allocate resources, | ||||||
|  |  *        starts rx & tx (if relevant) queues pair. Provides | ||||||
|  |  *        connecion handler as output parameter. | ||||||
|  |  * | ||||||
|  |  * @param p_hwfn | ||||||
|  |  * @param p_params		Contain various configuration properties | ||||||
|  |  * @param rx_num_desc | ||||||
|  |  * @param tx_num_desc | ||||||
|  |  * | ||||||
|  |  * @param p_connection_handle  Output container for LL2 connection's handle | ||||||
|  |  * | ||||||
|  |  * @return 0 on success, failure otherwise | ||||||
|  |  */ | ||||||
|  | int qed_ll2_acquire_connection(struct qed_hwfn *p_hwfn, | ||||||
|  | 			       struct qed_ll2_info *p_params, | ||||||
|  | 			       u16 rx_num_desc, | ||||||
|  | 			       u16 tx_num_desc, | ||||||
|  | 			       u8 *p_connection_handle); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief qed_ll2_establish_connection - start previously | ||||||
|  |  *        allocated LL2 queues pair | ||||||
|  |  * | ||||||
|  |  * @param p_hwfn | ||||||
|  |  * @param p_ptt | ||||||
|  |  * @param connection_handle	LL2 connection's handle obtained from | ||||||
|  |  *                              qed_ll2_require_connection | ||||||
|  |  * | ||||||
|  |  * @return 0 on success, failure otherwise | ||||||
|  |  */ | ||||||
|  | int qed_ll2_establish_connection(struct qed_hwfn *p_hwfn, u8 connection_handle); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief qed_ll2_post_rx_buffers - submit buffers to LL2 Rx queue. | ||||||
|  |  * | ||||||
|  |  * @param p_hwfn | ||||||
|  |  * @param connection_handle	LL2 connection's handle obtained from | ||||||
|  |  *				qed_ll2_require_connection | ||||||
|  |  * @param addr			rx (physical address) buffers to submit | ||||||
|  |  * @param cookie | ||||||
|  |  * @param notify_fw		produce corresponding Rx BD immediately | ||||||
|  |  * | ||||||
|  |  * @return 0 on success, failure otherwise | ||||||
|  |  */ | ||||||
|  | int qed_ll2_post_rx_buffer(struct qed_hwfn *p_hwfn, | ||||||
|  | 			   u8 connection_handle, | ||||||
|  | 			   dma_addr_t addr, | ||||||
|  | 			   u16 buf_len, void *cookie, u8 notify_fw); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief qed_ll2_prepare_tx_packet - request for start Tx BD | ||||||
|  |  *				      to prepare Tx packet submission to FW. | ||||||
|  |  * | ||||||
|  |  * @param p_hwfn | ||||||
|  |  * @param connection_handle	LL2 connection's handle obtained from | ||||||
|  |  *				qed_ll2_require_connection | ||||||
|  |  * @param num_of_bds		a number of requested BD equals a number of | ||||||
|  |  *				fragments in Tx packet | ||||||
|  |  * @param vlan			VLAN to insert to packet (if insertion set) | ||||||
|  |  * @param bd_flags | ||||||
|  |  * @param l4_hdr_offset_w	L4 Header Offset from start of packet | ||||||
|  |  *				(in words). This is needed if both l4_csum | ||||||
|  |  *				and ipv6_ext are set | ||||||
|  |  * @param first_frag | ||||||
|  |  * @param first_frag_len | ||||||
|  |  * @param cookie | ||||||
|  |  * | ||||||
|  |  * @param notify_fw | ||||||
|  |  * | ||||||
|  |  * @return 0 on success, failure otherwise | ||||||
|  |  */ | ||||||
|  | int qed_ll2_prepare_tx_packet(struct qed_hwfn *p_hwfn, | ||||||
|  | 			      u8 connection_handle, | ||||||
|  | 			      u8 num_of_bds, | ||||||
|  | 			      u16 vlan, | ||||||
|  | 			      u8 bd_flags, | ||||||
|  | 			      u16 l4_hdr_offset_w, | ||||||
|  | 			      dma_addr_t first_frag, | ||||||
|  | 			      u16 first_frag_len, void *cookie, u8 notify_fw); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief qed_ll2_release_connection -	releases resources | ||||||
|  |  *					allocated for LL2 connection | ||||||
|  |  * | ||||||
|  |  * @param p_hwfn | ||||||
|  |  * @param connection_handle		LL2 connection's handle obtained from | ||||||
|  |  *					qed_ll2_require_connection | ||||||
|  |  */ | ||||||
|  | void qed_ll2_release_connection(struct qed_hwfn *p_hwfn, u8 connection_handle); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief qed_ll2_set_fragment_of_tx_packet -	provides fragments to fill | ||||||
|  |  *						Tx BD of BDs requested by | ||||||
|  |  *						qed_ll2_prepare_tx_packet | ||||||
|  |  * | ||||||
|  |  * @param p_hwfn | ||||||
|  |  * @param connection_handle			LL2 connection's handle | ||||||
|  |  *						obtained from | ||||||
|  |  *						qed_ll2_require_connection | ||||||
|  |  * @param addr | ||||||
|  |  * @param nbytes | ||||||
|  |  * | ||||||
|  |  * @return 0 on success, failure otherwise | ||||||
|  |  */ | ||||||
|  | int qed_ll2_set_fragment_of_tx_packet(struct qed_hwfn *p_hwfn, | ||||||
|  | 				      u8 connection_handle, | ||||||
|  | 				      dma_addr_t addr, u16 nbytes); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief qed_ll2_terminate_connection -	stops Tx/Rx queues | ||||||
|  |  * | ||||||
|  |  * | ||||||
|  |  * @param p_hwfn | ||||||
|  |  * @param connection_handle			LL2 connection's handle | ||||||
|  |  *						obtained from | ||||||
|  |  *						qed_ll2_require_connection | ||||||
|  |  * | ||||||
|  |  * @return 0 on success, failure otherwise | ||||||
|  |  */ | ||||||
|  | int qed_ll2_terminate_connection(struct qed_hwfn *p_hwfn, u8 connection_handle); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief qed_ll2_get_stats -	get LL2 queue's statistics | ||||||
|  |  * | ||||||
|  |  * | ||||||
|  |  * @param p_hwfn | ||||||
|  |  * @param connection_handle	LL2 connection's handle obtained from | ||||||
|  |  *				qed_ll2_require_connection | ||||||
|  |  * @param p_stats | ||||||
|  |  * | ||||||
|  |  * @return 0 on success, failure otherwise | ||||||
|  |  */ | ||||||
|  | int qed_ll2_get_stats(struct qed_hwfn *p_hwfn, | ||||||
|  | 		      u8 connection_handle, struct qed_ll2_stats *p_stats); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief qed_ll2_alloc - Allocates LL2 connections set | ||||||
|  |  * | ||||||
|  |  * @param p_hwfn | ||||||
|  |  * | ||||||
|  |  * @return pointer to alocated qed_ll2_info or NULL | ||||||
|  |  */ | ||||||
|  | struct qed_ll2_info *qed_ll2_alloc(struct qed_hwfn *p_hwfn); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief qed_ll2_setup - Inits LL2 connections set | ||||||
|  |  * | ||||||
|  |  * @param p_hwfn | ||||||
|  |  * @param p_ll2_connections | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  | void qed_ll2_setup(struct qed_hwfn *p_hwfn, | ||||||
|  | 		   struct qed_ll2_info *p_ll2_connections); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief qed_ll2_free - Releases LL2 connections set | ||||||
|  |  * | ||||||
|  |  * @param p_hwfn | ||||||
|  |  * @param p_ll2_connections | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  | void qed_ll2_free(struct qed_hwfn *p_hwfn, | ||||||
|  | 		  struct qed_ll2_info *p_ll2_connections); | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
| @ -22,11 +22,13 @@ | |||||||
| #include <linux/etherdevice.h> | #include <linux/etherdevice.h> | ||||||
| #include <linux/vmalloc.h> | #include <linux/vmalloc.h> | ||||||
| #include <linux/qed/qed_if.h> | #include <linux/qed/qed_if.h> | ||||||
|  | #include <linux/qed/qed_ll2_if.h> | ||||||
| 
 | 
 | ||||||
| #include "qed.h" | #include "qed.h" | ||||||
| #include "qed_sriov.h" | #include "qed_sriov.h" | ||||||
| #include "qed_sp.h" | #include "qed_sp.h" | ||||||
| #include "qed_dev_api.h" | #include "qed_dev_api.h" | ||||||
|  | #include "qed_ll2.h" | ||||||
| #include "qed_mcp.h" | #include "qed_mcp.h" | ||||||
| #include "qed_hw.h" | #include "qed_hw.h" | ||||||
| #include "qed_selftest.h" | #include "qed_selftest.h" | ||||||
| @ -608,7 +610,16 @@ static int qed_nic_reset(struct qed_dev *cdev) | |||||||
| 
 | 
 | ||||||
| static int qed_nic_setup(struct qed_dev *cdev) | static int qed_nic_setup(struct qed_dev *cdev) | ||||||
| { | { | ||||||
| 	int rc; | 	int rc, i; | ||||||
|  | 
 | ||||||
|  | 	/* Determine if interface is going to require LL2 */ | ||||||
|  | 	if (QED_LEADING_HWFN(cdev)->hw_info.personality != QED_PCI_ETH) { | ||||||
|  | 		for (i = 0; i < cdev->num_hwfns; i++) { | ||||||
|  | 			struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; | ||||||
|  | 
 | ||||||
|  | 			p_hwfn->using_ll2 = true; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	rc = qed_resc_alloc(cdev); | 	rc = qed_resc_alloc(cdev); | ||||||
| 	if (rc) | 	if (rc) | ||||||
| @ -873,6 +884,12 @@ static int qed_slowpath_start(struct qed_dev *cdev, | |||||||
| 	DP_INFO(cdev, | 	DP_INFO(cdev, | ||||||
| 		"HW initialization and function start completed successfully\n"); | 		"HW initialization and function start completed successfully\n"); | ||||||
| 
 | 
 | ||||||
|  | 	/* Allocate LL2 interface if needed */ | ||||||
|  | 	if (QED_LEADING_HWFN(cdev)->using_ll2) { | ||||||
|  | 		rc = qed_ll2_alloc_if(cdev); | ||||||
|  | 		if (rc) | ||||||
|  | 			goto err3; | ||||||
|  | 	} | ||||||
| 	if (IS_PF(cdev)) { | 	if (IS_PF(cdev)) { | ||||||
| 		hwfn = QED_LEADING_HWFN(cdev); | 		hwfn = QED_LEADING_HWFN(cdev); | ||||||
| 		drv_version.version = (params->drv_major << 24) | | 		drv_version.version = (params->drv_major << 24) | | ||||||
| @ -893,6 +910,8 @@ static int qed_slowpath_start(struct qed_dev *cdev, | |||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| 
 | 
 | ||||||
|  | err3: | ||||||
|  | 	qed_hw_stop(cdev); | ||||||
| err2: | err2: | ||||||
| 	qed_hw_timers_stop_all(cdev); | 	qed_hw_timers_stop_all(cdev); | ||||||
| 	if (IS_PF(cdev)) | 	if (IS_PF(cdev)) | ||||||
| @ -915,6 +934,8 @@ static int qed_slowpath_stop(struct qed_dev *cdev) | |||||||
| 	if (!cdev) | 	if (!cdev) | ||||||
| 		return -ENODEV; | 		return -ENODEV; | ||||||
| 
 | 
 | ||||||
|  | 	qed_ll2_dealloc_if(cdev); | ||||||
|  | 
 | ||||||
| 	if (IS_PF(cdev)) { | 	if (IS_PF(cdev)) { | ||||||
| 		qed_free_stream_mem(cdev); | 		qed_free_stream_mem(cdev); | ||||||
| 		if (IS_QED_ETH_IF(cdev)) | 		if (IS_QED_ETH_IF(cdev)) | ||||||
|  | |||||||
| @ -208,6 +208,26 @@ | |||||||
| 	0x50196cUL | 	0x50196cUL | ||||||
| #define NIG_REG_LLH_CLS_TYPE_DUALMODE \ | #define NIG_REG_LLH_CLS_TYPE_DUALMODE \ | ||||||
| 	0x501964UL | 	0x501964UL | ||||||
|  | #define NIG_REG_LLH_FUNC_FILTER_VALUE \ | ||||||
|  | 	0x501a00UL | ||||||
|  | #define NIG_REG_LLH_FUNC_FILTER_VALUE_SIZE \ | ||||||
|  | 	32 | ||||||
|  | #define NIG_REG_LLH_FUNC_FILTER_EN \ | ||||||
|  | 	0x501a80UL | ||||||
|  | #define NIG_REG_LLH_FUNC_FILTER_EN_SIZE	\ | ||||||
|  | 	16 | ||||||
|  | #define NIG_REG_LLH_FUNC_FILTER_MODE \ | ||||||
|  | 	0x501ac0UL | ||||||
|  | #define NIG_REG_LLH_FUNC_FILTER_MODE_SIZE \ | ||||||
|  | 	16 | ||||||
|  | #define NIG_REG_LLH_FUNC_FILTER_PROTOCOL_TYPE \ | ||||||
|  | 	0x501b00UL | ||||||
|  | #define NIG_REG_LLH_FUNC_FILTER_PROTOCOL_TYPE_SIZE \ | ||||||
|  | 	16 | ||||||
|  | #define NIG_REG_LLH_FUNC_FILTER_HDR_SEL	\ | ||||||
|  | 	0x501b40UL | ||||||
|  | #define NIG_REG_LLH_FUNC_FILTER_HDR_SEL_SIZE \ | ||||||
|  | 	16 | ||||||
| #define  NCSI_REG_CONFIG	\ | #define  NCSI_REG_CONFIG	\ | ||||||
| 	0x040200UL | 	0x040200UL | ||||||
| #define  PBF_REG_INIT \ | #define  PBF_REG_INIT \ | ||||||
| @ -264,6 +284,8 @@ | |||||||
| 	0x1f0a1cUL | 	0x1f0a1cUL | ||||||
| #define PRS_REG_ROCE_DEST_QP_MAX_PF \ | #define PRS_REG_ROCE_DEST_QP_MAX_PF \ | ||||||
| 	0x1f0430UL | 	0x1f0430UL | ||||||
|  | #define PRS_REG_USE_LIGHT_L2 \ | ||||||
|  | 	0x1f096cUL | ||||||
| #define  PSDM_REG_ENABLE_IN1 \ | #define  PSDM_REG_ENABLE_IN1 \ | ||||||
| 	0xfa0004UL | 	0xfa0004UL | ||||||
| #define  PSEM_REG_ENABLE_IN \ | #define  PSEM_REG_ENABLE_IN \ | ||||||
|  | |||||||
| @ -61,6 +61,10 @@ union ramrod_data { | |||||||
| 	struct vport_start_ramrod_data vport_start; | 	struct vport_start_ramrod_data vport_start; | ||||||
| 	struct vport_stop_ramrod_data vport_stop; | 	struct vport_stop_ramrod_data vport_stop; | ||||||
| 	struct vport_update_ramrod_data vport_update; | 	struct vport_update_ramrod_data vport_update; | ||||||
|  | 	struct core_rx_start_ramrod_data core_rx_queue_start; | ||||||
|  | 	struct core_rx_stop_ramrod_data core_rx_queue_stop; | ||||||
|  | 	struct core_tx_start_ramrod_data core_tx_queue_start; | ||||||
|  | 	struct core_tx_stop_ramrod_data core_tx_queue_stop; | ||||||
| 	struct vport_filter_update_ramrod_data vport_filter_update; | 	struct vport_filter_update_ramrod_data vport_filter_update; | ||||||
| 
 | 
 | ||||||
| 	struct rdma_init_func_ramrod_data rdma_init_func; | 	struct rdma_init_func_ramrod_data rdma_init_func; | ||||||
|  | |||||||
| @ -627,6 +627,7 @@ enum DP_MODULE { | |||||||
| 	QED_MSG_SP	= 0x100000, | 	QED_MSG_SP	= 0x100000, | ||||||
| 	QED_MSG_STORAGE = 0x200000, | 	QED_MSG_STORAGE = 0x200000, | ||||||
| 	QED_MSG_CXT	= 0x800000, | 	QED_MSG_CXT	= 0x800000, | ||||||
|  | 	QED_MSG_LL2	= 0x1000000, | ||||||
| 	QED_MSG_ILT	= 0x2000000, | 	QED_MSG_ILT	= 0x2000000, | ||||||
| 	QED_MSG_ROCE	= 0x4000000, | 	QED_MSG_ROCE	= 0x4000000, | ||||||
| 	QED_MSG_DEBUG	= 0x8000000, | 	QED_MSG_DEBUG	= 0x8000000, | ||||||
|  | |||||||
							
								
								
									
										139
									
								
								include/linux/qed/qed_ll2_if.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								include/linux/qed/qed_ll2_if.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,139 @@ | |||||||
|  | /* QLogic qed NIC Driver
 | ||||||
|  |  * | ||||||
|  |  * Copyright (c) 2015 QLogic Corporation | ||||||
|  |  * | ||||||
|  |  * This software is available under the terms of the GNU General Public License | ||||||
|  |  * (GPL) Version 2, available from the file COPYING in the main directory of | ||||||
|  |  * this source tree. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #ifndef _QED_LL2_IF_H | ||||||
|  | #define _QED_LL2_IF_H | ||||||
|  | 
 | ||||||
|  | #include <linux/types.h> | ||||||
|  | #include <linux/interrupt.h> | ||||||
|  | #include <linux/netdevice.h> | ||||||
|  | #include <linux/pci.h> | ||||||
|  | #include <linux/skbuff.h> | ||||||
|  | #include <linux/version.h> | ||||||
|  | #include <linux/kernel.h> | ||||||
|  | #include <linux/slab.h> | ||||||
|  | #include <linux/qed/qed_if.h> | ||||||
|  | 
 | ||||||
|  | struct qed_ll2_stats { | ||||||
|  | 	u64 gsi_invalid_hdr; | ||||||
|  | 	u64 gsi_invalid_pkt_length; | ||||||
|  | 	u64 gsi_unsupported_pkt_typ; | ||||||
|  | 	u64 gsi_crcchksm_error; | ||||||
|  | 
 | ||||||
|  | 	u64 packet_too_big_discard; | ||||||
|  | 	u64 no_buff_discard; | ||||||
|  | 
 | ||||||
|  | 	u64 rcv_ucast_bytes; | ||||||
|  | 	u64 rcv_mcast_bytes; | ||||||
|  | 	u64 rcv_bcast_bytes; | ||||||
|  | 	u64 rcv_ucast_pkts; | ||||||
|  | 	u64 rcv_mcast_pkts; | ||||||
|  | 	u64 rcv_bcast_pkts; | ||||||
|  | 
 | ||||||
|  | 	u64 sent_ucast_bytes; | ||||||
|  | 	u64 sent_mcast_bytes; | ||||||
|  | 	u64 sent_bcast_bytes; | ||||||
|  | 	u64 sent_ucast_pkts; | ||||||
|  | 	u64 sent_mcast_pkts; | ||||||
|  | 	u64 sent_bcast_pkts; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #define QED_LL2_UNUSED_HANDLE   (0xff) | ||||||
|  | 
 | ||||||
|  | struct qed_ll2_cb_ops { | ||||||
|  | 	int (*rx_cb)(void *, struct sk_buff *, u32, u32); | ||||||
|  | 	int (*tx_cb)(void *, struct sk_buff *, bool); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct qed_ll2_params { | ||||||
|  | 	u16 mtu; | ||||||
|  | 	bool drop_ttl0_packets; | ||||||
|  | 	bool rx_vlan_stripping; | ||||||
|  | 	u8 tx_tc; | ||||||
|  | 	bool frags_mapped; | ||||||
|  | 	u8 ll2_mac_address[ETH_ALEN]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct qed_ll2_ops { | ||||||
|  | /**
 | ||||||
|  |  * @brief start - initializes ll2 | ||||||
|  |  * | ||||||
|  |  * @param cdev | ||||||
|  |  * @param params - protocol driver configuration for the ll2. | ||||||
|  |  * | ||||||
|  |  * @return 0 on success, otherwise error value. | ||||||
|  |  */ | ||||||
|  | 	int (*start)(struct qed_dev *cdev, struct qed_ll2_params *params); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief stop - stops the ll2 | ||||||
|  |  * | ||||||
|  |  * @param cdev | ||||||
|  |  * | ||||||
|  |  * @return 0 on success, otherwise error value. | ||||||
|  |  */ | ||||||
|  | 	int (*stop)(struct qed_dev *cdev); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief start_xmit - transmits an skb over the ll2 interface | ||||||
|  |  * | ||||||
|  |  * @param cdev | ||||||
|  |  * @param skb | ||||||
|  |  * | ||||||
|  |  * @return 0 on success, otherwise error value. | ||||||
|  |  */ | ||||||
|  | 	int (*start_xmit)(struct qed_dev *cdev, struct sk_buff *skb); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief register_cb_ops - protocol driver register the callback for Rx/Tx | ||||||
|  |  * packets. Should be called before `start'. | ||||||
|  |  * | ||||||
|  |  * @param cdev | ||||||
|  |  * @param cookie - to be passed to the callback functions. | ||||||
|  |  * @param ops - the callback functions to register for Rx / Tx. | ||||||
|  |  * | ||||||
|  |  * @return 0 on success, otherwise error value. | ||||||
|  |  */ | ||||||
|  | 	void (*register_cb_ops)(struct qed_dev *cdev, | ||||||
|  | 				const struct qed_ll2_cb_ops *ops, | ||||||
|  | 				void *cookie); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief get LL2 related statistics | ||||||
|  |  * | ||||||
|  |  * @param cdev | ||||||
|  |  * @param stats - pointer to struct that would be filled with stats | ||||||
|  |  * | ||||||
|  |  * @return 0 on success, error otherwise. | ||||||
|  |  */ | ||||||
|  | 	int (*get_stats)(struct qed_dev *cdev, struct qed_ll2_stats *stats); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #ifdef CONFIG_QED_LL2 | ||||||
|  | int qed_ll2_alloc_if(struct qed_dev *); | ||||||
|  | void qed_ll2_dealloc_if(struct qed_dev *); | ||||||
|  | #else | ||||||
|  | static const struct qed_ll2_ops qed_ll2_ops_pass = { | ||||||
|  | 	.start = NULL, | ||||||
|  | 	.stop = NULL, | ||||||
|  | 	.start_xmit = NULL, | ||||||
|  | 	.register_cb_ops = NULL, | ||||||
|  | 	.get_stats = NULL, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static inline int qed_ll2_alloc_if(struct qed_dev *cdev) | ||||||
|  | { | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline void qed_ll2_dealloc_if(struct qed_dev *cdev) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user