mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 01:10:04 +00:00
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
13 changed files with 2334 additions and 3 deletions
|
@ -88,6 +88,14 @@ config QED
|
|||
---help---
|
||||
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
|
||||
bool "QLogic QED 25/40/100Gb SR-IOV support"
|
||||
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_selftest.o qed_dcbx.o qed_debug.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_cxt_mngr;
|
||||
struct qed_sb_sp_info;
|
||||
struct qed_ll2_info;
|
||||
struct qed_mcp_info;
|
||||
|
||||
struct qed_rt_data {
|
||||
|
@ -152,6 +153,7 @@ enum QED_RESOURCES {
|
|||
QED_MAC,
|
||||
QED_VLAN,
|
||||
QED_ILT,
|
||||
QED_LL2_QUEUE,
|
||||
QED_MAX_RESC,
|
||||
};
|
||||
|
||||
|
@ -360,6 +362,8 @@ struct qed_hwfn {
|
|||
struct qed_sb_attn_info *p_sb_attn;
|
||||
|
||||
/* Protocol related */
|
||||
bool using_ll2;
|
||||
struct qed_ll2_info *p_ll2_info;
|
||||
struct qed_pf_params pf_params;
|
||||
|
||||
bool b_rdma_enabled_in_prs;
|
||||
|
@ -564,6 +568,11 @@ struct qed_dev {
|
|||
|
||||
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;
|
||||
};
|
||||
|
||||
|
|
|
@ -1839,6 +1839,8 @@ int qed_cxt_set_pf_params(struct qed_hwfn *p_hwfn)
|
|||
/* Set the number of required CORE connections */
|
||||
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);
|
||||
|
||||
switch (p_hwfn->hw_info.personality) {
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "qed_hw.h"
|
||||
#include "qed_init_ops.h"
|
||||
#include "qed_int.h"
|
||||
#include "qed_ll2.h"
|
||||
#include "qed_mcp.h"
|
||||
#include "qed_reg_addr.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_consq_free(p_hwfn, p_hwfn->p_consq);
|
||||
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_dmae_info_free(p_hwfn);
|
||||
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)
|
||||
{
|
||||
#ifdef CONFIG_QED_LL2
|
||||
struct qed_ll2_info *p_ll2_info;
|
||||
#endif
|
||||
struct qed_consq *p_consq;
|
||||
struct qed_eq *p_eq;
|
||||
int i, rc = 0;
|
||||
|
@ -513,6 +520,15 @@ int qed_resc_alloc(struct qed_dev *cdev)
|
|||
goto alloc_no_mem;
|
||||
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 */
|
||||
rc = qed_dmae_info_alloc(p_hwfn);
|
||||
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_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*/) /
|
||||
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++)
|
||||
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"
|
||||
"MAC = %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_start[QED_SB],
|
||||
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_start[QED_VLAN],
|
||||
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;
|
||||
}
|
||||
|
@ -2133,6 +2157,98 @@ int qed_fw_rss_eng(struct qed_hwfn *p_hwfn, u8 src_id, u8 *dst_id)
|
|||
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,
|
||||
u32 hw_addr, void *p_eth_qzone,
|
||||
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 *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
|
||||
*
|
||||
|
|
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/vmalloc.h>
|
||||
#include <linux/qed/qed_if.h>
|
||||
#include <linux/qed/qed_ll2_if.h>
|
||||
|
||||
#include "qed.h"
|
||||
#include "qed_sriov.h"
|
||||
#include "qed_sp.h"
|
||||
#include "qed_dev_api.h"
|
||||
#include "qed_ll2.h"
|
||||
#include "qed_mcp.h"
|
||||
#include "qed_hw.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)
|
||||
{
|
||||
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);
|
||||
if (rc)
|
||||
|
@ -873,6 +884,12 @@ static int qed_slowpath_start(struct qed_dev *cdev,
|
|||
DP_INFO(cdev,
|
||||
"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)) {
|
||||
hwfn = QED_LEADING_HWFN(cdev);
|
||||
drv_version.version = (params->drv_major << 24) |
|
||||
|
@ -893,6 +910,8 @@ static int qed_slowpath_start(struct qed_dev *cdev,
|
|||
|
||||
return 0;
|
||||
|
||||
err3:
|
||||
qed_hw_stop(cdev);
|
||||
err2:
|
||||
qed_hw_timers_stop_all(cdev);
|
||||
if (IS_PF(cdev))
|
||||
|
@ -915,6 +934,8 @@ static int qed_slowpath_stop(struct qed_dev *cdev)
|
|||
if (!cdev)
|
||||
return -ENODEV;
|
||||
|
||||
qed_ll2_dealloc_if(cdev);
|
||||
|
||||
if (IS_PF(cdev)) {
|
||||
qed_free_stream_mem(cdev);
|
||||
if (IS_QED_ETH_IF(cdev))
|
||||
|
|
|
@ -208,6 +208,26 @@
|
|||
0x50196cUL
|
||||
#define NIG_REG_LLH_CLS_TYPE_DUALMODE \
|
||||
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 \
|
||||
0x040200UL
|
||||
#define PBF_REG_INIT \
|
||||
|
@ -264,6 +284,8 @@
|
|||
0x1f0a1cUL
|
||||
#define PRS_REG_ROCE_DEST_QP_MAX_PF \
|
||||
0x1f0430UL
|
||||
#define PRS_REG_USE_LIGHT_L2 \
|
||||
0x1f096cUL
|
||||
#define PSDM_REG_ENABLE_IN1 \
|
||||
0xfa0004UL
|
||||
#define PSEM_REG_ENABLE_IN \
|
||||
|
|
|
@ -61,6 +61,10 @@ union ramrod_data {
|
|||
struct vport_start_ramrod_data vport_start;
|
||||
struct vport_stop_ramrod_data vport_stop;
|
||||
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 rdma_init_func_ramrod_data rdma_init_func;
|
||||
|
|
|
@ -627,6 +627,7 @@ enum DP_MODULE {
|
|||
QED_MSG_SP = 0x100000,
|
||||
QED_MSG_STORAGE = 0x200000,
|
||||
QED_MSG_CXT = 0x800000,
|
||||
QED_MSG_LL2 = 0x1000000,
|
||||
QED_MSG_ILT = 0x2000000,
|
||||
QED_MSG_ROCE = 0x4000000,
|
||||
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 a new issue