cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

cpsw_switchdev.c (13764B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Texas Instruments switchdev Driver
      4 *
      5 * Copyright (C) 2019 Texas Instruments
      6 *
      7 */
      8
      9#include <linux/etherdevice.h>
     10#include <linux/if_bridge.h>
     11#include <linux/netdevice.h>
     12#include <linux/workqueue.h>
     13#include <net/switchdev.h>
     14
     15#include "cpsw.h"
     16#include "cpsw_ale.h"
     17#include "cpsw_priv.h"
     18#include "cpsw_switchdev.h"
     19
     20struct cpsw_switchdev_event_work {
     21	struct work_struct work;
     22	struct switchdev_notifier_fdb_info fdb_info;
     23	struct cpsw_priv *priv;
     24	unsigned long event;
     25};
     26
     27static int cpsw_port_stp_state_set(struct cpsw_priv *priv, u8 state)
     28{
     29	struct cpsw_common *cpsw = priv->cpsw;
     30	u8 cpsw_state;
     31	int ret = 0;
     32
     33	switch (state) {
     34	case BR_STATE_FORWARDING:
     35		cpsw_state = ALE_PORT_STATE_FORWARD;
     36		break;
     37	case BR_STATE_LEARNING:
     38		cpsw_state = ALE_PORT_STATE_LEARN;
     39		break;
     40	case BR_STATE_DISABLED:
     41		cpsw_state = ALE_PORT_STATE_DISABLE;
     42		break;
     43	case BR_STATE_LISTENING:
     44	case BR_STATE_BLOCKING:
     45		cpsw_state = ALE_PORT_STATE_BLOCK;
     46		break;
     47	default:
     48		return -EOPNOTSUPP;
     49	}
     50
     51	ret = cpsw_ale_control_set(cpsw->ale, priv->emac_port,
     52				   ALE_PORT_STATE, cpsw_state);
     53	dev_dbg(priv->dev, "ale state: %u\n", cpsw_state);
     54
     55	return ret;
     56}
     57
     58static int cpsw_port_attr_br_flags_set(struct cpsw_priv *priv,
     59				       struct net_device *orig_dev,
     60				       struct switchdev_brport_flags flags)
     61{
     62	struct cpsw_common *cpsw = priv->cpsw;
     63
     64	if (flags.mask & BR_MCAST_FLOOD) {
     65		bool unreg_mcast_add = false;
     66
     67		if (flags.val & BR_MCAST_FLOOD)
     68			unreg_mcast_add = true;
     69
     70		dev_dbg(priv->dev, "BR_MCAST_FLOOD: %d port %u\n",
     71			unreg_mcast_add, priv->emac_port);
     72
     73		cpsw_ale_set_unreg_mcast(cpsw->ale, BIT(priv->emac_port),
     74					 unreg_mcast_add);
     75	}
     76
     77	return 0;
     78}
     79
     80static int cpsw_port_attr_br_flags_pre_set(struct net_device *netdev,
     81					   struct switchdev_brport_flags flags)
     82{
     83	if (flags.mask & ~(BR_LEARNING | BR_MCAST_FLOOD))
     84		return -EINVAL;
     85
     86	return 0;
     87}
     88
     89static int cpsw_port_attr_set(struct net_device *ndev, const void *ctx,
     90			      const struct switchdev_attr *attr,
     91			      struct netlink_ext_ack *extack)
     92{
     93	struct cpsw_priv *priv = netdev_priv(ndev);
     94	int ret;
     95
     96	dev_dbg(priv->dev, "attr: id %u port: %u\n", attr->id, priv->emac_port);
     97
     98	switch (attr->id) {
     99	case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS:
    100		ret = cpsw_port_attr_br_flags_pre_set(ndev,
    101						      attr->u.brport_flags);
    102		break;
    103	case SWITCHDEV_ATTR_ID_PORT_STP_STATE:
    104		ret = cpsw_port_stp_state_set(priv, attr->u.stp_state);
    105		dev_dbg(priv->dev, "stp state: %u\n", attr->u.stp_state);
    106		break;
    107	case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
    108		ret = cpsw_port_attr_br_flags_set(priv, attr->orig_dev,
    109						  attr->u.brport_flags);
    110		break;
    111	default:
    112		ret = -EOPNOTSUPP;
    113		break;
    114	}
    115
    116	return ret;
    117}
    118
    119static u16 cpsw_get_pvid(struct cpsw_priv *priv)
    120{
    121	struct cpsw_common *cpsw = priv->cpsw;
    122	u32 __iomem *port_vlan_reg;
    123	u32 pvid;
    124
    125	if (priv->emac_port) {
    126		int reg = CPSW2_PORT_VLAN;
    127
    128		if (cpsw->version == CPSW_VERSION_1)
    129			reg = CPSW1_PORT_VLAN;
    130		pvid = slave_read(cpsw->slaves + (priv->emac_port - 1), reg);
    131	} else {
    132		port_vlan_reg = &cpsw->host_port_regs->port_vlan;
    133		pvid = readl(port_vlan_reg);
    134	}
    135
    136	pvid = pvid & 0xfff;
    137
    138	return pvid;
    139}
    140
    141static void cpsw_set_pvid(struct cpsw_priv *priv, u16 vid, bool cfi, u32 cos)
    142{
    143	struct cpsw_common *cpsw = priv->cpsw;
    144	void __iomem *port_vlan_reg;
    145	u32 pvid;
    146
    147	pvid = vid;
    148	pvid |= cfi ? BIT(12) : 0;
    149	pvid |= (cos & 0x7) << 13;
    150
    151	if (priv->emac_port) {
    152		int reg = CPSW2_PORT_VLAN;
    153
    154		if (cpsw->version == CPSW_VERSION_1)
    155			reg = CPSW1_PORT_VLAN;
    156		/* no barrier */
    157		slave_write(cpsw->slaves + (priv->emac_port - 1), pvid, reg);
    158	} else {
    159		/* CPU port */
    160		port_vlan_reg = &cpsw->host_port_regs->port_vlan;
    161		writel(pvid, port_vlan_reg);
    162	}
    163}
    164
    165static int cpsw_port_vlan_add(struct cpsw_priv *priv, bool untag, bool pvid,
    166			      u16 vid, struct net_device *orig_dev)
    167{
    168	bool cpu_port = netif_is_bridge_master(orig_dev);
    169	struct cpsw_common *cpsw = priv->cpsw;
    170	int unreg_mcast_mask = 0;
    171	int reg_mcast_mask = 0;
    172	int untag_mask = 0;
    173	int port_mask;
    174	int ret = 0;
    175	u32 flags;
    176
    177	if (cpu_port) {
    178		port_mask = BIT(HOST_PORT_NUM);
    179		flags = orig_dev->flags;
    180		unreg_mcast_mask = port_mask;
    181	} else {
    182		port_mask = BIT(priv->emac_port);
    183		flags = priv->ndev->flags;
    184	}
    185
    186	if (flags & IFF_MULTICAST)
    187		reg_mcast_mask = port_mask;
    188
    189	if (untag)
    190		untag_mask = port_mask;
    191
    192	ret = cpsw_ale_vlan_add_modify(cpsw->ale, vid, port_mask, untag_mask,
    193				       reg_mcast_mask, unreg_mcast_mask);
    194	if (ret) {
    195		dev_err(priv->dev, "Unable to add vlan\n");
    196		return ret;
    197	}
    198
    199	if (cpu_port)
    200		cpsw_ale_add_ucast(cpsw->ale, priv->mac_addr,
    201				   HOST_PORT_NUM, ALE_VLAN, vid);
    202	if (!pvid)
    203		return ret;
    204
    205	cpsw_set_pvid(priv, vid, 0, 0);
    206
    207	dev_dbg(priv->dev, "VID add: %s: vid:%u ports:%X\n",
    208		priv->ndev->name, vid, port_mask);
    209	return ret;
    210}
    211
    212static int cpsw_port_vlan_del(struct cpsw_priv *priv, u16 vid,
    213			      struct net_device *orig_dev)
    214{
    215	bool cpu_port = netif_is_bridge_master(orig_dev);
    216	struct cpsw_common *cpsw = priv->cpsw;
    217	int port_mask;
    218	int ret = 0;
    219
    220	if (cpu_port)
    221		port_mask = BIT(HOST_PORT_NUM);
    222	else
    223		port_mask = BIT(priv->emac_port);
    224
    225	ret = cpsw_ale_vlan_del_modify(cpsw->ale, vid, port_mask);
    226	if (ret != 0)
    227		return ret;
    228
    229	/* We don't care for the return value here, error is returned only if
    230	 * the unicast entry is not present
    231	 */
    232	if (cpu_port)
    233		cpsw_ale_del_ucast(cpsw->ale, priv->mac_addr,
    234				   HOST_PORT_NUM, ALE_VLAN, vid);
    235
    236	if (vid == cpsw_get_pvid(priv))
    237		cpsw_set_pvid(priv, 0, 0, 0);
    238
    239	/* We don't care for the return value here, error is returned only if
    240	 * the multicast entry is not present
    241	 */
    242	cpsw_ale_del_mcast(cpsw->ale, priv->ndev->broadcast,
    243			   port_mask, ALE_VLAN, vid);
    244	dev_dbg(priv->dev, "VID del: %s: vid:%u ports:%X\n",
    245		priv->ndev->name, vid, port_mask);
    246
    247	return ret;
    248}
    249
    250static int cpsw_port_vlans_add(struct cpsw_priv *priv,
    251			       const struct switchdev_obj_port_vlan *vlan)
    252{
    253	bool untag = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
    254	struct net_device *orig_dev = vlan->obj.orig_dev;
    255	bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
    256
    257	dev_dbg(priv->dev, "VID add: %s: vid:%u flags:%X\n",
    258		priv->ndev->name, vlan->vid, vlan->flags);
    259
    260	return cpsw_port_vlan_add(priv, untag, pvid, vlan->vid, orig_dev);
    261}
    262
    263static int cpsw_port_mdb_add(struct cpsw_priv *priv,
    264			     struct switchdev_obj_port_mdb *mdb)
    265
    266{
    267	struct net_device *orig_dev = mdb->obj.orig_dev;
    268	bool cpu_port = netif_is_bridge_master(orig_dev);
    269	struct cpsw_common *cpsw = priv->cpsw;
    270	int port_mask;
    271	int err;
    272
    273	if (cpu_port)
    274		port_mask = BIT(HOST_PORT_NUM);
    275	else
    276		port_mask = BIT(priv->emac_port);
    277
    278	err = cpsw_ale_add_mcast(cpsw->ale, mdb->addr, port_mask,
    279				 ALE_VLAN, mdb->vid, 0);
    280	dev_dbg(priv->dev, "MDB add: %s: vid %u:%pM  ports: %X\n",
    281		priv->ndev->name, mdb->vid, mdb->addr, port_mask);
    282
    283	return err;
    284}
    285
    286static int cpsw_port_mdb_del(struct cpsw_priv *priv,
    287			     struct switchdev_obj_port_mdb *mdb)
    288
    289{
    290	struct net_device *orig_dev = mdb->obj.orig_dev;
    291	bool cpu_port = netif_is_bridge_master(orig_dev);
    292	struct cpsw_common *cpsw = priv->cpsw;
    293	int del_mask;
    294	int err;
    295
    296	if (cpu_port)
    297		del_mask = BIT(HOST_PORT_NUM);
    298	else
    299		del_mask = BIT(priv->emac_port);
    300
    301	err = cpsw_ale_del_mcast(cpsw->ale, mdb->addr, del_mask,
    302				 ALE_VLAN, mdb->vid);
    303	dev_dbg(priv->dev, "MDB del: %s: vid %u:%pM  ports: %X\n",
    304		priv->ndev->name, mdb->vid, mdb->addr, del_mask);
    305
    306	return err;
    307}
    308
    309static int cpsw_port_obj_add(struct net_device *ndev, const void *ctx,
    310			     const struct switchdev_obj *obj,
    311			     struct netlink_ext_ack *extack)
    312{
    313	struct switchdev_obj_port_vlan *vlan = SWITCHDEV_OBJ_PORT_VLAN(obj);
    314	struct switchdev_obj_port_mdb *mdb = SWITCHDEV_OBJ_PORT_MDB(obj);
    315	struct cpsw_priv *priv = netdev_priv(ndev);
    316	int err = 0;
    317
    318	dev_dbg(priv->dev, "obj_add: id %u port: %u\n",
    319		obj->id, priv->emac_port);
    320
    321	switch (obj->id) {
    322	case SWITCHDEV_OBJ_ID_PORT_VLAN:
    323		err = cpsw_port_vlans_add(priv, vlan);
    324		break;
    325	case SWITCHDEV_OBJ_ID_PORT_MDB:
    326	case SWITCHDEV_OBJ_ID_HOST_MDB:
    327		err = cpsw_port_mdb_add(priv, mdb);
    328		break;
    329	default:
    330		err = -EOPNOTSUPP;
    331		break;
    332	}
    333
    334	return err;
    335}
    336
    337static int cpsw_port_obj_del(struct net_device *ndev, const void *ctx,
    338			     const struct switchdev_obj *obj)
    339{
    340	struct switchdev_obj_port_vlan *vlan = SWITCHDEV_OBJ_PORT_VLAN(obj);
    341	struct switchdev_obj_port_mdb *mdb = SWITCHDEV_OBJ_PORT_MDB(obj);
    342	struct cpsw_priv *priv = netdev_priv(ndev);
    343	int err = 0;
    344
    345	dev_dbg(priv->dev, "obj_del: id %u port: %u\n",
    346		obj->id, priv->emac_port);
    347
    348	switch (obj->id) {
    349	case SWITCHDEV_OBJ_ID_PORT_VLAN:
    350		err = cpsw_port_vlan_del(priv, vlan->vid, vlan->obj.orig_dev);
    351		break;
    352	case SWITCHDEV_OBJ_ID_PORT_MDB:
    353	case SWITCHDEV_OBJ_ID_HOST_MDB:
    354		err = cpsw_port_mdb_del(priv, mdb);
    355		break;
    356	default:
    357		err = -EOPNOTSUPP;
    358		break;
    359	}
    360
    361	return err;
    362}
    363
    364static void cpsw_fdb_offload_notify(struct net_device *ndev,
    365				    struct switchdev_notifier_fdb_info *rcv)
    366{
    367	struct switchdev_notifier_fdb_info info = {};
    368
    369	info.addr = rcv->addr;
    370	info.vid = rcv->vid;
    371	info.offloaded = true;
    372	call_switchdev_notifiers(SWITCHDEV_FDB_OFFLOADED,
    373				 ndev, &info.info, NULL);
    374}
    375
    376static void cpsw_switchdev_event_work(struct work_struct *work)
    377{
    378	struct cpsw_switchdev_event_work *switchdev_work =
    379		container_of(work, struct cpsw_switchdev_event_work, work);
    380	struct cpsw_priv *priv = switchdev_work->priv;
    381	struct switchdev_notifier_fdb_info *fdb;
    382	struct cpsw_common *cpsw = priv->cpsw;
    383	int port = priv->emac_port;
    384
    385	rtnl_lock();
    386	switch (switchdev_work->event) {
    387	case SWITCHDEV_FDB_ADD_TO_DEVICE:
    388		fdb = &switchdev_work->fdb_info;
    389
    390		dev_dbg(cpsw->dev, "cpsw_fdb_add: MACID = %pM vid = %u flags = %u %u -- port %d\n",
    391			fdb->addr, fdb->vid, fdb->added_by_user,
    392			fdb->offloaded, port);
    393
    394		if (!fdb->added_by_user || fdb->is_local)
    395			break;
    396		if (memcmp(priv->mac_addr, (u8 *)fdb->addr, ETH_ALEN) == 0)
    397			port = HOST_PORT_NUM;
    398
    399		cpsw_ale_add_ucast(cpsw->ale, (u8 *)fdb->addr, port,
    400				   fdb->vid ? ALE_VLAN : 0, fdb->vid);
    401		cpsw_fdb_offload_notify(priv->ndev, fdb);
    402		break;
    403	case SWITCHDEV_FDB_DEL_TO_DEVICE:
    404		fdb = &switchdev_work->fdb_info;
    405
    406		dev_dbg(cpsw->dev, "cpsw_fdb_del: MACID = %pM vid = %u flags = %u %u -- port %d\n",
    407			fdb->addr, fdb->vid, fdb->added_by_user,
    408			fdb->offloaded, port);
    409
    410		if (!fdb->added_by_user || fdb->is_local)
    411			break;
    412		if (memcmp(priv->mac_addr, (u8 *)fdb->addr, ETH_ALEN) == 0)
    413			port = HOST_PORT_NUM;
    414
    415		cpsw_ale_del_ucast(cpsw->ale, (u8 *)fdb->addr, port,
    416				   fdb->vid ? ALE_VLAN : 0, fdb->vid);
    417		break;
    418	default:
    419		break;
    420	}
    421	rtnl_unlock();
    422
    423	kfree(switchdev_work->fdb_info.addr);
    424	kfree(switchdev_work);
    425	dev_put(priv->ndev);
    426}
    427
    428/* called under rcu_read_lock() */
    429static int cpsw_switchdev_event(struct notifier_block *unused,
    430				unsigned long event, void *ptr)
    431{
    432	struct net_device *ndev = switchdev_notifier_info_to_dev(ptr);
    433	struct switchdev_notifier_fdb_info *fdb_info = ptr;
    434	struct cpsw_switchdev_event_work *switchdev_work;
    435	struct cpsw_priv *priv = netdev_priv(ndev);
    436	int err;
    437
    438	if (event == SWITCHDEV_PORT_ATTR_SET) {
    439		err = switchdev_handle_port_attr_set(ndev, ptr,
    440						     cpsw_port_dev_check,
    441						     cpsw_port_attr_set);
    442		return notifier_from_errno(err);
    443	}
    444
    445	if (!cpsw_port_dev_check(ndev))
    446		return NOTIFY_DONE;
    447
    448	switchdev_work = kzalloc(sizeof(*switchdev_work), GFP_ATOMIC);
    449	if (WARN_ON(!switchdev_work))
    450		return NOTIFY_BAD;
    451
    452	INIT_WORK(&switchdev_work->work, cpsw_switchdev_event_work);
    453	switchdev_work->priv = priv;
    454	switchdev_work->event = event;
    455
    456	switch (event) {
    457	case SWITCHDEV_FDB_ADD_TO_DEVICE:
    458	case SWITCHDEV_FDB_DEL_TO_DEVICE:
    459		memcpy(&switchdev_work->fdb_info, ptr,
    460		       sizeof(switchdev_work->fdb_info));
    461		switchdev_work->fdb_info.addr = kzalloc(ETH_ALEN, GFP_ATOMIC);
    462		if (!switchdev_work->fdb_info.addr)
    463			goto err_addr_alloc;
    464		ether_addr_copy((u8 *)switchdev_work->fdb_info.addr,
    465				fdb_info->addr);
    466		dev_hold(ndev);
    467		break;
    468	default:
    469		kfree(switchdev_work);
    470		return NOTIFY_DONE;
    471	}
    472
    473	queue_work(system_long_wq, &switchdev_work->work);
    474
    475	return NOTIFY_DONE;
    476
    477err_addr_alloc:
    478	kfree(switchdev_work);
    479	return NOTIFY_BAD;
    480}
    481
    482static struct notifier_block cpsw_switchdev_notifier = {
    483	.notifier_call = cpsw_switchdev_event,
    484};
    485
    486static int cpsw_switchdev_blocking_event(struct notifier_block *unused,
    487					 unsigned long event, void *ptr)
    488{
    489	struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
    490	int err;
    491
    492	switch (event) {
    493	case SWITCHDEV_PORT_OBJ_ADD:
    494		err = switchdev_handle_port_obj_add(dev, ptr,
    495						    cpsw_port_dev_check,
    496						    cpsw_port_obj_add);
    497		return notifier_from_errno(err);
    498	case SWITCHDEV_PORT_OBJ_DEL:
    499		err = switchdev_handle_port_obj_del(dev, ptr,
    500						    cpsw_port_dev_check,
    501						    cpsw_port_obj_del);
    502		return notifier_from_errno(err);
    503	case SWITCHDEV_PORT_ATTR_SET:
    504		err = switchdev_handle_port_attr_set(dev, ptr,
    505						     cpsw_port_dev_check,
    506						     cpsw_port_attr_set);
    507		return notifier_from_errno(err);
    508	default:
    509		break;
    510	}
    511
    512	return NOTIFY_DONE;
    513}
    514
    515static struct notifier_block cpsw_switchdev_bl_notifier = {
    516	.notifier_call = cpsw_switchdev_blocking_event,
    517};
    518
    519int cpsw_switchdev_register_notifiers(struct cpsw_common *cpsw)
    520{
    521	int ret = 0;
    522
    523	ret = register_switchdev_notifier(&cpsw_switchdev_notifier);
    524	if (ret) {
    525		dev_err(cpsw->dev, "register switchdev notifier fail ret:%d\n",
    526			ret);
    527		return ret;
    528	}
    529
    530	ret = register_switchdev_blocking_notifier(&cpsw_switchdev_bl_notifier);
    531	if (ret) {
    532		dev_err(cpsw->dev, "register switchdev blocking notifier ret:%d\n",
    533			ret);
    534		unregister_switchdev_notifier(&cpsw_switchdev_notifier);
    535	}
    536
    537	return ret;
    538}
    539
    540void cpsw_switchdev_unregister_notifiers(struct cpsw_common *cpsw)
    541{
    542	unregister_switchdev_blocking_notifier(&cpsw_switchdev_bl_notifier);
    543	unregister_switchdev_notifier(&cpsw_switchdev_notifier);
    544}