/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) 2023, Jaguar Micro. All rights reserved. * * 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 _CRETE_H_ #define _CRETE_H_ #include #include #include #include #include #include #include #include #ifndef USE_JM_AUX_BUS #include #else #include "linux/auxiliary_bus.h" #endif #include "kcompat_std_defs.h" #include "rdma.h" #include "crete_txrx.h" #include "crete_sriov.h" #include "crete_eswitch.h" #include "crete_dcb_nl.h" #include "crete_lag.h" #include "crete_debugfs_statistics.h" /*micro filed*/ #define MAX_MSIX_ENTRIES 10 #define MAX_Q_VECTORS 8 #define CRETE_MAX_TX_QUEUES 8 #define CRETE_MAX_RX_QUEUES 8 #define CRETE_DEFAULT_TXD 256 #define CRETE_DEFAULT_TX_WORK 128 #define CRETE_MIN_TXD 80 #define CRETE_MAX_TXD 4096 #define CRETE_DEFAULT_RXD 256 #define CRETE_MIN_RXD 80 #define CRETE_MAX_RXD 4096 #define CRETE_DEFAULT_ITR 3 /* dynamic */ #define CRETE_MAX_ITR_USECS 10000 #define CRETE_MIN_ITR_USECS 10 #define CRETE_Q_VECTORS 1 #define CRETE_ETH_PKT_HDR_PAD (ETH_HLEN + ETH_FCS_LEN) /* As per the EAS the maximum supported size is 9.5KB (9728 bytes) */ #define MAX_JUMBO_FRAME_SIZE 0x2600 #define MAX_STD_JUMBO_FRAME_SIZE 9216 /* Supported Rx Buffer Sizes */ #define CRETE_RXBUFFER_256 256 #define CRETE_RXBUFFER_1536 1536 #define CRETE_RXBUFFER_2048 2048 #define CRETE_TS_HDR_LEN 16 #define ALIGN_TO_DW(a) (((a) + 3ULL) & (~3)) #define CRETE_CMD_WQ_MAX_NAME 32 /* device desc offset */ #define CRETE_JDH_OFFSET (CRETE_LEGACY_RESV) #define CRETE_JND_OFFSET (CRETE_JDH_OFFSET + sizeof(struct crete_desc_hdr)) #define CRETE_JRD_OFFSET (CRETE_JND_OFFSET + sizeof(struct crete_ndc_dpt)) #define CRETE_CAP_OFFSET 8 enum { CRETE_FLAG_DISABLE_ALL_ADEV = 1 << 0, CRETE_PAGE_MODE = 1 << 1, CRETE_FLAG_HAS_MSIX = 1 << 13, }; #define CRETE_LEGACY_RESV 0x0 #define CRETE_MAGIC_NUM 0xdeadbeef #define CRETE_EVENT_VECTOR 0 #define CRETE_CMD_DATA_BLOCK_SIZE 512 enum crete_coredev_type { CRETE_COREDEV_PF, CRETE_COREDEV_VF, CRETE_COREDEV_SF, }; enum crete_device_type { CRETE_DEVICE_CRETE, CRETE_DEVICE_PNIC, CRETE_DEVICE_RNIC, CRETE_DEVICE_FAKE, }; enum { CRETE_PCI_DEV_IS_VF = 1 << 0, }; #define CRETE_ADEV_NAME "crete_core" /*enum filed*/ enum crete_state_t { __CRETE_TESTING, __CRETE_RESETING, __CRETE_DOWN, }; /* Device Capability type */ enum crete_cap_type { CRETE_NET_CONF_CAP = 2, CRETE_RDMA_CONF_CAP = 3, CRETE_OFFLOAD_CONF_CAP = 4, CRETE_RES_CONF_CAP = 5, CRETE_DEVS_CONF_CAP = 6, CRETE_SHARES_DB_CAP = 7, CRETE_CAP_MAX, }; struct crete_init_seg { uint16_t fw_ver_minor; uint16_t fw_ver_major; uint16_t fw_revision; uint16_t cmd_interface_rev; uint8_t cp_status; uint8_t cp_caps; uint8_t dev_status; uint8_t reset_dev; uint32_t cmd_path_db; uint32_t cmd_path_entry[16]; uint32_t resv1[8]; uint32_t event_buffer[8]; uint32_t event_buffer_addr_low; uint32_t event_buffer_addr_hi; uint8_t event_busy; uint8_t event_buffer_size; uint16_t event_vector; uint32_t event_credit_doorbell; uint16_t resv2; uint16_t aq_queue_size; uint32_t aq_queue_db; uint32_t aq_base_addr_low; uint32_t aq_base_addr_hi; uint32_t shared_res_lock; uint32_t shared_res_db; uint32_t extra_admin_db; uint32_t resv3[13]; uint32_t timestamp[2]; } __packed; struct cmd_info { uint32_t owner:1; uint32_t out_inline:1; uint32_t in_inline:1; uint32_t event_notify:1; uint32_t status:4; uint32_t sig:8; uint32_t cmd_encap_type:8; uint32_t cid:8; }; struct crete_cmd_entry { uint32_t in_len; uint32_t out_len; uint64_t in_ptr; uint64_t out_ptr; uint8_t inline_data[36]; union { struct cmd_info cmd_info; uint32_t cmd_info_data; }; } __packed; struct crete_cmd_prot_block { u8 sig; u8 block_num; u8 rsvd0; u8 cid; uint32_t cmd_data_len;//CRETE_CMD_DATA_BLOCK_SIZE uint64_t next; uint32_t next_len; uint32_t cmd_data[]; } __packed; struct crete_cmd_mailbox { void *buf; dma_addr_t dma; struct crete_cmd_mailbox *next; }; struct crete_cmd_msg { struct list_head list; u32 msg_mode; u32 len; struct crete_cmd_mailbox *next; u8 inline_data[36]; //inline bd Optimize todo }__aligned(8); #define CRETE_MAX_COMMANDS 32 struct crete_cmd_work_ent { unsigned long state; struct crete_cmd_msg *inb; struct crete_cmd_msg *outb; void *out; int out_size; int idx; struct completion handling; struct completion done; struct crete_cmd *cmd; struct work_struct work; struct crete_cmd_entry *lay; int ret; u8 status;//fw return cmd status u16 cmd_id; bool polling; u64 ts1; u64 ts2; /* Track the max comp handlers */ refcount_t refcnt; }; struct crete_cmd { struct crete_nb nb; u8 mode; u8 poll_mode; void *cmd_buf; dma_addr_t cmd_dma; u32 cmd_size; u32 cmd_stride; struct dma_pool *pool; int max_cmds; unsigned long bitmask; char wq_name[CRETE_CMD_WQ_MAX_NAME]; struct workqueue_struct *wq; struct semaphore sem; spinlock_t alloc_lock; struct crete_cmd_work_ent *ent_arr[CRETE_MAX_COMMANDS]; }; /* for test qp create */ struct crete_qbase_info { void *va; dma_addr_t pa; }; struct crete_queue_info { uint8_t rx_qid; uint16_t q_size; uint16_t vec[2]; struct crete_qbase_info sq[2]; struct crete_qbase_info cq[2]; }; /* *Device Capability Descriptor *Device Capability Descriptor Header */ struct crete_desc_hdr { uint32_t magic; uint32_t cap_cnt:8; uint32_t len:12; uint32_t offset:12; }; // net device configuration descriptor,cap_type = 2 struct crete_ndc_dpt { uint32_t type:8; uint32_t resv:24; uint32_t len:12; uint32_t offset:20; }; // Rdma Device Configuration Descriptor,cap_type = 3 struct crete_rdma_cfg_desc { uint32_t cap_type:8; uint32_t resv:24; uint32_t len:12; uint32_t offset:20; }; // Offload Configuration Descriptor,cap_type = 4 struct crete_offload_cfg_desc { uint32_t cap_type:8; uint32_t resv:24; uint32_t len:12; uint32_t offset:20; }; // resource configuration descriptor,cap_type = 5 struct crete_rc_dpt { uint32_t type:8; uint32_t ru_size:12; uint32_t ru_max:12; uint32_t len:12; uint32_t offset:20; }; //Device-specific Configuration Descriptor,cap_type = 6 struct crete_devs_dpt { uint32_t cap_type:8; uint32_t resv:24; uint32_t len:12; uint32_t offset:20; }; //Shared Data Descriptor,cap_type = 7 struct crete_shared_dpt { uint32_t cap_type:8; uint32_t len:24; uint32_t offset; }; /* hw */ struct crete_hw { struct crete_init_seg __iomem *io_addr; struct crete_desc_hdr jdh; struct crete_ndc_dpt jnd; struct crete_rdma_cfg_desc rdma_desc; struct crete_offload_cfg_desc offload_desc; struct crete_rc_dpt jrd; struct crete_devs_dpt dev_spec_desc; struct crete_shared_dpt share_data_desc; }; struct crete_aux_dev { struct crete_core_dev *core_dev; struct auxiliary_device adev; int idx; }; #define CRETE_MAX_UC_ADDRS 4 #define CRETE_MAX_MC_ADDRS 16 #define L2_SET_RX_MASK_REQ_MASK_MCAST 0x1UL #define L2_SET_RX_MASK_REQ_MASK_ALL_MCAST 0x2UL #define L2_SET_RX_MASK_REQ_MASK_BCAST 0x4UL #define L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS 0x8UL struct crete_priv { struct crete_core_dev *coredev; struct crete_esw_rep *rep; struct net_device *netdev; struct workqueue_struct *wq; struct work_struct set_rx_mode_work; struct crete_dcbx dcbx; struct crete_dcbx_dp dcbx_dp; /* vport rx mode */ u32 rx_mask; __le64 fw_l2_filter_id[CRETE_MAX_UC_ADDRS]; /* index 0 always dev_addr */ u16 uc_filter_count; u8 *uc_list; u8 *mc_list; int mc_list_size; int mc_list_count; int vlan_range_num; }; struct crete_debugfs_entries { struct dentry *dbg_root; struct dentry *lag_debugfs; struct dentry *statistics_debugfs; }; struct crete_irq_info { char name[IFNAMSIZ + 2]; irq_handler_t handler; unsigned int vector; u8 requested:1; u8 have_cpumask:1; }; struct crete_pf_info { u16 fw_fid; u16 port_id; u8 mac_addr[ETH_ALEN]; u32 first_vf_id; u16 active_vfs; u16 registered_vfs; u16 max_vfs; void *hwrm_cmd_req_addr[4]; dma_addr_t hwrm_cmd_req_dma_addr[4]; struct crete_vf_info *vf; struct kobject *config; struct kobject *groups_config; struct crete_sriov_vf_sysfs *vf_sysfs; }; struct rdma_dev_adapt { unsigned int flags; unsigned int priv_flags; unsigned int bar_offset; unsigned int bar_len; phys_addr_t uar_base; unsigned int uar_size; void __iomem *reg_addr; /*bar addr*/ __le32 *cmd_db_reg; /* cmd db addr*/ __le32 __iomem *eq_db_reg; struct mutex intf_state_mutex; unsigned int vector_base; unsigned int vector_num; }; struct crete_qp_context { __le16 rx_qid; /* must be even */ __le16 event_credit; __le16 rx_sq_vq_size; /* vnet rx vq size */ __le16 rx_cq_size; /* unless for vnet */ __le16 tx_sq_vq_size; /* tx vq size for vnet */ __le16 tx_cq_size; /* useless for vnet */ __le16 rx_queue_vec; /* rx queue interrupt vector */ __le16 tx_queue_vec; /* tx queue interrupt vector */ __le64 rx_sq_desc_base; /* rx queue desc base address for vnet */ __le64 rx_cq_used_base; /* rx cq address ,rx used ring address for vnet */ __le64 tx_sq_desc_base; /* tx sq address, tx queue desc address for vnet */ __le64 tx_cq_used_base; /* tx cq address, tx queue used ring address for vnet */ }; struct crete_queue_context { __le16 qid; /* must be even */ __le16 queue_size; /* vnet io vq size */ __le16 cq_size; /* vnet cq size */ __le16 queue_vec; /*queue interrupt vector */ __le16 resv; /*reserved */ __le64 queue_desc_base; /* rx queue desc base address for vnet */ __le64 queue_used_base; /* rx cq address ,rx used ring address for vnet */ }; struct crete_core_qpcap { u16 max_queue_size; u8 max_qp_num; u8 ctrl_queue_size; }; struct crete_core_cap { struct crete_core_qpcap qpcap; __le64 hw_features; __le64 driver_features; // pf core cap need more }; struct crete_qp_cap { u8 ctrl_queue_size; u8 max_qp_num; __le16 max_queue_size; } __packed; struct crete_txq_stats { struct u64_stats_sync syncp; u64 packets; u64 bytes; u64 kicks; }; struct crete_rxq_stats { struct u64_stats_sync syncp; u64 packets; u64 bytes; u64 drops; u64 kicks; }; #define CRETE_TXQ_STATS(m) offsetof(struct crete_txq_stats, m) #define CRETE_RXQ_STATS(m) offsetof(struct crete_rxq_stats, m) struct crete_core_dev { #define CRETE_MAX_MSIX_NUM 4096U spinlock_t lock; struct device *device; void __iomem *db_base; struct pci_dev *pdev; struct crete_core_cap cap; struct crete_txring_info *txring; u16 *txring_mapping; // u16 txring_size; struct crete_rxring_info *rxring; u16 *rxring_mapping; // u16 rxring_size; u16 ring_size; // ring parameters u32 rx_buf_size; u32 rx_buf_use_size; /* useable size */ u16 rx_offset; u16 rx_dma_offset; struct crete_db *db; //struct crete_core_cap *cap; struct crete_napi *jnapi; struct crete_rxcp_ring_info *rxcpring; struct crete_txcp_ring_info *txcpring; u16 max_qp_num; unsigned long state; struct net_device *netdev; u64 netdev_features; u64 offload_features; unsigned int flags; u32 rss_queues; u8 __iomem *io_addr; phys_addr_t bar_addr; //for further consider struct crete_hw hw; struct crete_queue_info q_info; // for create qp test struct crete_aux_dev **adev; int adev_idx; struct crete_irq_info *irq_info; struct crete_cmd cmd; struct crete_event_irq *event_irq; u16 irq_num; unsigned long irqbit[BITS_TO_LONGS(CRETE_MAX_MSIX_NUM)]; struct msix_entry *msix_ent; enum crete_coredev_type coredev_type; enum crete_device_type device_type; struct crete_pf_info pf; struct crete_vf_info vf; bool sriov_cfg; struct jm_rdma_core rdma_coredev; struct rdma_dev_adapt rdma_adp; struct crete_eswitch *eswitch; struct crete_lag_cap lag_cap; struct crete_debugfs_entries dbg; struct crete_lag *lag_dev; struct crete_debugfs_statistics *debugfs_statis; u16 sfi_id; u16 lag_enable; }; enum crete_feature_type { CRETE_FEATURE_NETDEV, CRETE_FEATURE_OFFLOAD }; static inline unsigned int crete_rd32(struct crete_core_dev *p, u32 reg) { u8 __iomem *ioaddr = READ_ONCE(p->io_addr); u32 value = 0; value = readl(&ioaddr[reg]); return value; } static inline void crete_ioread32(void __iomem *addr, void *buffer, unsigned int count) { int i = 0; u32 *buf = buffer; u8 __iomem *address = addr; if (count) { for (i = 0; i < count; i++) readsl(address + i * 4, buf++, 1); } } static inline void crete_iowrite32(void __iomem *addr, void *buffer, unsigned int count) { int i = 0; u32 *buf = buffer; u8 __iomem *address = addr; if (count) { for (i = 0; i < count; i++) writesl(address + i * 4, buf++, 1); } } static inline struct device *crete_hw_to_dev(struct crete_hw *hw) { struct crete_core_dev *core_dev = container_of(hw, struct crete_core_dev, hw); return &core_dev->pdev->dev; } int crete_adev_idx_alloc(void); void crete_adev_idx_free(int idx); static inline bool crete_sriov_is_enabled(struct crete_core_dev *dev) { return pci_num_vf(dev->pdev) ? true : false; } static inline bool crete_core_is_pf(const struct crete_core_dev *dev) { return dev->coredev_type == CRETE_COREDEV_PF; } static inline bool crete_core_is_vf(const struct crete_core_dev *dev) { return dev->coredev_type == CRETE_COREDEV_VF; } static inline bool crete_have_rdma_cap(const struct crete_core_dev *dev) { return dev->hw.rdma_desc.cap_type == CRETE_RDMA_CONF_CAP; } static inline bool crete_have_net_cap(const struct crete_core_dev *dev) { return dev->hw.jnd.type == CRETE_NET_CONF_CAP; } static inline u16 fw_ver_maj(struct crete_core_dev *dev) { struct crete_hw *hw = &dev->hw; return readw(&hw->io_addr->fw_ver_major); } static inline u16 fw_ver_min(struct crete_core_dev *dev) { struct crete_hw *hw = &dev->hw; return readw(&hw->io_addr->fw_ver_minor); } static inline u16 fw_ver_sub(struct crete_core_dev *dev) { struct crete_hw *hw = &dev->hw; return readw(&hw->io_addr->cmd_interface_rev); } static inline u16 fw_ver_rev(struct crete_core_dev *dev) { struct crete_hw *hw = &dev->hw; return readw(&hw->io_addr->fw_revision); } int crete_req_msixirq(struct crete_core_dev *core_dev); void crete_free_msixirq(struct crete_core_dev *core_dev, int irq); static inline bool __crete_test_bit(const u64 features, unsigned int fbit) { /* Did you forget to fix assumptions on max features? */ if (__builtin_constant_p(fbit)) BUILD_BUG_ON(fbit >= 64); else WARN_ON_ONCE(fbit >= 64); return features & BIT_ULL(fbit); } static inline bool crete_has_feature(const struct crete_core_dev *cdev, enum crete_feature_type feature_type, unsigned int fbit) { if (feature_type == CRETE_FEATURE_NETDEV) return __crete_test_bit(cdev->netdev_features, fbit); else return __crete_test_bit(cdev->offload_features, fbit); } /* NEED_ETH_HW_ADDR_SET * * eth_hw_addr_set was added by upstream commit * 48eab831ae8b ("net: create netdev->dev_addr assignment helpers") * * Using eth_hw_addr_set became required in 5.17, when the dev_addr field in * the netdev struct was constified. See 48eab831ae8b ("net: create * netdev->dev_addr assignment helpers") */ #ifdef NEED_ETH_HW_ADDR_SET static inline void eth_hw_addr_set(struct net_device *dev, const u8 *addr) { ether_addr_copy(dev->dev_addr, addr); } #endif /* NEED_ETH_HW_ADDR_SET */ int crete_cmd_init(struct crete_core_dev *cdev); int crete_event_init(struct crete_hw *hw); void crete_cmd_exit(struct crete_core_dev *cdev); void crete_event_exit(struct crete_hw *hw); int crete_adev_init(struct crete_core_dev *core_dev); void crete_adev_cleanup(struct crete_core_dev *core_dev); int crete_rescan_drivers_locked(struct crete_core_dev *core_dev); int crete_rescan_drivers(struct crete_core_dev *dev); void crete_dev_list_lock(void); void crete_dev_list_unlock(void); int crete_dev_list_trylock(void); void crete_sriov_disable(struct pci_dev *pdev); int crete_register_device(struct crete_core_dev *core_dev); void crete_unregister_device(struct crete_core_dev *core_dev); void crete_detach_device(struct crete_core_dev *core_dev); int crete_attach_device(struct crete_core_dev *core_dev); int crete_change_mac_addr(struct net_device *netdev, void *p); void crete_set_rx_mode(struct net_device *dev); void crete_init_msix(struct crete_core_dev *core_dev); void crete_exit_irq(struct crete_core_dev *core_dev); extern struct dentry *crete_debugfs_root; void crete_register_debugfs(void); void crete_unregister_debugfs(void); struct dentry *crete_debugfs_get_dev_root(struct crete_core_dev *dev); extern const struct net_device_ops crete_netdev_ops; extern const struct ethtool_ops crete_ethtool_ops; #endif