|  | /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ | 
|  | /* QLogic qed NIC Driver | 
|  | * Copyright (c) 2015-2017  QLogic Corporation | 
|  | * Copyright (c) 2019-2020 Marvell International Ltd. | 
|  | */ | 
|  |  | 
|  | #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/kernel.h> | 
|  | #include <linux/slab.h> | 
|  | #include <linux/qed/qed_if.h> | 
|  |  | 
|  | enum qed_ll2_conn_type { | 
|  | QED_LL2_TYPE_FCOE, | 
|  | QED_LL2_TYPE_TCP_ULP, | 
|  | 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_CONN_TYPE | 
|  | }; | 
|  |  | 
|  | enum qed_ll2_rx_conn_type { | 
|  | QED_LL2_RX_TYPE_LEGACY, | 
|  | QED_LL2_RX_TYPE_CTX, | 
|  | 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_rx_conn_type rx_conn_type; | 
|  | 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; | 
|  | bool remove_stag; | 
|  | }; | 
|  |  | 
|  | #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]; | 
|  | }; | 
|  |  | 
|  | enum qed_ll2_xmit_flags { | 
|  | /* FIP discovery packet */ | 
|  | QED_LL2_XMIT_FLAGS_FIP_DISCOVERY | 
|  | }; | 
|  |  | 
|  | 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 | 
|  | * @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, | 
|  | unsigned long xmit_flags); | 
|  |  | 
|  | /** | 
|  | * @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 |