1 // SPDX-License-Identifier: (GPL-2.0 OR MIT) 2 /* Microsemi Ocelot Switch driver 3 * 4 * This contains glue logic between the switchdev driver operations and the 5 * mscc_ocelot_switch_lib. 6 * 7 * Copyright (c) 2017, 2019 Microsemi Corporation 8 * Copyright 2020-2021 NXP Semiconductors 9 */ 10 11 #include <linux/if_bridge.h> 12 #include <linux/mrp_bridge.h> 13 #include <soc/mscc/ocelot_vcap.h> 14 #include <uapi/linux/mrp_bridge.h> 15 #include "ocelot.h" 16 #include "ocelot_vcap.h" 17 18 static int ocelot_mrp_del_vcap(struct ocelot *ocelot, int port) 19 { 20 struct ocelot_vcap_block *block_vcap_is2; 21 struct ocelot_vcap_filter *filter; 22 23 block_vcap_is2 = &ocelot->block[VCAP_IS2]; 24 filter = ocelot_vcap_block_find_filter_by_id(block_vcap_is2, port, 25 false); 26 if (!filter) 27 return 0; 28 29 return ocelot_vcap_filter_del(ocelot, filter); 30 } 31 32 int ocelot_mrp_add(struct ocelot *ocelot, int port, 33 const struct switchdev_obj_mrp *mrp) 34 { 35 struct ocelot_port *ocelot_port = ocelot->ports[port]; 36 struct ocelot_port_private *priv; 37 struct net_device *dev; 38 39 if (!ocelot_port) 40 return -EOPNOTSUPP; 41 42 priv = container_of(ocelot_port, struct ocelot_port_private, port); 43 dev = priv->dev; 44 45 if (mrp->p_port != dev && mrp->s_port != dev) 46 return 0; 47 48 if (ocelot->mrp_ring_id != 0 && 49 ocelot->mrp_s_port && 50 ocelot->mrp_p_port) 51 return -EINVAL; 52 53 if (mrp->p_port == dev) 54 ocelot->mrp_p_port = dev; 55 56 if (mrp->s_port == dev) 57 ocelot->mrp_s_port = dev; 58 59 ocelot->mrp_ring_id = mrp->ring_id; 60 61 return 0; 62 } 63 EXPORT_SYMBOL(ocelot_mrp_add); 64 65 int ocelot_mrp_del(struct ocelot *ocelot, int port, 66 const struct switchdev_obj_mrp *mrp) 67 { 68 struct ocelot_port *ocelot_port = ocelot->ports[port]; 69 struct ocelot_port_private *priv; 70 struct net_device *dev; 71 72 if (!ocelot_port) 73 return -EOPNOTSUPP; 74 75 priv = container_of(ocelot_port, struct ocelot_port_private, port); 76 dev = priv->dev; 77 78 if (ocelot->mrp_p_port != dev && ocelot->mrp_s_port != dev) 79 return 0; 80 81 if (ocelot->mrp_ring_id == 0 && 82 !ocelot->mrp_s_port && 83 !ocelot->mrp_p_port) 84 return -EINVAL; 85 86 if (ocelot_mrp_del_vcap(ocelot, priv->chip_port)) 87 return -EINVAL; 88 89 if (ocelot->mrp_p_port == dev) 90 ocelot->mrp_p_port = NULL; 91 92 if (ocelot->mrp_s_port == dev) 93 ocelot->mrp_s_port = NULL; 94 95 ocelot->mrp_ring_id = 0; 96 97 return 0; 98 } 99 EXPORT_SYMBOL(ocelot_mrp_del); 100 101 int ocelot_mrp_add_ring_role(struct ocelot *ocelot, int port, 102 const struct switchdev_obj_ring_role_mrp *mrp) 103 { 104 struct ocelot_port *ocelot_port = ocelot->ports[port]; 105 struct ocelot_vcap_filter *filter; 106 struct ocelot_port_private *priv; 107 struct net_device *dev; 108 int err; 109 110 if (!ocelot_port) 111 return -EOPNOTSUPP; 112 113 priv = container_of(ocelot_port, struct ocelot_port_private, port); 114 dev = priv->dev; 115 116 if (ocelot->mrp_ring_id != mrp->ring_id) 117 return -EINVAL; 118 119 if (!mrp->sw_backup) 120 return -EOPNOTSUPP; 121 122 if (ocelot->mrp_p_port != dev && ocelot->mrp_s_port != dev) 123 return 0; 124 125 filter = kzalloc(sizeof(*filter), GFP_ATOMIC); 126 if (!filter) 127 return -ENOMEM; 128 129 filter->key_type = OCELOT_VCAP_KEY_ETYPE; 130 filter->prio = 1; 131 filter->id.cookie = priv->chip_port; 132 filter->id.tc_offload = false; 133 filter->block_id = VCAP_IS2; 134 filter->type = OCELOT_VCAP_FILTER_OFFLOAD; 135 filter->ingress_port_mask = BIT(priv->chip_port); 136 *(__be16 *)filter->key.etype.etype.value = htons(ETH_P_MRP); 137 *(__be16 *)filter->key.etype.etype.mask = htons(0xffff); 138 filter->action.mask_mode = OCELOT_MASK_MODE_PERMIT_DENY; 139 filter->action.port_mask = 0x0; 140 filter->action.cpu_copy_ena = true; 141 filter->action.cpu_qu_num = OCELOT_MRP_CPUQ; 142 143 err = ocelot_vcap_filter_add(ocelot, filter, NULL); 144 if (err) 145 kfree(filter); 146 147 return err; 148 } 149 EXPORT_SYMBOL(ocelot_mrp_add_ring_role); 150 151 int ocelot_mrp_del_ring_role(struct ocelot *ocelot, int port, 152 const struct switchdev_obj_ring_role_mrp *mrp) 153 { 154 struct ocelot_port *ocelot_port = ocelot->ports[port]; 155 struct ocelot_port_private *priv; 156 struct net_device *dev; 157 158 if (!ocelot_port) 159 return -EOPNOTSUPP; 160 161 priv = container_of(ocelot_port, struct ocelot_port_private, port); 162 dev = priv->dev; 163 164 if (ocelot->mrp_ring_id != mrp->ring_id) 165 return -EINVAL; 166 167 if (!mrp->sw_backup) 168 return -EOPNOTSUPP; 169 170 if (ocelot->mrp_p_port != dev && ocelot->mrp_s_port != dev) 171 return 0; 172 173 return ocelot_mrp_del_vcap(ocelot, priv->chip_port); 174 } 175 EXPORT_SYMBOL(ocelot_mrp_del_ring_role); 176