linux/net/dsa/user.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * net/dsa/user.c - user device handling
 * Copyright (c) 2008-2009 Marvell Semiconductor
 */

#include <linux/list.h>
#include <linux/etherdevice.h>
#include <linux/netdevice.h>
#include <linux/phy.h>
#include <linux/phy_fixed.h>
#include <linux/phylink.h>
#include <linux/of_net.h>
#include <linux/of_mdio.h>
#include <linux/mdio.h>
#include <net/rtnetlink.h>
#include <net/pkt_cls.h>
#include <net/selftests.h>
#include <net/tc_act/tc_mirred.h>
#include <linux/if_bridge.h>
#include <linux/if_hsr.h>
#include <net/dcbnl.h>
#include <linux/netpoll.h>
#include <linux/string.h>

#include "conduit.h"
#include "dsa.h"
#include "netlink.h"
#include "port.h"
#include "switch.h"
#include "tag.h"
#include "user.h"

struct dsa_switchdev_event_work {};

enum dsa_standalone_event {};

struct dsa_standalone_event_work {};

struct dsa_host_vlan_rx_filtering_ctx {};

static bool dsa_switch_supports_uc_filtering(struct dsa_switch *ds)
{}

static bool dsa_switch_supports_mc_filtering(struct dsa_switch *ds)
{}

static void dsa_user_standalone_event_work(struct work_struct *work)
{}

static int dsa_user_schedule_standalone_work(struct net_device *dev,
					     enum dsa_standalone_event event,
					     const unsigned char *addr,
					     u16 vid)
{}

static int dsa_user_host_vlan_rx_filtering(void *arg, int vid)
{}

static int dsa_user_vlan_for_each(struct net_device *dev,
				  int (*cb)(void *arg, int vid), void *arg)
{}

static int dsa_user_sync_uc(struct net_device *dev,
			    const unsigned char *addr)
{}

static int dsa_user_unsync_uc(struct net_device *dev,
			      const unsigned char *addr)
{}

static int dsa_user_sync_mc(struct net_device *dev,
			    const unsigned char *addr)
{}

static int dsa_user_unsync_mc(struct net_device *dev,
			      const unsigned char *addr)
{}

void dsa_user_sync_ha(struct net_device *dev)
{}

void dsa_user_unsync_ha(struct net_device *dev)
{}

/* user mii_bus handling ***************************************************/
static int dsa_user_phy_read(struct mii_bus *bus, int addr, int reg)
{}

static int dsa_user_phy_write(struct mii_bus *bus, int addr, int reg, u16 val)
{}

void dsa_user_mii_bus_init(struct dsa_switch *ds)
{}


/* user device handling ****************************************************/
static int dsa_user_get_iflink(const struct net_device *dev)
{}

int dsa_user_host_uc_install(struct net_device *dev, const u8 *addr)
{}

void dsa_user_host_uc_uninstall(struct net_device *dev)
{}

static int dsa_user_open(struct net_device *dev)
{}

static int dsa_user_close(struct net_device *dev)
{}

static void dsa_user_manage_host_flood(struct net_device *dev)
{}

static void dsa_user_change_rx_flags(struct net_device *dev, int change)
{}

static void dsa_user_set_rx_mode(struct net_device *dev)
{}

static int dsa_user_set_mac_address(struct net_device *dev, void *a)
{}

struct dsa_user_dump_ctx {};

static int
dsa_user_port_fdb_do_dump(const unsigned char *addr, u16 vid,
			  bool is_static, void *data)
{}

static int
dsa_user_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
		  struct net_device *dev, struct net_device *filter_dev,
		  int *idx)
{}

static int dsa_user_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{}

static int dsa_user_port_attr_set(struct net_device *dev, const void *ctx,
				  const struct switchdev_attr *attr,
				  struct netlink_ext_ack *extack)
{}

/* Must be called under rcu_read_lock() */
static int
dsa_user_vlan_check_for_8021q_uppers(struct net_device *user,
				     const struct switchdev_obj_port_vlan *vlan)
{}

static int dsa_user_vlan_add(struct net_device *dev,
			     const struct switchdev_obj *obj,
			     struct netlink_ext_ack *extack)
{}

/* Offload a VLAN installed on the bridge or on a foreign interface by
 * installing it as a VLAN towards the CPU port.
 */
static int dsa_user_host_vlan_add(struct net_device *dev,
				  const struct switchdev_obj *obj,
				  struct netlink_ext_ack *extack)
{}

static int dsa_user_port_obj_add(struct net_device *dev, const void *ctx,
				 const struct switchdev_obj *obj,
				 struct netlink_ext_ack *extack)
{}

static int dsa_user_vlan_del(struct net_device *dev,
			     const struct switchdev_obj *obj)
{}

static int dsa_user_host_vlan_del(struct net_device *dev,
				  const struct switchdev_obj *obj)
{}

static int dsa_user_port_obj_del(struct net_device *dev, const void *ctx,
				 const struct switchdev_obj *obj)
{}

static netdev_tx_t dsa_user_netpoll_send_skb(struct net_device *dev,
					     struct sk_buff *skb)
{}

static void dsa_skb_tx_timestamp(struct dsa_user_priv *p,
				 struct sk_buff *skb)
{}

netdev_tx_t dsa_enqueue_skb(struct sk_buff *skb, struct net_device *dev)
{}
EXPORT_SYMBOL_GPL();

static netdev_tx_t dsa_user_xmit(struct sk_buff *skb, struct net_device *dev)
{}

/* ethtool operations *******************************************************/

static void dsa_user_get_drvinfo(struct net_device *dev,
				 struct ethtool_drvinfo *drvinfo)
{}

static int dsa_user_get_regs_len(struct net_device *dev)
{}

static void
dsa_user_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *_p)
{}

static int dsa_user_nway_reset(struct net_device *dev)
{}

static int dsa_user_get_eeprom_len(struct net_device *dev)
{}

static int dsa_user_get_eeprom(struct net_device *dev,
			       struct ethtool_eeprom *eeprom, u8 *data)
{}

static int dsa_user_set_eeprom(struct net_device *dev,
			       struct ethtool_eeprom *eeprom, u8 *data)
{}

static void dsa_user_get_strings(struct net_device *dev,
				 uint32_t stringset, uint8_t *data)
{}

static void dsa_user_get_ethtool_stats(struct net_device *dev,
				       struct ethtool_stats *stats,
				       uint64_t *data)
{}

static int dsa_user_get_sset_count(struct net_device *dev, int sset)
{}

static void dsa_user_get_eth_phy_stats(struct net_device *dev,
				       struct ethtool_eth_phy_stats *phy_stats)
{}

static void dsa_user_get_eth_mac_stats(struct net_device *dev,
				       struct ethtool_eth_mac_stats *mac_stats)
{}

static void
dsa_user_get_eth_ctrl_stats(struct net_device *dev,
			    struct ethtool_eth_ctrl_stats *ctrl_stats)
{}

static void
dsa_user_get_rmon_stats(struct net_device *dev,
			struct ethtool_rmon_stats *rmon_stats,
			const struct ethtool_rmon_hist_range **ranges)
{}

static void dsa_user_net_selftest(struct net_device *ndev,
				  struct ethtool_test *etest, u64 *buf)
{}

static int dsa_user_get_mm(struct net_device *dev,
			   struct ethtool_mm_state *state)
{}

static int dsa_user_set_mm(struct net_device *dev, struct ethtool_mm_cfg *cfg,
			   struct netlink_ext_ack *extack)
{}

static void dsa_user_get_mm_stats(struct net_device *dev,
				  struct ethtool_mm_stats *stats)
{}

static void dsa_user_get_wol(struct net_device *dev, struct ethtool_wolinfo *w)
{}

static int dsa_user_set_wol(struct net_device *dev, struct ethtool_wolinfo *w)
{}

static int dsa_user_set_eee(struct net_device *dev, struct ethtool_keee *e)
{}

static int dsa_user_get_eee(struct net_device *dev, struct ethtool_keee *e)
{}

static int dsa_user_get_link_ksettings(struct net_device *dev,
				       struct ethtool_link_ksettings *cmd)
{}

static int dsa_user_set_link_ksettings(struct net_device *dev,
				       const struct ethtool_link_ksettings *cmd)
{}

static void dsa_user_get_pause_stats(struct net_device *dev,
				     struct ethtool_pause_stats *pause_stats)
{}

static void dsa_user_get_pauseparam(struct net_device *dev,
				    struct ethtool_pauseparam *pause)
{}

static int dsa_user_set_pauseparam(struct net_device *dev,
				   struct ethtool_pauseparam *pause)
{}

#ifdef CONFIG_NET_POLL_CONTROLLER
static int dsa_user_netpoll_setup(struct net_device *dev,
				  struct netpoll_info *ni)
{}

static void dsa_user_netpoll_cleanup(struct net_device *dev)
{}

static void dsa_user_poll_controller(struct net_device *dev)
{}
#endif

static struct dsa_mall_tc_entry *
dsa_user_mall_tc_entry_find(struct net_device *dev, unsigned long cookie)
{}

static int
dsa_user_add_cls_matchall_mirred(struct net_device *dev,
				 struct tc_cls_matchall_offload *cls,
				 bool ingress)
{}

static int
dsa_user_add_cls_matchall_police(struct net_device *dev,
				 struct tc_cls_matchall_offload *cls,
				 bool ingress)
{}

static int dsa_user_add_cls_matchall(struct net_device *dev,
				     struct tc_cls_matchall_offload *cls,
				     bool ingress)
{}

static void dsa_user_del_cls_matchall(struct net_device *dev,
				      struct tc_cls_matchall_offload *cls)
{}

static int dsa_user_setup_tc_cls_matchall(struct net_device *dev,
					  struct tc_cls_matchall_offload *cls,
					  bool ingress)
{}

static int dsa_user_add_cls_flower(struct net_device *dev,
				   struct flow_cls_offload *cls,
				   bool ingress)
{}

static int dsa_user_del_cls_flower(struct net_device *dev,
				   struct flow_cls_offload *cls,
				   bool ingress)
{}

static int dsa_user_stats_cls_flower(struct net_device *dev,
				     struct flow_cls_offload *cls,
				     bool ingress)
{}

static int dsa_user_setup_tc_cls_flower(struct net_device *dev,
					struct flow_cls_offload *cls,
					bool ingress)
{}

static int dsa_user_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
				      void *cb_priv, bool ingress)
{}

static int dsa_user_setup_tc_block_cb_ig(enum tc_setup_type type,
					 void *type_data, void *cb_priv)
{}

static int dsa_user_setup_tc_block_cb_eg(enum tc_setup_type type,
					 void *type_data, void *cb_priv)
{}

static LIST_HEAD(dsa_user_block_cb_list);

static int dsa_user_setup_tc_block(struct net_device *dev,
				   struct flow_block_offload *f)
{}

static int dsa_user_setup_ft_block(struct dsa_switch *ds, int port,
				   void *type_data)
{}

static int dsa_user_setup_tc(struct net_device *dev, enum tc_setup_type type,
			     void *type_data)
{}

static int dsa_user_get_rxnfc(struct net_device *dev,
			      struct ethtool_rxnfc *nfc, u32 *rule_locs)
{}

static int dsa_user_set_rxnfc(struct net_device *dev,
			      struct ethtool_rxnfc *nfc)
{}

static int dsa_user_get_ts_info(struct net_device *dev,
				struct kernel_ethtool_ts_info *ts)
{}

static int dsa_user_vlan_rx_add_vid(struct net_device *dev, __be16 proto,
				    u16 vid)
{}

static int dsa_user_vlan_rx_kill_vid(struct net_device *dev, __be16 proto,
				     u16 vid)
{}

static int dsa_user_restore_vlan(struct net_device *vdev, int vid, void *arg)
{}

static int dsa_user_clear_vlan(struct net_device *vdev, int vid, void *arg)
{}

/* Keep the VLAN RX filtering list in sync with the hardware only if VLAN
 * filtering is enabled. The baseline is that only ports that offload a
 * VLAN-aware bridge are VLAN-aware, and standalone ports are VLAN-unaware,
 * but there are exceptions for quirky hardware.
 *
 * If ds->vlan_filtering_is_global = true, then standalone ports which share
 * the same switch with other ports that offload a VLAN-aware bridge are also
 * inevitably VLAN-aware.
 *
 * To summarize, a DSA switch port offloads:
 *
 * - If standalone (this includes software bridge, software LAG):
 *     - if ds->needs_standalone_vlan_filtering = true, OR if
 *       (ds->vlan_filtering_is_global = true AND there are bridges spanning
 *       this switch chip which have vlan_filtering=1)
 *         - the 8021q upper VLANs
 *     - else (standalone VLAN filtering is not needed, VLAN filtering is not
 *       global, or it is, but no port is under a VLAN-aware bridge):
 *         - no VLAN (any 8021q upper is a software VLAN)
 *
 * - If under a vlan_filtering=0 bridge which it offload:
 *     - if ds->configure_vlan_while_not_filtering = true (default):
 *         - the bridge VLANs. These VLANs are committed to hardware but inactive.
 *     - else (deprecated):
 *         - no VLAN. The bridge VLANs are not restored when VLAN awareness is
 *           enabled, so this behavior is broken and discouraged.
 *
 * - If under a vlan_filtering=1 bridge which it offload:
 *     - the bridge VLANs
 *     - the 8021q upper VLANs
 */
int dsa_user_manage_vlan_filtering(struct net_device *user,
				   bool vlan_filtering)
{}

struct dsa_hw_port {};

static int dsa_hw_port_list_set_mtu(struct list_head *hw_port_list, int mtu)
{}

static void dsa_hw_port_list_free(struct list_head *hw_port_list)
{}

/* Make the hardware datapath to/from @dev limited to a common MTU */
static void dsa_bridge_mtu_normalization(struct dsa_port *dp)
{}

int dsa_user_change_mtu(struct net_device *dev, int new_mtu)
{}

static int __maybe_unused
dsa_user_dcbnl_set_apptrust(struct net_device *dev, u8 *sel, int nsel)
{}

static int __maybe_unused
dsa_user_dcbnl_get_apptrust(struct net_device *dev, u8 *sel, int *nsel)
{}

static int __maybe_unused
dsa_user_dcbnl_set_default_prio(struct net_device *dev, struct dcb_app *app)
{}

/* Update the DSCP prio entries on all user ports of the switch in case
 * the switch supports global DSCP prio instead of per port DSCP prios.
 */
static int dsa_user_dcbnl_ieee_global_dscp_setdel(struct net_device *dev,
						  struct dcb_app *app, bool del)
{}

static int __maybe_unused
dsa_user_dcbnl_add_dscp_prio(struct net_device *dev, struct dcb_app *app)
{}

static int __maybe_unused dsa_user_dcbnl_ieee_setapp(struct net_device *dev,
						     struct dcb_app *app)
{}

static int __maybe_unused
dsa_user_dcbnl_del_default_prio(struct net_device *dev, struct dcb_app *app)
{}

static int __maybe_unused
dsa_user_dcbnl_del_dscp_prio(struct net_device *dev, struct dcb_app *app)
{}

static int __maybe_unused dsa_user_dcbnl_ieee_delapp(struct net_device *dev,
						     struct dcb_app *app)
{}

/* Pre-populate the DCB application priority table with the priorities
 * configured during switch setup, which we read from hardware here.
 */
static int dsa_user_dcbnl_init(struct net_device *dev)
{}

static const struct ethtool_ops dsa_user_ethtool_ops =;

static const struct dcbnl_rtnl_ops __maybe_unused dsa_user_dcbnl_ops =;

static void dsa_user_get_stats64(struct net_device *dev,
				 struct rtnl_link_stats64 *s)
{}

static int dsa_user_fill_forward_path(struct net_device_path_ctx *ctx,
				      struct net_device_path *path)
{}

static const struct net_device_ops dsa_user_netdev_ops =;

static const struct device_type dsa_type =;

void dsa_port_phylink_mac_change(struct dsa_switch *ds, int port, bool up)
{}
EXPORT_SYMBOL_GPL();

static void dsa_user_phylink_fixed_state(struct phylink_config *config,
					 struct phylink_link_state *state)
{}

/* user device setup *******************************************************/
static int dsa_user_phy_connect(struct net_device *user_dev, int addr,
				u32 flags)
{}

static int dsa_user_phy_setup(struct net_device *user_dev)
{}

void dsa_user_setup_tagger(struct net_device *user)
{}

int dsa_user_suspend(struct net_device *user_dev)
{}

int dsa_user_resume(struct net_device *user_dev)
{}

int dsa_user_create(struct dsa_port *port)
{}

void dsa_user_destroy(struct net_device *user_dev)
{}

int dsa_user_change_conduit(struct net_device *dev, struct net_device *conduit,
			    struct netlink_ext_ack *extack)
{}

bool dsa_user_dev_check(const struct net_device *dev)
{}
EXPORT_SYMBOL_GPL();

static int dsa_user_changeupper(struct net_device *dev,
				struct netdev_notifier_changeupper_info *info)
{}

static int dsa_user_prechangeupper(struct net_device *dev,
				   struct netdev_notifier_changeupper_info *info)
{}

static int
dsa_user_lag_changeupper(struct net_device *dev,
			 struct netdev_notifier_changeupper_info *info)
{}

/* Same as dsa_user_lag_changeupper() except that it calls
 * dsa_user_prechangeupper()
 */
static int
dsa_user_lag_prechangeupper(struct net_device *dev,
			    struct netdev_notifier_changeupper_info *info)
{}

static int
dsa_prevent_bridging_8021q_upper(struct net_device *dev,
				 struct netdev_notifier_changeupper_info *info)
{}

static int
dsa_user_check_8021q_upper(struct net_device *dev,
			   struct netdev_notifier_changeupper_info *info)
{}

static int
dsa_user_prechangeupper_sanity_check(struct net_device *dev,
				     struct netdev_notifier_changeupper_info *info)
{}

/* To be eligible as a DSA conduit, a LAG must have all lower interfaces be
 * eligible DSA conduits. Additionally, all LAG slaves must be DSA conduits of
 * switches in the same switch tree.
 */
static int dsa_lag_conduit_validate(struct net_device *lag_dev,
				    struct netlink_ext_ack *extack)
{}

static int
dsa_conduit_prechangeupper_sanity_check(struct net_device *conduit,
					struct netdev_notifier_changeupper_info *info)
{}

static int
dsa_lag_conduit_prechangelower_sanity_check(struct net_device *dev,
					    struct netdev_notifier_changeupper_info *info)
{}

/* Don't allow bridging of DSA conduits, since the bridge layer rx_handler
 * prevents the DSA fake ethertype handler to be invoked, so we don't get the
 * chance to strip off and parse the DSA switch tag protocol header (the bridge
 * layer just returns RX_HANDLER_CONSUMED, stopping RX processing for these
 * frames).
 * The only case where that would not be an issue is when bridging can already
 * be offloaded, such as when the DSA conduit is itself a DSA or plain switchdev
 * port, and is bridged only with other ports from the same hardware device.
 */
static int
dsa_bridge_prechangelower_sanity_check(struct net_device *new_lower,
				       struct netdev_notifier_changeupper_info *info)
{}

static void dsa_tree_migrate_ports_from_lag_conduit(struct dsa_switch_tree *dst,
						    struct net_device *lag_dev)
{}

static int dsa_conduit_lag_join(struct net_device *conduit,
				struct net_device *lag_dev,
				struct netdev_lag_upper_info *uinfo,
				struct netlink_ext_ack *extack)
{}

static void dsa_conduit_lag_leave(struct net_device *conduit,
				  struct net_device *lag_dev)
{}

static int dsa_conduit_changeupper(struct net_device *dev,
				   struct netdev_notifier_changeupper_info *info)
{}

static int dsa_user_netdevice_event(struct notifier_block *nb,
				    unsigned long event, void *ptr)
{}

static void
dsa_fdb_offload_notify(struct dsa_switchdev_event_work *switchdev_work)
{}

static void dsa_user_switchdev_event_work(struct work_struct *work)
{}

static bool dsa_foreign_dev_check(const struct net_device *dev,
				  const struct net_device *foreign_dev)
{}

static int dsa_user_fdb_event(struct net_device *dev,
			      struct net_device *orig_dev,
			      unsigned long event, const void *ctx,
			      const struct switchdev_notifier_fdb_info *fdb_info)
{}

/* Called under rcu_read_lock() */
static int dsa_user_switchdev_event(struct notifier_block *unused,
				    unsigned long event, void *ptr)
{}

static int dsa_user_switchdev_blocking_event(struct notifier_block *unused,
					     unsigned long event, void *ptr)
{}

static struct notifier_block dsa_user_nb __read_mostly =;

struct notifier_block dsa_user_switchdev_notifier =;

struct notifier_block dsa_user_switchdev_blocking_notifier =;

int dsa_user_register_notifier(void)
{}

void dsa_user_unregister_notifier(void)
{}