1007f790cSJiri Pirko /* 2007f790cSJiri Pirko * net/switchdev/switchdev.c - Switch device API 3007f790cSJiri Pirko * Copyright (c) 2014 Jiri Pirko <[email protected]> 4007f790cSJiri Pirko * 5007f790cSJiri Pirko * This program is free software; you can redistribute it and/or modify 6007f790cSJiri Pirko * it under the terms of the GNU General Public License as published by 7007f790cSJiri Pirko * the Free Software Foundation; either version 2 of the License, or 8007f790cSJiri Pirko * (at your option) any later version. 9007f790cSJiri Pirko */ 10007f790cSJiri Pirko 11007f790cSJiri Pirko #include <linux/kernel.h> 12007f790cSJiri Pirko #include <linux/types.h> 13007f790cSJiri Pirko #include <linux/init.h> 1403bf0c28SJiri Pirko #include <linux/mutex.h> 1503bf0c28SJiri Pirko #include <linux/notifier.h> 16007f790cSJiri Pirko #include <linux/netdevice.h> 17007f790cSJiri Pirko #include <net/switchdev.h> 18007f790cSJiri Pirko 19007f790cSJiri Pirko /** 20007f790cSJiri Pirko * netdev_switch_parent_id_get - Get ID of a switch 21007f790cSJiri Pirko * @dev: port device 22007f790cSJiri Pirko * @psid: switch ID 23007f790cSJiri Pirko * 24007f790cSJiri Pirko * Get ID of a switch this port is part of. 25007f790cSJiri Pirko */ 26007f790cSJiri Pirko int netdev_switch_parent_id_get(struct net_device *dev, 27007f790cSJiri Pirko struct netdev_phys_item_id *psid) 28007f790cSJiri Pirko { 29007f790cSJiri Pirko const struct net_device_ops *ops = dev->netdev_ops; 30007f790cSJiri Pirko 31007f790cSJiri Pirko if (!ops->ndo_switch_parent_id_get) 32007f790cSJiri Pirko return -EOPNOTSUPP; 33007f790cSJiri Pirko return ops->ndo_switch_parent_id_get(dev, psid); 34007f790cSJiri Pirko } 35007f790cSJiri Pirko EXPORT_SYMBOL(netdev_switch_parent_id_get); 3638dcf357SScott Feldman 3738dcf357SScott Feldman /** 3838dcf357SScott Feldman * netdev_switch_port_stp_update - Notify switch device port of STP 3938dcf357SScott Feldman * state change 4038dcf357SScott Feldman * @dev: port device 4138dcf357SScott Feldman * @state: port STP state 4238dcf357SScott Feldman * 4338dcf357SScott Feldman * Notify switch device port of bridge port STP state change. 4438dcf357SScott Feldman */ 4538dcf357SScott Feldman int netdev_switch_port_stp_update(struct net_device *dev, u8 state) 4638dcf357SScott Feldman { 4738dcf357SScott Feldman const struct net_device_ops *ops = dev->netdev_ops; 4838dcf357SScott Feldman 4938dcf357SScott Feldman if (!ops->ndo_switch_port_stp_update) 5038dcf357SScott Feldman return -EOPNOTSUPP; 5138dcf357SScott Feldman WARN_ON(!ops->ndo_switch_parent_id_get); 5238dcf357SScott Feldman return ops->ndo_switch_port_stp_update(dev, state); 5338dcf357SScott Feldman } 5438dcf357SScott Feldman EXPORT_SYMBOL(netdev_switch_port_stp_update); 5503bf0c28SJiri Pirko 5603bf0c28SJiri Pirko static DEFINE_MUTEX(netdev_switch_mutex); 5703bf0c28SJiri Pirko static RAW_NOTIFIER_HEAD(netdev_switch_notif_chain); 5803bf0c28SJiri Pirko 5903bf0c28SJiri Pirko /** 6003bf0c28SJiri Pirko * register_netdev_switch_notifier - Register nofifier 6103bf0c28SJiri Pirko * @nb: notifier_block 6203bf0c28SJiri Pirko * 6303bf0c28SJiri Pirko * Register switch device notifier. This should be used by code 6403bf0c28SJiri Pirko * which needs to monitor events happening in particular device. 6503bf0c28SJiri Pirko * Return values are same as for atomic_notifier_chain_register(). 6603bf0c28SJiri Pirko */ 6703bf0c28SJiri Pirko int register_netdev_switch_notifier(struct notifier_block *nb) 6803bf0c28SJiri Pirko { 6903bf0c28SJiri Pirko int err; 7003bf0c28SJiri Pirko 7103bf0c28SJiri Pirko mutex_lock(&netdev_switch_mutex); 7203bf0c28SJiri Pirko err = raw_notifier_chain_register(&netdev_switch_notif_chain, nb); 7303bf0c28SJiri Pirko mutex_unlock(&netdev_switch_mutex); 7403bf0c28SJiri Pirko return err; 7503bf0c28SJiri Pirko } 7603bf0c28SJiri Pirko EXPORT_SYMBOL(register_netdev_switch_notifier); 7703bf0c28SJiri Pirko 7803bf0c28SJiri Pirko /** 7903bf0c28SJiri Pirko * unregister_netdev_switch_notifier - Unregister nofifier 8003bf0c28SJiri Pirko * @nb: notifier_block 8103bf0c28SJiri Pirko * 8203bf0c28SJiri Pirko * Unregister switch device notifier. 8303bf0c28SJiri Pirko * Return values are same as for atomic_notifier_chain_unregister(). 8403bf0c28SJiri Pirko */ 8503bf0c28SJiri Pirko int unregister_netdev_switch_notifier(struct notifier_block *nb) 8603bf0c28SJiri Pirko { 8703bf0c28SJiri Pirko int err; 8803bf0c28SJiri Pirko 8903bf0c28SJiri Pirko mutex_lock(&netdev_switch_mutex); 9003bf0c28SJiri Pirko err = raw_notifier_chain_unregister(&netdev_switch_notif_chain, nb); 9103bf0c28SJiri Pirko mutex_unlock(&netdev_switch_mutex); 9203bf0c28SJiri Pirko return err; 9303bf0c28SJiri Pirko } 9403bf0c28SJiri Pirko EXPORT_SYMBOL(unregister_netdev_switch_notifier); 9503bf0c28SJiri Pirko 9603bf0c28SJiri Pirko /** 9703bf0c28SJiri Pirko * call_netdev_switch_notifiers - Call nofifiers 9803bf0c28SJiri Pirko * @val: value passed unmodified to notifier function 9903bf0c28SJiri Pirko * @dev: port device 10003bf0c28SJiri Pirko * @info: notifier information data 10103bf0c28SJiri Pirko * 10203bf0c28SJiri Pirko * Call all network notifier blocks. This should be called by driver 10303bf0c28SJiri Pirko * when it needs to propagate hardware event. 10403bf0c28SJiri Pirko * Return values are same as for atomic_notifier_call_chain(). 10503bf0c28SJiri Pirko */ 10603bf0c28SJiri Pirko int call_netdev_switch_notifiers(unsigned long val, struct net_device *dev, 10703bf0c28SJiri Pirko struct netdev_switch_notifier_info *info) 10803bf0c28SJiri Pirko { 10903bf0c28SJiri Pirko int err; 11003bf0c28SJiri Pirko 11103bf0c28SJiri Pirko info->dev = dev; 11203bf0c28SJiri Pirko mutex_lock(&netdev_switch_mutex); 11303bf0c28SJiri Pirko err = raw_notifier_call_chain(&netdev_switch_notif_chain, val, info); 11403bf0c28SJiri Pirko mutex_unlock(&netdev_switch_mutex); 11503bf0c28SJiri Pirko return err; 11603bf0c28SJiri Pirko } 11703bf0c28SJiri Pirko EXPORT_SYMBOL(call_netdev_switch_notifiers); 118*8a44dbb2SRoopa Prabhu 119*8a44dbb2SRoopa Prabhu /** 120*8a44dbb2SRoopa Prabhu * netdev_switch_port_bridge_setlink - Notify switch device port of bridge 121*8a44dbb2SRoopa Prabhu * port attributes 122*8a44dbb2SRoopa Prabhu * 123*8a44dbb2SRoopa Prabhu * @dev: port device 124*8a44dbb2SRoopa Prabhu * @nlh: netlink msg with bridge port attributes 125*8a44dbb2SRoopa Prabhu * @flags: bridge setlink flags 126*8a44dbb2SRoopa Prabhu * 127*8a44dbb2SRoopa Prabhu * Notify switch device port of bridge port attributes 128*8a44dbb2SRoopa Prabhu */ 129*8a44dbb2SRoopa Prabhu int netdev_switch_port_bridge_setlink(struct net_device *dev, 130*8a44dbb2SRoopa Prabhu struct nlmsghdr *nlh, u16 flags) 131*8a44dbb2SRoopa Prabhu { 132*8a44dbb2SRoopa Prabhu const struct net_device_ops *ops = dev->netdev_ops; 133*8a44dbb2SRoopa Prabhu 134*8a44dbb2SRoopa Prabhu if (!(dev->features & NETIF_F_HW_SWITCH_OFFLOAD)) 135*8a44dbb2SRoopa Prabhu return 0; 136*8a44dbb2SRoopa Prabhu 137*8a44dbb2SRoopa Prabhu if (!ops->ndo_bridge_setlink) 138*8a44dbb2SRoopa Prabhu return -EOPNOTSUPP; 139*8a44dbb2SRoopa Prabhu 140*8a44dbb2SRoopa Prabhu return ops->ndo_bridge_setlink(dev, nlh, flags); 141*8a44dbb2SRoopa Prabhu } 142*8a44dbb2SRoopa Prabhu EXPORT_SYMBOL(netdev_switch_port_bridge_setlink); 143*8a44dbb2SRoopa Prabhu 144*8a44dbb2SRoopa Prabhu /** 145*8a44dbb2SRoopa Prabhu * netdev_switch_port_bridge_dellink - Notify switch device port of bridge 146*8a44dbb2SRoopa Prabhu * port attribute delete 147*8a44dbb2SRoopa Prabhu * 148*8a44dbb2SRoopa Prabhu * @dev: port device 149*8a44dbb2SRoopa Prabhu * @nlh: netlink msg with bridge port attributes 150*8a44dbb2SRoopa Prabhu * @flags: bridge setlink flags 151*8a44dbb2SRoopa Prabhu * 152*8a44dbb2SRoopa Prabhu * Notify switch device port of bridge port attribute delete 153*8a44dbb2SRoopa Prabhu */ 154*8a44dbb2SRoopa Prabhu int netdev_switch_port_bridge_dellink(struct net_device *dev, 155*8a44dbb2SRoopa Prabhu struct nlmsghdr *nlh, u16 flags) 156*8a44dbb2SRoopa Prabhu { 157*8a44dbb2SRoopa Prabhu const struct net_device_ops *ops = dev->netdev_ops; 158*8a44dbb2SRoopa Prabhu 159*8a44dbb2SRoopa Prabhu if (!(dev->features & NETIF_F_HW_SWITCH_OFFLOAD)) 160*8a44dbb2SRoopa Prabhu return 0; 161*8a44dbb2SRoopa Prabhu 162*8a44dbb2SRoopa Prabhu if (!ops->ndo_bridge_dellink) 163*8a44dbb2SRoopa Prabhu return -EOPNOTSUPP; 164*8a44dbb2SRoopa Prabhu 165*8a44dbb2SRoopa Prabhu return ops->ndo_bridge_dellink(dev, nlh, flags); 166*8a44dbb2SRoopa Prabhu } 167*8a44dbb2SRoopa Prabhu EXPORT_SYMBOL(netdev_switch_port_bridge_dellink); 168*8a44dbb2SRoopa Prabhu 169*8a44dbb2SRoopa Prabhu /** 170*8a44dbb2SRoopa Prabhu * ndo_dflt_netdev_switch_port_bridge_setlink - default ndo bridge setlink 171*8a44dbb2SRoopa Prabhu * op for master devices 172*8a44dbb2SRoopa Prabhu * 173*8a44dbb2SRoopa Prabhu * @dev: port device 174*8a44dbb2SRoopa Prabhu * @nlh: netlink msg with bridge port attributes 175*8a44dbb2SRoopa Prabhu * @flags: bridge setlink flags 176*8a44dbb2SRoopa Prabhu * 177*8a44dbb2SRoopa Prabhu * Notify master device slaves of bridge port attributes 178*8a44dbb2SRoopa Prabhu */ 179*8a44dbb2SRoopa Prabhu int ndo_dflt_netdev_switch_port_bridge_setlink(struct net_device *dev, 180*8a44dbb2SRoopa Prabhu struct nlmsghdr *nlh, u16 flags) 181*8a44dbb2SRoopa Prabhu { 182*8a44dbb2SRoopa Prabhu struct net_device *lower_dev; 183*8a44dbb2SRoopa Prabhu struct list_head *iter; 184*8a44dbb2SRoopa Prabhu int ret = 0, err = 0; 185*8a44dbb2SRoopa Prabhu 186*8a44dbb2SRoopa Prabhu if (!(dev->features & NETIF_F_HW_SWITCH_OFFLOAD)) 187*8a44dbb2SRoopa Prabhu return ret; 188*8a44dbb2SRoopa Prabhu 189*8a44dbb2SRoopa Prabhu netdev_for_each_lower_dev(dev, lower_dev, iter) { 190*8a44dbb2SRoopa Prabhu err = netdev_switch_port_bridge_setlink(lower_dev, nlh, flags); 191*8a44dbb2SRoopa Prabhu if (err && err != -EOPNOTSUPP) 192*8a44dbb2SRoopa Prabhu ret = err; 193*8a44dbb2SRoopa Prabhu } 194*8a44dbb2SRoopa Prabhu 195*8a44dbb2SRoopa Prabhu return ret; 196*8a44dbb2SRoopa Prabhu } 197*8a44dbb2SRoopa Prabhu EXPORT_SYMBOL(ndo_dflt_netdev_switch_port_bridge_setlink); 198*8a44dbb2SRoopa Prabhu 199*8a44dbb2SRoopa Prabhu /** 200*8a44dbb2SRoopa Prabhu * ndo_dflt_netdev_switch_port_bridge_dellink - default ndo bridge dellink 201*8a44dbb2SRoopa Prabhu * op for master devices 202*8a44dbb2SRoopa Prabhu * 203*8a44dbb2SRoopa Prabhu * @dev: port device 204*8a44dbb2SRoopa Prabhu * @nlh: netlink msg with bridge port attributes 205*8a44dbb2SRoopa Prabhu * @flags: bridge dellink flags 206*8a44dbb2SRoopa Prabhu * 207*8a44dbb2SRoopa Prabhu * Notify master device slaves of bridge port attribute deletes 208*8a44dbb2SRoopa Prabhu */ 209*8a44dbb2SRoopa Prabhu int ndo_dflt_netdev_switch_port_bridge_dellink(struct net_device *dev, 210*8a44dbb2SRoopa Prabhu struct nlmsghdr *nlh, u16 flags) 211*8a44dbb2SRoopa Prabhu { 212*8a44dbb2SRoopa Prabhu struct net_device *lower_dev; 213*8a44dbb2SRoopa Prabhu struct list_head *iter; 214*8a44dbb2SRoopa Prabhu int ret = 0, err = 0; 215*8a44dbb2SRoopa Prabhu 216*8a44dbb2SRoopa Prabhu if (!(dev->features & NETIF_F_HW_SWITCH_OFFLOAD)) 217*8a44dbb2SRoopa Prabhu return ret; 218*8a44dbb2SRoopa Prabhu 219*8a44dbb2SRoopa Prabhu netdev_for_each_lower_dev(dev, lower_dev, iter) { 220*8a44dbb2SRoopa Prabhu err = netdev_switch_port_bridge_dellink(lower_dev, nlh, flags); 221*8a44dbb2SRoopa Prabhu if (err && err != -EOPNOTSUPP) 222*8a44dbb2SRoopa Prabhu ret = err; 223*8a44dbb2SRoopa Prabhu } 224*8a44dbb2SRoopa Prabhu 225*8a44dbb2SRoopa Prabhu return ret; 226*8a44dbb2SRoopa Prabhu } 227*8a44dbb2SRoopa Prabhu EXPORT_SYMBOL(ndo_dflt_netdev_switch_port_bridge_dellink); 228