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

dpaa2-eth-devlink.c (9544B)


      1// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
      2#include "dpaa2-eth.h"
      3/* Copyright 2020 NXP
      4 */
      5
      6#define DPAA2_ETH_TRAP_DROP(_id, _group_id)					\
      7	DEVLINK_TRAP_GENERIC(DROP, DROP, _id,					\
      8			     DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, 0)
      9
     10static const struct devlink_trap_group dpaa2_eth_trap_groups_arr[] = {
     11	DEVLINK_TRAP_GROUP_GENERIC(PARSER_ERROR_DROPS, 0),
     12};
     13
     14static const struct devlink_trap dpaa2_eth_traps_arr[] = {
     15	DPAA2_ETH_TRAP_DROP(VXLAN_PARSING, PARSER_ERROR_DROPS),
     16	DPAA2_ETH_TRAP_DROP(LLC_SNAP_PARSING, PARSER_ERROR_DROPS),
     17	DPAA2_ETH_TRAP_DROP(VLAN_PARSING, PARSER_ERROR_DROPS),
     18	DPAA2_ETH_TRAP_DROP(PPPOE_PPP_PARSING, PARSER_ERROR_DROPS),
     19	DPAA2_ETH_TRAP_DROP(MPLS_PARSING, PARSER_ERROR_DROPS),
     20	DPAA2_ETH_TRAP_DROP(ARP_PARSING, PARSER_ERROR_DROPS),
     21	DPAA2_ETH_TRAP_DROP(IP_1_PARSING, PARSER_ERROR_DROPS),
     22	DPAA2_ETH_TRAP_DROP(IP_N_PARSING, PARSER_ERROR_DROPS),
     23	DPAA2_ETH_TRAP_DROP(GRE_PARSING, PARSER_ERROR_DROPS),
     24	DPAA2_ETH_TRAP_DROP(UDP_PARSING, PARSER_ERROR_DROPS),
     25	DPAA2_ETH_TRAP_DROP(TCP_PARSING, PARSER_ERROR_DROPS),
     26	DPAA2_ETH_TRAP_DROP(IPSEC_PARSING, PARSER_ERROR_DROPS),
     27	DPAA2_ETH_TRAP_DROP(SCTP_PARSING, PARSER_ERROR_DROPS),
     28	DPAA2_ETH_TRAP_DROP(DCCP_PARSING, PARSER_ERROR_DROPS),
     29	DPAA2_ETH_TRAP_DROP(GTP_PARSING, PARSER_ERROR_DROPS),
     30	DPAA2_ETH_TRAP_DROP(ESP_PARSING, PARSER_ERROR_DROPS),
     31};
     32
     33static int dpaa2_eth_dl_info_get(struct devlink *devlink,
     34				 struct devlink_info_req *req,
     35				 struct netlink_ext_ack *extack)
     36{
     37	struct dpaa2_eth_devlink_priv *dl_priv = devlink_priv(devlink);
     38	struct dpaa2_eth_priv *priv = dl_priv->dpaa2_priv;
     39	char buf[10];
     40	int err;
     41
     42	err = devlink_info_driver_name_put(req, KBUILD_MODNAME);
     43	if (err)
     44		return err;
     45
     46	scnprintf(buf, 10, "%d.%d", priv->dpni_ver_major, priv->dpni_ver_minor);
     47	err = devlink_info_version_running_put(req, "dpni", buf);
     48	if (err)
     49		return err;
     50
     51	return 0;
     52}
     53
     54static struct dpaa2_eth_trap_item *
     55dpaa2_eth_dl_trap_item_lookup(struct dpaa2_eth_priv *priv, u16 trap_id)
     56{
     57	struct dpaa2_eth_trap_data *dpaa2_eth_trap_data = priv->trap_data;
     58	int i;
     59
     60	for (i = 0; i < ARRAY_SIZE(dpaa2_eth_traps_arr); i++) {
     61		if (dpaa2_eth_traps_arr[i].id == trap_id)
     62			return &dpaa2_eth_trap_data->trap_items_arr[i];
     63	}
     64
     65	return NULL;
     66}
     67
     68struct dpaa2_eth_trap_item *dpaa2_eth_dl_get_trap(struct dpaa2_eth_priv *priv,
     69						  struct dpaa2_fapr *fapr)
     70{
     71	static const struct dpaa2_faf_error_bit {
     72		int position;
     73		enum devlink_trap_generic_id trap_id;
     74	} faf_bits[] = {
     75		{ .position = 5,  .trap_id = DEVLINK_TRAP_GENERIC_ID_VXLAN_PARSING },
     76		{ .position = 20, .trap_id = DEVLINK_TRAP_GENERIC_ID_LLC_SNAP_PARSING },
     77		{ .position = 24, .trap_id = DEVLINK_TRAP_GENERIC_ID_VLAN_PARSING },
     78		{ .position = 26, .trap_id = DEVLINK_TRAP_GENERIC_ID_PPPOE_PPP_PARSING },
     79		{ .position = 29, .trap_id = DEVLINK_TRAP_GENERIC_ID_MPLS_PARSING },
     80		{ .position = 31, .trap_id = DEVLINK_TRAP_GENERIC_ID_ARP_PARSING },
     81		{ .position = 52, .trap_id = DEVLINK_TRAP_GENERIC_ID_IP_1_PARSING },
     82		{ .position = 61, .trap_id = DEVLINK_TRAP_GENERIC_ID_IP_N_PARSING },
     83		{ .position = 67, .trap_id = DEVLINK_TRAP_GENERIC_ID_GRE_PARSING },
     84		{ .position = 71, .trap_id = DEVLINK_TRAP_GENERIC_ID_UDP_PARSING },
     85		{ .position = 76, .trap_id = DEVLINK_TRAP_GENERIC_ID_TCP_PARSING },
     86		{ .position = 80, .trap_id = DEVLINK_TRAP_GENERIC_ID_IPSEC_PARSING },
     87		{ .position = 82, .trap_id = DEVLINK_TRAP_GENERIC_ID_SCTP_PARSING },
     88		{ .position = 84, .trap_id = DEVLINK_TRAP_GENERIC_ID_DCCP_PARSING },
     89		{ .position = 88, .trap_id = DEVLINK_TRAP_GENERIC_ID_GTP_PARSING },
     90		{ .position = 90, .trap_id = DEVLINK_TRAP_GENERIC_ID_ESP_PARSING },
     91	};
     92	u64 faf_word;
     93	u64 mask;
     94	int i;
     95
     96	for (i = 0; i < ARRAY_SIZE(faf_bits); i++) {
     97		if (faf_bits[i].position < 32) {
     98			/* Low part of FAF.
     99			 * position ranges from 31 to 0, mask from 0 to 31.
    100			 */
    101			mask = 1ull << (31 - faf_bits[i].position);
    102			faf_word = __le32_to_cpu(fapr->faf_lo);
    103		} else {
    104			/* High part of FAF.
    105			 * position ranges from 95 to 32, mask from 0 to 63.
    106			 */
    107			mask = 1ull << (63 - (faf_bits[i].position - 32));
    108			faf_word = __le64_to_cpu(fapr->faf_hi);
    109		}
    110		if (faf_word & mask)
    111			return dpaa2_eth_dl_trap_item_lookup(priv, faf_bits[i].trap_id);
    112	}
    113	return NULL;
    114}
    115
    116static int dpaa2_eth_dl_trap_init(struct devlink *devlink,
    117				  const struct devlink_trap *trap,
    118				  void *trap_ctx)
    119{
    120	struct dpaa2_eth_devlink_priv *dl_priv = devlink_priv(devlink);
    121	struct dpaa2_eth_priv *priv = dl_priv->dpaa2_priv;
    122	struct dpaa2_eth_trap_item *dpaa2_eth_trap_item;
    123
    124	dpaa2_eth_trap_item = dpaa2_eth_dl_trap_item_lookup(priv, trap->id);
    125	if (WARN_ON(!dpaa2_eth_trap_item))
    126		return -ENOENT;
    127
    128	dpaa2_eth_trap_item->trap_ctx = trap_ctx;
    129
    130	return 0;
    131}
    132
    133static int dpaa2_eth_dl_trap_action_set(struct devlink *devlink,
    134					const struct devlink_trap *trap,
    135					enum devlink_trap_action action,
    136					struct netlink_ext_ack *extack)
    137{
    138	/* No support for changing the action of an independent packet trap,
    139	 * only per trap group - parser error drops
    140	 */
    141	NL_SET_ERR_MSG_MOD(extack,
    142			   "Cannot change trap action independently of group");
    143	return -EOPNOTSUPP;
    144}
    145
    146static int dpaa2_eth_dl_trap_group_action_set(struct devlink *devlink,
    147					      const struct devlink_trap_group *group,
    148					      enum devlink_trap_action action,
    149					      struct netlink_ext_ack *extack)
    150{
    151	struct dpaa2_eth_devlink_priv *dl_priv = devlink_priv(devlink);
    152	struct dpaa2_eth_priv *priv = dl_priv->dpaa2_priv;
    153	struct net_device *net_dev = priv->net_dev;
    154	struct device *dev = net_dev->dev.parent;
    155	struct dpni_error_cfg err_cfg = {0};
    156	int err;
    157
    158	if (group->id != DEVLINK_TRAP_GROUP_GENERIC_ID_PARSER_ERROR_DROPS)
    159		return -EOPNOTSUPP;
    160
    161	/* Configure handling of frames marked as errors from the parser */
    162	err_cfg.errors = DPAA2_FAS_RX_ERR_MASK;
    163	err_cfg.set_frame_annotation = 1;
    164
    165	switch (action) {
    166	case DEVLINK_TRAP_ACTION_DROP:
    167		err_cfg.error_action = DPNI_ERROR_ACTION_DISCARD;
    168		break;
    169	case DEVLINK_TRAP_ACTION_TRAP:
    170		err_cfg.error_action = DPNI_ERROR_ACTION_SEND_TO_ERROR_QUEUE;
    171		break;
    172	default:
    173		return -EOPNOTSUPP;
    174	}
    175
    176	err = dpni_set_errors_behavior(priv->mc_io, 0, priv->mc_token, &err_cfg);
    177	if (err) {
    178		dev_err(dev, "dpni_set_errors_behavior failed\n");
    179		return err;
    180	}
    181
    182	return 0;
    183}
    184
    185static const struct devlink_ops dpaa2_eth_devlink_ops = {
    186	.info_get = dpaa2_eth_dl_info_get,
    187	.trap_init = dpaa2_eth_dl_trap_init,
    188	.trap_action_set = dpaa2_eth_dl_trap_action_set,
    189	.trap_group_action_set = dpaa2_eth_dl_trap_group_action_set,
    190};
    191
    192int dpaa2_eth_dl_alloc(struct dpaa2_eth_priv *priv)
    193{
    194	struct net_device *net_dev = priv->net_dev;
    195	struct device *dev = net_dev->dev.parent;
    196	struct dpaa2_eth_devlink_priv *dl_priv;
    197
    198	priv->devlink =
    199		devlink_alloc(&dpaa2_eth_devlink_ops, sizeof(*dl_priv), dev);
    200	if (!priv->devlink) {
    201		dev_err(dev, "devlink_alloc failed\n");
    202		return -ENOMEM;
    203	}
    204	dl_priv = devlink_priv(priv->devlink);
    205	dl_priv->dpaa2_priv = priv;
    206	return 0;
    207}
    208
    209void dpaa2_eth_dl_free(struct dpaa2_eth_priv *priv)
    210{
    211	devlink_free(priv->devlink);
    212}
    213
    214
    215void dpaa2_eth_dl_register(struct dpaa2_eth_priv *priv)
    216{
    217	devlink_register(priv->devlink);
    218}
    219
    220void dpaa2_eth_dl_unregister(struct dpaa2_eth_priv *priv)
    221{
    222	devlink_unregister(priv->devlink);
    223}
    224
    225int dpaa2_eth_dl_port_add(struct dpaa2_eth_priv *priv)
    226{
    227	struct devlink_port *devlink_port = &priv->devlink_port;
    228	struct devlink_port_attrs attrs = {};
    229	int err;
    230
    231	attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
    232	devlink_port_attrs_set(devlink_port, &attrs);
    233
    234	err = devlink_port_register(priv->devlink, devlink_port, 0);
    235	if (err)
    236		return err;
    237
    238	devlink_port_type_eth_set(devlink_port, priv->net_dev);
    239
    240	return 0;
    241}
    242
    243void dpaa2_eth_dl_port_del(struct dpaa2_eth_priv *priv)
    244{
    245	struct devlink_port *devlink_port = &priv->devlink_port;
    246
    247	devlink_port_type_clear(devlink_port);
    248	devlink_port_unregister(devlink_port);
    249}
    250
    251int dpaa2_eth_dl_traps_register(struct dpaa2_eth_priv *priv)
    252{
    253	struct dpaa2_eth_trap_data *dpaa2_eth_trap_data;
    254	struct net_device *net_dev = priv->net_dev;
    255	struct device *dev = net_dev->dev.parent;
    256	int err;
    257
    258	dpaa2_eth_trap_data = kzalloc(sizeof(*dpaa2_eth_trap_data), GFP_KERNEL);
    259	if (!dpaa2_eth_trap_data)
    260		return -ENOMEM;
    261	priv->trap_data = dpaa2_eth_trap_data;
    262
    263	dpaa2_eth_trap_data->trap_items_arr = kcalloc(ARRAY_SIZE(dpaa2_eth_traps_arr),
    264						      sizeof(struct dpaa2_eth_trap_item),
    265						      GFP_KERNEL);
    266	if (!dpaa2_eth_trap_data->trap_items_arr) {
    267		err = -ENOMEM;
    268		goto trap_data_free;
    269	}
    270
    271	err = devlink_trap_groups_register(priv->devlink, dpaa2_eth_trap_groups_arr,
    272					   ARRAY_SIZE(dpaa2_eth_trap_groups_arr));
    273	if (err) {
    274		dev_err(dev, "devlink_trap_groups_register() = %d\n", err);
    275		goto trap_items_arr_free;
    276	}
    277
    278	err = devlink_traps_register(priv->devlink, dpaa2_eth_traps_arr,
    279				     ARRAY_SIZE(dpaa2_eth_traps_arr), priv);
    280	if (err) {
    281		dev_err(dev, "devlink_traps_register() = %d\n", err);
    282		goto trap_groups_unregiser;
    283	}
    284
    285	return 0;
    286
    287trap_groups_unregiser:
    288	devlink_trap_groups_unregister(priv->devlink, dpaa2_eth_trap_groups_arr,
    289				       ARRAY_SIZE(dpaa2_eth_trap_groups_arr));
    290trap_items_arr_free:
    291	kfree(dpaa2_eth_trap_data->trap_items_arr);
    292trap_data_free:
    293	kfree(dpaa2_eth_trap_data);
    294	priv->trap_data = NULL;
    295
    296	return err;
    297}
    298
    299void dpaa2_eth_dl_traps_unregister(struct dpaa2_eth_priv *priv)
    300{
    301	devlink_traps_unregister(priv->devlink, dpaa2_eth_traps_arr,
    302				 ARRAY_SIZE(dpaa2_eth_traps_arr));
    303	devlink_trap_groups_unregister(priv->devlink, dpaa2_eth_trap_groups_arr,
    304				       ARRAY_SIZE(dpaa2_eth_trap_groups_arr));
    305	kfree(priv->trap_data->trap_items_arr);
    306	kfree(priv->trap_data);
    307}