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