/* SPDX-License-Identifier: GPL-2.0+ */ #ifndef HWPA_PPE_INTERNAL_H #define HWPA_PPE_INTERNAL_H /* * uncomment to enable some debugging mechanisms and more verbose output */ //#define HWPA_PPE_DEBUG #ifdef HWPA_PPE_DEBUG #define pr_fmt(fmt) "%s:%s: " fmt, KBUILD_MODNAME, __func__ #else #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include "hwpa.h" #include "hwpa_ppe.h" #ifdef HWPA_PPE_DEBUG #define PR_DEVEL(fmt, ...) pr_err(fmt, ##__VA_ARGS__) #else #define PR_DEVEL(fmt, ...) #endif #ifdef HWPA_PPE_DEBUG_SYNC #define PR_DEVEL_SYNC(fmt, ...) pr_err(fmt, ##__VA_ARGS__) #else #define PR_DEVEL_SYNC(fmt, ...) #endif /* for debugfs outputs */ typedef int hwpa_ppe_fprintf(void *, const char *, ...); #define PPE_SWITCH_ID 0 /* ssdk device_id for internal ppe switch */ /* Maximum number of sessions the hwpa ppe holds */ #define HWPA_PPE_MAX_HW_SESSIONS CONFIG_AVM_PA_MAX_SESSION #define HWPA_PPE_MAX_HW_SESSIONS_LOG2 ilog2(HWPA_PPE_MAX_HW_SESSIONS) /* max amount of accelerators hwpa is able to handle. hws->accel_type sets this */ #define HWPA_PPE_ACCEL_TYPE_BITS 5 #define HWPA_PPE_MAX_ACCELERATORS ((1 << HWPA_PPE_ACCEL_TYPE_BITS) - 1) /* per accelerator max number of counters for e.g. errors */ #define HWPA_PPE_ACCELERATOR_MAX_COUNTERS 8 /* Common Length for string labels */ #define HWPA_PPE_LABEL_LEN 32 /* For WAN Egress Configuriation */ #define AVM_DTS_INTERNET_MAC "avm_mac_addr_macrouter_0" #define DTS_MAX_PATH 48 #define DTS_SYMBOLS_NODE "__symbols__" /* Default Value for VLAN IDs. Taken from ECM. */ #define HWPA_PPE_VLAN_ID_NOT_CONFIGURED 0xFFF enum hwpa_ppe_accelerator_type { HWPA_PPE_ACCELERATOR_PPE_IPV4, /* PPE IPV4 Flow */ HWPA_PPE_ACCELERATOR_PPE_IPV6, /* PPE IPV6 Flow */ HWPA_PPE_ACCELERATOR_PPE_MHT_L2, /* MHT L2 Flow */ HWPA_PPE_ACCELERATOR_MAX, }; enum hwpa_qca_accelerator_flags { HWPA_QCA_ACCEL_FLAG_INITIALIZED, HWPA_QCA_ACCEL_FLAG_MAX, }; enum hwpa_ppe_ctx_flag { HWPA_QCA_CTX_FLAG_ACTIVE, HWPA_QCA_CTX_FLAG_MAX, }; enum hwpa_ppe_pid_type { HWPA_PPE_PID_TYPE_UNDEFINED, HWPA_PPE_PID_TYPE_PP, HWPA_PPE_PID_TYPE_VP_WIFI, /* Also used for DS */ HWPA_PPE_PID_TYPE_VP_ATHTAG, HWPA_PPE_PID_TYPE_MAX, }; enum ppe_wan_egress_state { HWPA_PPE_WAN_EGRESS_STATE_NOT_INITIALIZED, /* No fos wan MAC given */ HWPA_PPE_WAN_EGRESS_STATE_INITIALIZED, /* fos wan MAC given but not assigned */ HWPA_PPE_WAN_EGRESS_STATE_ACTIVE, /* fos wan MAC given and assigned */ HWPA_PPE_WAN_EGRESS_STATE_MAX, }; enum HWPA_PPE_COUNTER { PPE_NO_FREE_HWS, PPE_OFFLOAD_FAILED, PPE_FLOW_FLUSHED, PPE_WAN_MAC_REFS, PPE_BAD_EG_MAC, PPE_COUNTER_MAX, }; struct hwpa_ppe_stats { uint32_t tx_bytes, tx_pkts; uint64_t total_tx_bytes, total_tx_pkts; }; struct hwpa_ppe_session { const struct avm_pa_session *sess_pa; struct hlist_node node; struct list_head accelerator_node; struct hwpa_ppe_stats stats; /* * Some information used for program flow and debugging * use bitfields to save memory. */ union { struct { uint8_t accel_type : HWPA_PPE_ACCEL_TYPE_BITS; /* hwpa_qca_accelerator_type */ bool on_free_list : 1; /* true if on free list */ bool on_used_list : 1; /* true if on used list */ bool stats_updated : 1; /* true if stats were update. false otherwise. */ bool hws_in_ifmac_added : 1; /* This flow added a mac to ppe l3 if mac table */ bool hws_eg_ifmac_added : 1; /* This flow uses a ppe egress mac */ bool session_flushed : 1; /* Indicates if the connection was flushed by ppe */ int32_t flow_index : 17; /* Index into the flow table or, if mht_l2 flow acl id */ }; uint32_t raw; }; }; struct hwpa_ppe_accelerator { /* accel_type for identifiying accelerator */ enum hwpa_ppe_accelerator_type accel_type; /* flag indicating accelerator state */ unsigned long flags; /* label for debugging and printing */ char label[HWPA_PPE_LABEL_LEN]; /* node for list of maintained accelerators in global context */ struct list_head ctx_node; /* accelerator API */ enum hwpa_backend_rv (*add_session)(struct hwpa_ppe_session *hws, uint32_t *hash); enum hwpa_backend_rv (*remove_session)(struct hwpa_ppe_session *hws); enum hwpa_backend_rv (*sync_session)(struct hwpa_ppe_session *hws); enum hwpa_backend_rv (*set_flushed_session)(struct hwpa_ppe_session *hws, void *tuple); enum hwpa_backend_rv (*init)(void); enum hwpa_backend_rv (*exit)(void); void (*dump_hws)(hwpa_ppe_fprintf fprintffunc, void *arg, const struct hwpa_ppe_session *hws); /* special counters */ atomic_t counter[HWPA_PPE_ACCELERATOR_MAX_COUNTERS]; const char counter_label[HWPA_PPE_ACCELERATOR_MAX_COUNTERS][HWPA_PPE_LABEL_LEN]; const uint32_t counter_count; /* Session Stats Valid Flags */ const unsigned long stats_updated_flags; }; struct hwpa_ppe_pid_info { enum hwpa_ppe_pid_type type; int mht_port_bmp; }; struct ppe_wan_egress_info { enum ppe_wan_egress_state state; /* wan egress state */ uint8_t fos_mac[ETH_ALEN]; /* fos wan mac */ uint8_t ppe_if_mac[ETH_ALEN]; /* save ppe if mac, so we can write it back if needed */ int16_t ppe_ifnum; /* currently active wan interface */ uint16_t refcount; spinlock_t lock; }; struct hwpa_ppe_context { /* Global flags indicating backend state */ unsigned long flags; /* static storage for hw sessions */ struct hwpa_ppe_session hws_storage[HWPA_PPE_MAX_HW_SESSIONS]; /* Lists for managing free and used hw sessions */ DECLARE_HASHTABLE(free_hws_hlist, HWPA_PPE_MAX_HW_SESSIONS_LOG2); DECLARE_HASHTABLE(used_hws_hlist, HWPA_PPE_MAX_HW_SESSIONS_LOG2); spinlock_t hws_list_lock; /* Synchronisation for stats */ struct workqueue_struct *workqueue; struct delayed_work work; spinlock_t hws_stats_lock; /* accelerator backends */ struct list_head accelerators; /* Info for wan egress acceleration */ struct ppe_wan_egress_info wan_egress; /* avm_pa pid information, +1 as 0 is an invalid pid and to be able to perform a direct mapping */ struct hwpa_ppe_pid_info pid_info[CONFIG_AVM_PA_MAX_PID + 1]; atomic_t counter[HWPA_PPE_ACCELERATOR_MAX_COUNTERS]; const char counter_label[HWPA_PPE_ACCELERATOR_MAX_COUNTERS][HWPA_PPE_LABEL_LEN]; const uint32_t counter_count; }; struct hwpa_ppe_context *hwpa_ppe_get_context(void); bool hwpa_ppe_valid_pid_handle(avm_pid_handle pid_handle); enum hwpa_backend_rv hwpa_ppe_add_session(struct hwpa_ppe_session *hws, uint32_t *hash); enum hwpa_backend_rv hwpa_ppe_rem_session(struct hwpa_ppe_session *hws); enum hwpa_backend_rv hwpa_ppe_accelerator_init(struct hwpa_ppe_accelerator *accelerator); enum hwpa_backend_rv hwpa_ppe_accelerator_exit(struct hwpa_ppe_accelerator *accelerator); enum hwpa_backend_rv hwpa_ppe_ipv4_register_accelerator(void); enum hwpa_backend_rv hwpa_ppe_ipv6_register_accelerator(void); #ifdef CONFIG_QCA_PPE_AVM_QCA838X_FRITZ_BOX enum hwpa_backend_rv hwpa_ppe_mht_l2_register_accelerator(void); #endif enum hwpa_backend_rv hwpa_ppe_register_accelerator(struct hwpa_ppe_accelerator *accelerator); void hwpa_ppe_debugfs_init(void); void hwpa_ppe_debugfs_exit(void); struct hwpa_ppe_accelerator *hwpa_ppe_get_accelerator(struct hwpa_ppe_session *hws); enum hwpa_backend_rv hwpa_ppe_get_and_hold_ppe_master(struct net_device *netdev, struct net_device **master_out); bool hwpa_ppe_mac_to_wan_if_op(ppe_drv_iface_t idx, const uint8_t *mac_addr, fal_ip_direction_t dir, bool add); enum hwpa_backend_rv hwpa_ppe_install_egress_mac(int32_t ifnum_out, struct net_device *out, bool *eg_mac_added); void hwpa_ppe_uninstall_egress_mac(void); bool hwpa_ppe_qdisc_enabled(struct net_device *dev); void hwpa_ppe_calc_delta_tx_stats(struct hwpa_ppe_session *hws, uint32_t delta_tx_bytes, uint32_t delta_tx_packets); void hwpa_ppe_calc_abs_tx_stats(struct hwpa_ppe_session *hws, uint64_t tx_bytes, uint64_t tx_packets); void hwpa_ppe_exception_init(void); void hwpa_ppe_exception_exit(void); #endif