linux/drivers/net/ethernet/emulex/benet/be_main.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) 2005 - 2016 Broadcom
 * All rights reserved.
 *
 * Contact Information:
 * [email protected]
 *
 * Emulex
 * 3333 Susan Street
 * Costa Mesa, CA 92626
 */

#include <linux/prefetch.h>
#include <linux/module.h>
#include "be.h"
#include "be_cmds.h"
#include <asm/div64.h>
#include <linux/if_bridge.h>
#include <net/busy_poll.h>
#include <net/vxlan.h>

MODULE_DESCRIPTION();
MODULE_AUTHOR();
MODULE_LICENSE();

/* num_vfs module param is obsolete.
 * Use sysfs method to enable/disable VFs.
 */
static unsigned int num_vfs;
module_param(num_vfs, uint, 0444);
MODULE_PARM_DESC();

static ushort rx_frag_size =;
module_param(rx_frag_size, ushort, 0444);
MODULE_PARM_DESC();

/* Per-module error detection/recovery workq shared across all functions.
 * Each function schedules its own work request on this shared workq.
 */
static struct workqueue_struct *be_err_recovery_workq;

static const struct pci_device_id be_dev_ids[] =;
MODULE_DEVICE_TABLE(pci, be_dev_ids);

/* Workqueue used by all functions for defering cmd calls to the adapter */
static struct workqueue_struct *be_wq;

/* UE Status Low CSR */
static const char * const ue_status_low_desc[] =;

/* UE Status High CSR */
static const char * const ue_status_hi_desc[] =;

#define BE_VF_IF_EN_FLAGS

static void be_queue_free(struct be_adapter *adapter, struct be_queue_info *q)
{}

static int be_queue_alloc(struct be_adapter *adapter, struct be_queue_info *q,
			  u16 len, u16 entry_size)
{}

static void be_reg_intr_set(struct be_adapter *adapter, bool enable)
{}

static void be_intr_set(struct be_adapter *adapter, bool enable)
{}

static void be_rxq_notify(struct be_adapter *adapter, u16 qid, u16 posted)
{}

static void be_txq_notify(struct be_adapter *adapter, struct be_tx_obj *txo,
			  u16 posted)
{}

static void be_eq_notify(struct be_adapter *adapter, u16 qid,
			 bool arm, bool clear_int, u16 num_popped,
			 u32 eq_delay_mult_enc)
{}

void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, u16 num_popped)
{}

static int be_dev_mac_add(struct be_adapter *adapter, const u8 *mac)
{}

static void be_dev_mac_del(struct be_adapter *adapter, int pmac_id)
{}

static int be_mac_addr_set(struct net_device *netdev, void *p)
{}

/* BE2 supports only v0 cmd */
static void *hw_stats_from_cmd(struct be_adapter *adapter)
{}

/* BE2 supports only v0 cmd */
static void *be_erx_stats_from_cmd(struct be_adapter *adapter)
{}

static void populate_be_v0_stats(struct be_adapter *adapter)
{}

static void populate_be_v1_stats(struct be_adapter *adapter)
{}

static void populate_be_v2_stats(struct be_adapter *adapter)
{}

static void populate_lancer_stats(struct be_adapter *adapter)
{}

static void accumulate_16bit_val(u32 *acc, u16 val)
{}

static void populate_erx_stats(struct be_adapter *adapter,
			       struct be_rx_obj *rxo, u32 erx_stat)
{}

void be_parse_stats(struct be_adapter *adapter)
{}

static void be_get_stats64(struct net_device *netdev,
			   struct rtnl_link_stats64 *stats)
{}

void be_link_status_update(struct be_adapter *adapter, u8 link_status)
{}

static int be_gso_hdr_len(struct sk_buff *skb)
{}

static void be_tx_stats_update(struct be_tx_obj *txo, struct sk_buff *skb)
{}

/* Returns number of WRBs needed for the skb */
static u32 skb_wrb_cnt(struct sk_buff *skb)
{}

static inline void wrb_fill(struct be_eth_wrb *wrb, u64 addr, int len)
{}

/* A dummy wrb is just all zeros. Using a separate routine for dummy-wrb
 * to avoid the swap and shift/mask operations in wrb_fill().
 */
static inline void wrb_fill_dummy(struct be_eth_wrb *wrb)
{}

static inline u16 be_get_tx_vlan_tag(struct be_adapter *adapter,
				     struct sk_buff *skb)
{}

/* Used only for IP tunnel packets */
static u16 skb_inner_ip_proto(struct sk_buff *skb)
{}

static u16 skb_ip_proto(struct sk_buff *skb)
{}

static inline bool be_is_txq_full(struct be_tx_obj *txo)
{}

static inline bool be_can_txq_wake(struct be_tx_obj *txo)
{}

static inline bool be_is_tx_compl_pending(struct be_tx_obj *txo)
{}

static void be_get_wrb_params_from_skb(struct be_adapter *adapter,
				       struct sk_buff *skb,
				       struct be_wrb_params *wrb_params)
{}

static void wrb_fill_hdr(struct be_adapter *adapter,
			 struct be_eth_hdr_wrb *hdr,
			 struct be_wrb_params *wrb_params,
			 struct sk_buff *skb)
{}

static void unmap_tx_frag(struct device *dev, struct be_eth_wrb *wrb,
			  bool unmap_single)
{}

/* Grab a WRB header for xmit */
static u32 be_tx_get_wrb_hdr(struct be_tx_obj *txo)
{}

/* Set up the WRB header for xmit */
static void be_tx_setup_wrb_hdr(struct be_adapter *adapter,
				struct be_tx_obj *txo,
				struct be_wrb_params *wrb_params,
				struct sk_buff *skb, u16 head)
{}

/* Setup a WRB fragment (buffer descriptor) for xmit */
static void be_tx_setup_wrb_frag(struct be_tx_obj *txo, dma_addr_t busaddr,
				 int len)
{}

/* Bring the queue back to the state it was in before be_xmit_enqueue() routine
 * was invoked. The producer index is restored to the previous packet and the
 * WRBs of the current packet are unmapped. Invoked to handle tx setup errors.
 */
static void be_xmit_restore(struct be_adapter *adapter,
			    struct be_tx_obj *txo, u32 head, bool map_single,
			    u32 copied)
{}

/* Enqueue the given packet for transmit. This routine allocates WRBs for the
 * packet, dma maps the packet buffers and sets up the WRBs. Returns the number
 * of WRBs used up by the packet.
 */
static u32 be_xmit_enqueue(struct be_adapter *adapter, struct be_tx_obj *txo,
			   struct sk_buff *skb,
			   struct be_wrb_params *wrb_params)
{}

static inline int qnq_async_evt_rcvd(struct be_adapter *adapter)
{}

static struct sk_buff *be_insert_vlan_in_pkt(struct be_adapter *adapter,
					     struct sk_buff *skb,
					     struct be_wrb_params
					     *wrb_params)
{}

static bool be_ipv6_exthdr_check(struct sk_buff *skb)
{}

static int be_vlan_tag_tx_chk(struct be_adapter *adapter, struct sk_buff *skb)
{}

static int be_ipv6_tx_stall_chk(struct be_adapter *adapter, struct sk_buff *skb)
{}

static struct sk_buff *be_lancer_xmit_workarounds(struct be_adapter *adapter,
						  struct sk_buff *skb,
						  struct be_wrb_params
						  *wrb_params)
{}

static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter,
					   struct sk_buff *skb,
					   struct be_wrb_params *wrb_params)
{}

static void be_xmit_flush(struct be_adapter *adapter, struct be_tx_obj *txo)
{}

/* OS2BMC related */

#define DHCP_CLIENT_PORT
#define DHCP_SERVER_PORT
#define NET_BIOS_PORT1
#define NET_BIOS_PORT2
#define DHCPV6_RAS_PORT

#define is_mc_allowed_on_bmc(adapter, eh)

#define is_bc_allowed_on_bmc(adapter, eh)

#define is_arp_allowed_on_bmc(adapter, skb)

#define is_arp(skb)

#define is_arp_filt_enabled(adapter)

#define is_dhcp_client_filt_enabled(adapter)

#define is_dhcp_srvr_filt_enabled(adapter)

#define is_nbios_filt_enabled(adapter)

#define is_ipv6_na_filt_enabled(adapter)

#define is_ipv6_ra_filt_enabled(adapter)

#define is_ipv6_ras_filt_enabled(adapter)

#define is_broadcast_filt_enabled(adapter)

#define is_multicast_filt_enabled(adapter)

static bool be_send_pkt_to_bmc(struct be_adapter *adapter,
			       struct sk_buff **skb)
{}

static netdev_tx_t be_xmit(struct sk_buff *skb, struct net_device *netdev)
{}

static void be_tx_timeout(struct net_device *netdev, unsigned int txqueue)
{}

static inline bool be_in_all_promisc(struct be_adapter *adapter)
{}

static int be_set_vlan_promisc(struct be_adapter *adapter)
{}

static int be_clear_vlan_promisc(struct be_adapter *adapter)
{}

/*
 * A max of 64 (BE_NUM_VLANS_SUPPORTED) vlans can be configured in BE.
 * If the user configures more, place BE in vlan promiscuous mode.
 */
static int be_vid_config(struct be_adapter *adapter)
{}

static int be_vlan_add_vid(struct net_device *netdev, __be16 proto, u16 vid)
{}

static int be_vlan_rem_vid(struct net_device *netdev, __be16 proto, u16 vid)
{}

static void be_set_all_promisc(struct be_adapter *adapter)
{}

static void be_set_mc_promisc(struct be_adapter *adapter)
{}

static void be_set_uc_promisc(struct be_adapter *adapter)
{}

static void be_clear_uc_promisc(struct be_adapter *adapter)
{}

/* The below 2 functions are the callback args for __dev_mc_sync/dev_uc_sync().
 * We use a single callback function for both sync and unsync. We really don't
 * add/remove addresses through this callback. But, we use it to detect changes
 * to the uc/mc lists. The entire uc/mc list is programmed in be_set_rx_mode().
 */
static int be_uc_list_update(struct net_device *netdev,
			     const unsigned char *addr)
{}

static int be_mc_list_update(struct net_device *netdev,
			     const unsigned char *addr)
{}

static void be_set_mc_list(struct be_adapter *adapter)
{}

static void be_clear_mc_list(struct be_adapter *adapter)
{}

static int be_uc_mac_add(struct be_adapter *adapter, int uc_idx)
{}

static void be_uc_mac_del(struct be_adapter *adapter, int pmac_id)
{}

static void be_set_uc_list(struct be_adapter *adapter)
{}

static void be_clear_uc_list(struct be_adapter *adapter)
{}

static void __be_set_rx_mode(struct be_adapter *adapter)
{}

static void be_work_set_rx_mode(struct work_struct *work)
{}

static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
{}

static int be_get_vf_config(struct net_device *netdev, int vf,
			    struct ifla_vf_info *vi)
{}

static int be_set_vf_tvt(struct be_adapter *adapter, int vf, u16 vlan)
{}

static int be_clear_vf_tvt(struct be_adapter *adapter, int vf)
{}

static int be_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos,
			  __be16 vlan_proto)
{}

static int be_set_vf_tx_rate(struct net_device *netdev, int vf,
			     int min_tx_rate, int max_tx_rate)
{}

static int be_set_vf_link_state(struct net_device *netdev, int vf,
				int link_state)
{}

static int be_set_vf_spoofchk(struct net_device *netdev, int vf, bool enable)
{}

static void be_aic_update(struct be_aic_obj *aic, u64 rx_pkts, u64 tx_pkts,
			  ulong now)
{}

static int be_get_new_eqd(struct be_eq_obj *eqo)
{}

/* For Skyhawk-R only */
static u32 be_get_eq_delay_mult_enc(struct be_eq_obj *eqo)
{}

void be_eqd_update(struct be_adapter *adapter, bool force_update)
{}

static void be_rx_stats_update(struct be_rx_obj *rxo,
			       struct be_rx_compl_info *rxcp)
{}

static inline bool csum_passed(struct be_rx_compl_info *rxcp)
{}

static struct be_rx_page_info *get_rx_page_info(struct be_rx_obj *rxo)
{}

/* Throwaway the data in the Rx completion */
static void be_rx_compl_discard(struct be_rx_obj *rxo,
				struct be_rx_compl_info *rxcp)
{}

/*
 * skb_fill_rx_data forms a complete skb for an ether frame
 * indicated by rxcp.
 */
static void skb_fill_rx_data(struct be_rx_obj *rxo, struct sk_buff *skb,
			     struct be_rx_compl_info *rxcp)
{}

/* Process the RX completion indicated by rxcp when GRO is disabled */
static void be_rx_compl_process(struct be_rx_obj *rxo, struct napi_struct *napi,
				struct be_rx_compl_info *rxcp)
{}

/* Process the RX completion indicated by rxcp when GRO is enabled */
static void be_rx_compl_process_gro(struct be_rx_obj *rxo,
				    struct napi_struct *napi,
				    struct be_rx_compl_info *rxcp)
{}

static void be_parse_rx_compl_v1(struct be_eth_rx_compl *compl,
				 struct be_rx_compl_info *rxcp)
{}

static void be_parse_rx_compl_v0(struct be_eth_rx_compl *compl,
				 struct be_rx_compl_info *rxcp)
{}

static struct be_rx_compl_info *be_rx_compl_get(struct be_rx_obj *rxo)
{}

static inline struct page *be_alloc_pages(u32 size, gfp_t gfp)
{}

/*
 * Allocate a page, split it to fragments of size rx_frag_size and post as
 * receive buffers to BE
 */
static void be_post_rx_frags(struct be_rx_obj *rxo, gfp_t gfp, u32 frags_needed)
{}

static inline void be_update_tx_err(struct be_tx_obj *txo, u8 status)
{}

static inline void lancer_update_tx_err(struct be_tx_obj *txo, u8 status)
{}

static struct be_tx_compl_info *be_tx_compl_get(struct be_adapter *adapter,
						struct be_tx_obj *txo)
{}

static u16 be_tx_compl_process(struct be_adapter *adapter,
			       struct be_tx_obj *txo, u16 last_index)
{}

/* Return the number of events in the event queue */
static inline int events_get(struct be_eq_obj *eqo)
{}

/* Leaves the EQ is disarmed state */
static void be_eq_clean(struct be_eq_obj *eqo)
{}

/* Free posted rx buffers that were not used */
static void be_rxq_clean(struct be_rx_obj *rxo)
{}

static void be_rx_cq_clean(struct be_rx_obj *rxo)
{}

static void be_tx_compl_clean(struct be_adapter *adapter)
{}

static void be_evt_queues_destroy(struct be_adapter *adapter)
{}

static int be_evt_queues_create(struct be_adapter *adapter)
{}

static void be_mcc_queues_destroy(struct be_adapter *adapter)
{}

/* Must be called only after TX qs are created as MCC shares TX EQ */
static int be_mcc_queues_create(struct be_adapter *adapter)
{}

static void be_tx_queues_destroy(struct be_adapter *adapter)
{}

static int be_tx_qs_create(struct be_adapter *adapter)
{}

static void be_rx_cqs_destroy(struct be_adapter *adapter)
{}

static int be_rx_cqs_create(struct be_adapter *adapter)
{}

static irqreturn_t be_intx(int irq, void *dev)
{}

static irqreturn_t be_msix(int irq, void *dev)
{}

static inline bool do_gro(struct be_rx_compl_info *rxcp)
{}

static int be_process_rx(struct be_rx_obj *rxo, struct napi_struct *napi,
			 int budget)
{}


static void be_process_tx(struct be_adapter *adapter, struct be_tx_obj *txo,
			  int idx)
{}

int be_poll(struct napi_struct *napi, int budget)
{}

void be_detect_error(struct be_adapter *adapter)
{}

static void be_msix_disable(struct be_adapter *adapter)
{}

static int be_msix_enable(struct be_adapter *adapter)
{}

static inline int be_msix_vec_get(struct be_adapter *adapter,
				  struct be_eq_obj *eqo)
{}

static int be_msix_register(struct be_adapter *adapter)
{}

static int be_irq_register(struct be_adapter *adapter)
{}

static void be_irq_unregister(struct be_adapter *adapter)
{}

static void be_rx_qs_destroy(struct be_adapter *adapter)
{}

static void be_disable_if_filters(struct be_adapter *adapter)
{}

static int be_close(struct net_device *netdev)
{}

static int be_rx_qs_create(struct be_adapter *adapter)
{}

static int be_enable_if_filters(struct be_adapter *adapter)
{}

static int be_open(struct net_device *netdev)
{}

static void be_vf_eth_addr_generate(struct be_adapter *adapter, u8 *mac)
{}

/*
 * Generate a seed MAC address from the PF MAC Address using jhash.
 * MAC Address for VFs are assigned incrementally starting from the seed.
 * These addresses are programmed in the ASIC by the PF and the VF driver
 * queries for the MAC address during its probe.
 */
static int be_vf_eth_addr_config(struct be_adapter *adapter)
{}

static int be_vfs_mac_query(struct be_adapter *adapter)
{}

static void be_vf_clear(struct be_adapter *adapter)
{}

static void be_clear_queues(struct be_adapter *adapter)
{}

static void be_cancel_worker(struct be_adapter *adapter)
{}

static void be_cancel_err_detection(struct be_adapter *adapter)
{}

/* VxLAN offload Notes:
 *
 * The stack defines tunnel offload flags (hw_enc_features) for IP and doesn't
 * distinguish various types of transports (VxLAN, GRE, NVGRE ..). So, offload
 * is expected to work across all types of IP tunnels once exported. Skyhawk
 * supports offloads for either VxLAN or NVGRE, exclusively. So we export VxLAN
 * offloads in hw_enc_features only when a VxLAN port is added. If other (non
 * VxLAN) tunnels are configured while VxLAN offloads are enabled, offloads for
 * those other tunnels are unexported on the fly through ndo_features_check().
 */
static int be_vxlan_set_port(struct net_device *netdev, unsigned int table,
			     unsigned int entry, struct udp_tunnel_info *ti)
{}

static int be_vxlan_unset_port(struct net_device *netdev, unsigned int table,
			       unsigned int entry, struct udp_tunnel_info *ti)
{}

static const struct udp_tunnel_nic_info be_udp_tunnels =;

static void be_calculate_vf_res(struct be_adapter *adapter, u16 num_vfs,
				struct be_resources *vft_res)
{}

static void be_if_destroy(struct be_adapter *adapter)
{}

static int be_clear(struct be_adapter *adapter)
{}

static int be_vfs_if_create(struct be_adapter *adapter)
{}

static int be_vf_setup_init(struct be_adapter *adapter)
{}

static int be_vf_setup(struct be_adapter *adapter)
{}

/* Converting function_mode bits on BE3 to SH mc_type enums */

static u8 be_convert_mc_type(u32 function_mode)
{}

/* On BE2/BE3 FW does not suggest the supported limits */
static void BEx_get_resources(struct be_adapter *adapter,
			      struct be_resources *res)
{}

static void be_setup_init(struct be_adapter *adapter)
{}

/* HW supports only MAX_PORT_RSS_TABLES RSS Policy Tables per port.
 * However, this HW limitation is not exposed to the host via any SLI cmd.
 * As a result, in the case of SRIOV and in particular multi-partition configs
 * the driver needs to calcuate a proportional share of RSS Tables per PF-pool
 * for distribution between the VFs. This self-imposed limit will determine the
 * no: of VFs for which RSS can be enabled.
 */
static void be_calculate_pf_pool_rss_tables(struct be_adapter *adapter)
{}

static int be_get_sriov_config(struct be_adapter *adapter)
{}

static void be_alloc_sriov_res(struct be_adapter *adapter)
{}

static int be_get_resources(struct be_adapter *adapter)
{}

static int be_get_config(struct be_adapter *adapter)
{}

static int be_mac_setup(struct be_adapter *adapter)
{}

static void be_schedule_worker(struct be_adapter *adapter)
{}

static void be_destroy_err_recovery_workq(void)
{}

static void be_schedule_err_detection(struct be_adapter *adapter, u32 delay)
{}

static int be_setup_queues(struct be_adapter *adapter)
{}

static int be_if_create(struct be_adapter *adapter)
{}

int be_update_queues(struct be_adapter *adapter)
{}

static inline int fw_major_num(const char *fw_ver)
{}

/* If it is error recovery, FLR the PF
 * Else if any VFs are already enabled don't FLR the PF
 */
static bool be_reset_required(struct be_adapter *adapter)
{}

/* Wait for the FW to be ready and perform the required initialization */
static int be_func_init(struct be_adapter *adapter)
{}

static int be_setup(struct be_adapter *adapter)
{}

#ifdef CONFIG_NET_POLL_CONTROLLER
static void be_netpoll(struct net_device *netdev)
{}
#endif

int be_load_fw(struct be_adapter *adapter, u8 *fw_file)
{}

static int be_ndo_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,
				 u16 flags, struct netlink_ext_ack *extack)
{}

static int be_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
				 struct net_device *dev, u32 filter_mask,
				 int nlflags)
{}

static struct be_cmd_work *be_alloc_work(struct be_adapter *adapter,
					 void (*func)(struct work_struct *))
{}

static netdev_features_t be_features_check(struct sk_buff *skb,
					   struct net_device *dev,
					   netdev_features_t features)
{}

static int be_get_phys_port_id(struct net_device *dev,
			       struct netdev_phys_item_id *ppid)
{}

static void be_set_rx_mode(struct net_device *dev)
{}

static const struct net_device_ops be_netdev_ops =;

static void be_netdev_init(struct net_device *netdev)
{}

static void be_cleanup(struct be_adapter *adapter)
{}

static int be_resume(struct be_adapter *adapter)
{}

static void be_soft_reset(struct be_adapter *adapter)
{}

static bool be_err_is_recoverable(struct be_adapter *adapter)
{}

static int be_tpe_recover(struct be_adapter *adapter)
{}

static int be_err_recover(struct be_adapter *adapter)
{}

static void be_err_detection_task(struct work_struct *work)
{}

static void be_log_sfp_info(struct be_adapter *adapter)
{}

static void be_worker(struct work_struct *work)
{}

static void be_unmap_pci_bars(struct be_adapter *adapter)
{}

static int db_bar(struct be_adapter *adapter)
{}

static int be_roce_map_pci_bars(struct be_adapter *adapter)
{}

static int be_map_pci_bars(struct be_adapter *adapter)
{}

static void be_drv_cleanup(struct be_adapter *adapter)
{}

/* Allocate and initialize various fields in be_adapter struct */
static int be_drv_init(struct be_adapter *adapter)
{}

static void be_remove(struct pci_dev *pdev)
{}

static ssize_t be_hwmon_show_temp(struct device *dev,
				  struct device_attribute *dev_attr,
				  char *buf)
{}

static SENSOR_DEVICE_ATTR(temp1_input, 0444,
			  be_hwmon_show_temp, NULL, 1);

static struct attribute *be_hwmon_attrs[] =;

ATTRIBUTE_GROUPS();

static char *mc_name(struct be_adapter *adapter)
{}

static inline char *func_name(struct be_adapter *adapter)
{}

static inline char *nic_name(struct pci_dev *pdev)
{}

static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id)
{}

static int __maybe_unused be_suspend(struct device *dev_d)
{}

static int __maybe_unused be_pci_resume(struct device *dev_d)
{}

/*
 * An FLR will stop BE from DMAing any data.
 */
static void be_shutdown(struct pci_dev *pdev)
{}

static pci_ers_result_t be_eeh_err_detected(struct pci_dev *pdev,
					    pci_channel_state_t state)
{}

static pci_ers_result_t be_eeh_reset(struct pci_dev *pdev)
{}

static void be_eeh_resume(struct pci_dev *pdev)
{}

static int be_pci_sriov_configure(struct pci_dev *pdev, int num_vfs)
{}

static const struct pci_error_handlers be_eeh_handlers =;

static SIMPLE_DEV_PM_OPS(be_pci_pm_ops, be_suspend, be_pci_resume);

static struct pci_driver be_driver =;

static int __init be_init_module(void)
{}
module_init();

static void __exit be_exit_module(void)
{}
module_exit(be_exit_module);