Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
0002 #include "dpaa2-eth.h"
0003 /* Copyright 2020 NXP
0004  */
0005 
0006 #define DPAA2_ETH_TRAP_DROP(_id, _group_id)                 \
0007     DEVLINK_TRAP_GENERIC(DROP, DROP, _id,                   \
0008                  DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, 0)
0009 
0010 static const struct devlink_trap_group dpaa2_eth_trap_groups_arr[] = {
0011     DEVLINK_TRAP_GROUP_GENERIC(PARSER_ERROR_DROPS, 0),
0012 };
0013 
0014 static const struct devlink_trap dpaa2_eth_traps_arr[] = {
0015     DPAA2_ETH_TRAP_DROP(VXLAN_PARSING, PARSER_ERROR_DROPS),
0016     DPAA2_ETH_TRAP_DROP(LLC_SNAP_PARSING, PARSER_ERROR_DROPS),
0017     DPAA2_ETH_TRAP_DROP(VLAN_PARSING, PARSER_ERROR_DROPS),
0018     DPAA2_ETH_TRAP_DROP(PPPOE_PPP_PARSING, PARSER_ERROR_DROPS),
0019     DPAA2_ETH_TRAP_DROP(MPLS_PARSING, PARSER_ERROR_DROPS),
0020     DPAA2_ETH_TRAP_DROP(ARP_PARSING, PARSER_ERROR_DROPS),
0021     DPAA2_ETH_TRAP_DROP(IP_1_PARSING, PARSER_ERROR_DROPS),
0022     DPAA2_ETH_TRAP_DROP(IP_N_PARSING, PARSER_ERROR_DROPS),
0023     DPAA2_ETH_TRAP_DROP(GRE_PARSING, PARSER_ERROR_DROPS),
0024     DPAA2_ETH_TRAP_DROP(UDP_PARSING, PARSER_ERROR_DROPS),
0025     DPAA2_ETH_TRAP_DROP(TCP_PARSING, PARSER_ERROR_DROPS),
0026     DPAA2_ETH_TRAP_DROP(IPSEC_PARSING, PARSER_ERROR_DROPS),
0027     DPAA2_ETH_TRAP_DROP(SCTP_PARSING, PARSER_ERROR_DROPS),
0028     DPAA2_ETH_TRAP_DROP(DCCP_PARSING, PARSER_ERROR_DROPS),
0029     DPAA2_ETH_TRAP_DROP(GTP_PARSING, PARSER_ERROR_DROPS),
0030     DPAA2_ETH_TRAP_DROP(ESP_PARSING, PARSER_ERROR_DROPS),
0031 };
0032 
0033 static int dpaa2_eth_dl_info_get(struct devlink *devlink,
0034                  struct devlink_info_req *req,
0035                  struct netlink_ext_ack *extack)
0036 {
0037     struct dpaa2_eth_devlink_priv *dl_priv = devlink_priv(devlink);
0038     struct dpaa2_eth_priv *priv = dl_priv->dpaa2_priv;
0039     char buf[10];
0040     int err;
0041 
0042     err = devlink_info_driver_name_put(req, KBUILD_MODNAME);
0043     if (err)
0044         return err;
0045 
0046     scnprintf(buf, 10, "%d.%d", priv->dpni_ver_major, priv->dpni_ver_minor);
0047     err = devlink_info_version_running_put(req, "dpni", buf);
0048     if (err)
0049         return err;
0050 
0051     return 0;
0052 }
0053 
0054 static struct dpaa2_eth_trap_item *
0055 dpaa2_eth_dl_trap_item_lookup(struct dpaa2_eth_priv *priv, u16 trap_id)
0056 {
0057     struct dpaa2_eth_trap_data *dpaa2_eth_trap_data = priv->trap_data;
0058     int i;
0059 
0060     for (i = 0; i < ARRAY_SIZE(dpaa2_eth_traps_arr); i++) {
0061         if (dpaa2_eth_traps_arr[i].id == trap_id)
0062             return &dpaa2_eth_trap_data->trap_items_arr[i];
0063     }
0064 
0065     return NULL;
0066 }
0067 
0068 struct dpaa2_eth_trap_item *dpaa2_eth_dl_get_trap(struct dpaa2_eth_priv *priv,
0069                           struct dpaa2_fapr *fapr)
0070 {
0071     static const struct dpaa2_faf_error_bit {
0072         int position;
0073         enum devlink_trap_generic_id trap_id;
0074     } faf_bits[] = {
0075         { .position = 5,  .trap_id = DEVLINK_TRAP_GENERIC_ID_VXLAN_PARSING },
0076         { .position = 20, .trap_id = DEVLINK_TRAP_GENERIC_ID_LLC_SNAP_PARSING },
0077         { .position = 24, .trap_id = DEVLINK_TRAP_GENERIC_ID_VLAN_PARSING },
0078         { .position = 26, .trap_id = DEVLINK_TRAP_GENERIC_ID_PPPOE_PPP_PARSING },
0079         { .position = 29, .trap_id = DEVLINK_TRAP_GENERIC_ID_MPLS_PARSING },
0080         { .position = 31, .trap_id = DEVLINK_TRAP_GENERIC_ID_ARP_PARSING },
0081         { .position = 52, .trap_id = DEVLINK_TRAP_GENERIC_ID_IP_1_PARSING },
0082         { .position = 61, .trap_id = DEVLINK_TRAP_GENERIC_ID_IP_N_PARSING },
0083         { .position = 67, .trap_id = DEVLINK_TRAP_GENERIC_ID_GRE_PARSING },
0084         { .position = 71, .trap_id = DEVLINK_TRAP_GENERIC_ID_UDP_PARSING },
0085         { .position = 76, .trap_id = DEVLINK_TRAP_GENERIC_ID_TCP_PARSING },
0086         { .position = 80, .trap_id = DEVLINK_TRAP_GENERIC_ID_IPSEC_PARSING },
0087         { .position = 82, .trap_id = DEVLINK_TRAP_GENERIC_ID_SCTP_PARSING },
0088         { .position = 84, .trap_id = DEVLINK_TRAP_GENERIC_ID_DCCP_PARSING },
0089         { .position = 88, .trap_id = DEVLINK_TRAP_GENERIC_ID_GTP_PARSING },
0090         { .position = 90, .trap_id = DEVLINK_TRAP_GENERIC_ID_ESP_PARSING },
0091     };
0092     u64 faf_word;
0093     u64 mask;
0094     int i;
0095 
0096     for (i = 0; i < ARRAY_SIZE(faf_bits); i++) {
0097         if (faf_bits[i].position < 32) {
0098             /* Low part of FAF.
0099              * position ranges from 31 to 0, mask from 0 to 31.
0100              */
0101             mask = 1ull << (31 - faf_bits[i].position);
0102             faf_word = __le32_to_cpu(fapr->faf_lo);
0103         } else {
0104             /* High part of FAF.
0105              * position ranges from 95 to 32, mask from 0 to 63.
0106              */
0107             mask = 1ull << (63 - (faf_bits[i].position - 32));
0108             faf_word = __le64_to_cpu(fapr->faf_hi);
0109         }
0110         if (faf_word & mask)
0111             return dpaa2_eth_dl_trap_item_lookup(priv, faf_bits[i].trap_id);
0112     }
0113     return NULL;
0114 }
0115 
0116 static int dpaa2_eth_dl_trap_init(struct devlink *devlink,
0117                   const struct devlink_trap *trap,
0118                   void *trap_ctx)
0119 {
0120     struct dpaa2_eth_devlink_priv *dl_priv = devlink_priv(devlink);
0121     struct dpaa2_eth_priv *priv = dl_priv->dpaa2_priv;
0122     struct dpaa2_eth_trap_item *dpaa2_eth_trap_item;
0123 
0124     dpaa2_eth_trap_item = dpaa2_eth_dl_trap_item_lookup(priv, trap->id);
0125     if (WARN_ON(!dpaa2_eth_trap_item))
0126         return -ENOENT;
0127 
0128     dpaa2_eth_trap_item->trap_ctx = trap_ctx;
0129 
0130     return 0;
0131 }
0132 
0133 static int dpaa2_eth_dl_trap_action_set(struct devlink *devlink,
0134                     const struct devlink_trap *trap,
0135                     enum devlink_trap_action action,
0136                     struct netlink_ext_ack *extack)
0137 {
0138     /* No support for changing the action of an independent packet trap,
0139      * only per trap group - parser error drops
0140      */
0141     NL_SET_ERR_MSG_MOD(extack,
0142                "Cannot change trap action independently of group");
0143     return -EOPNOTSUPP;
0144 }
0145 
0146 static int dpaa2_eth_dl_trap_group_action_set(struct devlink *devlink,
0147                           const struct devlink_trap_group *group,
0148                           enum devlink_trap_action action,
0149                           struct netlink_ext_ack *extack)
0150 {
0151     struct dpaa2_eth_devlink_priv *dl_priv = devlink_priv(devlink);
0152     struct dpaa2_eth_priv *priv = dl_priv->dpaa2_priv;
0153     struct net_device *net_dev = priv->net_dev;
0154     struct device *dev = net_dev->dev.parent;
0155     struct dpni_error_cfg err_cfg = {0};
0156     int err;
0157 
0158     if (group->id != DEVLINK_TRAP_GROUP_GENERIC_ID_PARSER_ERROR_DROPS)
0159         return -EOPNOTSUPP;
0160 
0161     /* Configure handling of frames marked as errors from the parser */
0162     err_cfg.errors = DPAA2_FAS_RX_ERR_MASK;
0163     err_cfg.set_frame_annotation = 1;
0164 
0165     switch (action) {
0166     case DEVLINK_TRAP_ACTION_DROP:
0167         err_cfg.error_action = DPNI_ERROR_ACTION_DISCARD;
0168         break;
0169     case DEVLINK_TRAP_ACTION_TRAP:
0170         err_cfg.error_action = DPNI_ERROR_ACTION_SEND_TO_ERROR_QUEUE;
0171         break;
0172     default:
0173         return -EOPNOTSUPP;
0174     }
0175 
0176     err = dpni_set_errors_behavior(priv->mc_io, 0, priv->mc_token, &err_cfg);
0177     if (err) {
0178         dev_err(dev, "dpni_set_errors_behavior failed\n");
0179         return err;
0180     }
0181 
0182     return 0;
0183 }
0184 
0185 static const struct devlink_ops dpaa2_eth_devlink_ops = {
0186     .info_get = dpaa2_eth_dl_info_get,
0187     .trap_init = dpaa2_eth_dl_trap_init,
0188     .trap_action_set = dpaa2_eth_dl_trap_action_set,
0189     .trap_group_action_set = dpaa2_eth_dl_trap_group_action_set,
0190 };
0191 
0192 int dpaa2_eth_dl_alloc(struct dpaa2_eth_priv *priv)
0193 {
0194     struct net_device *net_dev = priv->net_dev;
0195     struct device *dev = net_dev->dev.parent;
0196     struct dpaa2_eth_devlink_priv *dl_priv;
0197 
0198     priv->devlink =
0199         devlink_alloc(&dpaa2_eth_devlink_ops, sizeof(*dl_priv), dev);
0200     if (!priv->devlink) {
0201         dev_err(dev, "devlink_alloc failed\n");
0202         return -ENOMEM;
0203     }
0204     dl_priv = devlink_priv(priv->devlink);
0205     dl_priv->dpaa2_priv = priv;
0206     return 0;
0207 }
0208 
0209 void dpaa2_eth_dl_free(struct dpaa2_eth_priv *priv)
0210 {
0211     devlink_free(priv->devlink);
0212 }
0213 
0214 
0215 void dpaa2_eth_dl_register(struct dpaa2_eth_priv *priv)
0216 {
0217     devlink_register(priv->devlink);
0218 }
0219 
0220 void dpaa2_eth_dl_unregister(struct dpaa2_eth_priv *priv)
0221 {
0222     devlink_unregister(priv->devlink);
0223 }
0224 
0225 int dpaa2_eth_dl_port_add(struct dpaa2_eth_priv *priv)
0226 {
0227     struct devlink_port *devlink_port = &priv->devlink_port;
0228     struct devlink_port_attrs attrs = {};
0229     int err;
0230 
0231     attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
0232     devlink_port_attrs_set(devlink_port, &attrs);
0233 
0234     err = devlink_port_register(priv->devlink, devlink_port, 0);
0235     if (err)
0236         return err;
0237 
0238     devlink_port_type_eth_set(devlink_port, priv->net_dev);
0239 
0240     return 0;
0241 }
0242 
0243 void dpaa2_eth_dl_port_del(struct dpaa2_eth_priv *priv)
0244 {
0245     struct devlink_port *devlink_port = &priv->devlink_port;
0246 
0247     devlink_port_type_clear(devlink_port);
0248     devlink_port_unregister(devlink_port);
0249 }
0250 
0251 int dpaa2_eth_dl_traps_register(struct dpaa2_eth_priv *priv)
0252 {
0253     struct dpaa2_eth_trap_data *dpaa2_eth_trap_data;
0254     struct net_device *net_dev = priv->net_dev;
0255     struct device *dev = net_dev->dev.parent;
0256     int err;
0257 
0258     dpaa2_eth_trap_data = kzalloc(sizeof(*dpaa2_eth_trap_data), GFP_KERNEL);
0259     if (!dpaa2_eth_trap_data)
0260         return -ENOMEM;
0261     priv->trap_data = dpaa2_eth_trap_data;
0262 
0263     dpaa2_eth_trap_data->trap_items_arr = kcalloc(ARRAY_SIZE(dpaa2_eth_traps_arr),
0264                               sizeof(struct dpaa2_eth_trap_item),
0265                               GFP_KERNEL);
0266     if (!dpaa2_eth_trap_data->trap_items_arr) {
0267         err = -ENOMEM;
0268         goto trap_data_free;
0269     }
0270 
0271     err = devlink_trap_groups_register(priv->devlink, dpaa2_eth_trap_groups_arr,
0272                        ARRAY_SIZE(dpaa2_eth_trap_groups_arr));
0273     if (err) {
0274         dev_err(dev, "devlink_trap_groups_register() = %d\n", err);
0275         goto trap_items_arr_free;
0276     }
0277 
0278     err = devlink_traps_register(priv->devlink, dpaa2_eth_traps_arr,
0279                      ARRAY_SIZE(dpaa2_eth_traps_arr), priv);
0280     if (err) {
0281         dev_err(dev, "devlink_traps_register() = %d\n", err);
0282         goto trap_groups_unregiser;
0283     }
0284 
0285     return 0;
0286 
0287 trap_groups_unregiser:
0288     devlink_trap_groups_unregister(priv->devlink, dpaa2_eth_trap_groups_arr,
0289                        ARRAY_SIZE(dpaa2_eth_trap_groups_arr));
0290 trap_items_arr_free:
0291     kfree(dpaa2_eth_trap_data->trap_items_arr);
0292 trap_data_free:
0293     kfree(dpaa2_eth_trap_data);
0294     priv->trap_data = NULL;
0295 
0296     return err;
0297 }
0298 
0299 void dpaa2_eth_dl_traps_unregister(struct dpaa2_eth_priv *priv)
0300 {
0301     devlink_traps_unregister(priv->devlink, dpaa2_eth_traps_arr,
0302                  ARRAY_SIZE(dpaa2_eth_traps_arr));
0303     devlink_trap_groups_unregister(priv->devlink, dpaa2_eth_trap_groups_arr,
0304                        ARRAY_SIZE(dpaa2_eth_trap_groups_arr));
0305     kfree(priv->trap_data->trap_items_arr);
0306     kfree(priv->trap_data);
0307 }