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