1 // SPDX-License-Identifier: GPL-2.0 2 /* Marvell RVU PF/VF Netdev Devlink 3 * 4 * Copyright (C) 2021 Marvell. 5 */ 6 7 #include "otx2_common.h" 8 9 /* Devlink Params APIs */ 10 static int otx2_dl_mcam_count_validate(struct devlink *devlink, u32 id, 11 union devlink_param_value val, 12 struct netlink_ext_ack *extack) 13 { 14 struct otx2_devlink *otx2_dl = devlink_priv(devlink); 15 struct otx2_nic *pfvf = otx2_dl->pfvf; 16 struct otx2_flow_config *flow_cfg; 17 18 if (!pfvf->flow_cfg) { 19 NL_SET_ERR_MSG_MOD(extack, 20 "pfvf->flow_cfg not initialized"); 21 return -EINVAL; 22 } 23 24 flow_cfg = pfvf->flow_cfg; 25 if (flow_cfg && flow_cfg->nr_flows) { 26 NL_SET_ERR_MSG_MOD(extack, 27 "Cannot modify count when there are active rules"); 28 return -EINVAL; 29 } 30 31 return 0; 32 } 33 34 static int otx2_dl_mcam_count_set(struct devlink *devlink, u32 id, 35 struct devlink_param_gset_ctx *ctx, 36 struct netlink_ext_ack *extack) 37 { 38 struct otx2_devlink *otx2_dl = devlink_priv(devlink); 39 struct otx2_nic *pfvf = otx2_dl->pfvf; 40 41 if (!pfvf->flow_cfg) 42 return 0; 43 44 pfvf->flow_cfg->ntuple_cnt = ctx->val.vu16; 45 otx2_alloc_mcam_entries(pfvf, ctx->val.vu16); 46 47 return 0; 48 } 49 50 static int otx2_dl_mcam_count_get(struct devlink *devlink, u32 id, 51 struct devlink_param_gset_ctx *ctx) 52 { 53 struct otx2_devlink *otx2_dl = devlink_priv(devlink); 54 struct otx2_nic *pfvf = otx2_dl->pfvf; 55 struct otx2_flow_config *flow_cfg; 56 57 if (!pfvf->flow_cfg) { 58 ctx->val.vu16 = 0; 59 return 0; 60 } 61 62 flow_cfg = pfvf->flow_cfg; 63 ctx->val.vu16 = flow_cfg->max_flows; 64 65 return 0; 66 } 67 68 static int otx2_dl_ucast_flt_cnt_set(struct devlink *devlink, u32 id, 69 struct devlink_param_gset_ctx *ctx, 70 struct netlink_ext_ack *extack) 71 { 72 struct otx2_devlink *otx2_dl = devlink_priv(devlink); 73 struct otx2_nic *pfvf = otx2_dl->pfvf; 74 int err; 75 76 pfvf->flow_cfg->ucast_flt_cnt = ctx->val.vu8; 77 78 otx2_mcam_flow_del(pfvf); 79 err = otx2_mcam_entry_init(pfvf); 80 if (err) 81 return err; 82 83 return 0; 84 } 85 86 static int otx2_dl_ucast_flt_cnt_get(struct devlink *devlink, u32 id, 87 struct devlink_param_gset_ctx *ctx) 88 { 89 struct otx2_devlink *otx2_dl = devlink_priv(devlink); 90 struct otx2_nic *pfvf = otx2_dl->pfvf; 91 92 ctx->val.vu8 = pfvf->flow_cfg ? pfvf->flow_cfg->ucast_flt_cnt : 0; 93 94 return 0; 95 } 96 97 static int otx2_dl_ucast_flt_cnt_validate(struct devlink *devlink, u32 id, 98 union devlink_param_value val, 99 struct netlink_ext_ack *extack) 100 { 101 struct otx2_devlink *otx2_dl = devlink_priv(devlink); 102 struct otx2_nic *pfvf = otx2_dl->pfvf; 103 104 /* Check for UNICAST filter support*/ 105 if (!(pfvf->flags & OTX2_FLAG_UCAST_FLTR_SUPPORT)) { 106 NL_SET_ERR_MSG_MOD(extack, 107 "Unicast filter not enabled"); 108 return -EINVAL; 109 } 110 111 if (!pfvf->flow_cfg) { 112 NL_SET_ERR_MSG_MOD(extack, 113 "pfvf->flow_cfg not initialized"); 114 return -EINVAL; 115 } 116 117 if (pfvf->flow_cfg->nr_flows) { 118 NL_SET_ERR_MSG_MOD(extack, 119 "Cannot modify count when there are active rules"); 120 return -EINVAL; 121 } 122 123 return 0; 124 } 125 126 enum otx2_dl_param_id { 127 OTX2_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX, 128 OTX2_DEVLINK_PARAM_ID_MCAM_COUNT, 129 OTX2_DEVLINK_PARAM_ID_UCAST_FLT_CNT, 130 }; 131 132 static const struct devlink_param otx2_dl_params[] = { 133 DEVLINK_PARAM_DRIVER(OTX2_DEVLINK_PARAM_ID_MCAM_COUNT, 134 "mcam_count", DEVLINK_PARAM_TYPE_U16, 135 BIT(DEVLINK_PARAM_CMODE_RUNTIME), 136 otx2_dl_mcam_count_get, otx2_dl_mcam_count_set, 137 otx2_dl_mcam_count_validate), 138 DEVLINK_PARAM_DRIVER(OTX2_DEVLINK_PARAM_ID_UCAST_FLT_CNT, 139 "unicast_filter_count", DEVLINK_PARAM_TYPE_U8, 140 BIT(DEVLINK_PARAM_CMODE_RUNTIME), 141 otx2_dl_ucast_flt_cnt_get, otx2_dl_ucast_flt_cnt_set, 142 otx2_dl_ucast_flt_cnt_validate), 143 }; 144 145 #ifdef CONFIG_RVU_ESWITCH 146 static int otx2_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode) 147 { 148 struct otx2_devlink *otx2_dl = devlink_priv(devlink); 149 struct otx2_nic *pfvf = otx2_dl->pfvf; 150 151 if (!otx2_rep_dev(pfvf->pdev)) 152 return -EOPNOTSUPP; 153 154 *mode = pfvf->esw_mode; 155 156 return 0; 157 } 158 159 static int otx2_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode, 160 struct netlink_ext_ack *extack) 161 { 162 struct otx2_devlink *otx2_dl = devlink_priv(devlink); 163 struct otx2_nic *pfvf = otx2_dl->pfvf; 164 int ret = 0; 165 166 if (!otx2_rep_dev(pfvf->pdev)) 167 return -EOPNOTSUPP; 168 169 if (pfvf->esw_mode == mode) 170 return 0; 171 172 switch (mode) { 173 case DEVLINK_ESWITCH_MODE_LEGACY: 174 rvu_rep_destroy(pfvf); 175 break; 176 case DEVLINK_ESWITCH_MODE_SWITCHDEV: 177 ret = rvu_rep_create(pfvf, extack); 178 break; 179 default: 180 return -EINVAL; 181 } 182 183 if (!ret) 184 pfvf->esw_mode = mode; 185 186 return ret; 187 } 188 #endif 189 190 static const struct devlink_ops otx2_devlink_ops = { 191 #ifdef CONFIG_RVU_ESWITCH 192 .eswitch_mode_get = otx2_devlink_eswitch_mode_get, 193 .eswitch_mode_set = otx2_devlink_eswitch_mode_set, 194 #endif 195 }; 196 197 int otx2_register_dl(struct otx2_nic *pfvf) 198 { 199 struct otx2_devlink *otx2_dl; 200 struct devlink *dl; 201 int err; 202 203 dl = devlink_alloc(&otx2_devlink_ops, 204 sizeof(struct otx2_devlink), pfvf->dev); 205 if (!dl) { 206 dev_warn(pfvf->dev, "devlink_alloc failed\n"); 207 return -ENOMEM; 208 } 209 210 otx2_dl = devlink_priv(dl); 211 otx2_dl->dl = dl; 212 otx2_dl->pfvf = pfvf; 213 pfvf->dl = otx2_dl; 214 215 err = devlink_params_register(dl, otx2_dl_params, 216 ARRAY_SIZE(otx2_dl_params)); 217 if (err) { 218 dev_err(pfvf->dev, 219 "devlink params register failed with error %d", err); 220 goto err_dl; 221 } 222 223 devlink_register(dl); 224 return 0; 225 226 err_dl: 227 devlink_free(dl); 228 return err; 229 } 230 EXPORT_SYMBOL(otx2_register_dl); 231 232 void otx2_unregister_dl(struct otx2_nic *pfvf) 233 { 234 struct otx2_devlink *otx2_dl = pfvf->dl; 235 struct devlink *dl = otx2_dl->dl; 236 237 devlink_unregister(dl); 238 devlink_params_unregister(dl, otx2_dl_params, 239 ARRAY_SIZE(otx2_dl_params)); 240 devlink_free(dl); 241 } 242 EXPORT_SYMBOL(otx2_unregister_dl); 243