diff options
Diffstat (limited to 'net/dsa/dsa.c')
-rw-r--r-- | net/dsa/dsa.c | 229 |
1 files changed, 1 insertions, 228 deletions
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index 422f8853d1c4..6f87dd1ee6bf 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c @@ -10,127 +10,10 @@ #include <linux/module.h> #include <linux/netdevice.h> #include <linux/sysfs.h> -#include <linux/ptp_classify.h> -#include <net/dst_metadata.h> #include "dsa_priv.h" #include "slave.h" - -static LIST_HEAD(dsa_tag_drivers_list); -static DEFINE_MUTEX(dsa_tag_drivers_lock); - -static void dsa_tag_driver_register(struct dsa_tag_driver *dsa_tag_driver, - struct module *owner) -{ - dsa_tag_driver->owner = owner; - - mutex_lock(&dsa_tag_drivers_lock); - list_add_tail(&dsa_tag_driver->list, &dsa_tag_drivers_list); - mutex_unlock(&dsa_tag_drivers_lock); -} - -void dsa_tag_drivers_register(struct dsa_tag_driver *dsa_tag_driver_array[], - unsigned int count, struct module *owner) -{ - unsigned int i; - - for (i = 0; i < count; i++) - dsa_tag_driver_register(dsa_tag_driver_array[i], owner); -} - -static void dsa_tag_driver_unregister(struct dsa_tag_driver *dsa_tag_driver) -{ - mutex_lock(&dsa_tag_drivers_lock); - list_del(&dsa_tag_driver->list); - mutex_unlock(&dsa_tag_drivers_lock); -} -EXPORT_SYMBOL_GPL(dsa_tag_drivers_register); - -void dsa_tag_drivers_unregister(struct dsa_tag_driver *dsa_tag_driver_array[], - unsigned int count) -{ - unsigned int i; - - for (i = 0; i < count; i++) - dsa_tag_driver_unregister(dsa_tag_driver_array[i]); -} -EXPORT_SYMBOL_GPL(dsa_tag_drivers_unregister); - -const char *dsa_tag_protocol_to_str(const struct dsa_device_ops *ops) -{ - return ops->name; -}; - -/* Function takes a reference on the module owning the tagger, - * so dsa_tag_driver_put must be called afterwards. - */ -const struct dsa_device_ops *dsa_tag_driver_get_by_name(const char *name) -{ - const struct dsa_device_ops *ops = ERR_PTR(-ENOPROTOOPT); - struct dsa_tag_driver *dsa_tag_driver; - - request_module("%s%s", DSA_TAG_DRIVER_ALIAS, name); - - mutex_lock(&dsa_tag_drivers_lock); - list_for_each_entry(dsa_tag_driver, &dsa_tag_drivers_list, list) { - const struct dsa_device_ops *tmp = dsa_tag_driver->ops; - - if (strcmp(name, tmp->name)) - continue; - - if (!try_module_get(dsa_tag_driver->owner)) - break; - - ops = tmp; - break; - } - mutex_unlock(&dsa_tag_drivers_lock); - - return ops; -} - -const struct dsa_device_ops *dsa_tag_driver_get_by_id(int tag_protocol) -{ - struct dsa_tag_driver *dsa_tag_driver; - const struct dsa_device_ops *ops; - bool found = false; - - request_module("%sid-%d", DSA_TAG_DRIVER_ALIAS, tag_protocol); - - mutex_lock(&dsa_tag_drivers_lock); - list_for_each_entry(dsa_tag_driver, &dsa_tag_drivers_list, list) { - ops = dsa_tag_driver->ops; - if (ops->proto == tag_protocol) { - found = true; - break; - } - } - - if (found) { - if (!try_module_get(dsa_tag_driver->owner)) - ops = ERR_PTR(-ENOPROTOOPT); - } else { - ops = ERR_PTR(-ENOPROTOOPT); - } - - mutex_unlock(&dsa_tag_drivers_lock); - - return ops; -} - -void dsa_tag_driver_put(const struct dsa_device_ops *ops) -{ - struct dsa_tag_driver *dsa_tag_driver; - - mutex_lock(&dsa_tag_drivers_lock); - list_for_each_entry(dsa_tag_driver, &dsa_tag_drivers_list, list) { - if (dsa_tag_driver->ops == ops) { - module_put(dsa_tag_driver->owner); - break; - } - } - mutex_unlock(&dsa_tag_drivers_lock); -} +#include "tag.h" static int dev_is_class(struct device *dev, void *class) { @@ -168,111 +51,6 @@ struct net_device *dsa_dev_to_net_device(struct device *dev) return NULL; } -/* Determine if we should defer delivery of skb until we have a rx timestamp. - * - * Called from dsa_switch_rcv. For now, this will only work if tagging is - * enabled on the switch. Normally the MAC driver would retrieve the hardware - * timestamp when it reads the packet out of the hardware. However in a DSA - * switch, the DSA driver owning the interface to which the packet is - * delivered is never notified unless we do so here. - */ -static bool dsa_skb_defer_rx_timestamp(struct dsa_slave_priv *p, - struct sk_buff *skb) -{ - struct dsa_switch *ds = p->dp->ds; - unsigned int type; - - if (skb_headroom(skb) < ETH_HLEN) - return false; - - __skb_push(skb, ETH_HLEN); - - type = ptp_classify_raw(skb); - - __skb_pull(skb, ETH_HLEN); - - if (type == PTP_CLASS_NONE) - return false; - - if (likely(ds->ops->port_rxtstamp)) - return ds->ops->port_rxtstamp(ds, p->dp->index, skb, type); - - return false; -} - -static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev, - struct packet_type *pt, struct net_device *unused) -{ - struct metadata_dst *md_dst = skb_metadata_dst(skb); - struct dsa_port *cpu_dp = dev->dsa_ptr; - struct sk_buff *nskb = NULL; - struct dsa_slave_priv *p; - - if (unlikely(!cpu_dp)) { - kfree_skb(skb); - return 0; - } - - skb = skb_unshare(skb, GFP_ATOMIC); - if (!skb) - return 0; - - if (md_dst && md_dst->type == METADATA_HW_PORT_MUX) { - unsigned int port = md_dst->u.port_info.port_id; - - skb_dst_drop(skb); - if (!skb_has_extensions(skb)) - skb->slow_gro = 0; - - skb->dev = dsa_master_find_slave(dev, 0, port); - if (likely(skb->dev)) { - dsa_default_offload_fwd_mark(skb); - nskb = skb; - } - } else { - nskb = cpu_dp->rcv(skb, dev); - } - - if (!nskb) { - kfree_skb(skb); - return 0; - } - - skb = nskb; - skb_push(skb, ETH_HLEN); - skb->pkt_type = PACKET_HOST; - skb->protocol = eth_type_trans(skb, skb->dev); - - if (unlikely(!dsa_slave_dev_check(skb->dev))) { - /* Packet is to be injected directly on an upper - * device, e.g. a team/bond, so skip all DSA-port - * specific actions. - */ - netif_rx(skb); - return 0; - } - - p = netdev_priv(skb->dev); - - if (unlikely(cpu_dp->ds->untag_bridge_pvid)) { - nskb = dsa_untag_bridge_pvid(skb); - if (!nskb) { - kfree_skb(skb); - return 0; - } - skb = nskb; - } - - dev_sw_netstats_rx_add(skb->dev, skb->len); - - if (dsa_skb_defer_rx_timestamp(p, skb)) - return 0; - - gro_cells_receive(&p->gcells, skb); - - return 0; -} - #ifdef CONFIG_PM_SLEEP static bool dsa_port_is_initialized(const struct dsa_port *dp) { @@ -327,11 +105,6 @@ int dsa_switch_resume(struct dsa_switch *ds) EXPORT_SYMBOL_GPL(dsa_switch_resume); #endif -static struct packet_type dsa_pack_type __read_mostly = { - .type = cpu_to_be16(ETH_P_XDSA), - .func = dsa_switch_rcv, -}; - static struct workqueue_struct *dsa_owq; bool dsa_schedule_work(struct work_struct *work) |