blob: 266c1fb4538756a03b88ae39c0c54368991e704d [file] [log] [blame]
/* QLogic qed NIC Driver
* Copyright (c) 2015-2017 QLogic Corporation
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed 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, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and /or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#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>
enum qed_ll2_conn_type {
QED_LL2_TYPE_FCOE,
QED_LL2_TYPE_ISCSI,
QED_LL2_TYPE_TEST,
QED_LL2_TYPE_OOO,
QED_LL2_TYPE_RESERVED2,
QED_LL2_TYPE_ROCE,
QED_LL2_TYPE_IWARP,
QED_LL2_TYPE_RESERVED3,
MAX_QED_LL2_RX_CONN_TYPE
};
enum qed_ll2_roce_flavor_type {
QED_LL2_ROCE,
QED_LL2_RROCE,
MAX_QED_LL2_ROCE_FLAVOR_TYPE
};
enum qed_ll2_tx_dest {
QED_LL2_TX_DEST_NW, /* Light L2 TX Destination to the Network */
QED_LL2_TX_DEST_LB, /* Light L2 TX Destination to the Loopback */
QED_LL2_TX_DEST_DROP, /* Light L2 Drop the TX packet */
QED_LL2_TX_DEST_MAX
};
enum qed_ll2_error_handle {
QED_LL2_DROP_PACKET,
QED_LL2_DO_NOTHING,
QED_LL2_ASSERT,
};
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;
};
struct qed_ll2_comp_rx_data {
void *cookie;
dma_addr_t rx_buf_addr;
u16 parse_flags;
u16 err_flags;
u16 vlan;
bool b_last_packet;
u8 connection_handle;
union {
u16 packet_length;
u16 data_length;
} length;
u32 opaque_data_0;
u32 opaque_data_1;
/* GSI only */
u32 src_qp;
u16 qp_id;
union {
u8 placement_offset;
u8 data_length_error;
} u;
};
typedef
void (*qed_ll2_complete_rx_packet_cb)(void *cxt,
struct qed_ll2_comp_rx_data *data);
typedef
void (*qed_ll2_release_rx_packet_cb)(void *cxt,
u8 connection_handle,
void *cookie,
dma_addr_t rx_buf_addr,
bool b_last_packet);
typedef
void (*qed_ll2_complete_tx_packet_cb)(void *cxt,
u8 connection_handle,
void *cookie,
dma_addr_t first_frag_addr,
bool b_last_fragment,
bool b_last_packet);
typedef
void (*qed_ll2_release_tx_packet_cb)(void *cxt,
u8 connection_handle,
void *cookie,
dma_addr_t first_frag_addr,
bool b_last_fragment, bool b_last_packet);
typedef
void (*qed_ll2_slowpath_cb)(void *cxt, u8 connection_handle,
u32 opaque_data_0, u32 opaque_data_1);
struct qed_ll2_cbs {
qed_ll2_complete_rx_packet_cb rx_comp_cb;
qed_ll2_release_rx_packet_cb rx_release_cb;
qed_ll2_complete_tx_packet_cb tx_comp_cb;
qed_ll2_release_tx_packet_cb tx_release_cb;
qed_ll2_slowpath_cb slowpath_cb;
void *cookie;
};
struct qed_ll2_acquire_data_inputs {
enum qed_ll2_conn_type conn_type;
u16 mtu;
u16 rx_num_desc;
u16 rx_num_ooo_buffers;
u8 rx_drop_ttl0_flg;
u8 rx_vlan_removal_en;
u16 tx_num_desc;
u8 tx_max_bds_per_packet;
u8 tx_tc;
enum qed_ll2_tx_dest tx_dest;
enum qed_ll2_error_handle ai_err_packet_too_big;
enum qed_ll2_error_handle ai_err_no_buf;
bool secondary_queue;
u8 gsi_enable;
};
struct qed_ll2_acquire_data {
struct qed_ll2_acquire_data_inputs input;
const struct qed_ll2_cbs *cbs;
/* Output container for LL2 connection's handle */
u8 *p_connection_handle;
};
struct qed_ll2_tx_pkt_info {
void *cookie;
dma_addr_t first_frag;
enum qed_ll2_tx_dest tx_dest;
enum qed_ll2_roce_flavor_type qed_roce_flavor;
u16 vlan;
u16 l4_hdr_offset_w; /* from start of packet */
u16 first_frag_len;
u8 num_of_bds;
u8 bd_flags;
bool enable_ip_cksum;
bool enable_l4_cksum;
bool calc_ip_len;
};
#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