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