1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(C) 2020 Marvell International Ltd. 3 */ 4 5 #include <rte_malloc.h> 6 7 #include "octeontx_ethdev.h" 8 #include "octeontx_logs.h" 9 #include "octeontx_rxtx.h" 10 11 static int 12 octeontx_vlan_hw_filter(struct octeontx_nic *nic, uint8_t flag) 13 { 14 struct octeontx_vlan_info *vlan = &nic->vlan_info; 15 pki_port_vlan_filter_config_t fltr_conf; 16 int rc = 0; 17 18 if (vlan->filter_on == flag) 19 return rc; 20 21 fltr_conf.port_type = OCTTX_PORT_TYPE_NET; 22 fltr_conf.fltr_conf = flag; 23 24 rc = octeontx_pki_port_vlan_fltr_config(nic->port_id, &fltr_conf); 25 if (rc != 0) { 26 octeontx_log_err("Fail to configure vlan hw filter for port %d", 27 nic->port_id); 28 goto done; 29 } 30 31 vlan->filter_on = flag; 32 33 done: 34 return rc; 35 } 36 37 int 38 octeontx_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask) 39 { 40 struct octeontx_nic *nic = octeontx_pmd_priv(dev); 41 struct rte_eth_rxmode *rxmode; 42 int rc = 0; 43 44 rxmode = &dev->data->dev_conf.rxmode; 45 46 if (mask & ETH_VLAN_EXTEND_MASK) { 47 octeontx_log_err("Extend offload not supported"); 48 return -ENOTSUP; 49 } 50 51 if (mask & ETH_VLAN_STRIP_MASK) { 52 octeontx_log_err("VLAN strip offload not supported"); 53 return -ENOTSUP; 54 } 55 56 if (mask & ETH_VLAN_FILTER_MASK) { 57 if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_FILTER) { 58 rc = octeontx_vlan_hw_filter(nic, true); 59 if (rc) 60 goto done; 61 62 nic->rx_offloads |= DEV_RX_OFFLOAD_VLAN_FILTER; 63 nic->rx_offload_flags |= OCCTX_RX_VLAN_FLTR_F; 64 } else { 65 rc = octeontx_vlan_hw_filter(nic, false); 66 if (rc) 67 goto done; 68 69 nic->rx_offloads &= ~DEV_RX_OFFLOAD_VLAN_FILTER; 70 nic->rx_offload_flags &= ~OCCTX_RX_VLAN_FLTR_F; 71 } 72 } 73 74 done: 75 return rc; 76 } 77 78 int 79 octeontx_dev_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) 80 { 81 struct octeontx_nic *nic = octeontx_pmd_priv(dev); 82 struct octeontx_vlan_info *vlan = &nic->vlan_info; 83 pki_port_vlan_filter_entry_config_t fltr_entry; 84 struct vlan_entry *entry = NULL; 85 int entry_count = 0; 86 int rc = -EINVAL; 87 88 if (on) { 89 TAILQ_FOREACH(entry, &vlan->fltr_tbl, next) 90 if (entry->vlan_id == vlan_id) { 91 octeontx_log_dbg("Vlan Id is already set"); 92 return 0; 93 } 94 } else { 95 TAILQ_FOREACH(entry, &vlan->fltr_tbl, next) 96 entry_count++; 97 98 if (!entry_count) 99 return 0; 100 } 101 102 fltr_entry.port_type = OCTTX_PORT_TYPE_NET; 103 fltr_entry.vlan_tpid = RTE_ETHER_TYPE_VLAN; 104 fltr_entry.vlan_id = vlan_id; 105 fltr_entry.entry_conf = on; 106 107 if (on) { 108 entry = rte_zmalloc("octeontx_nic_vlan_entry", 109 sizeof(struct vlan_entry), 0); 110 if (!entry) { 111 octeontx_log_err("Failed to allocate memory"); 112 return -ENOMEM; 113 } 114 } 115 116 rc = octeontx_pki_port_vlan_fltr_entry_config(nic->port_id, 117 &fltr_entry); 118 if (rc != 0) { 119 octeontx_log_err("Fail to configure vlan filter entry " 120 "for port %d", nic->port_id); 121 if (entry) 122 rte_free(entry); 123 124 goto done; 125 } 126 127 if (on) { 128 entry->vlan_id = vlan_id; 129 TAILQ_INSERT_HEAD(&vlan->fltr_tbl, entry, next); 130 } else { 131 TAILQ_FOREACH(entry, &vlan->fltr_tbl, next) { 132 if (entry->vlan_id == vlan_id) { 133 TAILQ_REMOVE(&vlan->fltr_tbl, entry, next); 134 rte_free(entry); 135 break; 136 } 137 } 138 } 139 140 done: 141 return rc; 142 } 143 144 int 145 octeontx_dev_vlan_offload_init(struct rte_eth_dev *dev) 146 { 147 struct octeontx_nic *nic = octeontx_pmd_priv(dev); 148 int rc; 149 150 TAILQ_INIT(&nic->vlan_info.fltr_tbl); 151 152 rc = octeontx_dev_vlan_offload_set(dev, ETH_VLAN_FILTER_MASK); 153 if (rc) 154 octeontx_log_err("Failed to set vlan offload rc=%d", rc); 155 156 return rc; 157 } 158 159 int 160 octeontx_dev_vlan_offload_fini(struct rte_eth_dev *dev) 161 { 162 struct octeontx_nic *nic = octeontx_pmd_priv(dev); 163 struct octeontx_vlan_info *vlan = &nic->vlan_info; 164 pki_port_vlan_filter_entry_config_t fltr_entry; 165 struct vlan_entry *entry; 166 int rc = 0; 167 168 TAILQ_FOREACH(entry, &vlan->fltr_tbl, next) { 169 fltr_entry.port_type = OCTTX_PORT_TYPE_NET; 170 fltr_entry.vlan_tpid = RTE_ETHER_TYPE_VLAN; 171 fltr_entry.vlan_id = entry->vlan_id; 172 fltr_entry.entry_conf = 0; 173 174 rc = octeontx_pki_port_vlan_fltr_entry_config(nic->port_id, 175 &fltr_entry); 176 if (rc != 0) { 177 octeontx_log_err("Fail to configure vlan filter entry " 178 "for port %d", nic->port_id); 179 break; 180 } 181 } 182 183 return rc; 184 } 185 186 int 187 octeontx_dev_set_link_up(struct rte_eth_dev *eth_dev) 188 { 189 struct octeontx_nic *nic = octeontx_pmd_priv(eth_dev); 190 int rc, i; 191 192 rc = octeontx_bgx_port_set_link_state(nic->port_id, true); 193 if (rc) 194 goto done; 195 196 /* Start tx queues */ 197 for (i = 0; i < eth_dev->data->nb_tx_queues; i++) 198 octeontx_dev_tx_queue_start(eth_dev, i); 199 200 done: 201 return rc; 202 } 203 204 int 205 octeontx_dev_set_link_down(struct rte_eth_dev *eth_dev) 206 { 207 struct octeontx_nic *nic = octeontx_pmd_priv(eth_dev); 208 int i; 209 210 /* Stop tx queues */ 211 for (i = 0; i < eth_dev->data->nb_tx_queues; i++) 212 octeontx_dev_tx_queue_stop(eth_dev, i); 213 214 return octeontx_bgx_port_set_link_state(nic->port_id, false); 215 } 216 217 int 218 octeontx_dev_flow_ctrl_get(struct rte_eth_dev *dev, 219 struct rte_eth_fc_conf *fc_conf) 220 { 221 struct octeontx_nic *nic = octeontx_pmd_priv(dev); 222 octeontx_mbox_bgx_port_fc_cfg_t conf; 223 int rc; 224 225 memset(&conf, 0, sizeof(octeontx_mbox_bgx_port_fc_cfg_t)); 226 227 rc = octeontx_bgx_port_flow_ctrl_cfg(nic->port_id, &conf); 228 if (rc) 229 return rc; 230 231 if (conf.rx_pause && conf.tx_pause) 232 fc_conf->mode = RTE_FC_FULL; 233 else if (conf.rx_pause) 234 fc_conf->mode = RTE_FC_RX_PAUSE; 235 else if (conf.tx_pause) 236 fc_conf->mode = RTE_FC_TX_PAUSE; 237 else 238 fc_conf->mode = RTE_FC_NONE; 239 240 /* low_water & high_water values are in Bytes */ 241 fc_conf->low_water = conf.low_water; 242 fc_conf->high_water = conf.high_water; 243 244 return rc; 245 } 246 247 int 248 octeontx_dev_flow_ctrl_set(struct rte_eth_dev *dev, 249 struct rte_eth_fc_conf *fc_conf) 250 { 251 struct octeontx_nic *nic = octeontx_pmd_priv(dev); 252 struct octeontx_fc_info *fc = &nic->fc; 253 octeontx_mbox_bgx_port_fc_cfg_t conf; 254 uint8_t tx_pause, rx_pause; 255 uint16_t max_high_water; 256 int rc; 257 258 if (fc_conf->pause_time || fc_conf->mac_ctrl_frame_fwd || 259 fc_conf->autoneg) { 260 octeontx_log_err("Below flowctrl parameters are not supported " 261 "pause_time, mac_ctrl_frame_fwd and autoneg"); 262 return -EINVAL; 263 } 264 265 if (fc_conf->high_water == fc->high_water && 266 fc_conf->low_water == fc->low_water && 267 fc_conf->mode == fc->mode) 268 return 0; 269 270 max_high_water = fc->rx_fifosz - OCTEONTX_BGX_RSVD_RX_FIFOBYTES; 271 272 if (fc_conf->high_water > max_high_water || 273 fc_conf->high_water < fc_conf->low_water) { 274 octeontx_log_err("Invalid high/low water values " 275 "High_water(in Bytes) must <= 0x%x ", 276 max_high_water); 277 return -EINVAL; 278 } 279 280 if (fc_conf->high_water % BIT(4) || fc_conf->low_water % BIT(4)) { 281 octeontx_log_err("High/low water value must be multiple of 16"); 282 return -EINVAL; 283 } 284 285 rx_pause = (fc_conf->mode == RTE_FC_FULL) || 286 (fc_conf->mode == RTE_FC_RX_PAUSE); 287 tx_pause = (fc_conf->mode == RTE_FC_FULL) || 288 (fc_conf->mode == RTE_FC_TX_PAUSE); 289 290 conf.high_water = fc_conf->high_water; 291 conf.low_water = fc_conf->low_water; 292 conf.fc_cfg = BGX_PORT_FC_CFG_SET; 293 conf.rx_pause = rx_pause; 294 conf.tx_pause = tx_pause; 295 296 rc = octeontx_bgx_port_flow_ctrl_cfg(nic->port_id, &conf); 297 if (rc) 298 return rc; 299 300 fc->high_water = fc_conf->high_water; 301 fc->low_water = fc_conf->low_water; 302 fc->mode = fc_conf->mode; 303 304 return rc; 305 } 306 307 int 308 octeontx_dev_flow_ctrl_init(struct rte_eth_dev *dev) 309 { 310 struct octeontx_nic *nic = octeontx_pmd_priv(dev); 311 struct octeontx_fc_info *fc = &nic->fc; 312 struct rte_eth_fc_conf fc_conf; 313 int rc; 314 315 rc = octeontx_dev_flow_ctrl_get(dev, &fc_conf); 316 if (rc) { 317 octeontx_log_err("Failed to get flow control info"); 318 return rc; 319 } 320 321 fc->def_highmark = fc_conf.high_water; 322 fc->def_lowmark = fc_conf.low_water; 323 fc->def_mode = fc_conf.mode; 324 325 return rc; 326 } 327 328 int 329 octeontx_dev_flow_ctrl_fini(struct rte_eth_dev *dev) 330 { 331 struct octeontx_nic *nic = octeontx_pmd_priv(dev); 332 struct octeontx_fc_info *fc = &nic->fc; 333 struct rte_eth_fc_conf fc_conf; 334 335 memset(&fc_conf, 0, sizeof(struct rte_eth_fc_conf)); 336 337 /* Restore flow control parameters with default values */ 338 fc_conf.high_water = fc->def_highmark; 339 fc_conf.low_water = fc->def_lowmark; 340 fc_conf.mode = fc->def_mode; 341 342 return octeontx_dev_flow_ctrl_set(dev, &fc_conf); 343 } 344