1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2001-2020 Intel Corporation 3 */ 4 5 #include "ice_switch.h" 6 #include "ice_flex_type.h" 7 #include "ice_flow.h" 8 9 #define ICE_ETH_DA_OFFSET 0 10 #define ICE_ETH_ETHTYPE_OFFSET 12 11 #define ICE_ETH_VLAN_TCI_OFFSET 14 12 #define ICE_MAX_VLAN_ID 0xFFF 13 #define ICE_IPV4_NVGRE_PROTO_ID 0x002F 14 #define ICE_PPP_IPV6_PROTO_ID 0x0057 15 #define ICE_IPV6_ETHER_ID 0x86DD 16 #define ICE_TCP_PROTO_ID 0x06 17 18 /* Dummy ethernet header needed in the ice_aqc_sw_rules_elem 19 * struct to configure any switch filter rules. 20 * {DA (6 bytes), SA(6 bytes), 21 * Ether type (2 bytes for header without VLAN tag) OR 22 * VLAN tag (4 bytes for header with VLAN tag) } 23 * 24 * Word on Hardcoded values 25 * byte 0 = 0x2: to identify it as locally administered DA MAC 26 * byte 6 = 0x2: to identify it as locally administered SA MAC 27 * byte 12 = 0x81 & byte 13 = 0x00: 28 * In case of VLAN filter first two bytes defines ether type (0x8100) 29 * and remaining two bytes are placeholder for programming a given VLAN ID 30 * In case of Ether type filter it is treated as header without VLAN tag 31 * and byte 12 and 13 is used to program a given Ether type instead 32 */ 33 static const u8 dummy_eth_header[DUMMY_ETH_HDR_LEN] = { 0x2, 0, 0, 0, 0, 0, 34 0x2, 0, 0, 0, 0, 0, 35 0x81, 0, 0, 0}; 36 37 struct ice_dummy_pkt_offsets { 38 enum ice_protocol_type type; 39 u16 offset; /* ICE_PROTOCOL_LAST indicates end of list */ 40 }; 41 42 static const struct ice_dummy_pkt_offsets dummy_gre_tcp_packet_offsets[] = { 43 { ICE_MAC_OFOS, 0 }, 44 { ICE_ETYPE_OL, 12 }, 45 { ICE_IPV4_OFOS, 14 }, 46 { ICE_NVGRE, 34 }, 47 { ICE_MAC_IL, 42 }, 48 { ICE_IPV4_IL, 56 }, 49 { ICE_TCP_IL, 76 }, 50 { ICE_PROTOCOL_LAST, 0 }, 51 }; 52 53 static const u8 dummy_gre_tcp_packet[] = { 54 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 55 0x00, 0x00, 0x00, 0x00, 56 0x00, 0x00, 0x00, 0x00, 57 58 0x08, 0x00, /* ICE_ETYPE_OL 12 */ 59 60 0x45, 0x00, 0x00, 0x3E, /* ICE_IPV4_OFOS 14 */ 61 0x00, 0x00, 0x00, 0x00, 62 0x00, 0x2F, 0x00, 0x00, 63 0x00, 0x00, 0x00, 0x00, 64 0x00, 0x00, 0x00, 0x00, 65 66 0x80, 0x00, 0x65, 0x58, /* ICE_NVGRE 34 */ 67 0x00, 0x00, 0x00, 0x00, 68 69 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 42 */ 70 0x00, 0x00, 0x00, 0x00, 71 0x00, 0x00, 0x00, 0x00, 72 0x08, 0x00, 73 74 0x45, 0x00, 0x00, 0x14, /* ICE_IPV4_IL 56 */ 75 0x00, 0x00, 0x00, 0x00, 76 0x00, 0x06, 0x00, 0x00, 77 0x00, 0x00, 0x00, 0x00, 78 0x00, 0x00, 0x00, 0x00, 79 80 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 76 */ 81 0x00, 0x00, 0x00, 0x00, 82 0x00, 0x00, 0x00, 0x00, 83 0x50, 0x02, 0x20, 0x00, 84 0x00, 0x00, 0x00, 0x00 85 }; 86 87 static const struct ice_dummy_pkt_offsets dummy_gre_udp_packet_offsets[] = { 88 { ICE_MAC_OFOS, 0 }, 89 { ICE_ETYPE_OL, 12 }, 90 { ICE_IPV4_OFOS, 14 }, 91 { ICE_NVGRE, 34 }, 92 { ICE_MAC_IL, 42 }, 93 { ICE_IPV4_IL, 56 }, 94 { ICE_UDP_ILOS, 76 }, 95 { ICE_PROTOCOL_LAST, 0 }, 96 }; 97 98 static const u8 dummy_gre_udp_packet[] = { 99 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 100 0x00, 0x00, 0x00, 0x00, 101 0x00, 0x00, 0x00, 0x00, 102 103 0x08, 0x00, /* ICE_ETYPE_OL 12 */ 104 105 0x45, 0x00, 0x00, 0x3E, /* ICE_IPV4_OFOS 14 */ 106 0x00, 0x00, 0x00, 0x00, 107 0x00, 0x2F, 0x00, 0x00, 108 0x00, 0x00, 0x00, 0x00, 109 0x00, 0x00, 0x00, 0x00, 110 111 0x80, 0x00, 0x65, 0x58, /* ICE_NVGRE 34 */ 112 0x00, 0x00, 0x00, 0x00, 113 114 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 42 */ 115 0x00, 0x00, 0x00, 0x00, 116 0x00, 0x00, 0x00, 0x00, 117 0x08, 0x00, 118 119 0x45, 0x00, 0x00, 0x14, /* ICE_IPV4_IL 56 */ 120 0x00, 0x00, 0x00, 0x00, 121 0x00, 0x11, 0x00, 0x00, 122 0x00, 0x00, 0x00, 0x00, 123 0x00, 0x00, 0x00, 0x00, 124 125 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 76 */ 126 0x00, 0x08, 0x00, 0x00, 127 }; 128 129 static const struct ice_dummy_pkt_offsets dummy_udp_tun_tcp_packet_offsets[] = { 130 { ICE_MAC_OFOS, 0 }, 131 { ICE_ETYPE_OL, 12 }, 132 { ICE_IPV4_OFOS, 14 }, 133 { ICE_UDP_OF, 34 }, 134 { ICE_VXLAN, 42 }, 135 { ICE_GENEVE, 42 }, 136 { ICE_VXLAN_GPE, 42 }, 137 { ICE_MAC_IL, 50 }, 138 { ICE_IPV4_IL, 64 }, 139 { ICE_TCP_IL, 84 }, 140 { ICE_PROTOCOL_LAST, 0 }, 141 }; 142 143 static const u8 dummy_udp_tun_tcp_packet[] = { 144 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 145 0x00, 0x00, 0x00, 0x00, 146 0x00, 0x00, 0x00, 0x00, 147 148 0x08, 0x00, /* ICE_ETYPE_OL 12 */ 149 150 0x45, 0x00, 0x00, 0x5a, /* ICE_IPV4_OFOS 14 */ 151 0x00, 0x01, 0x00, 0x00, 152 0x40, 0x11, 0x00, 0x00, 153 0x00, 0x00, 0x00, 0x00, 154 0x00, 0x00, 0x00, 0x00, 155 156 0x00, 0x00, 0x12, 0xb5, /* ICE_UDP_OF 34 */ 157 0x00, 0x46, 0x00, 0x00, 158 159 0x00, 0x00, 0x65, 0x58, /* ICE_VXLAN 42 */ 160 0x00, 0x00, 0x00, 0x00, 161 162 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 50 */ 163 0x00, 0x00, 0x00, 0x00, 164 0x00, 0x00, 0x00, 0x00, 165 0x08, 0x00, 166 167 0x45, 0x00, 0x00, 0x28, /* ICE_IPV4_IL 64 */ 168 0x00, 0x01, 0x00, 0x00, 169 0x40, 0x06, 0x00, 0x00, 170 0x00, 0x00, 0x00, 0x00, 171 0x00, 0x00, 0x00, 0x00, 172 173 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 84 */ 174 0x00, 0x00, 0x00, 0x00, 175 0x00, 0x00, 0x00, 0x00, 176 0x50, 0x02, 0x20, 0x00, 177 0x00, 0x00, 0x00, 0x00 178 }; 179 180 static const struct ice_dummy_pkt_offsets dummy_udp_tun_udp_packet_offsets[] = { 181 { ICE_MAC_OFOS, 0 }, 182 { ICE_ETYPE_OL, 12 }, 183 { ICE_IPV4_OFOS, 14 }, 184 { ICE_UDP_OF, 34 }, 185 { ICE_VXLAN, 42 }, 186 { ICE_GENEVE, 42 }, 187 { ICE_VXLAN_GPE, 42 }, 188 { ICE_MAC_IL, 50 }, 189 { ICE_IPV4_IL, 64 }, 190 { ICE_UDP_ILOS, 84 }, 191 { ICE_PROTOCOL_LAST, 0 }, 192 }; 193 194 static const u8 dummy_udp_tun_udp_packet[] = { 195 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 196 0x00, 0x00, 0x00, 0x00, 197 0x00, 0x00, 0x00, 0x00, 198 199 0x08, 0x00, /* ICE_ETYPE_OL 12 */ 200 201 0x45, 0x00, 0x00, 0x4e, /* ICE_IPV4_OFOS 14 */ 202 0x00, 0x01, 0x00, 0x00, 203 0x00, 0x11, 0x00, 0x00, 204 0x00, 0x00, 0x00, 0x00, 205 0x00, 0x00, 0x00, 0x00, 206 207 0x00, 0x00, 0x12, 0xb5, /* ICE_UDP_OF 34 */ 208 0x00, 0x3a, 0x00, 0x00, 209 210 0x00, 0x00, 0x65, 0x58, /* ICE_VXLAN 42 */ 211 0x00, 0x00, 0x00, 0x00, 212 213 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 50 */ 214 0x00, 0x00, 0x00, 0x00, 215 0x00, 0x00, 0x00, 0x00, 216 0x08, 0x00, 217 218 0x45, 0x00, 0x00, 0x1c, /* ICE_IPV4_IL 64 */ 219 0x00, 0x01, 0x00, 0x00, 220 0x00, 0x11, 0x00, 0x00, 221 0x00, 0x00, 0x00, 0x00, 222 0x00, 0x00, 0x00, 0x00, 223 224 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 84 */ 225 0x00, 0x08, 0x00, 0x00, 226 }; 227 228 /* offset info for MAC + IPv4 + UDP dummy packet */ 229 static const struct ice_dummy_pkt_offsets dummy_udp_packet_offsets[] = { 230 { ICE_MAC_OFOS, 0 }, 231 { ICE_ETYPE_OL, 12 }, 232 { ICE_IPV4_OFOS, 14 }, 233 { ICE_UDP_ILOS, 34 }, 234 { ICE_PROTOCOL_LAST, 0 }, 235 }; 236 237 /* Dummy packet for MAC + IPv4 + UDP */ 238 static const u8 dummy_udp_packet[] = { 239 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 240 0x00, 0x00, 0x00, 0x00, 241 0x00, 0x00, 0x00, 0x00, 242 243 0x08, 0x00, /* ICE_ETYPE_OL 12 */ 244 245 0x45, 0x00, 0x00, 0x1c, /* ICE_IPV4_OFOS 14 */ 246 0x00, 0x01, 0x00, 0x00, 247 0x00, 0x11, 0x00, 0x00, 248 0x00, 0x00, 0x00, 0x00, 249 0x00, 0x00, 0x00, 0x00, 250 251 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 34 */ 252 0x00, 0x08, 0x00, 0x00, 253 254 0x00, 0x00, /* 2 bytes for 4 byte alignment */ 255 }; 256 257 /* offset info for MAC + VLAN + IPv4 + UDP dummy packet */ 258 static const struct ice_dummy_pkt_offsets dummy_vlan_udp_packet_offsets[] = { 259 { ICE_MAC_OFOS, 0 }, 260 { ICE_ETYPE_OL, 12 }, 261 { ICE_VLAN_OFOS, 14 }, 262 { ICE_IPV4_OFOS, 18 }, 263 { ICE_UDP_ILOS, 38 }, 264 { ICE_PROTOCOL_LAST, 0 }, 265 }; 266 267 /* C-tag (801.1Q), IPv4:UDP dummy packet */ 268 static const u8 dummy_vlan_udp_packet[] = { 269 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 270 0x00, 0x00, 0x00, 0x00, 271 0x00, 0x00, 0x00, 0x00, 272 273 0x81, 0x00, /* ICE_ETYPE_OL 12 */ 274 275 0x00, 0x00, 0x08, 0x00, /* ICE_VLAN_OFOS 14 */ 276 277 0x45, 0x00, 0x00, 0x1c, /* ICE_IPV4_OFOS 18 */ 278 0x00, 0x01, 0x00, 0x00, 279 0x00, 0x11, 0x00, 0x00, 280 0x00, 0x00, 0x00, 0x00, 281 0x00, 0x00, 0x00, 0x00, 282 283 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 38 */ 284 0x00, 0x08, 0x00, 0x00, 285 286 0x00, 0x00, /* 2 bytes for 4 byte alignment */ 287 }; 288 289 /* offset info for MAC + IPv4 + TCP dummy packet */ 290 static const struct ice_dummy_pkt_offsets dummy_tcp_packet_offsets[] = { 291 { ICE_MAC_OFOS, 0 }, 292 { ICE_ETYPE_OL, 12 }, 293 { ICE_IPV4_OFOS, 14 }, 294 { ICE_TCP_IL, 34 }, 295 { ICE_PROTOCOL_LAST, 0 }, 296 }; 297 298 /* Dummy packet for MAC + IPv4 + TCP */ 299 static const u8 dummy_tcp_packet[] = { 300 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 301 0x00, 0x00, 0x00, 0x00, 302 0x00, 0x00, 0x00, 0x00, 303 304 0x08, 0x00, /* ICE_ETYPE_OL 12 */ 305 306 0x45, 0x00, 0x00, 0x28, /* ICE_IPV4_OFOS 14 */ 307 0x00, 0x01, 0x00, 0x00, 308 0x00, 0x06, 0x00, 0x00, 309 0x00, 0x00, 0x00, 0x00, 310 0x00, 0x00, 0x00, 0x00, 311 312 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 34 */ 313 0x00, 0x00, 0x00, 0x00, 314 0x00, 0x00, 0x00, 0x00, 315 0x50, 0x00, 0x00, 0x00, 316 0x00, 0x00, 0x00, 0x00, 317 318 0x00, 0x00, /* 2 bytes for 4 byte alignment */ 319 }; 320 321 /* offset info for MAC + VLAN (C-tag, 802.1Q) + IPv4 + TCP dummy packet */ 322 static const struct ice_dummy_pkt_offsets dummy_vlan_tcp_packet_offsets[] = { 323 { ICE_MAC_OFOS, 0 }, 324 { ICE_ETYPE_OL, 12 }, 325 { ICE_VLAN_OFOS, 14 }, 326 { ICE_IPV4_OFOS, 18 }, 327 { ICE_TCP_IL, 38 }, 328 { ICE_PROTOCOL_LAST, 0 }, 329 }; 330 331 /* C-tag (801.1Q), IPv4:TCP dummy packet */ 332 static const u8 dummy_vlan_tcp_packet[] = { 333 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 334 0x00, 0x00, 0x00, 0x00, 335 0x00, 0x00, 0x00, 0x00, 336 337 0x81, 0x00, /* ICE_ETYPE_OL 12 */ 338 339 0x00, 0x00, 0x08, 0x00, /* ICE_VLAN_OFOS 14 */ 340 341 0x45, 0x00, 0x00, 0x28, /* ICE_IPV4_OFOS 18 */ 342 0x00, 0x01, 0x00, 0x00, 343 0x00, 0x06, 0x00, 0x00, 344 0x00, 0x00, 0x00, 0x00, 345 0x00, 0x00, 0x00, 0x00, 346 347 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 38 */ 348 0x00, 0x00, 0x00, 0x00, 349 0x00, 0x00, 0x00, 0x00, 350 0x50, 0x00, 0x00, 0x00, 351 0x00, 0x00, 0x00, 0x00, 352 353 0x00, 0x00, /* 2 bytes for 4 byte alignment */ 354 }; 355 356 static const struct ice_dummy_pkt_offsets dummy_tcp_ipv6_packet_offsets[] = { 357 { ICE_MAC_OFOS, 0 }, 358 { ICE_ETYPE_OL, 12 }, 359 { ICE_IPV6_OFOS, 14 }, 360 { ICE_TCP_IL, 54 }, 361 { ICE_PROTOCOL_LAST, 0 }, 362 }; 363 364 static const u8 dummy_tcp_ipv6_packet[] = { 365 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 366 0x00, 0x00, 0x00, 0x00, 367 0x00, 0x00, 0x00, 0x00, 368 369 0x86, 0xDD, /* ICE_ETYPE_OL 12 */ 370 371 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 40 */ 372 0x00, 0x14, 0x06, 0x00, /* Next header is TCP */ 373 0x00, 0x00, 0x00, 0x00, 374 0x00, 0x00, 0x00, 0x00, 375 0x00, 0x00, 0x00, 0x00, 376 0x00, 0x00, 0x00, 0x00, 377 0x00, 0x00, 0x00, 0x00, 378 0x00, 0x00, 0x00, 0x00, 379 0x00, 0x00, 0x00, 0x00, 380 0x00, 0x00, 0x00, 0x00, 381 382 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 54 */ 383 0x00, 0x00, 0x00, 0x00, 384 0x00, 0x00, 0x00, 0x00, 385 0x50, 0x00, 0x00, 0x00, 386 0x00, 0x00, 0x00, 0x00, 387 388 0x00, 0x00, /* 2 bytes for 4 byte alignment */ 389 }; 390 391 /* C-tag (802.1Q): IPv6 + TCP */ 392 static const struct ice_dummy_pkt_offsets 393 dummy_vlan_tcp_ipv6_packet_offsets[] = { 394 { ICE_MAC_OFOS, 0 }, 395 { ICE_ETYPE_OL, 12 }, 396 { ICE_VLAN_OFOS, 14 }, 397 { ICE_IPV6_OFOS, 18 }, 398 { ICE_TCP_IL, 58 }, 399 { ICE_PROTOCOL_LAST, 0 }, 400 }; 401 402 /* C-tag (802.1Q), IPv6 + TCP dummy packet */ 403 static const u8 dummy_vlan_tcp_ipv6_packet[] = { 404 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 405 0x00, 0x00, 0x00, 0x00, 406 0x00, 0x00, 0x00, 0x00, 407 408 0x81, 0x00, /* ICE_ETYPE_OL 12 */ 409 410 0x00, 0x00, 0x86, 0xDD, /* ICE_VLAN_OFOS 14 */ 411 412 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 18 */ 413 0x00, 0x14, 0x06, 0x00, /* Next header is TCP */ 414 0x00, 0x00, 0x00, 0x00, 415 0x00, 0x00, 0x00, 0x00, 416 0x00, 0x00, 0x00, 0x00, 417 0x00, 0x00, 0x00, 0x00, 418 0x00, 0x00, 0x00, 0x00, 419 0x00, 0x00, 0x00, 0x00, 420 0x00, 0x00, 0x00, 0x00, 421 0x00, 0x00, 0x00, 0x00, 422 423 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 58 */ 424 0x00, 0x00, 0x00, 0x00, 425 0x00, 0x00, 0x00, 0x00, 426 0x50, 0x00, 0x00, 0x00, 427 0x00, 0x00, 0x00, 0x00, 428 429 0x00, 0x00, /* 2 bytes for 4 byte alignment */ 430 }; 431 432 /* IPv6 + UDP */ 433 static const struct ice_dummy_pkt_offsets dummy_udp_ipv6_packet_offsets[] = { 434 { ICE_MAC_OFOS, 0 }, 435 { ICE_ETYPE_OL, 12 }, 436 { ICE_IPV6_OFOS, 14 }, 437 { ICE_UDP_ILOS, 54 }, 438 { ICE_PROTOCOL_LAST, 0 }, 439 }; 440 441 /* IPv6 + UDP dummy packet */ 442 static const u8 dummy_udp_ipv6_packet[] = { 443 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 444 0x00, 0x00, 0x00, 0x00, 445 0x00, 0x00, 0x00, 0x00, 446 447 0x86, 0xDD, /* ICE_ETYPE_OL 12 */ 448 449 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 40 */ 450 0x00, 0x10, 0x11, 0x00, /* Next header UDP */ 451 0x00, 0x00, 0x00, 0x00, 452 0x00, 0x00, 0x00, 0x00, 453 0x00, 0x00, 0x00, 0x00, 454 0x00, 0x00, 0x00, 0x00, 455 0x00, 0x00, 0x00, 0x00, 456 0x00, 0x00, 0x00, 0x00, 457 0x00, 0x00, 0x00, 0x00, 458 0x00, 0x00, 0x00, 0x00, 459 460 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 54 */ 461 0x00, 0x10, 0x00, 0x00, 462 463 0x00, 0x00, 0x00, 0x00, /* needed for ESP packets */ 464 0x00, 0x00, 0x00, 0x00, 465 466 0x00, 0x00, /* 2 bytes for 4 byte alignment */ 467 }; 468 469 /* C-tag (802.1Q): IPv6 + UDP */ 470 static const struct ice_dummy_pkt_offsets 471 dummy_vlan_udp_ipv6_packet_offsets[] = { 472 { ICE_MAC_OFOS, 0 }, 473 { ICE_ETYPE_OL, 12 }, 474 { ICE_VLAN_OFOS, 14 }, 475 { ICE_IPV6_OFOS, 18 }, 476 { ICE_UDP_ILOS, 58 }, 477 { ICE_PROTOCOL_LAST, 0 }, 478 }; 479 480 /* C-tag (802.1Q), IPv6 + UDP dummy packet */ 481 static const u8 dummy_vlan_udp_ipv6_packet[] = { 482 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 483 0x00, 0x00, 0x00, 0x00, 484 0x00, 0x00, 0x00, 0x00, 485 486 0x81, 0x00, /* ICE_ETYPE_OL 12 */ 487 488 0x00, 0x00, 0x86, 0xDD, /* ICE_VLAN_OFOS 14 */ 489 490 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 18 */ 491 0x00, 0x08, 0x11, 0x00, /* Next header UDP */ 492 0x00, 0x00, 0x00, 0x00, 493 0x00, 0x00, 0x00, 0x00, 494 0x00, 0x00, 0x00, 0x00, 495 0x00, 0x00, 0x00, 0x00, 496 0x00, 0x00, 0x00, 0x00, 497 0x00, 0x00, 0x00, 0x00, 498 0x00, 0x00, 0x00, 0x00, 499 0x00, 0x00, 0x00, 0x00, 500 501 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 58 */ 502 0x00, 0x08, 0x00, 0x00, 503 504 0x00, 0x00, /* 2 bytes for 4 byte alignment */ 505 }; 506 507 static const struct ice_dummy_pkt_offsets dummy_udp_gtp_packet_offsets[] = { 508 { ICE_MAC_OFOS, 0 }, 509 { ICE_IPV4_OFOS, 14 }, 510 { ICE_UDP_OF, 34 }, 511 { ICE_GTP, 42 }, 512 { ICE_PROTOCOL_LAST, 0 }, 513 }; 514 515 static const u8 dummy_udp_gtp_packet[] = { 516 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 517 0x00, 0x00, 0x00, 0x00, 518 0x00, 0x00, 0x00, 0x00, 519 0x08, 0x00, 520 521 0x45, 0x00, 0x00, 0x30, /* ICE_IPV4_OFOS 14 */ 522 0x00, 0x00, 0x00, 0x00, 523 0x00, 0x11, 0x00, 0x00, 524 0x00, 0x00, 0x00, 0x00, 525 0x00, 0x00, 0x00, 0x00, 526 527 0x00, 0x00, 0x08, 0x68, /* ICE_UDP_OF 34 */ 528 0x00, 0x1c, 0x00, 0x00, 529 530 0x34, 0xff, 0x00, 0x0c, /* ICE_GTP 42 */ 531 0x00, 0x00, 0x00, 0x00, 532 0x00, 0x00, 0x00, 0x85, 533 534 0x02, 0x00, 0x00, 0x00, /* PDU Session extension header */ 535 0x00, 0x00, 0x00, 0x00, 536 }; 537 538 static const struct ice_dummy_pkt_offsets dummy_pppoe_packet_offsets[] = { 539 { ICE_MAC_OFOS, 0 }, 540 { ICE_ETYPE_OL, 12 }, 541 { ICE_VLAN_OFOS, 14}, 542 { ICE_PPPOE, 18 }, 543 { ICE_PROTOCOL_LAST, 0 }, 544 }; 545 546 static const struct ice_dummy_pkt_offsets dummy_pppoe_packet_ipv4_offsets[] = { 547 { ICE_MAC_OFOS, 0 }, 548 { ICE_ETYPE_OL, 12 }, 549 { ICE_VLAN_OFOS, 14}, 550 { ICE_PPPOE, 18 }, 551 { ICE_IPV4_OFOS, 26 }, 552 { ICE_PROTOCOL_LAST, 0 }, 553 }; 554 555 static const u8 dummy_pppoe_ipv4_packet[] = { 556 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 557 0x00, 0x00, 0x00, 0x00, 558 0x00, 0x00, 0x00, 0x00, 559 560 0x81, 0x00, /* ICE_ETYPE_OL 12 */ 561 562 0x00, 0x00, 0x88, 0x64, /* ICE_VLAN_OFOS 14 */ 563 564 0x11, 0x00, 0x00, 0x00, /* ICE_PPPOE 18 */ 565 0x00, 0x16, 566 567 0x00, 0x21, /* PPP Link Layer 24 */ 568 569 0x45, 0x00, 0x00, 0x14, /* ICE_IPV4_IL 26 */ 570 0x00, 0x00, 0x00, 0x00, 571 0x00, 0x00, 0x00, 0x00, 572 0x00, 0x00, 0x00, 0x00, 573 0x00, 0x00, 0x00, 0x00, 574 575 0x00, 0x00, /* 2 bytes for 4 bytes alignment */ 576 }; 577 578 static const 579 struct ice_dummy_pkt_offsets dummy_pppoe_ipv4_tcp_packet_offsets[] = { 580 { ICE_MAC_OFOS, 0 }, 581 { ICE_ETYPE_OL, 12 }, 582 { ICE_VLAN_OFOS, 14}, 583 { ICE_PPPOE, 18 }, 584 { ICE_IPV4_OFOS, 26 }, 585 { ICE_TCP_IL, 46 }, 586 { ICE_PROTOCOL_LAST, 0 }, 587 }; 588 589 static const u8 dummy_pppoe_ipv4_tcp_packet[] = { 590 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 591 0x00, 0x00, 0x00, 0x00, 592 0x00, 0x00, 0x00, 0x00, 593 594 0x81, 0x00, /* ICE_ETYPE_OL 12 */ 595 596 0x00, 0x00, 0x88, 0x64, /* ICE_VLAN_OFOS 14 */ 597 598 0x11, 0x00, 0x00, 0x00, /* ICE_PPPOE 18 */ 599 0x00, 0x16, 600 601 0x00, 0x21, /* PPP Link Layer 24 */ 602 603 0x45, 0x00, 0x00, 0x28, /* ICE_IPV4_OFOS 26 */ 604 0x00, 0x01, 0x00, 0x00, 605 0x00, 0x06, 0x00, 0x00, 606 0x00, 0x00, 0x00, 0x00, 607 0x00, 0x00, 0x00, 0x00, 608 609 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 46 */ 610 0x00, 0x00, 0x00, 0x00, 611 0x00, 0x00, 0x00, 0x00, 612 0x50, 0x00, 0x00, 0x00, 613 0x00, 0x00, 0x00, 0x00, 614 615 0x00, 0x00, /* 2 bytes for 4 bytes alignment */ 616 }; 617 618 static const 619 struct ice_dummy_pkt_offsets dummy_pppoe_ipv4_udp_packet_offsets[] = { 620 { ICE_MAC_OFOS, 0 }, 621 { ICE_ETYPE_OL, 12 }, 622 { ICE_VLAN_OFOS, 14}, 623 { ICE_PPPOE, 18 }, 624 { ICE_IPV4_OFOS, 26 }, 625 { ICE_UDP_ILOS, 46 }, 626 { ICE_PROTOCOL_LAST, 0 }, 627 }; 628 629 static const u8 dummy_pppoe_ipv4_udp_packet[] = { 630 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 631 0x00, 0x00, 0x00, 0x00, 632 0x00, 0x00, 0x00, 0x00, 633 634 0x81, 0x00, /* ICE_ETYPE_OL 12 */ 635 636 0x00, 0x00, 0x88, 0x64, /* ICE_VLAN_OFOS 14 */ 637 638 0x11, 0x00, 0x00, 0x00, /* ICE_PPPOE 18 */ 639 0x00, 0x16, 640 641 0x00, 0x21, /* PPP Link Layer 24 */ 642 643 0x45, 0x00, 0x00, 0x1c, /* ICE_IPV4_OFOS 26 */ 644 0x00, 0x01, 0x00, 0x00, 645 0x00, 0x11, 0x00, 0x00, 646 0x00, 0x00, 0x00, 0x00, 647 0x00, 0x00, 0x00, 0x00, 648 649 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 46 */ 650 0x00, 0x08, 0x00, 0x00, 651 652 0x00, 0x00, /* 2 bytes for 4 bytes alignment */ 653 }; 654 655 static const struct ice_dummy_pkt_offsets dummy_pppoe_packet_ipv6_offsets[] = { 656 { ICE_MAC_OFOS, 0 }, 657 { ICE_ETYPE_OL, 12 }, 658 { ICE_VLAN_OFOS, 14}, 659 { ICE_PPPOE, 18 }, 660 { ICE_IPV6_OFOS, 26 }, 661 { ICE_PROTOCOL_LAST, 0 }, 662 }; 663 664 static const u8 dummy_pppoe_ipv6_packet[] = { 665 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 666 0x00, 0x00, 0x00, 0x00, 667 0x00, 0x00, 0x00, 0x00, 668 669 0x81, 0x00, /* ICE_ETYPE_OL 12 */ 670 671 0x00, 0x00, 0x88, 0x64, /* ICE_VLAN_OFOS 14 */ 672 673 0x11, 0x00, 0x00, 0x00, /* ICE_PPPOE 18 */ 674 0x00, 0x2a, 675 676 0x00, 0x57, /* PPP Link Layer 24 */ 677 678 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 26 */ 679 0x00, 0x00, 0x3b, 0x00, 680 0x00, 0x00, 0x00, 0x00, 681 0x00, 0x00, 0x00, 0x00, 682 0x00, 0x00, 0x00, 0x00, 683 0x00, 0x00, 0x00, 0x00, 684 0x00, 0x00, 0x00, 0x00, 685 0x00, 0x00, 0x00, 0x00, 686 0x00, 0x00, 0x00, 0x00, 687 0x00, 0x00, 0x00, 0x00, 688 689 0x00, 0x00, /* 2 bytes for 4 bytes alignment */ 690 }; 691 692 static const 693 struct ice_dummy_pkt_offsets dummy_pppoe_packet_ipv6_tcp_offsets[] = { 694 { ICE_MAC_OFOS, 0 }, 695 { ICE_ETYPE_OL, 12 }, 696 { ICE_VLAN_OFOS, 14}, 697 { ICE_PPPOE, 18 }, 698 { ICE_IPV6_OFOS, 26 }, 699 { ICE_TCP_IL, 66 }, 700 { ICE_PROTOCOL_LAST, 0 }, 701 }; 702 703 static const u8 dummy_pppoe_ipv6_tcp_packet[] = { 704 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 705 0x00, 0x00, 0x00, 0x00, 706 0x00, 0x00, 0x00, 0x00, 707 708 0x81, 0x00, /* ICE_ETYPE_OL 12 */ 709 710 0x00, 0x00, 0x88, 0x64, /* ICE_VLAN_OFOS 14 */ 711 712 0x11, 0x00, 0x00, 0x00, /* ICE_PPPOE 18 */ 713 0x00, 0x2a, 714 715 0x00, 0x57, /* PPP Link Layer 24 */ 716 717 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 26 */ 718 0x00, 0x14, 0x06, 0x00, /* Next header is TCP */ 719 0x00, 0x00, 0x00, 0x00, 720 0x00, 0x00, 0x00, 0x00, 721 0x00, 0x00, 0x00, 0x00, 722 0x00, 0x00, 0x00, 0x00, 723 0x00, 0x00, 0x00, 0x00, 724 0x00, 0x00, 0x00, 0x00, 725 0x00, 0x00, 0x00, 0x00, 726 0x00, 0x00, 0x00, 0x00, 727 728 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 66 */ 729 0x00, 0x00, 0x00, 0x00, 730 0x00, 0x00, 0x00, 0x00, 731 0x50, 0x00, 0x00, 0x00, 732 0x00, 0x00, 0x00, 0x00, 733 734 0x00, 0x00, /* 2 bytes for 4 bytes alignment */ 735 }; 736 737 static const 738 struct ice_dummy_pkt_offsets dummy_pppoe_packet_ipv6_udp_offsets[] = { 739 { ICE_MAC_OFOS, 0 }, 740 { ICE_ETYPE_OL, 12 }, 741 { ICE_VLAN_OFOS, 14}, 742 { ICE_PPPOE, 18 }, 743 { ICE_IPV6_OFOS, 26 }, 744 { ICE_UDP_ILOS, 66 }, 745 { ICE_PROTOCOL_LAST, 0 }, 746 }; 747 748 static const u8 dummy_pppoe_ipv6_udp_packet[] = { 749 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 750 0x00, 0x00, 0x00, 0x00, 751 0x00, 0x00, 0x00, 0x00, 752 753 0x81, 0x00, /* ICE_ETYPE_OL 12 */ 754 755 0x00, 0x00, 0x88, 0x64, /* ICE_VLAN_OFOS 14 */ 756 757 0x11, 0x00, 0x00, 0x00, /* ICE_PPPOE 18 */ 758 0x00, 0x2a, 759 760 0x00, 0x57, /* PPP Link Layer 24 */ 761 762 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 26 */ 763 0x00, 0x08, 0x11, 0x00, /* Next header UDP*/ 764 0x00, 0x00, 0x00, 0x00, 765 0x00, 0x00, 0x00, 0x00, 766 0x00, 0x00, 0x00, 0x00, 767 0x00, 0x00, 0x00, 0x00, 768 0x00, 0x00, 0x00, 0x00, 769 0x00, 0x00, 0x00, 0x00, 770 0x00, 0x00, 0x00, 0x00, 771 0x00, 0x00, 0x00, 0x00, 772 773 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 66 */ 774 0x00, 0x08, 0x00, 0x00, 775 776 0x00, 0x00, /* 2 bytes for 4 bytes alignment */ 777 }; 778 779 static const struct ice_dummy_pkt_offsets dummy_ipv4_esp_packet_offsets[] = { 780 { ICE_MAC_OFOS, 0 }, 781 { ICE_IPV4_OFOS, 14 }, 782 { ICE_ESP, 34 }, 783 { ICE_PROTOCOL_LAST, 0 }, 784 }; 785 786 static const u8 dummy_ipv4_esp_pkt[] = { 787 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 788 0x00, 0x00, 0x00, 0x00, 789 0x00, 0x00, 0x00, 0x00, 790 0x08, 0x00, 791 792 0x45, 0x00, 0x00, 0x1c, /* ICE_IPV4_IL 14 */ 793 0x00, 0x00, 0x40, 0x00, 794 0x40, 0x32, 0x00, 0x00, 795 0x00, 0x00, 0x00, 0x00, 796 0x00, 0x00, 0x00, 0x00, 797 798 0x00, 0x00, 0x00, 0x00, /* ICE_ESP 34 */ 799 0x00, 0x00, 0x00, 0x00, 800 0x00, 0x00, /* 2 bytes for 4 bytes alignment */ 801 }; 802 803 static const struct ice_dummy_pkt_offsets dummy_ipv6_esp_packet_offsets[] = { 804 { ICE_MAC_OFOS, 0 }, 805 { ICE_IPV6_OFOS, 14 }, 806 { ICE_ESP, 54 }, 807 { ICE_PROTOCOL_LAST, 0 }, 808 }; 809 810 static const u8 dummy_ipv6_esp_pkt[] = { 811 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 812 0x00, 0x00, 0x00, 0x00, 813 0x00, 0x00, 0x00, 0x00, 814 0x86, 0xDD, 815 816 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 14 */ 817 0x00, 0x08, 0x32, 0x00, /* Next header ESP */ 818 0x00, 0x00, 0x00, 0x00, 819 0x00, 0x00, 0x00, 0x00, 820 0x00, 0x00, 0x00, 0x00, 821 0x00, 0x00, 0x00, 0x00, 822 0x00, 0x00, 0x00, 0x00, 823 0x00, 0x00, 0x00, 0x00, 824 0x00, 0x00, 0x00, 0x00, 825 0x00, 0x00, 0x00, 0x00, 826 827 0x00, 0x00, 0x00, 0x00, /* ICE_ESP 54 */ 828 0x00, 0x00, 0x00, 0x00, 829 0x00, 0x00, /* 2 bytes for 4 bytes alignment */ 830 }; 831 832 static const struct ice_dummy_pkt_offsets dummy_ipv4_ah_packet_offsets[] = { 833 { ICE_MAC_OFOS, 0 }, 834 { ICE_IPV4_OFOS, 14 }, 835 { ICE_AH, 34 }, 836 { ICE_PROTOCOL_LAST, 0 }, 837 }; 838 839 static const u8 dummy_ipv4_ah_pkt[] = { 840 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 841 0x00, 0x00, 0x00, 0x00, 842 0x00, 0x00, 0x00, 0x00, 843 0x08, 0x00, 844 845 0x45, 0x00, 0x00, 0x20, /* ICE_IPV4_IL 14 */ 846 0x00, 0x00, 0x40, 0x00, 847 0x40, 0x33, 0x00, 0x00, 848 0x00, 0x00, 0x00, 0x00, 849 0x00, 0x00, 0x00, 0x00, 850 851 0x00, 0x00, 0x00, 0x00, /* ICE_AH 34 */ 852 0x00, 0x00, 0x00, 0x00, 853 0x00, 0x00, 0x00, 0x00, 854 0x00, 0x00, /* 2 bytes for 4 bytes alignment */ 855 }; 856 857 static const struct ice_dummy_pkt_offsets dummy_ipv6_ah_packet_offsets[] = { 858 { ICE_MAC_OFOS, 0 }, 859 { ICE_IPV6_OFOS, 14 }, 860 { ICE_AH, 54 }, 861 { ICE_PROTOCOL_LAST, 0 }, 862 }; 863 864 static const u8 dummy_ipv6_ah_pkt[] = { 865 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 866 0x00, 0x00, 0x00, 0x00, 867 0x00, 0x00, 0x00, 0x00, 868 0x86, 0xDD, 869 870 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 14 */ 871 0x00, 0x0c, 0x33, 0x00, /* Next header AH */ 872 0x00, 0x00, 0x00, 0x00, 873 0x00, 0x00, 0x00, 0x00, 874 0x00, 0x00, 0x00, 0x00, 875 0x00, 0x00, 0x00, 0x00, 876 0x00, 0x00, 0x00, 0x00, 877 0x00, 0x00, 0x00, 0x00, 878 0x00, 0x00, 0x00, 0x00, 879 0x00, 0x00, 0x00, 0x00, 880 881 0x00, 0x00, 0x00, 0x00, /* ICE_AH 54 */ 882 0x00, 0x00, 0x00, 0x00, 883 0x00, 0x00, 0x00, 0x00, 884 0x00, 0x00, /* 2 bytes for 4 bytes alignment */ 885 }; 886 887 static const struct ice_dummy_pkt_offsets dummy_ipv4_nat_packet_offsets[] = { 888 { ICE_MAC_OFOS, 0 }, 889 { ICE_IPV4_OFOS, 14 }, 890 { ICE_UDP_ILOS, 34 }, 891 { ICE_NAT_T, 42 }, 892 { ICE_PROTOCOL_LAST, 0 }, 893 }; 894 895 static const u8 dummy_ipv4_nat_pkt[] = { 896 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 897 0x00, 0x00, 0x00, 0x00, 898 0x00, 0x00, 0x00, 0x00, 899 0x08, 0x00, 900 901 0x45, 0x00, 0x00, 0x24, /* ICE_IPV4_IL 14 */ 902 0x00, 0x00, 0x40, 0x00, 903 0x40, 0x11, 0x00, 0x00, 904 0x00, 0x00, 0x00, 0x00, 905 0x00, 0x00, 0x00, 0x00, 906 907 0x00, 0x00, 0x11, 0x94, /* ICE_NAT_T 34 */ 908 0x00, 0x00, 0x00, 0x00, 909 910 0x00, 0x00, 0x00, 0x00, 911 0x00, 0x00, 0x00, 0x00, 912 0x00, 0x00, /* 2 bytes for 4 bytes alignment */ 913 }; 914 915 static const struct ice_dummy_pkt_offsets dummy_ipv6_nat_packet_offsets[] = { 916 { ICE_MAC_OFOS, 0 }, 917 { ICE_IPV6_OFOS, 14 }, 918 { ICE_UDP_ILOS, 54 }, 919 { ICE_NAT_T, 62 }, 920 { ICE_PROTOCOL_LAST, 0 }, 921 }; 922 923 static const u8 dummy_ipv6_nat_pkt[] = { 924 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 925 0x00, 0x00, 0x00, 0x00, 926 0x00, 0x00, 0x00, 0x00, 927 0x86, 0xDD, 928 929 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 14 */ 930 0x00, 0x10, 0x11, 0x00, /* Next header NAT_T */ 931 0x00, 0x00, 0x00, 0x00, 932 0x00, 0x00, 0x00, 0x00, 933 0x00, 0x00, 0x00, 0x00, 934 0x00, 0x00, 0x00, 0x00, 935 0x00, 0x00, 0x00, 0x00, 936 0x00, 0x00, 0x00, 0x00, 937 0x00, 0x00, 0x00, 0x00, 938 0x00, 0x00, 0x00, 0x00, 939 940 0x00, 0x00, 0x11, 0x94, /* ICE_NAT_T 54 */ 941 0x00, 0x00, 0x00, 0x00, 942 943 0x00, 0x00, 0x00, 0x00, 944 0x00, 0x00, 0x00, 0x00, 945 0x00, 0x00, /* 2 bytes for 4 bytes alignment */ 946 947 }; 948 949 static const struct ice_dummy_pkt_offsets dummy_ipv4_l2tpv3_packet_offsets[] = { 950 { ICE_MAC_OFOS, 0 }, 951 { ICE_IPV4_OFOS, 14 }, 952 { ICE_L2TPV3, 34 }, 953 { ICE_PROTOCOL_LAST, 0 }, 954 }; 955 956 static const u8 dummy_ipv4_l2tpv3_pkt[] = { 957 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 958 0x00, 0x00, 0x00, 0x00, 959 0x00, 0x00, 0x00, 0x00, 960 0x08, 0x00, 961 962 0x45, 0x00, 0x00, 0x20, /* ICE_IPV4_IL 14 */ 963 0x00, 0x00, 0x40, 0x00, 964 0x40, 0x73, 0x00, 0x00, 965 0x00, 0x00, 0x00, 0x00, 966 0x00, 0x00, 0x00, 0x00, 967 968 0x00, 0x00, 0x00, 0x00, /* ICE_L2TPV3 34 */ 969 0x00, 0x00, 0x00, 0x00, 970 0x00, 0x00, 0x00, 0x00, 971 0x00, 0x00, /* 2 bytes for 4 bytes alignment */ 972 }; 973 974 static const struct ice_dummy_pkt_offsets dummy_ipv6_l2tpv3_packet_offsets[] = { 975 { ICE_MAC_OFOS, 0 }, 976 { ICE_IPV6_OFOS, 14 }, 977 { ICE_L2TPV3, 54 }, 978 { ICE_PROTOCOL_LAST, 0 }, 979 }; 980 981 static const u8 dummy_ipv6_l2tpv3_pkt[] = { 982 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 983 0x00, 0x00, 0x00, 0x00, 984 0x00, 0x00, 0x00, 0x00, 985 0x86, 0xDD, 986 987 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_IL 14 */ 988 0x00, 0x0c, 0x73, 0x40, 989 0x00, 0x00, 0x00, 0x00, 990 0x00, 0x00, 0x00, 0x00, 991 0x00, 0x00, 0x00, 0x00, 992 0x00, 0x00, 0x00, 0x00, 993 0x00, 0x00, 0x00, 0x00, 994 0x00, 0x00, 0x00, 0x00, 995 0x00, 0x00, 0x00, 0x00, 996 0x00, 0x00, 0x00, 0x00, 997 998 0x00, 0x00, 0x00, 0x00, /* ICE_L2TPV3 54 */ 999 0x00, 0x00, 0x00, 0x00, 1000 0x00, 0x00, 0x00, 0x00, 1001 0x00, 0x00, /* 2 bytes for 4 bytes alignment */ 1002 }; 1003 1004 /* this is a recipe to profile association bitmap */ 1005 static ice_declare_bitmap(recipe_to_profile[ICE_MAX_NUM_RECIPES], 1006 ICE_MAX_NUM_PROFILES); 1007 1008 /* this is a profile to recipe association bitmap */ 1009 static ice_declare_bitmap(profile_to_recipe[ICE_MAX_NUM_PROFILES], 1010 ICE_MAX_NUM_RECIPES); 1011 1012 static void ice_get_recp_to_prof_map(struct ice_hw *hw); 1013 1014 /** 1015 * ice_collect_result_idx - copy result index values 1016 * @buf: buffer that contains the result index 1017 * @recp: the recipe struct to copy data into 1018 */ 1019 static void ice_collect_result_idx(struct ice_aqc_recipe_data_elem *buf, 1020 struct ice_sw_recipe *recp) 1021 { 1022 if (buf->content.result_indx & ICE_AQ_RECIPE_RESULT_EN) 1023 ice_set_bit(buf->content.result_indx & 1024 ~ICE_AQ_RECIPE_RESULT_EN, recp->res_idxs); 1025 } 1026 1027 /** 1028 * ice_get_tun_type_for_recipe - get tunnel type for the recipe 1029 * @rid: recipe ID that we are populating 1030 */ 1031 static enum ice_sw_tunnel_type ice_get_tun_type_for_recipe(u8 rid) 1032 { 1033 u8 vxlan_profile[12] = {10, 11, 12, 16, 17, 18, 22, 23, 24, 25, 26, 27}; 1034 u8 gre_profile[12] = {13, 14, 15, 19, 20, 21, 28, 29, 30, 31, 32, 33}; 1035 u8 pppoe_profile[7] = {34, 35, 36, 37, 38, 39, 40}; 1036 u8 non_tun_profile[6] = {4, 5, 6, 7, 8, 9}; 1037 enum ice_sw_tunnel_type tun_type = ICE_NON_TUN; 1038 u16 i, j, profile_num = 0; 1039 bool non_tun_valid = false; 1040 bool pppoe_valid = false; 1041 bool vxlan_valid = false; 1042 bool gre_valid = false; 1043 bool gtp_valid = false; 1044 bool flag_valid = false; 1045 1046 for (j = 0; j < ICE_MAX_NUM_PROFILES; j++) { 1047 if (!ice_is_bit_set(recipe_to_profile[rid], j)) 1048 continue; 1049 else 1050 profile_num++; 1051 1052 for (i = 0; i < 12; i++) { 1053 if (gre_profile[i] == j) 1054 gre_valid = true; 1055 } 1056 1057 for (i = 0; i < 12; i++) { 1058 if (vxlan_profile[i] == j) 1059 vxlan_valid = true; 1060 } 1061 1062 for (i = 0; i < 7; i++) { 1063 if (pppoe_profile[i] == j) 1064 pppoe_valid = true; 1065 } 1066 1067 for (i = 0; i < 6; i++) { 1068 if (non_tun_profile[i] == j) 1069 non_tun_valid = true; 1070 } 1071 1072 if (j >= ICE_PROFID_IPV4_GTPC_TEID && 1073 j <= ICE_PROFID_IPV6_GTPU_IPV6_OTHER) 1074 gtp_valid = true; 1075 1076 if (j >= ICE_PROFID_IPV4_ESP && 1077 j <= ICE_PROFID_IPV6_PFCP_SESSION) 1078 flag_valid = true; 1079 } 1080 1081 if (!non_tun_valid && vxlan_valid) 1082 tun_type = ICE_SW_TUN_VXLAN; 1083 else if (!non_tun_valid && gre_valid) 1084 tun_type = ICE_SW_TUN_NVGRE; 1085 else if (!non_tun_valid && pppoe_valid) 1086 tun_type = ICE_SW_TUN_PPPOE; 1087 else if (!non_tun_valid && gtp_valid) 1088 tun_type = ICE_SW_TUN_GTP; 1089 else if (non_tun_valid && 1090 (vxlan_valid || gre_valid || gtp_valid || pppoe_valid)) 1091 tun_type = ICE_SW_TUN_AND_NON_TUN; 1092 else if (non_tun_valid && !vxlan_valid && !gre_valid && !gtp_valid && 1093 !pppoe_valid) 1094 tun_type = ICE_NON_TUN; 1095 1096 if (profile_num > 1 && tun_type == ICE_SW_TUN_PPPOE) { 1097 i = ice_is_bit_set(recipe_to_profile[rid], 1098 ICE_PROFID_PPPOE_IPV4_OTHER); 1099 j = ice_is_bit_set(recipe_to_profile[rid], 1100 ICE_PROFID_PPPOE_IPV6_OTHER); 1101 if (i && !j) 1102 tun_type = ICE_SW_TUN_PPPOE_IPV4; 1103 else if (!i && j) 1104 tun_type = ICE_SW_TUN_PPPOE_IPV6; 1105 } 1106 1107 if (profile_num == 1 && (flag_valid || non_tun_valid || pppoe_valid)) { 1108 for (j = 0; j < ICE_MAX_NUM_PROFILES; j++) { 1109 if (ice_is_bit_set(recipe_to_profile[rid], j)) { 1110 switch (j) { 1111 case ICE_PROFID_IPV4_TCP: 1112 tun_type = ICE_SW_IPV4_TCP; 1113 break; 1114 case ICE_PROFID_IPV4_UDP: 1115 tun_type = ICE_SW_IPV4_UDP; 1116 break; 1117 case ICE_PROFID_IPV6_TCP: 1118 tun_type = ICE_SW_IPV6_TCP; 1119 break; 1120 case ICE_PROFID_IPV6_UDP: 1121 tun_type = ICE_SW_IPV6_UDP; 1122 break; 1123 case ICE_PROFID_PPPOE_PAY: 1124 tun_type = ICE_SW_TUN_PPPOE_PAY; 1125 break; 1126 case ICE_PROFID_PPPOE_IPV4_TCP: 1127 tun_type = ICE_SW_TUN_PPPOE_IPV4_TCP; 1128 break; 1129 case ICE_PROFID_PPPOE_IPV4_UDP: 1130 tun_type = ICE_SW_TUN_PPPOE_IPV4_UDP; 1131 break; 1132 case ICE_PROFID_PPPOE_IPV4_OTHER: 1133 tun_type = ICE_SW_TUN_PPPOE_IPV4; 1134 break; 1135 case ICE_PROFID_PPPOE_IPV6_TCP: 1136 tun_type = ICE_SW_TUN_PPPOE_IPV6_TCP; 1137 break; 1138 case ICE_PROFID_PPPOE_IPV6_UDP: 1139 tun_type = ICE_SW_TUN_PPPOE_IPV4_UDP; 1140 break; 1141 case ICE_PROFID_PPPOE_IPV6_OTHER: 1142 tun_type = ICE_SW_TUN_PPPOE_IPV6; 1143 break; 1144 case ICE_PROFID_IPV4_ESP: 1145 tun_type = ICE_SW_TUN_IPV4_ESP; 1146 break; 1147 case ICE_PROFID_IPV6_ESP: 1148 tun_type = ICE_SW_TUN_IPV6_ESP; 1149 break; 1150 case ICE_PROFID_IPV4_AH: 1151 tun_type = ICE_SW_TUN_IPV4_AH; 1152 break; 1153 case ICE_PROFID_IPV6_AH: 1154 tun_type = ICE_SW_TUN_IPV6_AH; 1155 break; 1156 case ICE_PROFID_IPV4_NAT_T: 1157 tun_type = ICE_SW_TUN_IPV4_NAT_T; 1158 break; 1159 case ICE_PROFID_IPV6_NAT_T: 1160 tun_type = ICE_SW_TUN_IPV6_NAT_T; 1161 break; 1162 case ICE_PROFID_IPV4_PFCP_NODE: 1163 tun_type = 1164 ICE_SW_TUN_PROFID_IPV4_PFCP_NODE; 1165 break; 1166 case ICE_PROFID_IPV6_PFCP_NODE: 1167 tun_type = 1168 ICE_SW_TUN_PROFID_IPV6_PFCP_NODE; 1169 break; 1170 case ICE_PROFID_IPV4_PFCP_SESSION: 1171 tun_type = 1172 ICE_SW_TUN_PROFID_IPV4_PFCP_SESSION; 1173 break; 1174 case ICE_PROFID_IPV6_PFCP_SESSION: 1175 tun_type = 1176 ICE_SW_TUN_PROFID_IPV6_PFCP_SESSION; 1177 break; 1178 case ICE_PROFID_MAC_IPV4_L2TPV3: 1179 tun_type = ICE_SW_TUN_IPV4_L2TPV3; 1180 break; 1181 case ICE_PROFID_MAC_IPV6_L2TPV3: 1182 tun_type = ICE_SW_TUN_IPV6_L2TPV3; 1183 break; 1184 default: 1185 break; 1186 } 1187 1188 return tun_type; 1189 } 1190 } 1191 } 1192 1193 return tun_type; 1194 } 1195 1196 /** 1197 * ice_get_recp_frm_fw - update SW bookkeeping from FW recipe entries 1198 * @hw: pointer to hardware structure 1199 * @recps: struct that we need to populate 1200 * @rid: recipe ID that we are populating 1201 * @refresh_required: true if we should get recipe to profile mapping from FW 1202 * 1203 * This function is used to populate all the necessary entries into our 1204 * bookkeeping so that we have a current list of all the recipes that are 1205 * programmed in the firmware. 1206 */ 1207 static enum ice_status 1208 ice_get_recp_frm_fw(struct ice_hw *hw, struct ice_sw_recipe *recps, u8 rid, 1209 bool *refresh_required) 1210 { 1211 ice_declare_bitmap(result_bm, ICE_MAX_FV_WORDS); 1212 struct ice_aqc_recipe_data_elem *tmp; 1213 u16 num_recps = ICE_MAX_NUM_RECIPES; 1214 struct ice_prot_lkup_ext *lkup_exts; 1215 enum ice_status status; 1216 u8 fv_word_idx = 0; 1217 u16 sub_recps; 1218 1219 ice_zero_bitmap(result_bm, ICE_MAX_FV_WORDS); 1220 1221 /* we need a buffer big enough to accommodate all the recipes */ 1222 tmp = (struct ice_aqc_recipe_data_elem *)ice_calloc(hw, 1223 ICE_MAX_NUM_RECIPES, sizeof(*tmp)); 1224 if (!tmp) 1225 return ICE_ERR_NO_MEMORY; 1226 1227 tmp[0].recipe_indx = rid; 1228 status = ice_aq_get_recipe(hw, tmp, &num_recps, rid, NULL); 1229 /* non-zero status meaning recipe doesn't exist */ 1230 if (status) 1231 goto err_unroll; 1232 1233 /* Get recipe to profile map so that we can get the fv from lkups that 1234 * we read for a recipe from FW. Since we want to minimize the number of 1235 * times we make this FW call, just make one call and cache the copy 1236 * until a new recipe is added. This operation is only required the 1237 * first time to get the changes from FW. Then to search existing 1238 * entries we don't need to update the cache again until another recipe 1239 * gets added. 1240 */ 1241 if (*refresh_required) { 1242 ice_get_recp_to_prof_map(hw); 1243 *refresh_required = false; 1244 } 1245 1246 /* Start populating all the entries for recps[rid] based on lkups from 1247 * firmware. Note that we are only creating the root recipe in our 1248 * database. 1249 */ 1250 lkup_exts = &recps[rid].lkup_exts; 1251 1252 for (sub_recps = 0; sub_recps < num_recps; sub_recps++) { 1253 struct ice_aqc_recipe_data_elem root_bufs = tmp[sub_recps]; 1254 struct ice_recp_grp_entry *rg_entry; 1255 u8 i, prof, idx, prot = 0; 1256 bool is_root; 1257 u16 off = 0; 1258 1259 rg_entry = (struct ice_recp_grp_entry *) 1260 ice_malloc(hw, sizeof(*rg_entry)); 1261 if (!rg_entry) { 1262 status = ICE_ERR_NO_MEMORY; 1263 goto err_unroll; 1264 } 1265 1266 idx = root_bufs.recipe_indx; 1267 is_root = root_bufs.content.rid & ICE_AQ_RECIPE_ID_IS_ROOT; 1268 1269 /* Mark all result indices in this chain */ 1270 if (root_bufs.content.result_indx & ICE_AQ_RECIPE_RESULT_EN) 1271 ice_set_bit(root_bufs.content.result_indx & 1272 ~ICE_AQ_RECIPE_RESULT_EN, result_bm); 1273 1274 /* get the first profile that is associated with rid */ 1275 prof = ice_find_first_bit(recipe_to_profile[idx], 1276 ICE_MAX_NUM_PROFILES); 1277 for (i = 0; i < ICE_NUM_WORDS_RECIPE; i++) { 1278 u8 lkup_indx = root_bufs.content.lkup_indx[i + 1]; 1279 1280 rg_entry->fv_idx[i] = lkup_indx; 1281 rg_entry->fv_mask[i] = 1282 LE16_TO_CPU(root_bufs.content.mask[i + 1]); 1283 1284 /* If the recipe is a chained recipe then all its 1285 * child recipe's result will have a result index. 1286 * To fill fv_words we should not use those result 1287 * index, we only need the protocol ids and offsets. 1288 * We will skip all the fv_idx which stores result 1289 * index in them. We also need to skip any fv_idx which 1290 * has ICE_AQ_RECIPE_LKUP_IGNORE or 0 since it isn't a 1291 * valid offset value. 1292 */ 1293 if (ice_is_bit_set(hw->switch_info->prof_res_bm[prof], 1294 rg_entry->fv_idx[i]) || 1295 rg_entry->fv_idx[i] & ICE_AQ_RECIPE_LKUP_IGNORE || 1296 rg_entry->fv_idx[i] == 0) 1297 continue; 1298 1299 ice_find_prot_off(hw, ICE_BLK_SW, prof, 1300 rg_entry->fv_idx[i], &prot, &off); 1301 lkup_exts->fv_words[fv_word_idx].prot_id = prot; 1302 lkup_exts->fv_words[fv_word_idx].off = off; 1303 lkup_exts->field_mask[fv_word_idx] = 1304 rg_entry->fv_mask[i]; 1305 fv_word_idx++; 1306 } 1307 /* populate rg_list with the data from the child entry of this 1308 * recipe 1309 */ 1310 LIST_ADD(&rg_entry->l_entry, &recps[rid].rg_list); 1311 1312 /* Propagate some data to the recipe database */ 1313 recps[idx].is_root = !!is_root; 1314 recps[idx].priority = root_bufs.content.act_ctrl_fwd_priority; 1315 ice_zero_bitmap(recps[idx].res_idxs, ICE_MAX_FV_WORDS); 1316 if (root_bufs.content.result_indx & ICE_AQ_RECIPE_RESULT_EN) { 1317 recps[idx].chain_idx = root_bufs.content.result_indx & 1318 ~ICE_AQ_RECIPE_RESULT_EN; 1319 ice_set_bit(recps[idx].chain_idx, recps[idx].res_idxs); 1320 } else { 1321 recps[idx].chain_idx = ICE_INVAL_CHAIN_IND; 1322 } 1323 1324 if (!is_root) 1325 continue; 1326 1327 /* Only do the following for root recipes entries */ 1328 ice_memcpy(recps[idx].r_bitmap, root_bufs.recipe_bitmap, 1329 sizeof(recps[idx].r_bitmap), ICE_NONDMA_TO_NONDMA); 1330 recps[idx].root_rid = root_bufs.content.rid & 1331 ~ICE_AQ_RECIPE_ID_IS_ROOT; 1332 recps[idx].priority = root_bufs.content.act_ctrl_fwd_priority; 1333 } 1334 1335 /* Complete initialization of the root recipe entry */ 1336 lkup_exts->n_val_words = fv_word_idx; 1337 recps[rid].big_recp = (num_recps > 1); 1338 recps[rid].n_grp_count = (u8)num_recps; 1339 recps[rid].tun_type = ice_get_tun_type_for_recipe(rid); 1340 recps[rid].root_buf = (struct ice_aqc_recipe_data_elem *) 1341 ice_memdup(hw, tmp, recps[rid].n_grp_count * 1342 sizeof(*recps[rid].root_buf), ICE_NONDMA_TO_NONDMA); 1343 if (!recps[rid].root_buf) 1344 goto err_unroll; 1345 1346 /* Copy result indexes */ 1347 ice_cp_bitmap(recps[rid].res_idxs, result_bm, ICE_MAX_FV_WORDS); 1348 recps[rid].recp_created = true; 1349 1350 err_unroll: 1351 ice_free(hw, tmp); 1352 return status; 1353 } 1354 1355 /** 1356 * ice_get_recp_to_prof_map - updates recipe to profile mapping 1357 * @hw: pointer to hardware structure 1358 * 1359 * This function is used to populate recipe_to_profile matrix where index to 1360 * this array is the recipe ID and the element is the mapping of which profiles 1361 * is this recipe mapped to. 1362 */ 1363 static void ice_get_recp_to_prof_map(struct ice_hw *hw) 1364 { 1365 ice_declare_bitmap(r_bitmap, ICE_MAX_NUM_RECIPES); 1366 u16 i; 1367 1368 for (i = 0; i < ICE_MAX_NUM_PROFILES; i++) { 1369 u16 j; 1370 1371 ice_zero_bitmap(profile_to_recipe[i], ICE_MAX_NUM_RECIPES); 1372 ice_zero_bitmap(r_bitmap, ICE_MAX_NUM_RECIPES); 1373 if (ice_aq_get_recipe_to_profile(hw, i, (u8 *)r_bitmap, NULL)) 1374 continue; 1375 ice_cp_bitmap(profile_to_recipe[i], r_bitmap, 1376 ICE_MAX_NUM_RECIPES); 1377 for (j = 0; j < ICE_MAX_NUM_RECIPES; j++) 1378 if (ice_is_bit_set(r_bitmap, j)) 1379 ice_set_bit(i, recipe_to_profile[j]); 1380 } 1381 } 1382 1383 /** 1384 * ice_init_def_sw_recp - initialize the recipe book keeping tables 1385 * @hw: pointer to the HW struct 1386 * @recp_list: pointer to sw recipe list 1387 * 1388 * Allocate memory for the entire recipe table and initialize the structures/ 1389 * entries corresponding to basic recipes. 1390 */ 1391 enum ice_status 1392 ice_init_def_sw_recp(struct ice_hw *hw, struct ice_sw_recipe **recp_list) 1393 { 1394 struct ice_sw_recipe *recps; 1395 u8 i; 1396 1397 recps = (struct ice_sw_recipe *) 1398 ice_calloc(hw, ICE_MAX_NUM_RECIPES, sizeof(*recps)); 1399 if (!recps) 1400 return ICE_ERR_NO_MEMORY; 1401 1402 for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) { 1403 recps[i].root_rid = i; 1404 INIT_LIST_HEAD(&recps[i].filt_rules); 1405 INIT_LIST_HEAD(&recps[i].filt_replay_rules); 1406 INIT_LIST_HEAD(&recps[i].rg_list); 1407 ice_init_lock(&recps[i].filt_rule_lock); 1408 } 1409 1410 *recp_list = recps; 1411 1412 return ICE_SUCCESS; 1413 } 1414 1415 /** 1416 * ice_aq_get_sw_cfg - get switch configuration 1417 * @hw: pointer to the hardware structure 1418 * @buf: pointer to the result buffer 1419 * @buf_size: length of the buffer available for response 1420 * @req_desc: pointer to requested descriptor 1421 * @num_elems: pointer to number of elements 1422 * @cd: pointer to command details structure or NULL 1423 * 1424 * Get switch configuration (0x0200) to be placed in 'buff'. 1425 * This admin command returns information such as initial VSI/port number 1426 * and switch ID it belongs to. 1427 * 1428 * NOTE: *req_desc is both an input/output parameter. 1429 * The caller of this function first calls this function with *request_desc set 1430 * to 0. If the response from f/w has *req_desc set to 0, all the switch 1431 * configuration information has been returned; if non-zero (meaning not all 1432 * the information was returned), the caller should call this function again 1433 * with *req_desc set to the previous value returned by f/w to get the 1434 * next block of switch configuration information. 1435 * 1436 * *num_elems is output only parameter. This reflects the number of elements 1437 * in response buffer. The caller of this function to use *num_elems while 1438 * parsing the response buffer. 1439 */ 1440 static enum ice_status 1441 ice_aq_get_sw_cfg(struct ice_hw *hw, struct ice_aqc_get_sw_cfg_resp *buf, 1442 u16 buf_size, u16 *req_desc, u16 *num_elems, 1443 struct ice_sq_cd *cd) 1444 { 1445 struct ice_aqc_get_sw_cfg *cmd; 1446 enum ice_status status; 1447 struct ice_aq_desc desc; 1448 1449 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_sw_cfg); 1450 cmd = &desc.params.get_sw_conf; 1451 cmd->element = CPU_TO_LE16(*req_desc); 1452 1453 status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); 1454 if (!status) { 1455 *req_desc = LE16_TO_CPU(cmd->element); 1456 *num_elems = LE16_TO_CPU(cmd->num_elems); 1457 } 1458 1459 return status; 1460 } 1461 1462 /** 1463 * ice_alloc_sw - allocate resources specific to switch 1464 * @hw: pointer to the HW struct 1465 * @ena_stats: true to turn on VEB stats 1466 * @shared_res: true for shared resource, false for dedicated resource 1467 * @sw_id: switch ID returned 1468 * @counter_id: VEB counter ID returned 1469 * 1470 * allocates switch resources (SWID and VEB counter) (0x0208) 1471 */ 1472 enum ice_status 1473 ice_alloc_sw(struct ice_hw *hw, bool ena_stats, bool shared_res, u16 *sw_id, 1474 u16 *counter_id) 1475 { 1476 struct ice_aqc_alloc_free_res_elem *sw_buf; 1477 struct ice_aqc_res_elem *sw_ele; 1478 enum ice_status status; 1479 u16 buf_len; 1480 1481 buf_len = sizeof(*sw_buf); 1482 sw_buf = (struct ice_aqc_alloc_free_res_elem *) 1483 ice_malloc(hw, buf_len); 1484 if (!sw_buf) 1485 return ICE_ERR_NO_MEMORY; 1486 1487 /* Prepare buffer for switch ID. 1488 * The number of resource entries in buffer is passed as 1 since only a 1489 * single switch/VEB instance is allocated, and hence a single sw_id 1490 * is requested. 1491 */ 1492 sw_buf->num_elems = CPU_TO_LE16(1); 1493 sw_buf->res_type = 1494 CPU_TO_LE16(ICE_AQC_RES_TYPE_SWID | 1495 (shared_res ? ICE_AQC_RES_TYPE_FLAG_SHARED : 1496 ICE_AQC_RES_TYPE_FLAG_DEDICATED)); 1497 1498 status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, 1499 ice_aqc_opc_alloc_res, NULL); 1500 1501 if (status) 1502 goto ice_alloc_sw_exit; 1503 1504 sw_ele = &sw_buf->elem[0]; 1505 *sw_id = LE16_TO_CPU(sw_ele->e.sw_resp); 1506 1507 if (ena_stats) { 1508 /* Prepare buffer for VEB Counter */ 1509 enum ice_adminq_opc opc = ice_aqc_opc_alloc_res; 1510 struct ice_aqc_alloc_free_res_elem *counter_buf; 1511 struct ice_aqc_res_elem *counter_ele; 1512 1513 counter_buf = (struct ice_aqc_alloc_free_res_elem *) 1514 ice_malloc(hw, buf_len); 1515 if (!counter_buf) { 1516 status = ICE_ERR_NO_MEMORY; 1517 goto ice_alloc_sw_exit; 1518 } 1519 1520 /* The number of resource entries in buffer is passed as 1 since 1521 * only a single switch/VEB instance is allocated, and hence a 1522 * single VEB counter is requested. 1523 */ 1524 counter_buf->num_elems = CPU_TO_LE16(1); 1525 counter_buf->res_type = 1526 CPU_TO_LE16(ICE_AQC_RES_TYPE_VEB_COUNTER | 1527 ICE_AQC_RES_TYPE_FLAG_DEDICATED); 1528 status = ice_aq_alloc_free_res(hw, 1, counter_buf, buf_len, 1529 opc, NULL); 1530 1531 if (status) { 1532 ice_free(hw, counter_buf); 1533 goto ice_alloc_sw_exit; 1534 } 1535 counter_ele = &counter_buf->elem[0]; 1536 *counter_id = LE16_TO_CPU(counter_ele->e.sw_resp); 1537 ice_free(hw, counter_buf); 1538 } 1539 1540 ice_alloc_sw_exit: 1541 ice_free(hw, sw_buf); 1542 return status; 1543 } 1544 1545 /** 1546 * ice_free_sw - free resources specific to switch 1547 * @hw: pointer to the HW struct 1548 * @sw_id: switch ID returned 1549 * @counter_id: VEB counter ID returned 1550 * 1551 * free switch resources (SWID and VEB counter) (0x0209) 1552 * 1553 * NOTE: This function frees multiple resources. It continues 1554 * releasing other resources even after it encounters error. 1555 * The error code returned is the last error it encountered. 1556 */ 1557 enum ice_status ice_free_sw(struct ice_hw *hw, u16 sw_id, u16 counter_id) 1558 { 1559 struct ice_aqc_alloc_free_res_elem *sw_buf, *counter_buf; 1560 enum ice_status status, ret_status; 1561 u16 buf_len; 1562 1563 buf_len = sizeof(*sw_buf); 1564 sw_buf = (struct ice_aqc_alloc_free_res_elem *) 1565 ice_malloc(hw, buf_len); 1566 if (!sw_buf) 1567 return ICE_ERR_NO_MEMORY; 1568 1569 /* Prepare buffer to free for switch ID res. 1570 * The number of resource entries in buffer is passed as 1 since only a 1571 * single switch/VEB instance is freed, and hence a single sw_id 1572 * is released. 1573 */ 1574 sw_buf->num_elems = CPU_TO_LE16(1); 1575 sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_SWID); 1576 sw_buf->elem[0].e.sw_resp = CPU_TO_LE16(sw_id); 1577 1578 ret_status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, 1579 ice_aqc_opc_free_res, NULL); 1580 1581 if (ret_status) 1582 ice_debug(hw, ICE_DBG_SW, "CQ CMD Buffer:\n"); 1583 1584 /* Prepare buffer to free for VEB Counter resource */ 1585 counter_buf = (struct ice_aqc_alloc_free_res_elem *) 1586 ice_malloc(hw, buf_len); 1587 if (!counter_buf) { 1588 ice_free(hw, sw_buf); 1589 return ICE_ERR_NO_MEMORY; 1590 } 1591 1592 /* The number of resource entries in buffer is passed as 1 since only a 1593 * single switch/VEB instance is freed, and hence a single VEB counter 1594 * is released 1595 */ 1596 counter_buf->num_elems = CPU_TO_LE16(1); 1597 counter_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_VEB_COUNTER); 1598 counter_buf->elem[0].e.sw_resp = CPU_TO_LE16(counter_id); 1599 1600 status = ice_aq_alloc_free_res(hw, 1, counter_buf, buf_len, 1601 ice_aqc_opc_free_res, NULL); 1602 if (status) { 1603 ice_debug(hw, ICE_DBG_SW, 1604 "VEB counter resource could not be freed\n"); 1605 ret_status = status; 1606 } 1607 1608 ice_free(hw, counter_buf); 1609 ice_free(hw, sw_buf); 1610 return ret_status; 1611 } 1612 1613 /** 1614 * ice_aq_add_vsi 1615 * @hw: pointer to the HW struct 1616 * @vsi_ctx: pointer to a VSI context struct 1617 * @cd: pointer to command details structure or NULL 1618 * 1619 * Add a VSI context to the hardware (0x0210) 1620 */ 1621 enum ice_status 1622 ice_aq_add_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx, 1623 struct ice_sq_cd *cd) 1624 { 1625 struct ice_aqc_add_update_free_vsi_resp *res; 1626 struct ice_aqc_add_get_update_free_vsi *cmd; 1627 struct ice_aq_desc desc; 1628 enum ice_status status; 1629 1630 cmd = &desc.params.vsi_cmd; 1631 res = &desc.params.add_update_free_vsi_res; 1632 1633 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_vsi); 1634 1635 if (!vsi_ctx->alloc_from_pool) 1636 cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num | 1637 ICE_AQ_VSI_IS_VALID); 1638 1639 cmd->vsi_flags = CPU_TO_LE16(vsi_ctx->flags); 1640 1641 desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD); 1642 1643 status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info, 1644 sizeof(vsi_ctx->info), cd); 1645 1646 if (!status) { 1647 vsi_ctx->vsi_num = LE16_TO_CPU(res->vsi_num) & ICE_AQ_VSI_NUM_M; 1648 vsi_ctx->vsis_allocd = LE16_TO_CPU(res->vsi_used); 1649 vsi_ctx->vsis_unallocated = LE16_TO_CPU(res->vsi_free); 1650 } 1651 1652 return status; 1653 } 1654 1655 /** 1656 * ice_aq_free_vsi 1657 * @hw: pointer to the HW struct 1658 * @vsi_ctx: pointer to a VSI context struct 1659 * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources 1660 * @cd: pointer to command details structure or NULL 1661 * 1662 * Free VSI context info from hardware (0x0213) 1663 */ 1664 enum ice_status 1665 ice_aq_free_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx, 1666 bool keep_vsi_alloc, struct ice_sq_cd *cd) 1667 { 1668 struct ice_aqc_add_update_free_vsi_resp *resp; 1669 struct ice_aqc_add_get_update_free_vsi *cmd; 1670 struct ice_aq_desc desc; 1671 enum ice_status status; 1672 1673 cmd = &desc.params.vsi_cmd; 1674 resp = &desc.params.add_update_free_vsi_res; 1675 1676 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_free_vsi); 1677 1678 cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID); 1679 if (keep_vsi_alloc) 1680 cmd->cmd_flags = CPU_TO_LE16(ICE_AQ_VSI_KEEP_ALLOC); 1681 1682 status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 1683 if (!status) { 1684 vsi_ctx->vsis_allocd = LE16_TO_CPU(resp->vsi_used); 1685 vsi_ctx->vsis_unallocated = LE16_TO_CPU(resp->vsi_free); 1686 } 1687 1688 return status; 1689 } 1690 1691 /** 1692 * ice_aq_update_vsi 1693 * @hw: pointer to the HW struct 1694 * @vsi_ctx: pointer to a VSI context struct 1695 * @cd: pointer to command details structure or NULL 1696 * 1697 * Update VSI context in the hardware (0x0211) 1698 */ 1699 enum ice_status 1700 ice_aq_update_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx, 1701 struct ice_sq_cd *cd) 1702 { 1703 struct ice_aqc_add_update_free_vsi_resp *resp; 1704 struct ice_aqc_add_get_update_free_vsi *cmd; 1705 struct ice_aq_desc desc; 1706 enum ice_status status; 1707 1708 cmd = &desc.params.vsi_cmd; 1709 resp = &desc.params.add_update_free_vsi_res; 1710 1711 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_update_vsi); 1712 1713 cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID); 1714 1715 desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD); 1716 1717 status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info, 1718 sizeof(vsi_ctx->info), cd); 1719 1720 if (!status) { 1721 vsi_ctx->vsis_allocd = LE16_TO_CPU(resp->vsi_used); 1722 vsi_ctx->vsis_unallocated = LE16_TO_CPU(resp->vsi_free); 1723 } 1724 1725 return status; 1726 } 1727 1728 /** 1729 * ice_is_vsi_valid - check whether the VSI is valid or not 1730 * @hw: pointer to the HW struct 1731 * @vsi_handle: VSI handle 1732 * 1733 * check whether the VSI is valid or not 1734 */ 1735 bool ice_is_vsi_valid(struct ice_hw *hw, u16 vsi_handle) 1736 { 1737 return vsi_handle < ICE_MAX_VSI && hw->vsi_ctx[vsi_handle]; 1738 } 1739 1740 /** 1741 * ice_get_hw_vsi_num - return the HW VSI number 1742 * @hw: pointer to the HW struct 1743 * @vsi_handle: VSI handle 1744 * 1745 * return the HW VSI number 1746 * Caution: call this function only if VSI is valid (ice_is_vsi_valid) 1747 */ 1748 u16 ice_get_hw_vsi_num(struct ice_hw *hw, u16 vsi_handle) 1749 { 1750 return hw->vsi_ctx[vsi_handle]->vsi_num; 1751 } 1752 1753 /** 1754 * ice_get_vsi_ctx - return the VSI context entry for a given VSI handle 1755 * @hw: pointer to the HW struct 1756 * @vsi_handle: VSI handle 1757 * 1758 * return the VSI context entry for a given VSI handle 1759 */ 1760 struct ice_vsi_ctx *ice_get_vsi_ctx(struct ice_hw *hw, u16 vsi_handle) 1761 { 1762 return (vsi_handle >= ICE_MAX_VSI) ? NULL : hw->vsi_ctx[vsi_handle]; 1763 } 1764 1765 /** 1766 * ice_save_vsi_ctx - save the VSI context for a given VSI handle 1767 * @hw: pointer to the HW struct 1768 * @vsi_handle: VSI handle 1769 * @vsi: VSI context pointer 1770 * 1771 * save the VSI context entry for a given VSI handle 1772 */ 1773 static void 1774 ice_save_vsi_ctx(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi) 1775 { 1776 hw->vsi_ctx[vsi_handle] = vsi; 1777 } 1778 1779 /** 1780 * ice_clear_vsi_q_ctx - clear VSI queue contexts for all TCs 1781 * @hw: pointer to the HW struct 1782 * @vsi_handle: VSI handle 1783 */ 1784 static void ice_clear_vsi_q_ctx(struct ice_hw *hw, u16 vsi_handle) 1785 { 1786 struct ice_vsi_ctx *vsi; 1787 u8 i; 1788 1789 vsi = ice_get_vsi_ctx(hw, vsi_handle); 1790 if (!vsi) 1791 return; 1792 ice_for_each_traffic_class(i) { 1793 if (vsi->lan_q_ctx[i]) { 1794 ice_free(hw, vsi->lan_q_ctx[i]); 1795 vsi->lan_q_ctx[i] = NULL; 1796 } 1797 } 1798 } 1799 1800 /** 1801 * ice_clear_vsi_ctx - clear the VSI context entry 1802 * @hw: pointer to the HW struct 1803 * @vsi_handle: VSI handle 1804 * 1805 * clear the VSI context entry 1806 */ 1807 static void ice_clear_vsi_ctx(struct ice_hw *hw, u16 vsi_handle) 1808 { 1809 struct ice_vsi_ctx *vsi; 1810 1811 vsi = ice_get_vsi_ctx(hw, vsi_handle); 1812 if (vsi) { 1813 ice_clear_vsi_q_ctx(hw, vsi_handle); 1814 ice_free(hw, vsi); 1815 hw->vsi_ctx[vsi_handle] = NULL; 1816 } 1817 } 1818 1819 /** 1820 * ice_clear_all_vsi_ctx - clear all the VSI context entries 1821 * @hw: pointer to the HW struct 1822 */ 1823 void ice_clear_all_vsi_ctx(struct ice_hw *hw) 1824 { 1825 u16 i; 1826 1827 for (i = 0; i < ICE_MAX_VSI; i++) 1828 ice_clear_vsi_ctx(hw, i); 1829 } 1830 1831 /** 1832 * ice_add_vsi - add VSI context to the hardware and VSI handle list 1833 * @hw: pointer to the HW struct 1834 * @vsi_handle: unique VSI handle provided by drivers 1835 * @vsi_ctx: pointer to a VSI context struct 1836 * @cd: pointer to command details structure or NULL 1837 * 1838 * Add a VSI context to the hardware also add it into the VSI handle list. 1839 * If this function gets called after reset for existing VSIs then update 1840 * with the new HW VSI number in the corresponding VSI handle list entry. 1841 */ 1842 enum ice_status 1843 ice_add_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx, 1844 struct ice_sq_cd *cd) 1845 { 1846 struct ice_vsi_ctx *tmp_vsi_ctx; 1847 enum ice_status status; 1848 1849 if (vsi_handle >= ICE_MAX_VSI) 1850 return ICE_ERR_PARAM; 1851 status = ice_aq_add_vsi(hw, vsi_ctx, cd); 1852 if (status) 1853 return status; 1854 tmp_vsi_ctx = ice_get_vsi_ctx(hw, vsi_handle); 1855 if (!tmp_vsi_ctx) { 1856 /* Create a new VSI context */ 1857 tmp_vsi_ctx = (struct ice_vsi_ctx *) 1858 ice_malloc(hw, sizeof(*tmp_vsi_ctx)); 1859 if (!tmp_vsi_ctx) { 1860 ice_aq_free_vsi(hw, vsi_ctx, false, cd); 1861 return ICE_ERR_NO_MEMORY; 1862 } 1863 *tmp_vsi_ctx = *vsi_ctx; 1864 1865 ice_save_vsi_ctx(hw, vsi_handle, tmp_vsi_ctx); 1866 } else { 1867 /* update with new HW VSI num */ 1868 tmp_vsi_ctx->vsi_num = vsi_ctx->vsi_num; 1869 } 1870 1871 return ICE_SUCCESS; 1872 } 1873 1874 /** 1875 * ice_free_vsi- free VSI context from hardware and VSI handle list 1876 * @hw: pointer to the HW struct 1877 * @vsi_handle: unique VSI handle 1878 * @vsi_ctx: pointer to a VSI context struct 1879 * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources 1880 * @cd: pointer to command details structure or NULL 1881 * 1882 * Free VSI context info from hardware as well as from VSI handle list 1883 */ 1884 enum ice_status 1885 ice_free_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx, 1886 bool keep_vsi_alloc, struct ice_sq_cd *cd) 1887 { 1888 enum ice_status status; 1889 1890 if (!ice_is_vsi_valid(hw, vsi_handle)) 1891 return ICE_ERR_PARAM; 1892 vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle); 1893 status = ice_aq_free_vsi(hw, vsi_ctx, keep_vsi_alloc, cd); 1894 if (!status) 1895 ice_clear_vsi_ctx(hw, vsi_handle); 1896 return status; 1897 } 1898 1899 /** 1900 * ice_update_vsi 1901 * @hw: pointer to the HW struct 1902 * @vsi_handle: unique VSI handle 1903 * @vsi_ctx: pointer to a VSI context struct 1904 * @cd: pointer to command details structure or NULL 1905 * 1906 * Update VSI context in the hardware 1907 */ 1908 enum ice_status 1909 ice_update_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx, 1910 struct ice_sq_cd *cd) 1911 { 1912 if (!ice_is_vsi_valid(hw, vsi_handle)) 1913 return ICE_ERR_PARAM; 1914 vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle); 1915 return ice_aq_update_vsi(hw, vsi_ctx, cd); 1916 } 1917 1918 /** 1919 * ice_aq_get_vsi_params 1920 * @hw: pointer to the HW struct 1921 * @vsi_ctx: pointer to a VSI context struct 1922 * @cd: pointer to command details structure or NULL 1923 * 1924 * Get VSI context info from hardware (0x0212) 1925 */ 1926 enum ice_status 1927 ice_aq_get_vsi_params(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx, 1928 struct ice_sq_cd *cd) 1929 { 1930 struct ice_aqc_add_get_update_free_vsi *cmd; 1931 struct ice_aqc_get_vsi_resp *resp; 1932 struct ice_aq_desc desc; 1933 enum ice_status status; 1934 1935 cmd = &desc.params.vsi_cmd; 1936 resp = &desc.params.get_vsi_resp; 1937 1938 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_vsi_params); 1939 1940 cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID); 1941 1942 status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info, 1943 sizeof(vsi_ctx->info), cd); 1944 if (!status) { 1945 vsi_ctx->vsi_num = LE16_TO_CPU(resp->vsi_num) & 1946 ICE_AQ_VSI_NUM_M; 1947 vsi_ctx->vsis_allocd = LE16_TO_CPU(resp->vsi_used); 1948 vsi_ctx->vsis_unallocated = LE16_TO_CPU(resp->vsi_free); 1949 } 1950 1951 return status; 1952 } 1953 1954 /** 1955 * ice_aq_add_update_mir_rule - add/update a mirror rule 1956 * @hw: pointer to the HW struct 1957 * @rule_type: Rule Type 1958 * @dest_vsi: VSI number to which packets will be mirrored 1959 * @count: length of the list 1960 * @mr_buf: buffer for list of mirrored VSI numbers 1961 * @cd: pointer to command details structure or NULL 1962 * @rule_id: Rule ID 1963 * 1964 * Add/Update Mirror Rule (0x260). 1965 */ 1966 enum ice_status 1967 ice_aq_add_update_mir_rule(struct ice_hw *hw, u16 rule_type, u16 dest_vsi, 1968 u16 count, struct ice_mir_rule_buf *mr_buf, 1969 struct ice_sq_cd *cd, u16 *rule_id) 1970 { 1971 struct ice_aqc_add_update_mir_rule *cmd; 1972 struct ice_aq_desc desc; 1973 enum ice_status status; 1974 __le16 *mr_list = NULL; 1975 u16 buf_size = 0; 1976 1977 switch (rule_type) { 1978 case ICE_AQC_RULE_TYPE_VPORT_INGRESS: 1979 case ICE_AQC_RULE_TYPE_VPORT_EGRESS: 1980 /* Make sure count and mr_buf are set for these rule_types */ 1981 if (!(count && mr_buf)) 1982 return ICE_ERR_PARAM; 1983 1984 buf_size = count * sizeof(__le16); 1985 mr_list = (_FORCE_ __le16 *)ice_malloc(hw, buf_size); 1986 if (!mr_list) 1987 return ICE_ERR_NO_MEMORY; 1988 break; 1989 case ICE_AQC_RULE_TYPE_PPORT_INGRESS: 1990 case ICE_AQC_RULE_TYPE_PPORT_EGRESS: 1991 /* Make sure count and mr_buf are not set for these 1992 * rule_types 1993 */ 1994 if (count || mr_buf) 1995 return ICE_ERR_PARAM; 1996 break; 1997 default: 1998 ice_debug(hw, ICE_DBG_SW, 1999 "Error due to unsupported rule_type %u\n", rule_type); 2000 return ICE_ERR_OUT_OF_RANGE; 2001 } 2002 2003 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_update_mir_rule); 2004 2005 /* Pre-process 'mr_buf' items for add/update of virtual port 2006 * ingress/egress mirroring (but not physical port ingress/egress 2007 * mirroring) 2008 */ 2009 if (mr_buf) { 2010 int i; 2011 2012 for (i = 0; i < count; i++) { 2013 u16 id; 2014 2015 id = mr_buf[i].vsi_idx & ICE_AQC_RULE_MIRRORED_VSI_M; 2016 2017 /* Validate specified VSI number, make sure it is less 2018 * than ICE_MAX_VSI, if not return with error. 2019 */ 2020 if (id >= ICE_MAX_VSI) { 2021 ice_debug(hw, ICE_DBG_SW, 2022 "Error VSI index (%u) out-of-range\n", 2023 id); 2024 ice_free(hw, mr_list); 2025 return ICE_ERR_OUT_OF_RANGE; 2026 } 2027 2028 /* add VSI to mirror rule */ 2029 if (mr_buf[i].add) 2030 mr_list[i] = 2031 CPU_TO_LE16(id | ICE_AQC_RULE_ACT_M); 2032 else /* remove VSI from mirror rule */ 2033 mr_list[i] = CPU_TO_LE16(id); 2034 } 2035 } 2036 2037 cmd = &desc.params.add_update_rule; 2038 if ((*rule_id) != ICE_INVAL_MIRROR_RULE_ID) 2039 cmd->rule_id = CPU_TO_LE16(((*rule_id) & ICE_AQC_RULE_ID_M) | 2040 ICE_AQC_RULE_ID_VALID_M); 2041 cmd->rule_type = CPU_TO_LE16(rule_type & ICE_AQC_RULE_TYPE_M); 2042 cmd->num_entries = CPU_TO_LE16(count); 2043 cmd->dest = CPU_TO_LE16(dest_vsi); 2044 2045 status = ice_aq_send_cmd(hw, &desc, mr_list, buf_size, cd); 2046 if (!status) 2047 *rule_id = LE16_TO_CPU(cmd->rule_id) & ICE_AQC_RULE_ID_M; 2048 2049 ice_free(hw, mr_list); 2050 2051 return status; 2052 } 2053 2054 /** 2055 * ice_aq_delete_mir_rule - delete a mirror rule 2056 * @hw: pointer to the HW struct 2057 * @rule_id: Mirror rule ID (to be deleted) 2058 * @keep_allocd: if set, the VSI stays part of the PF allocated res, 2059 * otherwise it is returned to the shared pool 2060 * @cd: pointer to command details structure or NULL 2061 * 2062 * Delete Mirror Rule (0x261). 2063 */ 2064 enum ice_status 2065 ice_aq_delete_mir_rule(struct ice_hw *hw, u16 rule_id, bool keep_allocd, 2066 struct ice_sq_cd *cd) 2067 { 2068 struct ice_aqc_delete_mir_rule *cmd; 2069 struct ice_aq_desc desc; 2070 2071 /* rule_id should be in the range 0...63 */ 2072 if (rule_id >= ICE_MAX_NUM_MIRROR_RULES) 2073 return ICE_ERR_OUT_OF_RANGE; 2074 2075 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_del_mir_rule); 2076 2077 cmd = &desc.params.del_rule; 2078 rule_id |= ICE_AQC_RULE_ID_VALID_M; 2079 cmd->rule_id = CPU_TO_LE16(rule_id); 2080 2081 if (keep_allocd) 2082 cmd->flags = CPU_TO_LE16(ICE_AQC_FLAG_KEEP_ALLOCD_M); 2083 2084 return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 2085 } 2086 2087 /** 2088 * ice_aq_alloc_free_vsi_list 2089 * @hw: pointer to the HW struct 2090 * @vsi_list_id: VSI list ID returned or used for lookup 2091 * @lkup_type: switch rule filter lookup type 2092 * @opc: switch rules population command type - pass in the command opcode 2093 * 2094 * allocates or free a VSI list resource 2095 */ 2096 static enum ice_status 2097 ice_aq_alloc_free_vsi_list(struct ice_hw *hw, u16 *vsi_list_id, 2098 enum ice_sw_lkup_type lkup_type, 2099 enum ice_adminq_opc opc) 2100 { 2101 struct ice_aqc_alloc_free_res_elem *sw_buf; 2102 struct ice_aqc_res_elem *vsi_ele; 2103 enum ice_status status; 2104 u16 buf_len; 2105 2106 buf_len = sizeof(*sw_buf); 2107 sw_buf = (struct ice_aqc_alloc_free_res_elem *) 2108 ice_malloc(hw, buf_len); 2109 if (!sw_buf) 2110 return ICE_ERR_NO_MEMORY; 2111 sw_buf->num_elems = CPU_TO_LE16(1); 2112 2113 if (lkup_type == ICE_SW_LKUP_MAC || 2114 lkup_type == ICE_SW_LKUP_MAC_VLAN || 2115 lkup_type == ICE_SW_LKUP_ETHERTYPE || 2116 lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC || 2117 lkup_type == ICE_SW_LKUP_PROMISC || 2118 lkup_type == ICE_SW_LKUP_PROMISC_VLAN || 2119 lkup_type == ICE_SW_LKUP_LAST) { 2120 sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_VSI_LIST_REP); 2121 } else if (lkup_type == ICE_SW_LKUP_VLAN) { 2122 sw_buf->res_type = 2123 CPU_TO_LE16(ICE_AQC_RES_TYPE_VSI_LIST_PRUNE); 2124 } else { 2125 status = ICE_ERR_PARAM; 2126 goto ice_aq_alloc_free_vsi_list_exit; 2127 } 2128 2129 if (opc == ice_aqc_opc_free_res) 2130 sw_buf->elem[0].e.sw_resp = CPU_TO_LE16(*vsi_list_id); 2131 2132 status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, opc, NULL); 2133 if (status) 2134 goto ice_aq_alloc_free_vsi_list_exit; 2135 2136 if (opc == ice_aqc_opc_alloc_res) { 2137 vsi_ele = &sw_buf->elem[0]; 2138 *vsi_list_id = LE16_TO_CPU(vsi_ele->e.sw_resp); 2139 } 2140 2141 ice_aq_alloc_free_vsi_list_exit: 2142 ice_free(hw, sw_buf); 2143 return status; 2144 } 2145 2146 /** 2147 * ice_aq_set_storm_ctrl - Sets storm control configuration 2148 * @hw: pointer to the HW struct 2149 * @bcast_thresh: represents the upper threshold for broadcast storm control 2150 * @mcast_thresh: represents the upper threshold for multicast storm control 2151 * @ctl_bitmask: storm control control knobs 2152 * 2153 * Sets the storm control configuration (0x0280) 2154 */ 2155 enum ice_status 2156 ice_aq_set_storm_ctrl(struct ice_hw *hw, u32 bcast_thresh, u32 mcast_thresh, 2157 u32 ctl_bitmask) 2158 { 2159 struct ice_aqc_storm_cfg *cmd; 2160 struct ice_aq_desc desc; 2161 2162 cmd = &desc.params.storm_conf; 2163 2164 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_storm_cfg); 2165 2166 cmd->bcast_thresh_size = CPU_TO_LE32(bcast_thresh & ICE_AQ_THRESHOLD_M); 2167 cmd->mcast_thresh_size = CPU_TO_LE32(mcast_thresh & ICE_AQ_THRESHOLD_M); 2168 cmd->storm_ctrl_ctrl = CPU_TO_LE32(ctl_bitmask); 2169 2170 return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 2171 } 2172 2173 /** 2174 * ice_aq_get_storm_ctrl - gets storm control configuration 2175 * @hw: pointer to the HW struct 2176 * @bcast_thresh: represents the upper threshold for broadcast storm control 2177 * @mcast_thresh: represents the upper threshold for multicast storm control 2178 * @ctl_bitmask: storm control control knobs 2179 * 2180 * Gets the storm control configuration (0x0281) 2181 */ 2182 enum ice_status 2183 ice_aq_get_storm_ctrl(struct ice_hw *hw, u32 *bcast_thresh, u32 *mcast_thresh, 2184 u32 *ctl_bitmask) 2185 { 2186 enum ice_status status; 2187 struct ice_aq_desc desc; 2188 2189 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_storm_cfg); 2190 2191 status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 2192 if (!status) { 2193 struct ice_aqc_storm_cfg *resp = &desc.params.storm_conf; 2194 2195 if (bcast_thresh) 2196 *bcast_thresh = LE32_TO_CPU(resp->bcast_thresh_size) & 2197 ICE_AQ_THRESHOLD_M; 2198 if (mcast_thresh) 2199 *mcast_thresh = LE32_TO_CPU(resp->mcast_thresh_size) & 2200 ICE_AQ_THRESHOLD_M; 2201 if (ctl_bitmask) 2202 *ctl_bitmask = LE32_TO_CPU(resp->storm_ctrl_ctrl); 2203 } 2204 2205 return status; 2206 } 2207 2208 /** 2209 * ice_aq_sw_rules - add/update/remove switch rules 2210 * @hw: pointer to the HW struct 2211 * @rule_list: pointer to switch rule population list 2212 * @rule_list_sz: total size of the rule list in bytes 2213 * @num_rules: number of switch rules in the rule_list 2214 * @opc: switch rules population command type - pass in the command opcode 2215 * @cd: pointer to command details structure or NULL 2216 * 2217 * Add(0x02a0)/Update(0x02a1)/Remove(0x02a2) switch rules commands to firmware 2218 */ 2219 static enum ice_status 2220 ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz, 2221 u8 num_rules, enum ice_adminq_opc opc, struct ice_sq_cd *cd) 2222 { 2223 struct ice_aq_desc desc; 2224 enum ice_status status; 2225 2226 ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 2227 2228 if (opc != ice_aqc_opc_add_sw_rules && 2229 opc != ice_aqc_opc_update_sw_rules && 2230 opc != ice_aqc_opc_remove_sw_rules) 2231 return ICE_ERR_PARAM; 2232 2233 ice_fill_dflt_direct_cmd_desc(&desc, opc); 2234 2235 desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD); 2236 desc.params.sw_rules.num_rules_fltr_entry_index = 2237 CPU_TO_LE16(num_rules); 2238 status = ice_aq_send_cmd(hw, &desc, rule_list, rule_list_sz, cd); 2239 if (opc != ice_aqc_opc_add_sw_rules && 2240 hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT) 2241 status = ICE_ERR_DOES_NOT_EXIST; 2242 2243 return status; 2244 } 2245 2246 /** 2247 * ice_aq_add_recipe - add switch recipe 2248 * @hw: pointer to the HW struct 2249 * @s_recipe_list: pointer to switch rule population list 2250 * @num_recipes: number of switch recipes in the list 2251 * @cd: pointer to command details structure or NULL 2252 * 2253 * Add(0x0290) 2254 */ 2255 enum ice_status 2256 ice_aq_add_recipe(struct ice_hw *hw, 2257 struct ice_aqc_recipe_data_elem *s_recipe_list, 2258 u16 num_recipes, struct ice_sq_cd *cd) 2259 { 2260 struct ice_aqc_add_get_recipe *cmd; 2261 struct ice_aq_desc desc; 2262 u16 buf_size; 2263 2264 ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 2265 cmd = &desc.params.add_get_recipe; 2266 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_recipe); 2267 2268 cmd->num_sub_recipes = CPU_TO_LE16(num_recipes); 2269 desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD); 2270 2271 buf_size = num_recipes * sizeof(*s_recipe_list); 2272 2273 return ice_aq_send_cmd(hw, &desc, s_recipe_list, buf_size, cd); 2274 } 2275 2276 /** 2277 * ice_aq_get_recipe - get switch recipe 2278 * @hw: pointer to the HW struct 2279 * @s_recipe_list: pointer to switch rule population list 2280 * @num_recipes: pointer to the number of recipes (input and output) 2281 * @recipe_root: root recipe number of recipe(s) to retrieve 2282 * @cd: pointer to command details structure or NULL 2283 * 2284 * Get(0x0292) 2285 * 2286 * On input, *num_recipes should equal the number of entries in s_recipe_list. 2287 * On output, *num_recipes will equal the number of entries returned in 2288 * s_recipe_list. 2289 * 2290 * The caller must supply enough space in s_recipe_list to hold all possible 2291 * recipes and *num_recipes must equal ICE_MAX_NUM_RECIPES. 2292 */ 2293 enum ice_status 2294 ice_aq_get_recipe(struct ice_hw *hw, 2295 struct ice_aqc_recipe_data_elem *s_recipe_list, 2296 u16 *num_recipes, u16 recipe_root, struct ice_sq_cd *cd) 2297 { 2298 struct ice_aqc_add_get_recipe *cmd; 2299 struct ice_aq_desc desc; 2300 enum ice_status status; 2301 u16 buf_size; 2302 2303 if (*num_recipes != ICE_MAX_NUM_RECIPES) 2304 return ICE_ERR_PARAM; 2305 2306 ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 2307 cmd = &desc.params.add_get_recipe; 2308 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_recipe); 2309 2310 cmd->return_index = CPU_TO_LE16(recipe_root); 2311 cmd->num_sub_recipes = 0; 2312 2313 buf_size = *num_recipes * sizeof(*s_recipe_list); 2314 2315 status = ice_aq_send_cmd(hw, &desc, s_recipe_list, buf_size, cd); 2316 /* cppcheck-suppress constArgument */ 2317 *num_recipes = LE16_TO_CPU(cmd->num_sub_recipes); 2318 2319 return status; 2320 } 2321 2322 /** 2323 * ice_aq_map_recipe_to_profile - Map recipe to packet profile 2324 * @hw: pointer to the HW struct 2325 * @profile_id: package profile ID to associate the recipe with 2326 * @r_bitmap: Recipe bitmap filled in and need to be returned as response 2327 * @cd: pointer to command details structure or NULL 2328 * Recipe to profile association (0x0291) 2329 */ 2330 enum ice_status 2331 ice_aq_map_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap, 2332 struct ice_sq_cd *cd) 2333 { 2334 struct ice_aqc_recipe_to_profile *cmd; 2335 struct ice_aq_desc desc; 2336 2337 ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 2338 cmd = &desc.params.recipe_to_profile; 2339 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_recipe_to_profile); 2340 cmd->profile_id = CPU_TO_LE16(profile_id); 2341 /* Set the recipe ID bit in the bitmask to let the device know which 2342 * profile we are associating the recipe to 2343 */ 2344 ice_memcpy(cmd->recipe_assoc, r_bitmap, sizeof(cmd->recipe_assoc), 2345 ICE_NONDMA_TO_NONDMA); 2346 2347 return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 2348 } 2349 2350 /** 2351 * ice_aq_get_recipe_to_profile - Map recipe to packet profile 2352 * @hw: pointer to the HW struct 2353 * @profile_id: package profile ID to associate the recipe with 2354 * @r_bitmap: Recipe bitmap filled in and need to be returned as response 2355 * @cd: pointer to command details structure or NULL 2356 * Associate profile ID with given recipe (0x0293) 2357 */ 2358 enum ice_status 2359 ice_aq_get_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap, 2360 struct ice_sq_cd *cd) 2361 { 2362 struct ice_aqc_recipe_to_profile *cmd; 2363 struct ice_aq_desc desc; 2364 enum ice_status status; 2365 2366 ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 2367 cmd = &desc.params.recipe_to_profile; 2368 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_recipe_to_profile); 2369 cmd->profile_id = CPU_TO_LE16(profile_id); 2370 2371 status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 2372 if (!status) 2373 ice_memcpy(r_bitmap, cmd->recipe_assoc, 2374 sizeof(cmd->recipe_assoc), ICE_NONDMA_TO_NONDMA); 2375 2376 return status; 2377 } 2378 2379 /** 2380 * ice_alloc_recipe - add recipe resource 2381 * @hw: pointer to the hardware structure 2382 * @rid: recipe ID returned as response to AQ call 2383 */ 2384 enum ice_status ice_alloc_recipe(struct ice_hw *hw, u16 *rid) 2385 { 2386 struct ice_aqc_alloc_free_res_elem *sw_buf; 2387 enum ice_status status; 2388 u16 buf_len; 2389 2390 buf_len = sizeof(*sw_buf); 2391 sw_buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len); 2392 if (!sw_buf) 2393 return ICE_ERR_NO_MEMORY; 2394 2395 sw_buf->num_elems = CPU_TO_LE16(1); 2396 sw_buf->res_type = CPU_TO_LE16((ICE_AQC_RES_TYPE_RECIPE << 2397 ICE_AQC_RES_TYPE_S) | 2398 ICE_AQC_RES_TYPE_FLAG_SHARED); 2399 status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, 2400 ice_aqc_opc_alloc_res, NULL); 2401 if (!status) 2402 *rid = LE16_TO_CPU(sw_buf->elem[0].e.sw_resp); 2403 ice_free(hw, sw_buf); 2404 2405 return status; 2406 } 2407 2408 /* ice_init_port_info - Initialize port_info with switch configuration data 2409 * @pi: pointer to port_info 2410 * @vsi_port_num: VSI number or port number 2411 * @type: Type of switch element (port or VSI) 2412 * @swid: switch ID of the switch the element is attached to 2413 * @pf_vf_num: PF or VF number 2414 * @is_vf: true if the element is a VF, false otherwise 2415 */ 2416 static void 2417 ice_init_port_info(struct ice_port_info *pi, u16 vsi_port_num, u8 type, 2418 u16 swid, u16 pf_vf_num, bool is_vf) 2419 { 2420 switch (type) { 2421 case ICE_AQC_GET_SW_CONF_RESP_PHYS_PORT: 2422 pi->lport = (u8)(vsi_port_num & ICE_LPORT_MASK); 2423 pi->sw_id = swid; 2424 pi->pf_vf_num = pf_vf_num; 2425 pi->is_vf = is_vf; 2426 pi->dflt_tx_vsi_num = ICE_DFLT_VSI_INVAL; 2427 pi->dflt_rx_vsi_num = ICE_DFLT_VSI_INVAL; 2428 break; 2429 default: 2430 ice_debug(pi->hw, ICE_DBG_SW, 2431 "incorrect VSI/port type received\n"); 2432 break; 2433 } 2434 } 2435 2436 /* ice_get_initial_sw_cfg - Get initial port and default VSI data 2437 * @hw: pointer to the hardware structure 2438 */ 2439 enum ice_status ice_get_initial_sw_cfg(struct ice_hw *hw) 2440 { 2441 struct ice_aqc_get_sw_cfg_resp *rbuf; 2442 enum ice_status status; 2443 u8 num_total_ports; 2444 u16 req_desc = 0; 2445 u16 num_elems; 2446 u8 j = 0; 2447 u16 i; 2448 2449 num_total_ports = 1; 2450 2451 rbuf = (struct ice_aqc_get_sw_cfg_resp *) 2452 ice_malloc(hw, ICE_SW_CFG_MAX_BUF_LEN); 2453 2454 if (!rbuf) 2455 return ICE_ERR_NO_MEMORY; 2456 2457 /* Multiple calls to ice_aq_get_sw_cfg may be required 2458 * to get all the switch configuration information. The need 2459 * for additional calls is indicated by ice_aq_get_sw_cfg 2460 * writing a non-zero value in req_desc 2461 */ 2462 do { 2463 status = ice_aq_get_sw_cfg(hw, rbuf, ICE_SW_CFG_MAX_BUF_LEN, 2464 &req_desc, &num_elems, NULL); 2465 2466 if (status) 2467 break; 2468 2469 for (i = 0; i < num_elems; i++) { 2470 struct ice_aqc_get_sw_cfg_resp_elem *ele; 2471 u16 pf_vf_num, swid, vsi_port_num; 2472 bool is_vf = false; 2473 u8 res_type; 2474 2475 ele = rbuf[i].elements; 2476 vsi_port_num = LE16_TO_CPU(ele->vsi_port_num) & 2477 ICE_AQC_GET_SW_CONF_RESP_VSI_PORT_NUM_M; 2478 2479 pf_vf_num = LE16_TO_CPU(ele->pf_vf_num) & 2480 ICE_AQC_GET_SW_CONF_RESP_FUNC_NUM_M; 2481 2482 swid = LE16_TO_CPU(ele->swid); 2483 2484 if (LE16_TO_CPU(ele->pf_vf_num) & 2485 ICE_AQC_GET_SW_CONF_RESP_IS_VF) 2486 is_vf = true; 2487 2488 res_type = (u8)(LE16_TO_CPU(ele->vsi_port_num) >> 2489 ICE_AQC_GET_SW_CONF_RESP_TYPE_S); 2490 2491 switch (res_type) { 2492 case ICE_AQC_GET_SW_CONF_RESP_PHYS_PORT: 2493 case ICE_AQC_GET_SW_CONF_RESP_VIRT_PORT: 2494 if (j == num_total_ports) { 2495 ice_debug(hw, ICE_DBG_SW, 2496 "more ports than expected\n"); 2497 status = ICE_ERR_CFG; 2498 goto out; 2499 } 2500 ice_init_port_info(hw->port_info, 2501 vsi_port_num, res_type, swid, 2502 pf_vf_num, is_vf); 2503 j++; 2504 break; 2505 default: 2506 break; 2507 } 2508 } 2509 } while (req_desc && !status); 2510 2511 out: 2512 ice_free(hw, (void *)rbuf); 2513 return status; 2514 } 2515 2516 /** 2517 * ice_fill_sw_info - Helper function to populate lb_en and lan_en 2518 * @hw: pointer to the hardware structure 2519 * @fi: filter info structure to fill/update 2520 * 2521 * This helper function populates the lb_en and lan_en elements of the provided 2522 * ice_fltr_info struct using the switch's type and characteristics of the 2523 * switch rule being configured. 2524 */ 2525 static void ice_fill_sw_info(struct ice_hw *hw, struct ice_fltr_info *fi) 2526 { 2527 if ((fi->flag & ICE_FLTR_RX) && 2528 (fi->fltr_act == ICE_FWD_TO_VSI || 2529 fi->fltr_act == ICE_FWD_TO_VSI_LIST) && 2530 fi->lkup_type == ICE_SW_LKUP_LAST) 2531 fi->lan_en = true; 2532 fi->lb_en = false; 2533 fi->lan_en = false; 2534 if ((fi->flag & ICE_FLTR_TX) && 2535 (fi->fltr_act == ICE_FWD_TO_VSI || 2536 fi->fltr_act == ICE_FWD_TO_VSI_LIST || 2537 fi->fltr_act == ICE_FWD_TO_Q || 2538 fi->fltr_act == ICE_FWD_TO_QGRP)) { 2539 /* Setting LB for prune actions will result in replicated 2540 * packets to the internal switch that will be dropped. 2541 */ 2542 if (fi->lkup_type != ICE_SW_LKUP_VLAN) 2543 fi->lb_en = true; 2544 2545 /* Set lan_en to TRUE if 2546 * 1. The switch is a VEB AND 2547 * 2 2548 * 2.1 The lookup is a directional lookup like ethertype, 2549 * promiscuous, ethertype-MAC, promiscuous-VLAN 2550 * and default-port OR 2551 * 2.2 The lookup is VLAN, OR 2552 * 2.3 The lookup is MAC with mcast or bcast addr for MAC, OR 2553 * 2.4 The lookup is MAC_VLAN with mcast or bcast addr for MAC. 2554 * 2555 * OR 2556 * 2557 * The switch is a VEPA. 2558 * 2559 * In all other cases, the LAN enable has to be set to false. 2560 */ 2561 if (hw->evb_veb) { 2562 if (fi->lkup_type == ICE_SW_LKUP_ETHERTYPE || 2563 fi->lkup_type == ICE_SW_LKUP_PROMISC || 2564 fi->lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC || 2565 fi->lkup_type == ICE_SW_LKUP_PROMISC_VLAN || 2566 fi->lkup_type == ICE_SW_LKUP_DFLT || 2567 fi->lkup_type == ICE_SW_LKUP_VLAN || 2568 (fi->lkup_type == ICE_SW_LKUP_MAC && 2569 !IS_UNICAST_ETHER_ADDR(fi->l_data.mac.mac_addr)) || 2570 (fi->lkup_type == ICE_SW_LKUP_MAC_VLAN && 2571 !IS_UNICAST_ETHER_ADDR(fi->l_data.mac.mac_addr))) 2572 fi->lan_en = true; 2573 } else { 2574 fi->lan_en = true; 2575 } 2576 } 2577 } 2578 2579 /** 2580 * ice_fill_sw_rule - Helper function to fill switch rule structure 2581 * @hw: pointer to the hardware structure 2582 * @f_info: entry containing packet forwarding information 2583 * @s_rule: switch rule structure to be filled in based on mac_entry 2584 * @opc: switch rules population command type - pass in the command opcode 2585 */ 2586 static void 2587 ice_fill_sw_rule(struct ice_hw *hw, struct ice_fltr_info *f_info, 2588 struct ice_aqc_sw_rules_elem *s_rule, enum ice_adminq_opc opc) 2589 { 2590 u16 vlan_id = ICE_MAX_VLAN_ID + 1; 2591 void *daddr = NULL; 2592 u16 eth_hdr_sz; 2593 u8 *eth_hdr; 2594 u32 act = 0; 2595 __be16 *off; 2596 u8 q_rgn; 2597 2598 if (opc == ice_aqc_opc_remove_sw_rules) { 2599 s_rule->pdata.lkup_tx_rx.act = 0; 2600 s_rule->pdata.lkup_tx_rx.index = 2601 CPU_TO_LE16(f_info->fltr_rule_id); 2602 s_rule->pdata.lkup_tx_rx.hdr_len = 0; 2603 return; 2604 } 2605 2606 eth_hdr_sz = sizeof(dummy_eth_header); 2607 eth_hdr = s_rule->pdata.lkup_tx_rx.hdr; 2608 2609 /* initialize the ether header with a dummy header */ 2610 ice_memcpy(eth_hdr, dummy_eth_header, eth_hdr_sz, ICE_NONDMA_TO_NONDMA); 2611 ice_fill_sw_info(hw, f_info); 2612 2613 switch (f_info->fltr_act) { 2614 case ICE_FWD_TO_VSI: 2615 act |= (f_info->fwd_id.hw_vsi_id << ICE_SINGLE_ACT_VSI_ID_S) & 2616 ICE_SINGLE_ACT_VSI_ID_M; 2617 if (f_info->lkup_type != ICE_SW_LKUP_VLAN) 2618 act |= ICE_SINGLE_ACT_VSI_FORWARDING | 2619 ICE_SINGLE_ACT_VALID_BIT; 2620 break; 2621 case ICE_FWD_TO_VSI_LIST: 2622 act |= ICE_SINGLE_ACT_VSI_LIST; 2623 act |= (f_info->fwd_id.vsi_list_id << 2624 ICE_SINGLE_ACT_VSI_LIST_ID_S) & 2625 ICE_SINGLE_ACT_VSI_LIST_ID_M; 2626 if (f_info->lkup_type != ICE_SW_LKUP_VLAN) 2627 act |= ICE_SINGLE_ACT_VSI_FORWARDING | 2628 ICE_SINGLE_ACT_VALID_BIT; 2629 break; 2630 case ICE_FWD_TO_Q: 2631 act |= ICE_SINGLE_ACT_TO_Q; 2632 act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) & 2633 ICE_SINGLE_ACT_Q_INDEX_M; 2634 break; 2635 case ICE_DROP_PACKET: 2636 act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_DROP | 2637 ICE_SINGLE_ACT_VALID_BIT; 2638 break; 2639 case ICE_FWD_TO_QGRP: 2640 q_rgn = f_info->qgrp_size > 0 ? 2641 (u8)ice_ilog2(f_info->qgrp_size) : 0; 2642 act |= ICE_SINGLE_ACT_TO_Q; 2643 act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) & 2644 ICE_SINGLE_ACT_Q_INDEX_M; 2645 act |= (q_rgn << ICE_SINGLE_ACT_Q_REGION_S) & 2646 ICE_SINGLE_ACT_Q_REGION_M; 2647 break; 2648 default: 2649 return; 2650 } 2651 2652 if (f_info->lb_en) 2653 act |= ICE_SINGLE_ACT_LB_ENABLE; 2654 if (f_info->lan_en) 2655 act |= ICE_SINGLE_ACT_LAN_ENABLE; 2656 2657 switch (f_info->lkup_type) { 2658 case ICE_SW_LKUP_MAC: 2659 daddr = f_info->l_data.mac.mac_addr; 2660 break; 2661 case ICE_SW_LKUP_VLAN: 2662 vlan_id = f_info->l_data.vlan.vlan_id; 2663 if (f_info->fltr_act == ICE_FWD_TO_VSI || 2664 f_info->fltr_act == ICE_FWD_TO_VSI_LIST) { 2665 act |= ICE_SINGLE_ACT_PRUNE; 2666 act |= ICE_SINGLE_ACT_EGRESS | ICE_SINGLE_ACT_INGRESS; 2667 } 2668 break; 2669 case ICE_SW_LKUP_ETHERTYPE_MAC: 2670 daddr = f_info->l_data.ethertype_mac.mac_addr; 2671 /* fall-through */ 2672 case ICE_SW_LKUP_ETHERTYPE: 2673 off = (_FORCE_ __be16 *)(eth_hdr + ICE_ETH_ETHTYPE_OFFSET); 2674 *off = CPU_TO_BE16(f_info->l_data.ethertype_mac.ethertype); 2675 break; 2676 case ICE_SW_LKUP_MAC_VLAN: 2677 daddr = f_info->l_data.mac_vlan.mac_addr; 2678 vlan_id = f_info->l_data.mac_vlan.vlan_id; 2679 break; 2680 case ICE_SW_LKUP_PROMISC_VLAN: 2681 vlan_id = f_info->l_data.mac_vlan.vlan_id; 2682 /* fall-through */ 2683 case ICE_SW_LKUP_PROMISC: 2684 daddr = f_info->l_data.mac_vlan.mac_addr; 2685 break; 2686 default: 2687 break; 2688 } 2689 2690 s_rule->type = (f_info->flag & ICE_FLTR_RX) ? 2691 CPU_TO_LE16(ICE_AQC_SW_RULES_T_LKUP_RX) : 2692 CPU_TO_LE16(ICE_AQC_SW_RULES_T_LKUP_TX); 2693 2694 /* Recipe set depending on lookup type */ 2695 s_rule->pdata.lkup_tx_rx.recipe_id = CPU_TO_LE16(f_info->lkup_type); 2696 s_rule->pdata.lkup_tx_rx.src = CPU_TO_LE16(f_info->src); 2697 s_rule->pdata.lkup_tx_rx.act = CPU_TO_LE32(act); 2698 2699 if (daddr) 2700 ice_memcpy(eth_hdr + ICE_ETH_DA_OFFSET, daddr, ETH_ALEN, 2701 ICE_NONDMA_TO_NONDMA); 2702 2703 if (!(vlan_id > ICE_MAX_VLAN_ID)) { 2704 off = (_FORCE_ __be16 *)(eth_hdr + ICE_ETH_VLAN_TCI_OFFSET); 2705 *off = CPU_TO_BE16(vlan_id); 2706 } 2707 2708 /* Create the switch rule with the final dummy Ethernet header */ 2709 if (opc != ice_aqc_opc_update_sw_rules) 2710 s_rule->pdata.lkup_tx_rx.hdr_len = CPU_TO_LE16(eth_hdr_sz); 2711 } 2712 2713 /** 2714 * ice_add_marker_act 2715 * @hw: pointer to the hardware structure 2716 * @m_ent: the management entry for which sw marker needs to be added 2717 * @sw_marker: sw marker to tag the Rx descriptor with 2718 * @l_id: large action resource ID 2719 * 2720 * Create a large action to hold software marker and update the switch rule 2721 * entry pointed by m_ent with newly created large action 2722 */ 2723 static enum ice_status 2724 ice_add_marker_act(struct ice_hw *hw, struct ice_fltr_mgmt_list_entry *m_ent, 2725 u16 sw_marker, u16 l_id) 2726 { 2727 struct ice_aqc_sw_rules_elem *lg_act, *rx_tx; 2728 /* For software marker we need 3 large actions 2729 * 1. FWD action: FWD TO VSI or VSI LIST 2730 * 2. GENERIC VALUE action to hold the profile ID 2731 * 3. GENERIC VALUE action to hold the software marker ID 2732 */ 2733 const u16 num_lg_acts = 3; 2734 enum ice_status status; 2735 u16 lg_act_size; 2736 u16 rules_size; 2737 u32 act; 2738 u16 id; 2739 2740 if (m_ent->fltr_info.lkup_type != ICE_SW_LKUP_MAC) 2741 return ICE_ERR_PARAM; 2742 2743 /* Create two back-to-back switch rules and submit them to the HW using 2744 * one memory buffer: 2745 * 1. Large Action 2746 * 2. Look up Tx Rx 2747 */ 2748 lg_act_size = (u16)ICE_SW_RULE_LG_ACT_SIZE(num_lg_acts); 2749 rules_size = lg_act_size + ICE_SW_RULE_RX_TX_ETH_HDR_SIZE; 2750 lg_act = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, rules_size); 2751 if (!lg_act) 2752 return ICE_ERR_NO_MEMORY; 2753 2754 rx_tx = (struct ice_aqc_sw_rules_elem *)((u8 *)lg_act + lg_act_size); 2755 2756 /* Fill in the first switch rule i.e. large action */ 2757 lg_act->type = CPU_TO_LE16(ICE_AQC_SW_RULES_T_LG_ACT); 2758 lg_act->pdata.lg_act.index = CPU_TO_LE16(l_id); 2759 lg_act->pdata.lg_act.size = CPU_TO_LE16(num_lg_acts); 2760 2761 /* First action VSI forwarding or VSI list forwarding depending on how 2762 * many VSIs 2763 */ 2764 id = (m_ent->vsi_count > 1) ? m_ent->fltr_info.fwd_id.vsi_list_id : 2765 m_ent->fltr_info.fwd_id.hw_vsi_id; 2766 2767 act = ICE_LG_ACT_VSI_FORWARDING | ICE_LG_ACT_VALID_BIT; 2768 act |= (id << ICE_LG_ACT_VSI_LIST_ID_S) & 2769 ICE_LG_ACT_VSI_LIST_ID_M; 2770 if (m_ent->vsi_count > 1) 2771 act |= ICE_LG_ACT_VSI_LIST; 2772 lg_act->pdata.lg_act.act[0] = CPU_TO_LE32(act); 2773 2774 /* Second action descriptor type */ 2775 act = ICE_LG_ACT_GENERIC; 2776 2777 act |= (1 << ICE_LG_ACT_GENERIC_VALUE_S) & ICE_LG_ACT_GENERIC_VALUE_M; 2778 lg_act->pdata.lg_act.act[1] = CPU_TO_LE32(act); 2779 2780 act = (ICE_LG_ACT_GENERIC_OFF_RX_DESC_PROF_IDX << 2781 ICE_LG_ACT_GENERIC_OFFSET_S) & ICE_LG_ACT_GENERIC_OFFSET_M; 2782 2783 /* Third action Marker value */ 2784 act |= ICE_LG_ACT_GENERIC; 2785 act |= (sw_marker << ICE_LG_ACT_GENERIC_VALUE_S) & 2786 ICE_LG_ACT_GENERIC_VALUE_M; 2787 2788 lg_act->pdata.lg_act.act[2] = CPU_TO_LE32(act); 2789 2790 /* call the fill switch rule to fill the lookup Tx Rx structure */ 2791 ice_fill_sw_rule(hw, &m_ent->fltr_info, rx_tx, 2792 ice_aqc_opc_update_sw_rules); 2793 2794 /* Update the action to point to the large action ID */ 2795 rx_tx->pdata.lkup_tx_rx.act = 2796 CPU_TO_LE32(ICE_SINGLE_ACT_PTR | 2797 ((l_id << ICE_SINGLE_ACT_PTR_VAL_S) & 2798 ICE_SINGLE_ACT_PTR_VAL_M)); 2799 2800 /* Use the filter rule ID of the previously created rule with single 2801 * act. Once the update happens, hardware will treat this as large 2802 * action 2803 */ 2804 rx_tx->pdata.lkup_tx_rx.index = 2805 CPU_TO_LE16(m_ent->fltr_info.fltr_rule_id); 2806 2807 status = ice_aq_sw_rules(hw, lg_act, rules_size, 2, 2808 ice_aqc_opc_update_sw_rules, NULL); 2809 if (!status) { 2810 m_ent->lg_act_idx = l_id; 2811 m_ent->sw_marker_id = sw_marker; 2812 } 2813 2814 ice_free(hw, lg_act); 2815 return status; 2816 } 2817 2818 /** 2819 * ice_add_counter_act - add/update filter rule with counter action 2820 * @hw: pointer to the hardware structure 2821 * @m_ent: the management entry for which counter needs to be added 2822 * @counter_id: VLAN counter ID returned as part of allocate resource 2823 * @l_id: large action resource ID 2824 */ 2825 static enum ice_status 2826 ice_add_counter_act(struct ice_hw *hw, struct ice_fltr_mgmt_list_entry *m_ent, 2827 u16 counter_id, u16 l_id) 2828 { 2829 struct ice_aqc_sw_rules_elem *lg_act; 2830 struct ice_aqc_sw_rules_elem *rx_tx; 2831 enum ice_status status; 2832 /* 2 actions will be added while adding a large action counter */ 2833 const int num_acts = 2; 2834 u16 lg_act_size; 2835 u16 rules_size; 2836 u16 f_rule_id; 2837 u32 act; 2838 u16 id; 2839 2840 if (m_ent->fltr_info.lkup_type != ICE_SW_LKUP_MAC) 2841 return ICE_ERR_PARAM; 2842 2843 /* Create two back-to-back switch rules and submit them to the HW using 2844 * one memory buffer: 2845 * 1. Large Action 2846 * 2. Look up Tx Rx 2847 */ 2848 lg_act_size = (u16)ICE_SW_RULE_LG_ACT_SIZE(num_acts); 2849 rules_size = lg_act_size + ICE_SW_RULE_RX_TX_ETH_HDR_SIZE; 2850 lg_act = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, 2851 rules_size); 2852 if (!lg_act) 2853 return ICE_ERR_NO_MEMORY; 2854 2855 rx_tx = (struct ice_aqc_sw_rules_elem *) 2856 ((u8 *)lg_act + lg_act_size); 2857 2858 /* Fill in the first switch rule i.e. large action */ 2859 lg_act->type = CPU_TO_LE16(ICE_AQC_SW_RULES_T_LG_ACT); 2860 lg_act->pdata.lg_act.index = CPU_TO_LE16(l_id); 2861 lg_act->pdata.lg_act.size = CPU_TO_LE16(num_acts); 2862 2863 /* First action VSI forwarding or VSI list forwarding depending on how 2864 * many VSIs 2865 */ 2866 id = (m_ent->vsi_count > 1) ? m_ent->fltr_info.fwd_id.vsi_list_id : 2867 m_ent->fltr_info.fwd_id.hw_vsi_id; 2868 2869 act = ICE_LG_ACT_VSI_FORWARDING | ICE_LG_ACT_VALID_BIT; 2870 act |= (id << ICE_LG_ACT_VSI_LIST_ID_S) & 2871 ICE_LG_ACT_VSI_LIST_ID_M; 2872 if (m_ent->vsi_count > 1) 2873 act |= ICE_LG_ACT_VSI_LIST; 2874 lg_act->pdata.lg_act.act[0] = CPU_TO_LE32(act); 2875 2876 /* Second action counter ID */ 2877 act = ICE_LG_ACT_STAT_COUNT; 2878 act |= (counter_id << ICE_LG_ACT_STAT_COUNT_S) & 2879 ICE_LG_ACT_STAT_COUNT_M; 2880 lg_act->pdata.lg_act.act[1] = CPU_TO_LE32(act); 2881 2882 /* call the fill switch rule to fill the lookup Tx Rx structure */ 2883 ice_fill_sw_rule(hw, &m_ent->fltr_info, rx_tx, 2884 ice_aqc_opc_update_sw_rules); 2885 2886 act = ICE_SINGLE_ACT_PTR; 2887 act |= (l_id << ICE_SINGLE_ACT_PTR_VAL_S) & ICE_SINGLE_ACT_PTR_VAL_M; 2888 rx_tx->pdata.lkup_tx_rx.act = CPU_TO_LE32(act); 2889 2890 /* Use the filter rule ID of the previously created rule with single 2891 * act. Once the update happens, hardware will treat this as large 2892 * action 2893 */ 2894 f_rule_id = m_ent->fltr_info.fltr_rule_id; 2895 rx_tx->pdata.lkup_tx_rx.index = CPU_TO_LE16(f_rule_id); 2896 2897 status = ice_aq_sw_rules(hw, lg_act, rules_size, 2, 2898 ice_aqc_opc_update_sw_rules, NULL); 2899 if (!status) { 2900 m_ent->lg_act_idx = l_id; 2901 m_ent->counter_index = counter_id; 2902 } 2903 2904 ice_free(hw, lg_act); 2905 return status; 2906 } 2907 2908 /** 2909 * ice_create_vsi_list_map 2910 * @hw: pointer to the hardware structure 2911 * @vsi_handle_arr: array of VSI handles to set in the VSI mapping 2912 * @num_vsi: number of VSI handles in the array 2913 * @vsi_list_id: VSI list ID generated as part of allocate resource 2914 * 2915 * Helper function to create a new entry of VSI list ID to VSI mapping 2916 * using the given VSI list ID 2917 */ 2918 static struct ice_vsi_list_map_info * 2919 ice_create_vsi_list_map(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi, 2920 u16 vsi_list_id) 2921 { 2922 struct ice_switch_info *sw = hw->switch_info; 2923 struct ice_vsi_list_map_info *v_map; 2924 int i; 2925 2926 v_map = (struct ice_vsi_list_map_info *)ice_calloc(hw, 1, 2927 sizeof(*v_map)); 2928 if (!v_map) 2929 return NULL; 2930 2931 v_map->vsi_list_id = vsi_list_id; 2932 v_map->ref_cnt = 1; 2933 for (i = 0; i < num_vsi; i++) 2934 ice_set_bit(vsi_handle_arr[i], v_map->vsi_map); 2935 2936 LIST_ADD(&v_map->list_entry, &sw->vsi_list_map_head); 2937 return v_map; 2938 } 2939 2940 /** 2941 * ice_update_vsi_list_rule 2942 * @hw: pointer to the hardware structure 2943 * @vsi_handle_arr: array of VSI handles to form a VSI list 2944 * @num_vsi: number of VSI handles in the array 2945 * @vsi_list_id: VSI list ID generated as part of allocate resource 2946 * @remove: Boolean value to indicate if this is a remove action 2947 * @opc: switch rules population command type - pass in the command opcode 2948 * @lkup_type: lookup type of the filter 2949 * 2950 * Call AQ command to add a new switch rule or update existing switch rule 2951 * using the given VSI list ID 2952 */ 2953 static enum ice_status 2954 ice_update_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi, 2955 u16 vsi_list_id, bool remove, enum ice_adminq_opc opc, 2956 enum ice_sw_lkup_type lkup_type) 2957 { 2958 struct ice_aqc_sw_rules_elem *s_rule; 2959 enum ice_status status; 2960 u16 s_rule_size; 2961 u16 rule_type; 2962 int i; 2963 2964 if (!num_vsi) 2965 return ICE_ERR_PARAM; 2966 2967 if (lkup_type == ICE_SW_LKUP_MAC || 2968 lkup_type == ICE_SW_LKUP_MAC_VLAN || 2969 lkup_type == ICE_SW_LKUP_ETHERTYPE || 2970 lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC || 2971 lkup_type == ICE_SW_LKUP_PROMISC || 2972 lkup_type == ICE_SW_LKUP_PROMISC_VLAN || 2973 lkup_type == ICE_SW_LKUP_LAST) 2974 rule_type = remove ? ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR : 2975 ICE_AQC_SW_RULES_T_VSI_LIST_SET; 2976 else if (lkup_type == ICE_SW_LKUP_VLAN) 2977 rule_type = remove ? ICE_AQC_SW_RULES_T_PRUNE_LIST_CLEAR : 2978 ICE_AQC_SW_RULES_T_PRUNE_LIST_SET; 2979 else 2980 return ICE_ERR_PARAM; 2981 2982 s_rule_size = (u16)ICE_SW_RULE_VSI_LIST_SIZE(num_vsi); 2983 s_rule = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, s_rule_size); 2984 if (!s_rule) 2985 return ICE_ERR_NO_MEMORY; 2986 for (i = 0; i < num_vsi; i++) { 2987 if (!ice_is_vsi_valid(hw, vsi_handle_arr[i])) { 2988 status = ICE_ERR_PARAM; 2989 goto exit; 2990 } 2991 /* AQ call requires hw_vsi_id(s) */ 2992 s_rule->pdata.vsi_list.vsi[i] = 2993 CPU_TO_LE16(ice_get_hw_vsi_num(hw, vsi_handle_arr[i])); 2994 } 2995 2996 s_rule->type = CPU_TO_LE16(rule_type); 2997 s_rule->pdata.vsi_list.number_vsi = CPU_TO_LE16(num_vsi); 2998 s_rule->pdata.vsi_list.index = CPU_TO_LE16(vsi_list_id); 2999 3000 status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opc, NULL); 3001 3002 exit: 3003 ice_free(hw, s_rule); 3004 return status; 3005 } 3006 3007 /** 3008 * ice_create_vsi_list_rule - Creates and populates a VSI list rule 3009 * @hw: pointer to the HW struct 3010 * @vsi_handle_arr: array of VSI handles to form a VSI list 3011 * @num_vsi: number of VSI handles in the array 3012 * @vsi_list_id: stores the ID of the VSI list to be created 3013 * @lkup_type: switch rule filter's lookup type 3014 */ 3015 static enum ice_status 3016 ice_create_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi, 3017 u16 *vsi_list_id, enum ice_sw_lkup_type lkup_type) 3018 { 3019 enum ice_status status; 3020 3021 status = ice_aq_alloc_free_vsi_list(hw, vsi_list_id, lkup_type, 3022 ice_aqc_opc_alloc_res); 3023 if (status) 3024 return status; 3025 3026 /* Update the newly created VSI list to include the specified VSIs */ 3027 return ice_update_vsi_list_rule(hw, vsi_handle_arr, num_vsi, 3028 *vsi_list_id, false, 3029 ice_aqc_opc_add_sw_rules, lkup_type); 3030 } 3031 3032 /** 3033 * ice_create_pkt_fwd_rule 3034 * @hw: pointer to the hardware structure 3035 * @recp_list: corresponding filter management list 3036 * @f_entry: entry containing packet forwarding information 3037 * 3038 * Create switch rule with given filter information and add an entry 3039 * to the corresponding filter management list to track this switch rule 3040 * and VSI mapping 3041 */ 3042 static enum ice_status 3043 ice_create_pkt_fwd_rule(struct ice_hw *hw, struct ice_sw_recipe *recp_list, 3044 struct ice_fltr_list_entry *f_entry) 3045 { 3046 struct ice_fltr_mgmt_list_entry *fm_entry; 3047 struct ice_aqc_sw_rules_elem *s_rule; 3048 enum ice_status status; 3049 3050 s_rule = (struct ice_aqc_sw_rules_elem *) 3051 ice_malloc(hw, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE); 3052 if (!s_rule) 3053 return ICE_ERR_NO_MEMORY; 3054 fm_entry = (struct ice_fltr_mgmt_list_entry *) 3055 ice_malloc(hw, sizeof(*fm_entry)); 3056 if (!fm_entry) { 3057 status = ICE_ERR_NO_MEMORY; 3058 goto ice_create_pkt_fwd_rule_exit; 3059 } 3060 3061 fm_entry->fltr_info = f_entry->fltr_info; 3062 3063 /* Initialize all the fields for the management entry */ 3064 fm_entry->vsi_count = 1; 3065 fm_entry->lg_act_idx = ICE_INVAL_LG_ACT_INDEX; 3066 fm_entry->sw_marker_id = ICE_INVAL_SW_MARKER_ID; 3067 fm_entry->counter_index = ICE_INVAL_COUNTER_ID; 3068 3069 ice_fill_sw_rule(hw, &fm_entry->fltr_info, s_rule, 3070 ice_aqc_opc_add_sw_rules); 3071 3072 status = ice_aq_sw_rules(hw, s_rule, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, 1, 3073 ice_aqc_opc_add_sw_rules, NULL); 3074 if (status) { 3075 ice_free(hw, fm_entry); 3076 goto ice_create_pkt_fwd_rule_exit; 3077 } 3078 3079 f_entry->fltr_info.fltr_rule_id = 3080 LE16_TO_CPU(s_rule->pdata.lkup_tx_rx.index); 3081 fm_entry->fltr_info.fltr_rule_id = 3082 LE16_TO_CPU(s_rule->pdata.lkup_tx_rx.index); 3083 3084 /* The book keeping entries will get removed when base driver 3085 * calls remove filter AQ command 3086 */ 3087 LIST_ADD(&fm_entry->list_entry, &recp_list->filt_rules); 3088 3089 ice_create_pkt_fwd_rule_exit: 3090 ice_free(hw, s_rule); 3091 return status; 3092 } 3093 3094 /** 3095 * ice_update_pkt_fwd_rule 3096 * @hw: pointer to the hardware structure 3097 * @f_info: filter information for switch rule 3098 * 3099 * Call AQ command to update a previously created switch rule with a 3100 * VSI list ID 3101 */ 3102 static enum ice_status 3103 ice_update_pkt_fwd_rule(struct ice_hw *hw, struct ice_fltr_info *f_info) 3104 { 3105 struct ice_aqc_sw_rules_elem *s_rule; 3106 enum ice_status status; 3107 3108 s_rule = (struct ice_aqc_sw_rules_elem *) 3109 ice_malloc(hw, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE); 3110 if (!s_rule) 3111 return ICE_ERR_NO_MEMORY; 3112 3113 ice_fill_sw_rule(hw, f_info, s_rule, ice_aqc_opc_update_sw_rules); 3114 3115 s_rule->pdata.lkup_tx_rx.index = CPU_TO_LE16(f_info->fltr_rule_id); 3116 3117 /* Update switch rule with new rule set to forward VSI list */ 3118 status = ice_aq_sw_rules(hw, s_rule, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, 1, 3119 ice_aqc_opc_update_sw_rules, NULL); 3120 3121 ice_free(hw, s_rule); 3122 return status; 3123 } 3124 3125 /** 3126 * ice_update_sw_rule_bridge_mode 3127 * @hw: pointer to the HW struct 3128 * 3129 * Updates unicast switch filter rules based on VEB/VEPA mode 3130 */ 3131 enum ice_status ice_update_sw_rule_bridge_mode(struct ice_hw *hw) 3132 { 3133 struct ice_switch_info *sw = hw->switch_info; 3134 struct ice_fltr_mgmt_list_entry *fm_entry; 3135 enum ice_status status = ICE_SUCCESS; 3136 struct LIST_HEAD_TYPE *rule_head; 3137 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 3138 3139 rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock; 3140 rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules; 3141 3142 ice_acquire_lock(rule_lock); 3143 LIST_FOR_EACH_ENTRY(fm_entry, rule_head, ice_fltr_mgmt_list_entry, 3144 list_entry) { 3145 struct ice_fltr_info *fi = &fm_entry->fltr_info; 3146 u8 *addr = fi->l_data.mac.mac_addr; 3147 3148 /* Update unicast Tx rules to reflect the selected 3149 * VEB/VEPA mode 3150 */ 3151 if ((fi->flag & ICE_FLTR_TX) && IS_UNICAST_ETHER_ADDR(addr) && 3152 (fi->fltr_act == ICE_FWD_TO_VSI || 3153 fi->fltr_act == ICE_FWD_TO_VSI_LIST || 3154 fi->fltr_act == ICE_FWD_TO_Q || 3155 fi->fltr_act == ICE_FWD_TO_QGRP)) { 3156 status = ice_update_pkt_fwd_rule(hw, fi); 3157 if (status) 3158 break; 3159 } 3160 } 3161 3162 ice_release_lock(rule_lock); 3163 3164 return status; 3165 } 3166 3167 /** 3168 * ice_add_update_vsi_list 3169 * @hw: pointer to the hardware structure 3170 * @m_entry: pointer to current filter management list entry 3171 * @cur_fltr: filter information from the book keeping entry 3172 * @new_fltr: filter information with the new VSI to be added 3173 * 3174 * Call AQ command to add or update previously created VSI list with new VSI. 3175 * 3176 * Helper function to do book keeping associated with adding filter information 3177 * The algorithm to do the book keeping is described below : 3178 * When a VSI needs to subscribe to a given filter (MAC/VLAN/Ethtype etc.) 3179 * if only one VSI has been added till now 3180 * Allocate a new VSI list and add two VSIs 3181 * to this list using switch rule command 3182 * Update the previously created switch rule with the 3183 * newly created VSI list ID 3184 * if a VSI list was previously created 3185 * Add the new VSI to the previously created VSI list set 3186 * using the update switch rule command 3187 */ 3188 static enum ice_status 3189 ice_add_update_vsi_list(struct ice_hw *hw, 3190 struct ice_fltr_mgmt_list_entry *m_entry, 3191 struct ice_fltr_info *cur_fltr, 3192 struct ice_fltr_info *new_fltr) 3193 { 3194 enum ice_status status = ICE_SUCCESS; 3195 u16 vsi_list_id = 0; 3196 3197 if ((cur_fltr->fltr_act == ICE_FWD_TO_Q || 3198 cur_fltr->fltr_act == ICE_FWD_TO_QGRP)) 3199 return ICE_ERR_NOT_IMPL; 3200 3201 if ((new_fltr->fltr_act == ICE_FWD_TO_Q || 3202 new_fltr->fltr_act == ICE_FWD_TO_QGRP) && 3203 (cur_fltr->fltr_act == ICE_FWD_TO_VSI || 3204 cur_fltr->fltr_act == ICE_FWD_TO_VSI_LIST)) 3205 return ICE_ERR_NOT_IMPL; 3206 3207 if (m_entry->vsi_count < 2 && !m_entry->vsi_list_info) { 3208 /* Only one entry existed in the mapping and it was not already 3209 * a part of a VSI list. So, create a VSI list with the old and 3210 * new VSIs. 3211 */ 3212 struct ice_fltr_info tmp_fltr; 3213 u16 vsi_handle_arr[2]; 3214 3215 /* A rule already exists with the new VSI being added */ 3216 if (cur_fltr->fwd_id.hw_vsi_id == new_fltr->fwd_id.hw_vsi_id) 3217 return ICE_ERR_ALREADY_EXISTS; 3218 3219 vsi_handle_arr[0] = cur_fltr->vsi_handle; 3220 vsi_handle_arr[1] = new_fltr->vsi_handle; 3221 status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2, 3222 &vsi_list_id, 3223 new_fltr->lkup_type); 3224 if (status) 3225 return status; 3226 3227 tmp_fltr = *new_fltr; 3228 tmp_fltr.fltr_rule_id = cur_fltr->fltr_rule_id; 3229 tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST; 3230 tmp_fltr.fwd_id.vsi_list_id = vsi_list_id; 3231 /* Update the previous switch rule of "MAC forward to VSI" to 3232 * "MAC fwd to VSI list" 3233 */ 3234 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr); 3235 if (status) 3236 return status; 3237 3238 cur_fltr->fwd_id.vsi_list_id = vsi_list_id; 3239 cur_fltr->fltr_act = ICE_FWD_TO_VSI_LIST; 3240 m_entry->vsi_list_info = 3241 ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2, 3242 vsi_list_id); 3243 3244 /* If this entry was large action then the large action needs 3245 * to be updated to point to FWD to VSI list 3246 */ 3247 if (m_entry->sw_marker_id != ICE_INVAL_SW_MARKER_ID) 3248 status = 3249 ice_add_marker_act(hw, m_entry, 3250 m_entry->sw_marker_id, 3251 m_entry->lg_act_idx); 3252 } else { 3253 u16 vsi_handle = new_fltr->vsi_handle; 3254 enum ice_adminq_opc opcode; 3255 3256 if (!m_entry->vsi_list_info) 3257 return ICE_ERR_CFG; 3258 3259 /* A rule already exists with the new VSI being added */ 3260 if (ice_is_bit_set(m_entry->vsi_list_info->vsi_map, vsi_handle)) 3261 return ICE_SUCCESS; 3262 3263 /* Update the previously created VSI list set with 3264 * the new VSI ID passed in 3265 */ 3266 vsi_list_id = cur_fltr->fwd_id.vsi_list_id; 3267 opcode = ice_aqc_opc_update_sw_rules; 3268 3269 status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, 3270 vsi_list_id, false, opcode, 3271 new_fltr->lkup_type); 3272 /* update VSI list mapping info with new VSI ID */ 3273 if (!status) 3274 ice_set_bit(vsi_handle, 3275 m_entry->vsi_list_info->vsi_map); 3276 } 3277 if (!status) 3278 m_entry->vsi_count++; 3279 return status; 3280 } 3281 3282 /** 3283 * ice_find_rule_entry - Search a rule entry 3284 * @list_head: head of rule list 3285 * @f_info: rule information 3286 * 3287 * Helper function to search for a given rule entry 3288 * Returns pointer to entry storing the rule if found 3289 */ 3290 static struct ice_fltr_mgmt_list_entry * 3291 ice_find_rule_entry(struct LIST_HEAD_TYPE *list_head, 3292 struct ice_fltr_info *f_info) 3293 { 3294 struct ice_fltr_mgmt_list_entry *list_itr, *ret = NULL; 3295 3296 LIST_FOR_EACH_ENTRY(list_itr, list_head, ice_fltr_mgmt_list_entry, 3297 list_entry) { 3298 if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data, 3299 sizeof(f_info->l_data)) && 3300 f_info->flag == list_itr->fltr_info.flag) { 3301 ret = list_itr; 3302 break; 3303 } 3304 } 3305 return ret; 3306 } 3307 3308 /** 3309 * ice_find_vsi_list_entry - Search VSI list map with VSI count 1 3310 * @recp_list: VSI lists needs to be searched 3311 * @vsi_handle: VSI handle to be found in VSI list 3312 * @vsi_list_id: VSI list ID found containing vsi_handle 3313 * 3314 * Helper function to search a VSI list with single entry containing given VSI 3315 * handle element. This can be extended further to search VSI list with more 3316 * than 1 vsi_count. Returns pointer to VSI list entry if found. 3317 */ 3318 static struct ice_vsi_list_map_info * 3319 ice_find_vsi_list_entry(struct ice_sw_recipe *recp_list, u16 vsi_handle, 3320 u16 *vsi_list_id) 3321 { 3322 struct ice_vsi_list_map_info *map_info = NULL; 3323 struct LIST_HEAD_TYPE *list_head; 3324 3325 list_head = &recp_list->filt_rules; 3326 if (recp_list->adv_rule) { 3327 struct ice_adv_fltr_mgmt_list_entry *list_itr; 3328 3329 LIST_FOR_EACH_ENTRY(list_itr, list_head, 3330 ice_adv_fltr_mgmt_list_entry, 3331 list_entry) { 3332 if (list_itr->vsi_list_info) { 3333 map_info = list_itr->vsi_list_info; 3334 if (ice_is_bit_set(map_info->vsi_map, 3335 vsi_handle)) { 3336 *vsi_list_id = map_info->vsi_list_id; 3337 return map_info; 3338 } 3339 } 3340 } 3341 } else { 3342 struct ice_fltr_mgmt_list_entry *list_itr; 3343 3344 LIST_FOR_EACH_ENTRY(list_itr, list_head, 3345 ice_fltr_mgmt_list_entry, 3346 list_entry) { 3347 if (list_itr->vsi_count == 1 && 3348 list_itr->vsi_list_info) { 3349 map_info = list_itr->vsi_list_info; 3350 if (ice_is_bit_set(map_info->vsi_map, 3351 vsi_handle)) { 3352 *vsi_list_id = map_info->vsi_list_id; 3353 return map_info; 3354 } 3355 } 3356 } 3357 } 3358 return NULL; 3359 } 3360 3361 /** 3362 * ice_add_rule_internal - add rule for a given lookup type 3363 * @hw: pointer to the hardware structure 3364 * @recp_list: recipe list for which rule has to be added 3365 * @lport: logic port number on which function add rule 3366 * @f_entry: structure containing MAC forwarding information 3367 * 3368 * Adds or updates the rule lists for a given recipe 3369 */ 3370 static enum ice_status 3371 ice_add_rule_internal(struct ice_hw *hw, struct ice_sw_recipe *recp_list, 3372 u8 lport, struct ice_fltr_list_entry *f_entry) 3373 { 3374 struct ice_fltr_info *new_fltr, *cur_fltr; 3375 struct ice_fltr_mgmt_list_entry *m_entry; 3376 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 3377 enum ice_status status = ICE_SUCCESS; 3378 3379 if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle)) 3380 return ICE_ERR_PARAM; 3381 3382 /* Load the hw_vsi_id only if the fwd action is fwd to VSI */ 3383 if (f_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI) 3384 f_entry->fltr_info.fwd_id.hw_vsi_id = 3385 ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle); 3386 3387 rule_lock = &recp_list->filt_rule_lock; 3388 3389 ice_acquire_lock(rule_lock); 3390 new_fltr = &f_entry->fltr_info; 3391 if (new_fltr->flag & ICE_FLTR_RX) 3392 new_fltr->src = lport; 3393 else if (new_fltr->flag & ICE_FLTR_TX) 3394 new_fltr->src = 3395 ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle); 3396 3397 m_entry = ice_find_rule_entry(&recp_list->filt_rules, new_fltr); 3398 if (!m_entry) { 3399 status = ice_create_pkt_fwd_rule(hw, recp_list, f_entry); 3400 goto exit_add_rule_internal; 3401 } 3402 3403 cur_fltr = &m_entry->fltr_info; 3404 status = ice_add_update_vsi_list(hw, m_entry, cur_fltr, new_fltr); 3405 3406 exit_add_rule_internal: 3407 ice_release_lock(rule_lock); 3408 return status; 3409 } 3410 3411 /** 3412 * ice_remove_vsi_list_rule 3413 * @hw: pointer to the hardware structure 3414 * @vsi_list_id: VSI list ID generated as part of allocate resource 3415 * @lkup_type: switch rule filter lookup type 3416 * 3417 * The VSI list should be emptied before this function is called to remove the 3418 * VSI list. 3419 */ 3420 static enum ice_status 3421 ice_remove_vsi_list_rule(struct ice_hw *hw, u16 vsi_list_id, 3422 enum ice_sw_lkup_type lkup_type) 3423 { 3424 /* Free the vsi_list resource that we allocated. It is assumed that the 3425 * list is empty at this point. 3426 */ 3427 return ice_aq_alloc_free_vsi_list(hw, &vsi_list_id, lkup_type, 3428 ice_aqc_opc_free_res); 3429 } 3430 3431 /** 3432 * ice_rem_update_vsi_list 3433 * @hw: pointer to the hardware structure 3434 * @vsi_handle: VSI handle of the VSI to remove 3435 * @fm_list: filter management entry for which the VSI list management needs to 3436 * be done 3437 */ 3438 static enum ice_status 3439 ice_rem_update_vsi_list(struct ice_hw *hw, u16 vsi_handle, 3440 struct ice_fltr_mgmt_list_entry *fm_list) 3441 { 3442 enum ice_sw_lkup_type lkup_type; 3443 enum ice_status status = ICE_SUCCESS; 3444 u16 vsi_list_id; 3445 3446 if (fm_list->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST || 3447 fm_list->vsi_count == 0) 3448 return ICE_ERR_PARAM; 3449 3450 /* A rule with the VSI being removed does not exist */ 3451 if (!ice_is_bit_set(fm_list->vsi_list_info->vsi_map, vsi_handle)) 3452 return ICE_ERR_DOES_NOT_EXIST; 3453 3454 lkup_type = fm_list->fltr_info.lkup_type; 3455 vsi_list_id = fm_list->fltr_info.fwd_id.vsi_list_id; 3456 status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, vsi_list_id, true, 3457 ice_aqc_opc_update_sw_rules, 3458 lkup_type); 3459 if (status) 3460 return status; 3461 3462 fm_list->vsi_count--; 3463 ice_clear_bit(vsi_handle, fm_list->vsi_list_info->vsi_map); 3464 3465 if (fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) { 3466 struct ice_fltr_info tmp_fltr_info = fm_list->fltr_info; 3467 struct ice_vsi_list_map_info *vsi_list_info = 3468 fm_list->vsi_list_info; 3469 u16 rem_vsi_handle; 3470 3471 rem_vsi_handle = ice_find_first_bit(vsi_list_info->vsi_map, 3472 ICE_MAX_VSI); 3473 if (!ice_is_vsi_valid(hw, rem_vsi_handle)) 3474 return ICE_ERR_OUT_OF_RANGE; 3475 3476 /* Make sure VSI list is empty before removing it below */ 3477 status = ice_update_vsi_list_rule(hw, &rem_vsi_handle, 1, 3478 vsi_list_id, true, 3479 ice_aqc_opc_update_sw_rules, 3480 lkup_type); 3481 if (status) 3482 return status; 3483 3484 tmp_fltr_info.fltr_act = ICE_FWD_TO_VSI; 3485 tmp_fltr_info.fwd_id.hw_vsi_id = 3486 ice_get_hw_vsi_num(hw, rem_vsi_handle); 3487 tmp_fltr_info.vsi_handle = rem_vsi_handle; 3488 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr_info); 3489 if (status) { 3490 ice_debug(hw, ICE_DBG_SW, 3491 "Failed to update pkt fwd rule to FWD_TO_VSI on HW VSI %d, error %d\n", 3492 tmp_fltr_info.fwd_id.hw_vsi_id, status); 3493 return status; 3494 } 3495 3496 fm_list->fltr_info = tmp_fltr_info; 3497 } 3498 3499 if ((fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) || 3500 (fm_list->vsi_count == 0 && lkup_type == ICE_SW_LKUP_VLAN)) { 3501 struct ice_vsi_list_map_info *vsi_list_info = 3502 fm_list->vsi_list_info; 3503 3504 /* Remove the VSI list since it is no longer used */ 3505 status = ice_remove_vsi_list_rule(hw, vsi_list_id, lkup_type); 3506 if (status) { 3507 ice_debug(hw, ICE_DBG_SW, 3508 "Failed to remove VSI list %d, error %d\n", 3509 vsi_list_id, status); 3510 return status; 3511 } 3512 3513 LIST_DEL(&vsi_list_info->list_entry); 3514 ice_free(hw, vsi_list_info); 3515 fm_list->vsi_list_info = NULL; 3516 } 3517 3518 return status; 3519 } 3520 3521 /** 3522 * ice_remove_rule_internal - Remove a filter rule of a given type 3523 * 3524 * @hw: pointer to the hardware structure 3525 * @recp_list: recipe list for which the rule needs to removed 3526 * @f_entry: rule entry containing filter information 3527 */ 3528 static enum ice_status 3529 ice_remove_rule_internal(struct ice_hw *hw, struct ice_sw_recipe *recp_list, 3530 struct ice_fltr_list_entry *f_entry) 3531 { 3532 struct ice_fltr_mgmt_list_entry *list_elem; 3533 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 3534 enum ice_status status = ICE_SUCCESS; 3535 bool remove_rule = false; 3536 u16 vsi_handle; 3537 3538 if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle)) 3539 return ICE_ERR_PARAM; 3540 f_entry->fltr_info.fwd_id.hw_vsi_id = 3541 ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle); 3542 3543 rule_lock = &recp_list->filt_rule_lock; 3544 ice_acquire_lock(rule_lock); 3545 list_elem = ice_find_rule_entry(&recp_list->filt_rules, 3546 &f_entry->fltr_info); 3547 if (!list_elem) { 3548 status = ICE_ERR_DOES_NOT_EXIST; 3549 goto exit; 3550 } 3551 3552 if (list_elem->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST) { 3553 remove_rule = true; 3554 } else if (!list_elem->vsi_list_info) { 3555 status = ICE_ERR_DOES_NOT_EXIST; 3556 goto exit; 3557 } else if (list_elem->vsi_list_info->ref_cnt > 1) { 3558 /* a ref_cnt > 1 indicates that the vsi_list is being 3559 * shared by multiple rules. Decrement the ref_cnt and 3560 * remove this rule, but do not modify the list, as it 3561 * is in-use by other rules. 3562 */ 3563 list_elem->vsi_list_info->ref_cnt--; 3564 remove_rule = true; 3565 } else { 3566 /* a ref_cnt of 1 indicates the vsi_list is only used 3567 * by one rule. However, the original removal request is only 3568 * for a single VSI. Update the vsi_list first, and only 3569 * remove the rule if there are no further VSIs in this list. 3570 */ 3571 vsi_handle = f_entry->fltr_info.vsi_handle; 3572 status = ice_rem_update_vsi_list(hw, vsi_handle, list_elem); 3573 if (status) 3574 goto exit; 3575 /* if VSI count goes to zero after updating the VSI list */ 3576 if (list_elem->vsi_count == 0) 3577 remove_rule = true; 3578 } 3579 3580 if (remove_rule) { 3581 /* Remove the lookup rule */ 3582 struct ice_aqc_sw_rules_elem *s_rule; 3583 3584 s_rule = (struct ice_aqc_sw_rules_elem *) 3585 ice_malloc(hw, ICE_SW_RULE_RX_TX_NO_HDR_SIZE); 3586 if (!s_rule) { 3587 status = ICE_ERR_NO_MEMORY; 3588 goto exit; 3589 } 3590 3591 ice_fill_sw_rule(hw, &list_elem->fltr_info, s_rule, 3592 ice_aqc_opc_remove_sw_rules); 3593 3594 status = ice_aq_sw_rules(hw, s_rule, 3595 ICE_SW_RULE_RX_TX_NO_HDR_SIZE, 1, 3596 ice_aqc_opc_remove_sw_rules, NULL); 3597 3598 /* Remove a book keeping from the list */ 3599 ice_free(hw, s_rule); 3600 3601 if (status) 3602 goto exit; 3603 3604 LIST_DEL(&list_elem->list_entry); 3605 ice_free(hw, list_elem); 3606 } 3607 exit: 3608 ice_release_lock(rule_lock); 3609 return status; 3610 } 3611 3612 /** 3613 * ice_aq_get_res_alloc - get allocated resources 3614 * @hw: pointer to the HW struct 3615 * @num_entries: pointer to u16 to store the number of resource entries returned 3616 * @buf: pointer to user-supplied buffer 3617 * @buf_size: size of buff 3618 * @cd: pointer to command details structure or NULL 3619 * 3620 * The user-supplied buffer must be large enough to store the resource 3621 * information for all resource types. Each resource type is an 3622 * ice_aqc_get_res_resp_data_elem structure. 3623 */ 3624 enum ice_status 3625 ice_aq_get_res_alloc(struct ice_hw *hw, u16 *num_entries, void *buf, 3626 u16 buf_size, struct ice_sq_cd *cd) 3627 { 3628 struct ice_aqc_get_res_alloc *resp; 3629 enum ice_status status; 3630 struct ice_aq_desc desc; 3631 3632 if (!buf) 3633 return ICE_ERR_BAD_PTR; 3634 3635 if (buf_size < ICE_AQ_GET_RES_ALLOC_BUF_LEN) 3636 return ICE_ERR_INVAL_SIZE; 3637 3638 resp = &desc.params.get_res; 3639 3640 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_res_alloc); 3641 status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); 3642 3643 if (!status && num_entries) 3644 *num_entries = LE16_TO_CPU(resp->resp_elem_num); 3645 3646 return status; 3647 } 3648 3649 /** 3650 * ice_aq_get_res_descs - get allocated resource descriptors 3651 * @hw: pointer to the hardware structure 3652 * @num_entries: number of resource entries in buffer 3653 * @buf: Indirect buffer to hold data parameters and response 3654 * @buf_size: size of buffer for indirect commands 3655 * @res_type: resource type 3656 * @res_shared: is resource shared 3657 * @desc_id: input - first desc ID to start; output - next desc ID 3658 * @cd: pointer to command details structure or NULL 3659 */ 3660 enum ice_status 3661 ice_aq_get_res_descs(struct ice_hw *hw, u16 num_entries, 3662 struct ice_aqc_get_allocd_res_desc_resp *buf, 3663 u16 buf_size, u16 res_type, bool res_shared, u16 *desc_id, 3664 struct ice_sq_cd *cd) 3665 { 3666 struct ice_aqc_get_allocd_res_desc *cmd; 3667 struct ice_aq_desc desc; 3668 enum ice_status status; 3669 3670 ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 3671 3672 cmd = &desc.params.get_res_desc; 3673 3674 if (!buf) 3675 return ICE_ERR_PARAM; 3676 3677 if (buf_size != (num_entries * sizeof(*buf))) 3678 return ICE_ERR_PARAM; 3679 3680 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_allocd_res_desc); 3681 3682 cmd->ops.cmd.res = CPU_TO_LE16(((res_type << ICE_AQC_RES_TYPE_S) & 3683 ICE_AQC_RES_TYPE_M) | (res_shared ? 3684 ICE_AQC_RES_TYPE_FLAG_SHARED : 0)); 3685 cmd->ops.cmd.first_desc = CPU_TO_LE16(*desc_id); 3686 3687 status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); 3688 if (!status) 3689 *desc_id = LE16_TO_CPU(cmd->ops.resp.next_desc); 3690 3691 return status; 3692 } 3693 3694 /** 3695 * ice_add_mac_rule - Add a MAC address based filter rule 3696 * @hw: pointer to the hardware structure 3697 * @m_list: list of MAC addresses and forwarding information 3698 * @sw: pointer to switch info struct for which function add rule 3699 * @lport: logic port number on which function add rule 3700 * 3701 * IMPORTANT: When the ucast_shared flag is set to false and m_list has 3702 * multiple unicast addresses, the function assumes that all the 3703 * addresses are unique in a given add_mac call. It doesn't 3704 * check for duplicates in this case, removing duplicates from a given 3705 * list should be taken care of in the caller of this function. 3706 */ 3707 static enum ice_status 3708 ice_add_mac_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *m_list, 3709 struct ice_switch_info *sw, u8 lport) 3710 { 3711 struct ice_sw_recipe *recp_list = &sw->recp_list[ICE_SW_LKUP_MAC]; 3712 struct ice_aqc_sw_rules_elem *s_rule, *r_iter; 3713 struct ice_fltr_list_entry *m_list_itr; 3714 struct LIST_HEAD_TYPE *rule_head; 3715 u16 total_elem_left, s_rule_size; 3716 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 3717 enum ice_status status = ICE_SUCCESS; 3718 u16 num_unicast = 0; 3719 u8 elem_sent; 3720 3721 s_rule = NULL; 3722 rule_lock = &recp_list->filt_rule_lock; 3723 rule_head = &recp_list->filt_rules; 3724 3725 LIST_FOR_EACH_ENTRY(m_list_itr, m_list, ice_fltr_list_entry, 3726 list_entry) { 3727 u8 *add = &m_list_itr->fltr_info.l_data.mac.mac_addr[0]; 3728 u16 vsi_handle; 3729 u16 hw_vsi_id; 3730 3731 m_list_itr->fltr_info.flag = ICE_FLTR_TX; 3732 vsi_handle = m_list_itr->fltr_info.vsi_handle; 3733 if (!ice_is_vsi_valid(hw, vsi_handle)) 3734 return ICE_ERR_PARAM; 3735 hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 3736 m_list_itr->fltr_info.fwd_id.hw_vsi_id = hw_vsi_id; 3737 /* update the src in case it is VSI num */ 3738 if (m_list_itr->fltr_info.src_id != ICE_SRC_ID_VSI) 3739 return ICE_ERR_PARAM; 3740 m_list_itr->fltr_info.src = hw_vsi_id; 3741 if (m_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_MAC || 3742 IS_ZERO_ETHER_ADDR(add)) 3743 return ICE_ERR_PARAM; 3744 if (IS_UNICAST_ETHER_ADDR(add) && !hw->ucast_shared) { 3745 /* Don't overwrite the unicast address */ 3746 ice_acquire_lock(rule_lock); 3747 if (ice_find_rule_entry(rule_head, 3748 &m_list_itr->fltr_info)) { 3749 ice_release_lock(rule_lock); 3750 return ICE_ERR_ALREADY_EXISTS; 3751 } 3752 ice_release_lock(rule_lock); 3753 num_unicast++; 3754 } else if (IS_MULTICAST_ETHER_ADDR(add) || 3755 (IS_UNICAST_ETHER_ADDR(add) && hw->ucast_shared)) { 3756 m_list_itr->status = 3757 ice_add_rule_internal(hw, recp_list, lport, 3758 m_list_itr); 3759 if (m_list_itr->status) 3760 return m_list_itr->status; 3761 } 3762 } 3763 3764 ice_acquire_lock(rule_lock); 3765 /* Exit if no suitable entries were found for adding bulk switch rule */ 3766 if (!num_unicast) { 3767 status = ICE_SUCCESS; 3768 goto ice_add_mac_exit; 3769 } 3770 3771 /* Allocate switch rule buffer for the bulk update for unicast */ 3772 s_rule_size = ICE_SW_RULE_RX_TX_ETH_HDR_SIZE; 3773 s_rule = (struct ice_aqc_sw_rules_elem *) 3774 ice_calloc(hw, num_unicast, s_rule_size); 3775 if (!s_rule) { 3776 status = ICE_ERR_NO_MEMORY; 3777 goto ice_add_mac_exit; 3778 } 3779 3780 r_iter = s_rule; 3781 LIST_FOR_EACH_ENTRY(m_list_itr, m_list, ice_fltr_list_entry, 3782 list_entry) { 3783 struct ice_fltr_info *f_info = &m_list_itr->fltr_info; 3784 u8 *mac_addr = &f_info->l_data.mac.mac_addr[0]; 3785 3786 if (IS_UNICAST_ETHER_ADDR(mac_addr)) { 3787 ice_fill_sw_rule(hw, &m_list_itr->fltr_info, r_iter, 3788 ice_aqc_opc_add_sw_rules); 3789 r_iter = (struct ice_aqc_sw_rules_elem *) 3790 ((u8 *)r_iter + s_rule_size); 3791 } 3792 } 3793 3794 /* Call AQ bulk switch rule update for all unicast addresses */ 3795 r_iter = s_rule; 3796 /* Call AQ switch rule in AQ_MAX chunk */ 3797 for (total_elem_left = num_unicast; total_elem_left > 0; 3798 total_elem_left -= elem_sent) { 3799 struct ice_aqc_sw_rules_elem *entry = r_iter; 3800 3801 elem_sent = MIN_T(u8, total_elem_left, 3802 (ICE_AQ_MAX_BUF_LEN / s_rule_size)); 3803 status = ice_aq_sw_rules(hw, entry, elem_sent * s_rule_size, 3804 elem_sent, ice_aqc_opc_add_sw_rules, 3805 NULL); 3806 if (status) 3807 goto ice_add_mac_exit; 3808 r_iter = (struct ice_aqc_sw_rules_elem *) 3809 ((u8 *)r_iter + (elem_sent * s_rule_size)); 3810 } 3811 3812 /* Fill up rule ID based on the value returned from FW */ 3813 r_iter = s_rule; 3814 LIST_FOR_EACH_ENTRY(m_list_itr, m_list, ice_fltr_list_entry, 3815 list_entry) { 3816 struct ice_fltr_info *f_info = &m_list_itr->fltr_info; 3817 u8 *mac_addr = &f_info->l_data.mac.mac_addr[0]; 3818 struct ice_fltr_mgmt_list_entry *fm_entry; 3819 3820 if (IS_UNICAST_ETHER_ADDR(mac_addr)) { 3821 f_info->fltr_rule_id = 3822 LE16_TO_CPU(r_iter->pdata.lkup_tx_rx.index); 3823 f_info->fltr_act = ICE_FWD_TO_VSI; 3824 /* Create an entry to track this MAC address */ 3825 fm_entry = (struct ice_fltr_mgmt_list_entry *) 3826 ice_malloc(hw, sizeof(*fm_entry)); 3827 if (!fm_entry) { 3828 status = ICE_ERR_NO_MEMORY; 3829 goto ice_add_mac_exit; 3830 } 3831 fm_entry->fltr_info = *f_info; 3832 fm_entry->vsi_count = 1; 3833 /* The book keeping entries will get removed when 3834 * base driver calls remove filter AQ command 3835 */ 3836 3837 LIST_ADD(&fm_entry->list_entry, rule_head); 3838 r_iter = (struct ice_aqc_sw_rules_elem *) 3839 ((u8 *)r_iter + s_rule_size); 3840 } 3841 } 3842 3843 ice_add_mac_exit: 3844 ice_release_lock(rule_lock); 3845 if (s_rule) 3846 ice_free(hw, s_rule); 3847 return status; 3848 } 3849 3850 /** 3851 * ice_add_mac - Add a MAC address based filter rule 3852 * @hw: pointer to the hardware structure 3853 * @m_list: list of MAC addresses and forwarding information 3854 * 3855 * Function add MAC rule for logical port from HW struct 3856 */ 3857 enum ice_status ice_add_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *m_list) 3858 { 3859 if (!m_list || !hw) 3860 return ICE_ERR_PARAM; 3861 3862 return ice_add_mac_rule(hw, m_list, hw->switch_info, 3863 hw->port_info->lport); 3864 } 3865 3866 /** 3867 * ice_add_vlan_internal - Add one VLAN based filter rule 3868 * @hw: pointer to the hardware structure 3869 * @recp_list: recipe list for which rule has to be added 3870 * @f_entry: filter entry containing one VLAN information 3871 */ 3872 static enum ice_status 3873 ice_add_vlan_internal(struct ice_hw *hw, struct ice_sw_recipe *recp_list, 3874 struct ice_fltr_list_entry *f_entry) 3875 { 3876 struct ice_fltr_mgmt_list_entry *v_list_itr; 3877 struct ice_fltr_info *new_fltr, *cur_fltr; 3878 enum ice_sw_lkup_type lkup_type; 3879 u16 vsi_list_id = 0, vsi_handle; 3880 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 3881 enum ice_status status = ICE_SUCCESS; 3882 3883 if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle)) 3884 return ICE_ERR_PARAM; 3885 3886 f_entry->fltr_info.fwd_id.hw_vsi_id = 3887 ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle); 3888 new_fltr = &f_entry->fltr_info; 3889 3890 /* VLAN ID should only be 12 bits */ 3891 if (new_fltr->l_data.vlan.vlan_id > ICE_MAX_VLAN_ID) 3892 return ICE_ERR_PARAM; 3893 3894 if (new_fltr->src_id != ICE_SRC_ID_VSI) 3895 return ICE_ERR_PARAM; 3896 3897 new_fltr->src = new_fltr->fwd_id.hw_vsi_id; 3898 lkup_type = new_fltr->lkup_type; 3899 vsi_handle = new_fltr->vsi_handle; 3900 rule_lock = &recp_list->filt_rule_lock; 3901 ice_acquire_lock(rule_lock); 3902 v_list_itr = ice_find_rule_entry(&recp_list->filt_rules, new_fltr); 3903 if (!v_list_itr) { 3904 struct ice_vsi_list_map_info *map_info = NULL; 3905 3906 if (new_fltr->fltr_act == ICE_FWD_TO_VSI) { 3907 /* All VLAN pruning rules use a VSI list. Check if 3908 * there is already a VSI list containing VSI that we 3909 * want to add. If found, use the same vsi_list_id for 3910 * this new VLAN rule or else create a new list. 3911 */ 3912 map_info = ice_find_vsi_list_entry(recp_list, 3913 vsi_handle, 3914 &vsi_list_id); 3915 if (!map_info) { 3916 status = ice_create_vsi_list_rule(hw, 3917 &vsi_handle, 3918 1, 3919 &vsi_list_id, 3920 lkup_type); 3921 if (status) 3922 goto exit; 3923 } 3924 /* Convert the action to forwarding to a VSI list. */ 3925 new_fltr->fltr_act = ICE_FWD_TO_VSI_LIST; 3926 new_fltr->fwd_id.vsi_list_id = vsi_list_id; 3927 } 3928 3929 status = ice_create_pkt_fwd_rule(hw, recp_list, f_entry); 3930 if (!status) { 3931 v_list_itr = ice_find_rule_entry(&recp_list->filt_rules, 3932 new_fltr); 3933 if (!v_list_itr) { 3934 status = ICE_ERR_DOES_NOT_EXIST; 3935 goto exit; 3936 } 3937 /* reuse VSI list for new rule and increment ref_cnt */ 3938 if (map_info) { 3939 v_list_itr->vsi_list_info = map_info; 3940 map_info->ref_cnt++; 3941 } else { 3942 v_list_itr->vsi_list_info = 3943 ice_create_vsi_list_map(hw, &vsi_handle, 3944 1, vsi_list_id); 3945 } 3946 } 3947 } else if (v_list_itr->vsi_list_info->ref_cnt == 1) { 3948 /* Update existing VSI list to add new VSI ID only if it used 3949 * by one VLAN rule. 3950 */ 3951 cur_fltr = &v_list_itr->fltr_info; 3952 status = ice_add_update_vsi_list(hw, v_list_itr, cur_fltr, 3953 new_fltr); 3954 } else { 3955 /* If VLAN rule exists and VSI list being used by this rule is 3956 * referenced by more than 1 VLAN rule. Then create a new VSI 3957 * list appending previous VSI with new VSI and update existing 3958 * VLAN rule to point to new VSI list ID 3959 */ 3960 struct ice_fltr_info tmp_fltr; 3961 u16 vsi_handle_arr[2]; 3962 u16 cur_handle; 3963 3964 /* Current implementation only supports reusing VSI list with 3965 * one VSI count. We should never hit below condition 3966 */ 3967 if (v_list_itr->vsi_count > 1 && 3968 v_list_itr->vsi_list_info->ref_cnt > 1) { 3969 ice_debug(hw, ICE_DBG_SW, 3970 "Invalid configuration: Optimization to reuse VSI list with more than one VSI is not being done yet\n"); 3971 status = ICE_ERR_CFG; 3972 goto exit; 3973 } 3974 3975 cur_handle = 3976 ice_find_first_bit(v_list_itr->vsi_list_info->vsi_map, 3977 ICE_MAX_VSI); 3978 3979 /* A rule already exists with the new VSI being added */ 3980 if (cur_handle == vsi_handle) { 3981 status = ICE_ERR_ALREADY_EXISTS; 3982 goto exit; 3983 } 3984 3985 vsi_handle_arr[0] = cur_handle; 3986 vsi_handle_arr[1] = vsi_handle; 3987 status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2, 3988 &vsi_list_id, lkup_type); 3989 if (status) 3990 goto exit; 3991 3992 tmp_fltr = v_list_itr->fltr_info; 3993 tmp_fltr.fltr_rule_id = v_list_itr->fltr_info.fltr_rule_id; 3994 tmp_fltr.fwd_id.vsi_list_id = vsi_list_id; 3995 tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST; 3996 /* Update the previous switch rule to a new VSI list which 3997 * includes current VSI that is requested 3998 */ 3999 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr); 4000 if (status) 4001 goto exit; 4002 4003 /* before overriding VSI list map info. decrement ref_cnt of 4004 * previous VSI list 4005 */ 4006 v_list_itr->vsi_list_info->ref_cnt--; 4007 4008 /* now update to newly created list */ 4009 v_list_itr->fltr_info.fwd_id.vsi_list_id = vsi_list_id; 4010 v_list_itr->vsi_list_info = 4011 ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2, 4012 vsi_list_id); 4013 v_list_itr->vsi_count++; 4014 } 4015 4016 exit: 4017 ice_release_lock(rule_lock); 4018 return status; 4019 } 4020 4021 /** 4022 * ice_add_vlan_rule - Add VLAN based filter rule 4023 * @hw: pointer to the hardware structure 4024 * @v_list: list of VLAN entries and forwarding information 4025 * @sw: pointer to switch info struct for which function add rule 4026 */ 4027 static enum ice_status 4028 ice_add_vlan_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list, 4029 struct ice_switch_info *sw) 4030 { 4031 struct ice_fltr_list_entry *v_list_itr; 4032 struct ice_sw_recipe *recp_list; 4033 4034 recp_list = &sw->recp_list[ICE_SW_LKUP_VLAN]; 4035 LIST_FOR_EACH_ENTRY(v_list_itr, v_list, ice_fltr_list_entry, 4036 list_entry) { 4037 if (v_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_VLAN) 4038 return ICE_ERR_PARAM; 4039 v_list_itr->fltr_info.flag = ICE_FLTR_TX; 4040 v_list_itr->status = ice_add_vlan_internal(hw, recp_list, 4041 v_list_itr); 4042 if (v_list_itr->status) 4043 return v_list_itr->status; 4044 } 4045 return ICE_SUCCESS; 4046 } 4047 4048 /** 4049 * ice_add_vlan - Add a VLAN based filter rule 4050 * @hw: pointer to the hardware structure 4051 * @v_list: list of VLAN and forwarding information 4052 * 4053 * Function add VLAN rule for logical port from HW struct 4054 */ 4055 enum ice_status ice_add_vlan(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list) 4056 { 4057 if (!v_list || !hw) 4058 return ICE_ERR_PARAM; 4059 4060 return ice_add_vlan_rule(hw, v_list, hw->switch_info); 4061 } 4062 4063 /** 4064 * ice_add_mac_vlan - Add MAC and VLAN pair based filter rule 4065 * @hw: pointer to the hardware structure 4066 * @mv_list: list of MAC and VLAN filters 4067 * @sw: pointer to switch info struct for which function add rule 4068 * @lport: logic port number on which function add rule 4069 * 4070 * If the VSI on which the MAC-VLAN pair has to be added has Rx and Tx VLAN 4071 * pruning bits enabled, then it is the responsibility of the caller to make 4072 * sure to add a VLAN only filter on the same VSI. Packets belonging to that 4073 * VLAN won't be received on that VSI otherwise. 4074 */ 4075 static enum ice_status 4076 ice_add_mac_vlan_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *mv_list, 4077 struct ice_switch_info *sw, u8 lport) 4078 { 4079 struct ice_fltr_list_entry *mv_list_itr; 4080 struct ice_sw_recipe *recp_list; 4081 4082 if (!mv_list || !hw) 4083 return ICE_ERR_PARAM; 4084 4085 recp_list = &sw->recp_list[ICE_SW_LKUP_MAC_VLAN]; 4086 LIST_FOR_EACH_ENTRY(mv_list_itr, mv_list, ice_fltr_list_entry, 4087 list_entry) { 4088 enum ice_sw_lkup_type l_type = 4089 mv_list_itr->fltr_info.lkup_type; 4090 4091 if (l_type != ICE_SW_LKUP_MAC_VLAN) 4092 return ICE_ERR_PARAM; 4093 mv_list_itr->fltr_info.flag = ICE_FLTR_TX; 4094 mv_list_itr->status = 4095 ice_add_rule_internal(hw, recp_list, lport, 4096 mv_list_itr); 4097 if (mv_list_itr->status) 4098 return mv_list_itr->status; 4099 } 4100 return ICE_SUCCESS; 4101 } 4102 4103 /** 4104 * ice_add_mac_vlan - Add a MAC VLAN address based filter rule 4105 * @hw: pointer to the hardware structure 4106 * @mv_list: list of MAC VLAN addresses and forwarding information 4107 * 4108 * Function add MAC VLAN rule for logical port from HW struct 4109 */ 4110 enum ice_status 4111 ice_add_mac_vlan(struct ice_hw *hw, struct LIST_HEAD_TYPE *mv_list) 4112 { 4113 if (!mv_list || !hw) 4114 return ICE_ERR_PARAM; 4115 4116 return ice_add_mac_vlan_rule(hw, mv_list, hw->switch_info, 4117 hw->port_info->lport); 4118 } 4119 4120 /** 4121 * ice_add_eth_mac_rule - Add ethertype and MAC based filter rule 4122 * @hw: pointer to the hardware structure 4123 * @em_list: list of ether type MAC filter, MAC is optional 4124 * @sw: pointer to switch info struct for which function add rule 4125 * @lport: logic port number on which function add rule 4126 * 4127 * This function requires the caller to populate the entries in 4128 * the filter list with the necessary fields (including flags to 4129 * indicate Tx or Rx rules). 4130 */ 4131 static enum ice_status 4132 ice_add_eth_mac_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *em_list, 4133 struct ice_switch_info *sw, u8 lport) 4134 { 4135 struct ice_fltr_list_entry *em_list_itr; 4136 4137 LIST_FOR_EACH_ENTRY(em_list_itr, em_list, ice_fltr_list_entry, 4138 list_entry) { 4139 struct ice_sw_recipe *recp_list; 4140 enum ice_sw_lkup_type l_type; 4141 4142 l_type = em_list_itr->fltr_info.lkup_type; 4143 recp_list = &sw->recp_list[l_type]; 4144 4145 if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC && 4146 l_type != ICE_SW_LKUP_ETHERTYPE) 4147 return ICE_ERR_PARAM; 4148 4149 em_list_itr->status = ice_add_rule_internal(hw, recp_list, 4150 lport, 4151 em_list_itr); 4152 if (em_list_itr->status) 4153 return em_list_itr->status; 4154 } 4155 return ICE_SUCCESS; 4156 } 4157 4158 /** 4159 * ice_add_eth_mac - Add a ethertype based filter rule 4160 * @hw: pointer to the hardware structure 4161 * @em_list: list of ethertype and forwarding information 4162 * 4163 * Function add ethertype rule for logical port from HW struct 4164 */ 4165 enum ice_status 4166 ice_add_eth_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *em_list) 4167 { 4168 if (!em_list || !hw) 4169 return ICE_ERR_PARAM; 4170 4171 return ice_add_eth_mac_rule(hw, em_list, hw->switch_info, 4172 hw->port_info->lport); 4173 } 4174 4175 /** 4176 * ice_remove_eth_mac_rule - Remove an ethertype (or MAC) based filter rule 4177 * @hw: pointer to the hardware structure 4178 * @em_list: list of ethertype or ethertype MAC entries 4179 * @sw: pointer to switch info struct for which function add rule 4180 */ 4181 static enum ice_status 4182 ice_remove_eth_mac_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *em_list, 4183 struct ice_switch_info *sw) 4184 { 4185 struct ice_fltr_list_entry *em_list_itr, *tmp; 4186 4187 LIST_FOR_EACH_ENTRY_SAFE(em_list_itr, tmp, em_list, ice_fltr_list_entry, 4188 list_entry) { 4189 struct ice_sw_recipe *recp_list; 4190 enum ice_sw_lkup_type l_type; 4191 4192 l_type = em_list_itr->fltr_info.lkup_type; 4193 4194 if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC && 4195 l_type != ICE_SW_LKUP_ETHERTYPE) 4196 return ICE_ERR_PARAM; 4197 4198 recp_list = &sw->recp_list[l_type]; 4199 em_list_itr->status = ice_remove_rule_internal(hw, recp_list, 4200 em_list_itr); 4201 if (em_list_itr->status) 4202 return em_list_itr->status; 4203 } 4204 return ICE_SUCCESS; 4205 } 4206 4207 /** 4208 * ice_remove_eth_mac - remove a ethertype based filter rule 4209 * @hw: pointer to the hardware structure 4210 * @em_list: list of ethertype and forwarding information 4211 * 4212 */ 4213 enum ice_status 4214 ice_remove_eth_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *em_list) 4215 { 4216 if (!em_list || !hw) 4217 return ICE_ERR_PARAM; 4218 4219 return ice_remove_eth_mac_rule(hw, em_list, hw->switch_info); 4220 } 4221 4222 /** 4223 * ice_rem_sw_rule_info 4224 * @hw: pointer to the hardware structure 4225 * @rule_head: pointer to the switch list structure that we want to delete 4226 */ 4227 static void 4228 ice_rem_sw_rule_info(struct ice_hw *hw, struct LIST_HEAD_TYPE *rule_head) 4229 { 4230 if (!LIST_EMPTY(rule_head)) { 4231 struct ice_fltr_mgmt_list_entry *entry; 4232 struct ice_fltr_mgmt_list_entry *tmp; 4233 4234 LIST_FOR_EACH_ENTRY_SAFE(entry, tmp, rule_head, 4235 ice_fltr_mgmt_list_entry, list_entry) { 4236 LIST_DEL(&entry->list_entry); 4237 ice_free(hw, entry); 4238 } 4239 } 4240 } 4241 4242 /** 4243 * ice_rem_adv_rule_info 4244 * @hw: pointer to the hardware structure 4245 * @rule_head: pointer to the switch list structure that we want to delete 4246 */ 4247 static void 4248 ice_rem_adv_rule_info(struct ice_hw *hw, struct LIST_HEAD_TYPE *rule_head) 4249 { 4250 struct ice_adv_fltr_mgmt_list_entry *tmp_entry; 4251 struct ice_adv_fltr_mgmt_list_entry *lst_itr; 4252 4253 if (LIST_EMPTY(rule_head)) 4254 return; 4255 4256 LIST_FOR_EACH_ENTRY_SAFE(lst_itr, tmp_entry, rule_head, 4257 ice_adv_fltr_mgmt_list_entry, list_entry) { 4258 LIST_DEL(&lst_itr->list_entry); 4259 ice_free(hw, lst_itr->lkups); 4260 ice_free(hw, lst_itr); 4261 } 4262 } 4263 4264 /** 4265 * ice_rem_all_sw_rules_info 4266 * @hw: pointer to the hardware structure 4267 */ 4268 void ice_rem_all_sw_rules_info(struct ice_hw *hw) 4269 { 4270 struct ice_switch_info *sw = hw->switch_info; 4271 u8 i; 4272 4273 for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) { 4274 struct LIST_HEAD_TYPE *rule_head; 4275 4276 rule_head = &sw->recp_list[i].filt_rules; 4277 if (!sw->recp_list[i].adv_rule) 4278 ice_rem_sw_rule_info(hw, rule_head); 4279 else 4280 ice_rem_adv_rule_info(hw, rule_head); 4281 if (sw->recp_list[i].adv_rule && 4282 LIST_EMPTY(&sw->recp_list[i].filt_rules)) 4283 sw->recp_list[i].adv_rule = false; 4284 } 4285 } 4286 4287 /** 4288 * ice_cfg_dflt_vsi - change state of VSI to set/clear default 4289 * @pi: pointer to the port_info structure 4290 * @vsi_handle: VSI handle to set as default 4291 * @set: true to add the above mentioned switch rule, false to remove it 4292 * @direction: ICE_FLTR_RX or ICE_FLTR_TX 4293 * 4294 * add filter rule to set/unset given VSI as default VSI for the switch 4295 * (represented by swid) 4296 */ 4297 enum ice_status 4298 ice_cfg_dflt_vsi(struct ice_port_info *pi, u16 vsi_handle, bool set, 4299 u8 direction) 4300 { 4301 struct ice_aqc_sw_rules_elem *s_rule; 4302 struct ice_fltr_info f_info; 4303 struct ice_hw *hw = pi->hw; 4304 enum ice_adminq_opc opcode; 4305 enum ice_status status; 4306 u16 s_rule_size; 4307 u16 hw_vsi_id; 4308 4309 if (!ice_is_vsi_valid(hw, vsi_handle)) 4310 return ICE_ERR_PARAM; 4311 hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 4312 4313 s_rule_size = set ? ICE_SW_RULE_RX_TX_ETH_HDR_SIZE : 4314 ICE_SW_RULE_RX_TX_NO_HDR_SIZE; 4315 s_rule = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, s_rule_size); 4316 if (!s_rule) 4317 return ICE_ERR_NO_MEMORY; 4318 4319 ice_memset(&f_info, 0, sizeof(f_info), ICE_NONDMA_MEM); 4320 4321 f_info.lkup_type = ICE_SW_LKUP_DFLT; 4322 f_info.flag = direction; 4323 f_info.fltr_act = ICE_FWD_TO_VSI; 4324 f_info.fwd_id.hw_vsi_id = hw_vsi_id; 4325 4326 if (f_info.flag & ICE_FLTR_RX) { 4327 f_info.src = pi->lport; 4328 f_info.src_id = ICE_SRC_ID_LPORT; 4329 if (!set) 4330 f_info.fltr_rule_id = 4331 pi->dflt_rx_vsi_rule_id; 4332 } else if (f_info.flag & ICE_FLTR_TX) { 4333 f_info.src_id = ICE_SRC_ID_VSI; 4334 f_info.src = hw_vsi_id; 4335 if (!set) 4336 f_info.fltr_rule_id = 4337 pi->dflt_tx_vsi_rule_id; 4338 } 4339 4340 if (set) 4341 opcode = ice_aqc_opc_add_sw_rules; 4342 else 4343 opcode = ice_aqc_opc_remove_sw_rules; 4344 4345 ice_fill_sw_rule(hw, &f_info, s_rule, opcode); 4346 4347 status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opcode, NULL); 4348 if (status || !(f_info.flag & ICE_FLTR_TX_RX)) 4349 goto out; 4350 if (set) { 4351 u16 index = LE16_TO_CPU(s_rule->pdata.lkup_tx_rx.index); 4352 4353 if (f_info.flag & ICE_FLTR_TX) { 4354 pi->dflt_tx_vsi_num = hw_vsi_id; 4355 pi->dflt_tx_vsi_rule_id = index; 4356 } else if (f_info.flag & ICE_FLTR_RX) { 4357 pi->dflt_rx_vsi_num = hw_vsi_id; 4358 pi->dflt_rx_vsi_rule_id = index; 4359 } 4360 } else { 4361 if (f_info.flag & ICE_FLTR_TX) { 4362 pi->dflt_tx_vsi_num = ICE_DFLT_VSI_INVAL; 4363 pi->dflt_tx_vsi_rule_id = ICE_INVAL_ACT; 4364 } else if (f_info.flag & ICE_FLTR_RX) { 4365 pi->dflt_rx_vsi_num = ICE_DFLT_VSI_INVAL; 4366 pi->dflt_rx_vsi_rule_id = ICE_INVAL_ACT; 4367 } 4368 } 4369 4370 out: 4371 ice_free(hw, s_rule); 4372 return status; 4373 } 4374 4375 /** 4376 * ice_find_ucast_rule_entry - Search for a unicast MAC filter rule entry 4377 * @list_head: head of rule list 4378 * @f_info: rule information 4379 * 4380 * Helper function to search for a unicast rule entry - this is to be used 4381 * to remove unicast MAC filter that is not shared with other VSIs on the 4382 * PF switch. 4383 * 4384 * Returns pointer to entry storing the rule if found 4385 */ 4386 static struct ice_fltr_mgmt_list_entry * 4387 ice_find_ucast_rule_entry(struct LIST_HEAD_TYPE *list_head, 4388 struct ice_fltr_info *f_info) 4389 { 4390 struct ice_fltr_mgmt_list_entry *list_itr; 4391 4392 LIST_FOR_EACH_ENTRY(list_itr, list_head, ice_fltr_mgmt_list_entry, 4393 list_entry) { 4394 if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data, 4395 sizeof(f_info->l_data)) && 4396 f_info->fwd_id.hw_vsi_id == 4397 list_itr->fltr_info.fwd_id.hw_vsi_id && 4398 f_info->flag == list_itr->fltr_info.flag) 4399 return list_itr; 4400 } 4401 return NULL; 4402 } 4403 4404 /** 4405 * ice_remove_mac_rule - remove a MAC based filter rule 4406 * @hw: pointer to the hardware structure 4407 * @m_list: list of MAC addresses and forwarding information 4408 * @recp_list: list from which function remove MAC address 4409 * 4410 * This function removes either a MAC filter rule or a specific VSI from a 4411 * VSI list for a multicast MAC address. 4412 * 4413 * Returns ICE_ERR_DOES_NOT_EXIST if a given entry was not added by 4414 * ice_add_mac. Caller should be aware that this call will only work if all 4415 * the entries passed into m_list were added previously. It will not attempt to 4416 * do a partial remove of entries that were found. 4417 */ 4418 static enum ice_status 4419 ice_remove_mac_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *m_list, 4420 struct ice_sw_recipe *recp_list) 4421 { 4422 struct ice_fltr_list_entry *list_itr, *tmp; 4423 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 4424 4425 if (!m_list) 4426 return ICE_ERR_PARAM; 4427 4428 rule_lock = &recp_list->filt_rule_lock; 4429 LIST_FOR_EACH_ENTRY_SAFE(list_itr, tmp, m_list, ice_fltr_list_entry, 4430 list_entry) { 4431 enum ice_sw_lkup_type l_type = list_itr->fltr_info.lkup_type; 4432 u8 *add = &list_itr->fltr_info.l_data.mac.mac_addr[0]; 4433 u16 vsi_handle; 4434 4435 if (l_type != ICE_SW_LKUP_MAC) 4436 return ICE_ERR_PARAM; 4437 4438 vsi_handle = list_itr->fltr_info.vsi_handle; 4439 if (!ice_is_vsi_valid(hw, vsi_handle)) 4440 return ICE_ERR_PARAM; 4441 4442 list_itr->fltr_info.fwd_id.hw_vsi_id = 4443 ice_get_hw_vsi_num(hw, vsi_handle); 4444 if (IS_UNICAST_ETHER_ADDR(add) && !hw->ucast_shared) { 4445 /* Don't remove the unicast address that belongs to 4446 * another VSI on the switch, since it is not being 4447 * shared... 4448 */ 4449 ice_acquire_lock(rule_lock); 4450 if (!ice_find_ucast_rule_entry(&recp_list->filt_rules, 4451 &list_itr->fltr_info)) { 4452 ice_release_lock(rule_lock); 4453 return ICE_ERR_DOES_NOT_EXIST; 4454 } 4455 ice_release_lock(rule_lock); 4456 } 4457 list_itr->status = ice_remove_rule_internal(hw, recp_list, 4458 list_itr); 4459 if (list_itr->status) 4460 return list_itr->status; 4461 } 4462 return ICE_SUCCESS; 4463 } 4464 4465 /** 4466 * ice_remove_mac - remove a MAC address based filter rule 4467 * @hw: pointer to the hardware structure 4468 * @m_list: list of MAC addresses and forwarding information 4469 * 4470 */ 4471 enum ice_status ice_remove_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *m_list) 4472 { 4473 struct ice_sw_recipe *recp_list; 4474 4475 recp_list = &hw->switch_info->recp_list[ICE_SW_LKUP_MAC]; 4476 return ice_remove_mac_rule(hw, m_list, recp_list); 4477 } 4478 4479 /** 4480 * ice_remove_vlan_rule - Remove VLAN based filter rule 4481 * @hw: pointer to the hardware structure 4482 * @v_list: list of VLAN entries and forwarding information 4483 * @recp_list: list from which function remove VLAN 4484 */ 4485 static enum ice_status 4486 ice_remove_vlan_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list, 4487 struct ice_sw_recipe *recp_list) 4488 { 4489 struct ice_fltr_list_entry *v_list_itr, *tmp; 4490 4491 LIST_FOR_EACH_ENTRY_SAFE(v_list_itr, tmp, v_list, ice_fltr_list_entry, 4492 list_entry) { 4493 enum ice_sw_lkup_type l_type = v_list_itr->fltr_info.lkup_type; 4494 4495 if (l_type != ICE_SW_LKUP_VLAN) 4496 return ICE_ERR_PARAM; 4497 v_list_itr->status = ice_remove_rule_internal(hw, recp_list, 4498 v_list_itr); 4499 if (v_list_itr->status) 4500 return v_list_itr->status; 4501 } 4502 return ICE_SUCCESS; 4503 } 4504 4505 /** 4506 * ice_remove_vlan - remove a VLAN address based filter rule 4507 * @hw: pointer to the hardware structure 4508 * @v_list: list of VLAN and forwarding information 4509 * 4510 */ 4511 enum ice_status 4512 ice_remove_vlan(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list) 4513 { 4514 struct ice_sw_recipe *recp_list; 4515 4516 if (!v_list || !hw) 4517 return ICE_ERR_PARAM; 4518 4519 recp_list = &hw->switch_info->recp_list[ICE_SW_LKUP_VLAN]; 4520 return ice_remove_vlan_rule(hw, v_list, recp_list); 4521 } 4522 4523 /** 4524 * ice_remove_mac_vlan_rule - Remove MAC VLAN based filter rule 4525 * @hw: pointer to the hardware structure 4526 * @v_list: list of MAC VLAN entries and forwarding information 4527 * @recp_list: list from which function remove MAC VLAN 4528 */ 4529 static enum ice_status 4530 ice_remove_mac_vlan_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list, 4531 struct ice_sw_recipe *recp_list) 4532 { 4533 struct ice_fltr_list_entry *v_list_itr, *tmp; 4534 4535 recp_list = &hw->switch_info->recp_list[ICE_SW_LKUP_MAC_VLAN]; 4536 LIST_FOR_EACH_ENTRY_SAFE(v_list_itr, tmp, v_list, ice_fltr_list_entry, 4537 list_entry) { 4538 enum ice_sw_lkup_type l_type = v_list_itr->fltr_info.lkup_type; 4539 4540 if (l_type != ICE_SW_LKUP_MAC_VLAN) 4541 return ICE_ERR_PARAM; 4542 v_list_itr->status = 4543 ice_remove_rule_internal(hw, recp_list, 4544 v_list_itr); 4545 if (v_list_itr->status) 4546 return v_list_itr->status; 4547 } 4548 return ICE_SUCCESS; 4549 } 4550 4551 /** 4552 * ice_remove_mac_vlan - remove a MAC VLAN address based filter rule 4553 * @hw: pointer to the hardware structure 4554 * @mv_list: list of MAC VLAN and forwarding information 4555 */ 4556 enum ice_status 4557 ice_remove_mac_vlan(struct ice_hw *hw, struct LIST_HEAD_TYPE *mv_list) 4558 { 4559 struct ice_sw_recipe *recp_list; 4560 4561 if (!mv_list || !hw) 4562 return ICE_ERR_PARAM; 4563 4564 recp_list = &hw->switch_info->recp_list[ICE_SW_LKUP_MAC_VLAN]; 4565 return ice_remove_mac_vlan_rule(hw, mv_list, recp_list); 4566 } 4567 4568 /** 4569 * ice_vsi_uses_fltr - Determine if given VSI uses specified filter 4570 * @fm_entry: filter entry to inspect 4571 * @vsi_handle: VSI handle to compare with filter info 4572 */ 4573 static bool 4574 ice_vsi_uses_fltr(struct ice_fltr_mgmt_list_entry *fm_entry, u16 vsi_handle) 4575 { 4576 return ((fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI && 4577 fm_entry->fltr_info.vsi_handle == vsi_handle) || 4578 (fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI_LIST && 4579 (ice_is_bit_set(fm_entry->vsi_list_info->vsi_map, 4580 vsi_handle)))); 4581 } 4582 4583 /** 4584 * ice_add_entry_to_vsi_fltr_list - Add copy of fltr_list_entry to remove list 4585 * @hw: pointer to the hardware structure 4586 * @vsi_handle: VSI handle to remove filters from 4587 * @vsi_list_head: pointer to the list to add entry to 4588 * @fi: pointer to fltr_info of filter entry to copy & add 4589 * 4590 * Helper function, used when creating a list of filters to remove from 4591 * a specific VSI. The entry added to vsi_list_head is a COPY of the 4592 * original filter entry, with the exception of fltr_info.fltr_act and 4593 * fltr_info.fwd_id fields. These are set such that later logic can 4594 * extract which VSI to remove the fltr from, and pass on that information. 4595 */ 4596 static enum ice_status 4597 ice_add_entry_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle, 4598 struct LIST_HEAD_TYPE *vsi_list_head, 4599 struct ice_fltr_info *fi) 4600 { 4601 struct ice_fltr_list_entry *tmp; 4602 4603 /* this memory is freed up in the caller function 4604 * once filters for this VSI are removed 4605 */ 4606 tmp = (struct ice_fltr_list_entry *)ice_malloc(hw, sizeof(*tmp)); 4607 if (!tmp) 4608 return ICE_ERR_NO_MEMORY; 4609 4610 tmp->fltr_info = *fi; 4611 4612 /* Overwrite these fields to indicate which VSI to remove filter from, 4613 * so find and remove logic can extract the information from the 4614 * list entries. Note that original entries will still have proper 4615 * values. 4616 */ 4617 tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI; 4618 tmp->fltr_info.vsi_handle = vsi_handle; 4619 tmp->fltr_info.fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 4620 4621 LIST_ADD(&tmp->list_entry, vsi_list_head); 4622 4623 return ICE_SUCCESS; 4624 } 4625 4626 /** 4627 * ice_add_to_vsi_fltr_list - Add VSI filters to the list 4628 * @hw: pointer to the hardware structure 4629 * @vsi_handle: VSI handle to remove filters from 4630 * @lkup_list_head: pointer to the list that has certain lookup type filters 4631 * @vsi_list_head: pointer to the list pertaining to VSI with vsi_handle 4632 * 4633 * Locates all filters in lkup_list_head that are used by the given VSI, 4634 * and adds COPIES of those entries to vsi_list_head (intended to be used 4635 * to remove the listed filters). 4636 * Note that this means all entries in vsi_list_head must be explicitly 4637 * deallocated by the caller when done with list. 4638 */ 4639 static enum ice_status 4640 ice_add_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle, 4641 struct LIST_HEAD_TYPE *lkup_list_head, 4642 struct LIST_HEAD_TYPE *vsi_list_head) 4643 { 4644 struct ice_fltr_mgmt_list_entry *fm_entry; 4645 enum ice_status status = ICE_SUCCESS; 4646 4647 /* check to make sure VSI ID is valid and within boundary */ 4648 if (!ice_is_vsi_valid(hw, vsi_handle)) 4649 return ICE_ERR_PARAM; 4650 4651 LIST_FOR_EACH_ENTRY(fm_entry, lkup_list_head, 4652 ice_fltr_mgmt_list_entry, list_entry) { 4653 struct ice_fltr_info *fi; 4654 4655 fi = &fm_entry->fltr_info; 4656 if (!fi || !ice_vsi_uses_fltr(fm_entry, vsi_handle)) 4657 continue; 4658 4659 status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle, 4660 vsi_list_head, fi); 4661 if (status) 4662 return status; 4663 } 4664 return status; 4665 } 4666 4667 /** 4668 * ice_determine_promisc_mask 4669 * @fi: filter info to parse 4670 * 4671 * Helper function to determine which ICE_PROMISC_ mask corresponds 4672 * to given filter into. 4673 */ 4674 static u8 ice_determine_promisc_mask(struct ice_fltr_info *fi) 4675 { 4676 u16 vid = fi->l_data.mac_vlan.vlan_id; 4677 u8 *macaddr = fi->l_data.mac.mac_addr; 4678 bool is_tx_fltr = false; 4679 u8 promisc_mask = 0; 4680 4681 if (fi->flag == ICE_FLTR_TX) 4682 is_tx_fltr = true; 4683 4684 if (IS_BROADCAST_ETHER_ADDR(macaddr)) 4685 promisc_mask |= is_tx_fltr ? 4686 ICE_PROMISC_BCAST_TX : ICE_PROMISC_BCAST_RX; 4687 else if (IS_MULTICAST_ETHER_ADDR(macaddr)) 4688 promisc_mask |= is_tx_fltr ? 4689 ICE_PROMISC_MCAST_TX : ICE_PROMISC_MCAST_RX; 4690 else if (IS_UNICAST_ETHER_ADDR(macaddr)) 4691 promisc_mask |= is_tx_fltr ? 4692 ICE_PROMISC_UCAST_TX : ICE_PROMISC_UCAST_RX; 4693 if (vid) 4694 promisc_mask |= is_tx_fltr ? 4695 ICE_PROMISC_VLAN_TX : ICE_PROMISC_VLAN_RX; 4696 4697 return promisc_mask; 4698 } 4699 4700 /** 4701 * _ice_get_vsi_promisc - get promiscuous mode of given VSI 4702 * @hw: pointer to the hardware structure 4703 * @vsi_handle: VSI handle to retrieve info from 4704 * @promisc_mask: pointer to mask to be filled in 4705 * @vid: VLAN ID of promisc VLAN VSI 4706 * @sw: pointer to switch info struct for which function add rule 4707 */ 4708 static enum ice_status 4709 _ice_get_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 *promisc_mask, 4710 u16 *vid, struct ice_switch_info *sw) 4711 { 4712 struct ice_fltr_mgmt_list_entry *itr; 4713 struct LIST_HEAD_TYPE *rule_head; 4714 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 4715 4716 if (!ice_is_vsi_valid(hw, vsi_handle)) 4717 return ICE_ERR_PARAM; 4718 4719 *vid = 0; 4720 *promisc_mask = 0; 4721 rule_head = &sw->recp_list[ICE_SW_LKUP_PROMISC].filt_rules; 4722 rule_lock = &sw->recp_list[ICE_SW_LKUP_PROMISC].filt_rule_lock; 4723 4724 ice_acquire_lock(rule_lock); 4725 LIST_FOR_EACH_ENTRY(itr, rule_head, 4726 ice_fltr_mgmt_list_entry, list_entry) { 4727 /* Continue if this filter doesn't apply to this VSI or the 4728 * VSI ID is not in the VSI map for this filter 4729 */ 4730 if (!ice_vsi_uses_fltr(itr, vsi_handle)) 4731 continue; 4732 4733 *promisc_mask |= ice_determine_promisc_mask(&itr->fltr_info); 4734 } 4735 ice_release_lock(rule_lock); 4736 4737 return ICE_SUCCESS; 4738 } 4739 4740 /** 4741 * ice_get_vsi_promisc - get promiscuous mode of given VSI 4742 * @hw: pointer to the hardware structure 4743 * @vsi_handle: VSI handle to retrieve info from 4744 * @promisc_mask: pointer to mask to be filled in 4745 * @vid: VLAN ID of promisc VLAN VSI 4746 */ 4747 enum ice_status 4748 ice_get_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 *promisc_mask, 4749 u16 *vid) 4750 { 4751 return _ice_get_vsi_promisc(hw, vsi_handle, promisc_mask, 4752 vid, hw->switch_info); 4753 } 4754 4755 /** 4756 * ice_get_vsi_vlan_promisc - get VLAN promiscuous mode of given VSI 4757 * @hw: pointer to the hardware structure 4758 * @vsi_handle: VSI handle to retrieve info from 4759 * @promisc_mask: pointer to mask to be filled in 4760 * @vid: VLAN ID of promisc VLAN VSI 4761 * @sw: pointer to switch info struct for which function add rule 4762 */ 4763 static enum ice_status 4764 _ice_get_vsi_vlan_promisc(struct ice_hw *hw, u16 vsi_handle, u8 *promisc_mask, 4765 u16 *vid, struct ice_switch_info *sw) 4766 { 4767 struct ice_fltr_mgmt_list_entry *itr; 4768 struct LIST_HEAD_TYPE *rule_head; 4769 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 4770 4771 if (!ice_is_vsi_valid(hw, vsi_handle)) 4772 return ICE_ERR_PARAM; 4773 4774 *vid = 0; 4775 *promisc_mask = 0; 4776 rule_head = &sw->recp_list[ICE_SW_LKUP_PROMISC_VLAN].filt_rules; 4777 rule_lock = &sw->recp_list[ICE_SW_LKUP_PROMISC_VLAN].filt_rule_lock; 4778 4779 ice_acquire_lock(rule_lock); 4780 LIST_FOR_EACH_ENTRY(itr, rule_head, ice_fltr_mgmt_list_entry, 4781 list_entry) { 4782 /* Continue if this filter doesn't apply to this VSI or the 4783 * VSI ID is not in the VSI map for this filter 4784 */ 4785 if (!ice_vsi_uses_fltr(itr, vsi_handle)) 4786 continue; 4787 4788 *promisc_mask |= ice_determine_promisc_mask(&itr->fltr_info); 4789 } 4790 ice_release_lock(rule_lock); 4791 4792 return ICE_SUCCESS; 4793 } 4794 4795 /** 4796 * ice_get_vsi_vlan_promisc - get VLAN promiscuous mode of given VSI 4797 * @hw: pointer to the hardware structure 4798 * @vsi_handle: VSI handle to retrieve info from 4799 * @promisc_mask: pointer to mask to be filled in 4800 * @vid: VLAN ID of promisc VLAN VSI 4801 */ 4802 enum ice_status 4803 ice_get_vsi_vlan_promisc(struct ice_hw *hw, u16 vsi_handle, u8 *promisc_mask, 4804 u16 *vid) 4805 { 4806 return _ice_get_vsi_vlan_promisc(hw, vsi_handle, promisc_mask, 4807 vid, hw->switch_info); 4808 } 4809 4810 /** 4811 * ice_remove_promisc - Remove promisc based filter rules 4812 * @hw: pointer to the hardware structure 4813 * @recp_id: recipe ID for which the rule needs to removed 4814 * @v_list: list of promisc entries 4815 */ 4816 static enum ice_status 4817 ice_remove_promisc(struct ice_hw *hw, u8 recp_id, 4818 struct LIST_HEAD_TYPE *v_list) 4819 { 4820 struct ice_fltr_list_entry *v_list_itr, *tmp; 4821 struct ice_sw_recipe *recp_list; 4822 4823 recp_list = &hw->switch_info->recp_list[recp_id]; 4824 LIST_FOR_EACH_ENTRY_SAFE(v_list_itr, tmp, v_list, ice_fltr_list_entry, 4825 list_entry) { 4826 v_list_itr->status = 4827 ice_remove_rule_internal(hw, recp_list, v_list_itr); 4828 if (v_list_itr->status) 4829 return v_list_itr->status; 4830 } 4831 return ICE_SUCCESS; 4832 } 4833 4834 /** 4835 * _ice_clear_vsi_promisc - clear specified promiscuous mode(s) 4836 * @hw: pointer to the hardware structure 4837 * @vsi_handle: VSI handle to clear mode 4838 * @promisc_mask: mask of promiscuous config bits to clear 4839 * @vid: VLAN ID to clear VLAN promiscuous 4840 * @sw: pointer to switch info struct for which function add rule 4841 */ 4842 static enum ice_status 4843 _ice_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, 4844 u16 vid, struct ice_switch_info *sw) 4845 { 4846 struct ice_fltr_list_entry *fm_entry, *tmp; 4847 struct LIST_HEAD_TYPE remove_list_head; 4848 struct ice_fltr_mgmt_list_entry *itr; 4849 struct LIST_HEAD_TYPE *rule_head; 4850 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 4851 enum ice_status status = ICE_SUCCESS; 4852 u8 recipe_id; 4853 4854 if (!ice_is_vsi_valid(hw, vsi_handle)) 4855 return ICE_ERR_PARAM; 4856 4857 if (promisc_mask & (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX)) 4858 recipe_id = ICE_SW_LKUP_PROMISC_VLAN; 4859 else 4860 recipe_id = ICE_SW_LKUP_PROMISC; 4861 4862 rule_head = &sw->recp_list[recipe_id].filt_rules; 4863 rule_lock = &sw->recp_list[recipe_id].filt_rule_lock; 4864 4865 INIT_LIST_HEAD(&remove_list_head); 4866 4867 ice_acquire_lock(rule_lock); 4868 LIST_FOR_EACH_ENTRY(itr, rule_head, 4869 ice_fltr_mgmt_list_entry, list_entry) { 4870 struct ice_fltr_info *fltr_info; 4871 u8 fltr_promisc_mask = 0; 4872 4873 if (!ice_vsi_uses_fltr(itr, vsi_handle)) 4874 continue; 4875 fltr_info = &itr->fltr_info; 4876 4877 if (recipe_id == ICE_SW_LKUP_PROMISC_VLAN && 4878 vid != fltr_info->l_data.mac_vlan.vlan_id) 4879 continue; 4880 4881 fltr_promisc_mask |= ice_determine_promisc_mask(fltr_info); 4882 4883 /* Skip if filter is not completely specified by given mask */ 4884 if (fltr_promisc_mask & ~promisc_mask) 4885 continue; 4886 4887 status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle, 4888 &remove_list_head, 4889 fltr_info); 4890 if (status) { 4891 ice_release_lock(rule_lock); 4892 goto free_fltr_list; 4893 } 4894 } 4895 ice_release_lock(rule_lock); 4896 4897 status = ice_remove_promisc(hw, recipe_id, &remove_list_head); 4898 4899 free_fltr_list: 4900 LIST_FOR_EACH_ENTRY_SAFE(fm_entry, tmp, &remove_list_head, 4901 ice_fltr_list_entry, list_entry) { 4902 LIST_DEL(&fm_entry->list_entry); 4903 ice_free(hw, fm_entry); 4904 } 4905 4906 return status; 4907 } 4908 4909 /** 4910 * ice_clear_vsi_promisc - clear specified promiscuous mode(s) for given VSI 4911 * @hw: pointer to the hardware structure 4912 * @vsi_handle: VSI handle to clear mode 4913 * @promisc_mask: mask of promiscuous config bits to clear 4914 * @vid: VLAN ID to clear VLAN promiscuous 4915 */ 4916 enum ice_status 4917 ice_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, 4918 u8 promisc_mask, u16 vid) 4919 { 4920 return _ice_clear_vsi_promisc(hw, vsi_handle, promisc_mask, 4921 vid, hw->switch_info); 4922 } 4923 4924 /** 4925 * _ice_set_vsi_promisc - set given VSI to given promiscuous mode(s) 4926 * @hw: pointer to the hardware structure 4927 * @vsi_handle: VSI handle to configure 4928 * @promisc_mask: mask of promiscuous config bits 4929 * @vid: VLAN ID to set VLAN promiscuous 4930 * @lport: logical port number to configure promisc mode 4931 * @sw: pointer to switch info struct for which function add rule 4932 */ 4933 static enum ice_status 4934 _ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, 4935 u16 vid, u8 lport, struct ice_switch_info *sw) 4936 { 4937 enum { UCAST_FLTR = 1, MCAST_FLTR, BCAST_FLTR }; 4938 struct ice_fltr_list_entry f_list_entry; 4939 struct ice_fltr_info new_fltr; 4940 enum ice_status status = ICE_SUCCESS; 4941 bool is_tx_fltr; 4942 u16 hw_vsi_id; 4943 int pkt_type; 4944 u8 recipe_id; 4945 4946 ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 4947 4948 if (!ice_is_vsi_valid(hw, vsi_handle)) 4949 return ICE_ERR_PARAM; 4950 hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 4951 4952 ice_memset(&new_fltr, 0, sizeof(new_fltr), ICE_NONDMA_MEM); 4953 4954 if (promisc_mask & (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX)) { 4955 new_fltr.lkup_type = ICE_SW_LKUP_PROMISC_VLAN; 4956 new_fltr.l_data.mac_vlan.vlan_id = vid; 4957 recipe_id = ICE_SW_LKUP_PROMISC_VLAN; 4958 } else { 4959 new_fltr.lkup_type = ICE_SW_LKUP_PROMISC; 4960 recipe_id = ICE_SW_LKUP_PROMISC; 4961 } 4962 4963 /* Separate filters must be set for each direction/packet type 4964 * combination, so we will loop over the mask value, store the 4965 * individual type, and clear it out in the input mask as it 4966 * is found. 4967 */ 4968 while (promisc_mask) { 4969 struct ice_sw_recipe *recp_list; 4970 u8 *mac_addr; 4971 4972 pkt_type = 0; 4973 is_tx_fltr = false; 4974 4975 if (promisc_mask & ICE_PROMISC_UCAST_RX) { 4976 promisc_mask &= ~ICE_PROMISC_UCAST_RX; 4977 pkt_type = UCAST_FLTR; 4978 } else if (promisc_mask & ICE_PROMISC_UCAST_TX) { 4979 promisc_mask &= ~ICE_PROMISC_UCAST_TX; 4980 pkt_type = UCAST_FLTR; 4981 is_tx_fltr = true; 4982 } else if (promisc_mask & ICE_PROMISC_MCAST_RX) { 4983 promisc_mask &= ~ICE_PROMISC_MCAST_RX; 4984 pkt_type = MCAST_FLTR; 4985 } else if (promisc_mask & ICE_PROMISC_MCAST_TX) { 4986 promisc_mask &= ~ICE_PROMISC_MCAST_TX; 4987 pkt_type = MCAST_FLTR; 4988 is_tx_fltr = true; 4989 } else if (promisc_mask & ICE_PROMISC_BCAST_RX) { 4990 promisc_mask &= ~ICE_PROMISC_BCAST_RX; 4991 pkt_type = BCAST_FLTR; 4992 } else if (promisc_mask & ICE_PROMISC_BCAST_TX) { 4993 promisc_mask &= ~ICE_PROMISC_BCAST_TX; 4994 pkt_type = BCAST_FLTR; 4995 is_tx_fltr = true; 4996 } 4997 4998 /* Check for VLAN promiscuous flag */ 4999 if (promisc_mask & ICE_PROMISC_VLAN_RX) { 5000 promisc_mask &= ~ICE_PROMISC_VLAN_RX; 5001 } else if (promisc_mask & ICE_PROMISC_VLAN_TX) { 5002 promisc_mask &= ~ICE_PROMISC_VLAN_TX; 5003 is_tx_fltr = true; 5004 } 5005 5006 /* Set filter DA based on packet type */ 5007 mac_addr = new_fltr.l_data.mac.mac_addr; 5008 if (pkt_type == BCAST_FLTR) { 5009 ice_memset(mac_addr, 0xff, ETH_ALEN, ICE_NONDMA_MEM); 5010 } else if (pkt_type == MCAST_FLTR || 5011 pkt_type == UCAST_FLTR) { 5012 /* Use the dummy ether header DA */ 5013 ice_memcpy(mac_addr, dummy_eth_header, ETH_ALEN, 5014 ICE_NONDMA_TO_NONDMA); 5015 if (pkt_type == MCAST_FLTR) 5016 mac_addr[0] |= 0x1; /* Set multicast bit */ 5017 } 5018 5019 /* Need to reset this to zero for all iterations */ 5020 new_fltr.flag = 0; 5021 if (is_tx_fltr) { 5022 new_fltr.flag |= ICE_FLTR_TX; 5023 new_fltr.src = hw_vsi_id; 5024 } else { 5025 new_fltr.flag |= ICE_FLTR_RX; 5026 new_fltr.src = lport; 5027 } 5028 5029 new_fltr.fltr_act = ICE_FWD_TO_VSI; 5030 new_fltr.vsi_handle = vsi_handle; 5031 new_fltr.fwd_id.hw_vsi_id = hw_vsi_id; 5032 f_list_entry.fltr_info = new_fltr; 5033 recp_list = &sw->recp_list[recipe_id]; 5034 5035 status = ice_add_rule_internal(hw, recp_list, lport, 5036 &f_list_entry); 5037 if (status != ICE_SUCCESS) 5038 goto set_promisc_exit; 5039 } 5040 5041 set_promisc_exit: 5042 return status; 5043 } 5044 5045 /** 5046 * ice_set_vsi_promisc - set given VSI to given promiscuous mode(s) 5047 * @hw: pointer to the hardware structure 5048 * @vsi_handle: VSI handle to configure 5049 * @promisc_mask: mask of promiscuous config bits 5050 * @vid: VLAN ID to set VLAN promiscuous 5051 */ 5052 enum ice_status 5053 ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, 5054 u16 vid) 5055 { 5056 return _ice_set_vsi_promisc(hw, vsi_handle, promisc_mask, vid, 5057 hw->port_info->lport, 5058 hw->switch_info); 5059 } 5060 5061 /** 5062 * _ice_set_vlan_vsi_promisc 5063 * @hw: pointer to the hardware structure 5064 * @vsi_handle: VSI handle to configure 5065 * @promisc_mask: mask of promiscuous config bits 5066 * @rm_vlan_promisc: Clear VLANs VSI promisc mode 5067 * @lport: logical port number to configure promisc mode 5068 * @sw: pointer to switch info struct for which function add rule 5069 * 5070 * Configure VSI with all associated VLANs to given promiscuous mode(s) 5071 */ 5072 static enum ice_status 5073 _ice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, 5074 bool rm_vlan_promisc, u8 lport, 5075 struct ice_switch_info *sw) 5076 { 5077 struct ice_fltr_list_entry *list_itr, *tmp; 5078 struct LIST_HEAD_TYPE vsi_list_head; 5079 struct LIST_HEAD_TYPE *vlan_head; 5080 struct ice_lock *vlan_lock; /* Lock to protect filter rule list */ 5081 enum ice_status status; 5082 u16 vlan_id; 5083 5084 INIT_LIST_HEAD(&vsi_list_head); 5085 vlan_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock; 5086 vlan_head = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rules; 5087 ice_acquire_lock(vlan_lock); 5088 status = ice_add_to_vsi_fltr_list(hw, vsi_handle, vlan_head, 5089 &vsi_list_head); 5090 ice_release_lock(vlan_lock); 5091 if (status) 5092 goto free_fltr_list; 5093 5094 LIST_FOR_EACH_ENTRY(list_itr, &vsi_list_head, ice_fltr_list_entry, 5095 list_entry) { 5096 vlan_id = list_itr->fltr_info.l_data.vlan.vlan_id; 5097 if (rm_vlan_promisc) 5098 status = _ice_clear_vsi_promisc(hw, vsi_handle, 5099 promisc_mask, 5100 vlan_id, sw); 5101 else 5102 status = _ice_set_vsi_promisc(hw, vsi_handle, 5103 promisc_mask, vlan_id, 5104 lport, sw); 5105 if (status) 5106 break; 5107 } 5108 5109 free_fltr_list: 5110 LIST_FOR_EACH_ENTRY_SAFE(list_itr, tmp, &vsi_list_head, 5111 ice_fltr_list_entry, list_entry) { 5112 LIST_DEL(&list_itr->list_entry); 5113 ice_free(hw, list_itr); 5114 } 5115 return status; 5116 } 5117 5118 /** 5119 * ice_set_vlan_vsi_promisc 5120 * @hw: pointer to the hardware structure 5121 * @vsi_handle: VSI handle to configure 5122 * @promisc_mask: mask of promiscuous config bits 5123 * @rm_vlan_promisc: Clear VLANs VSI promisc mode 5124 * 5125 * Configure VSI with all associated VLANs to given promiscuous mode(s) 5126 */ 5127 enum ice_status 5128 ice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, 5129 bool rm_vlan_promisc) 5130 { 5131 return _ice_set_vlan_vsi_promisc(hw, vsi_handle, promisc_mask, 5132 rm_vlan_promisc, hw->port_info->lport, 5133 hw->switch_info); 5134 } 5135 5136 /** 5137 * ice_remove_vsi_lkup_fltr - Remove lookup type filters for a VSI 5138 * @hw: pointer to the hardware structure 5139 * @vsi_handle: VSI handle to remove filters from 5140 * @recp_list: recipe list from which function remove fltr 5141 * @lkup: switch rule filter lookup type 5142 */ 5143 static void 5144 ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_handle, 5145 struct ice_sw_recipe *recp_list, 5146 enum ice_sw_lkup_type lkup) 5147 { 5148 struct ice_fltr_list_entry *fm_entry; 5149 struct LIST_HEAD_TYPE remove_list_head; 5150 struct LIST_HEAD_TYPE *rule_head; 5151 struct ice_fltr_list_entry *tmp; 5152 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 5153 enum ice_status status; 5154 5155 INIT_LIST_HEAD(&remove_list_head); 5156 rule_lock = &recp_list[lkup].filt_rule_lock; 5157 rule_head = &recp_list[lkup].filt_rules; 5158 ice_acquire_lock(rule_lock); 5159 status = ice_add_to_vsi_fltr_list(hw, vsi_handle, rule_head, 5160 &remove_list_head); 5161 ice_release_lock(rule_lock); 5162 if (status) 5163 return; 5164 5165 switch (lkup) { 5166 case ICE_SW_LKUP_MAC: 5167 ice_remove_mac_rule(hw, &remove_list_head, &recp_list[lkup]); 5168 break; 5169 case ICE_SW_LKUP_VLAN: 5170 ice_remove_vlan_rule(hw, &remove_list_head, &recp_list[lkup]); 5171 break; 5172 case ICE_SW_LKUP_PROMISC: 5173 case ICE_SW_LKUP_PROMISC_VLAN: 5174 ice_remove_promisc(hw, lkup, &remove_list_head); 5175 break; 5176 case ICE_SW_LKUP_MAC_VLAN: 5177 ice_remove_mac_vlan(hw, &remove_list_head); 5178 break; 5179 case ICE_SW_LKUP_ETHERTYPE: 5180 case ICE_SW_LKUP_ETHERTYPE_MAC: 5181 ice_remove_eth_mac(hw, &remove_list_head); 5182 break; 5183 case ICE_SW_LKUP_DFLT: 5184 ice_debug(hw, ICE_DBG_SW, 5185 "Remove filters for this lookup type hasn't been implemented yet\n"); 5186 break; 5187 case ICE_SW_LKUP_LAST: 5188 ice_debug(hw, ICE_DBG_SW, "Unsupported lookup type\n"); 5189 break; 5190 } 5191 5192 LIST_FOR_EACH_ENTRY_SAFE(fm_entry, tmp, &remove_list_head, 5193 ice_fltr_list_entry, list_entry) { 5194 LIST_DEL(&fm_entry->list_entry); 5195 ice_free(hw, fm_entry); 5196 } 5197 } 5198 5199 /** 5200 * ice_remove_vsi_fltr_rule - Remove all filters for a VSI 5201 * @hw: pointer to the hardware structure 5202 * @vsi_handle: VSI handle to remove filters from 5203 * @sw: pointer to switch info struct 5204 */ 5205 static void 5206 ice_remove_vsi_fltr_rule(struct ice_hw *hw, u16 vsi_handle, 5207 struct ice_switch_info *sw) 5208 { 5209 ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 5210 5211 ice_remove_vsi_lkup_fltr(hw, vsi_handle, 5212 sw->recp_list, ICE_SW_LKUP_MAC); 5213 ice_remove_vsi_lkup_fltr(hw, vsi_handle, 5214 sw->recp_list, ICE_SW_LKUP_MAC_VLAN); 5215 ice_remove_vsi_lkup_fltr(hw, vsi_handle, 5216 sw->recp_list, ICE_SW_LKUP_PROMISC); 5217 ice_remove_vsi_lkup_fltr(hw, vsi_handle, 5218 sw->recp_list, ICE_SW_LKUP_VLAN); 5219 ice_remove_vsi_lkup_fltr(hw, vsi_handle, 5220 sw->recp_list, ICE_SW_LKUP_DFLT); 5221 ice_remove_vsi_lkup_fltr(hw, vsi_handle, 5222 sw->recp_list, ICE_SW_LKUP_ETHERTYPE); 5223 ice_remove_vsi_lkup_fltr(hw, vsi_handle, 5224 sw->recp_list, ICE_SW_LKUP_ETHERTYPE_MAC); 5225 ice_remove_vsi_lkup_fltr(hw, vsi_handle, 5226 sw->recp_list, ICE_SW_LKUP_PROMISC_VLAN); 5227 } 5228 5229 /** 5230 * ice_remove_vsi_fltr - Remove all filters for a VSI 5231 * @hw: pointer to the hardware structure 5232 * @vsi_handle: VSI handle to remove filters from 5233 */ 5234 void ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_handle) 5235 { 5236 ice_remove_vsi_fltr_rule(hw, vsi_handle, hw->switch_info); 5237 } 5238 5239 /** 5240 * ice_alloc_res_cntr - allocating resource counter 5241 * @hw: pointer to the hardware structure 5242 * @type: type of resource 5243 * @alloc_shared: if set it is shared else dedicated 5244 * @num_items: number of entries requested for FD resource type 5245 * @counter_id: counter index returned by AQ call 5246 */ 5247 enum ice_status 5248 ice_alloc_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items, 5249 u16 *counter_id) 5250 { 5251 struct ice_aqc_alloc_free_res_elem *buf; 5252 enum ice_status status; 5253 u16 buf_len; 5254 5255 /* Allocate resource */ 5256 buf_len = sizeof(*buf); 5257 buf = (struct ice_aqc_alloc_free_res_elem *) 5258 ice_malloc(hw, buf_len); 5259 if (!buf) 5260 return ICE_ERR_NO_MEMORY; 5261 5262 buf->num_elems = CPU_TO_LE16(num_items); 5263 buf->res_type = CPU_TO_LE16(((type << ICE_AQC_RES_TYPE_S) & 5264 ICE_AQC_RES_TYPE_M) | alloc_shared); 5265 5266 status = ice_aq_alloc_free_res(hw, 1, buf, buf_len, 5267 ice_aqc_opc_alloc_res, NULL); 5268 if (status) 5269 goto exit; 5270 5271 *counter_id = LE16_TO_CPU(buf->elem[0].e.sw_resp); 5272 5273 exit: 5274 ice_free(hw, buf); 5275 return status; 5276 } 5277 5278 /** 5279 * ice_free_res_cntr - free resource counter 5280 * @hw: pointer to the hardware structure 5281 * @type: type of resource 5282 * @alloc_shared: if set it is shared else dedicated 5283 * @num_items: number of entries to be freed for FD resource type 5284 * @counter_id: counter ID resource which needs to be freed 5285 */ 5286 enum ice_status 5287 ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items, 5288 u16 counter_id) 5289 { 5290 struct ice_aqc_alloc_free_res_elem *buf; 5291 enum ice_status status; 5292 u16 buf_len; 5293 5294 /* Free resource */ 5295 buf_len = sizeof(*buf); 5296 buf = (struct ice_aqc_alloc_free_res_elem *) 5297 ice_malloc(hw, buf_len); 5298 if (!buf) 5299 return ICE_ERR_NO_MEMORY; 5300 5301 buf->num_elems = CPU_TO_LE16(num_items); 5302 buf->res_type = CPU_TO_LE16(((type << ICE_AQC_RES_TYPE_S) & 5303 ICE_AQC_RES_TYPE_M) | alloc_shared); 5304 buf->elem[0].e.sw_resp = CPU_TO_LE16(counter_id); 5305 5306 status = ice_aq_alloc_free_res(hw, 1, buf, buf_len, 5307 ice_aqc_opc_free_res, NULL); 5308 if (status) 5309 ice_debug(hw, ICE_DBG_SW, 5310 "counter resource could not be freed\n"); 5311 5312 ice_free(hw, buf); 5313 return status; 5314 } 5315 5316 /** 5317 * ice_alloc_vlan_res_counter - obtain counter resource for VLAN type 5318 * @hw: pointer to the hardware structure 5319 * @counter_id: returns counter index 5320 */ 5321 enum ice_status ice_alloc_vlan_res_counter(struct ice_hw *hw, u16 *counter_id) 5322 { 5323 return ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_VLAN_COUNTER, 5324 ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1, 5325 counter_id); 5326 } 5327 5328 /** 5329 * ice_free_vlan_res_counter - Free counter resource for VLAN type 5330 * @hw: pointer to the hardware structure 5331 * @counter_id: counter index to be freed 5332 */ 5333 enum ice_status ice_free_vlan_res_counter(struct ice_hw *hw, u16 counter_id) 5334 { 5335 return ice_free_res_cntr(hw, ICE_AQC_RES_TYPE_VLAN_COUNTER, 5336 ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1, 5337 counter_id); 5338 } 5339 5340 /** 5341 * ice_alloc_res_lg_act - add large action resource 5342 * @hw: pointer to the hardware structure 5343 * @l_id: large action ID to fill it in 5344 * @num_acts: number of actions to hold with a large action entry 5345 */ 5346 static enum ice_status 5347 ice_alloc_res_lg_act(struct ice_hw *hw, u16 *l_id, u16 num_acts) 5348 { 5349 struct ice_aqc_alloc_free_res_elem *sw_buf; 5350 enum ice_status status; 5351 u16 buf_len; 5352 5353 if (num_acts > ICE_MAX_LG_ACT || num_acts == 0) 5354 return ICE_ERR_PARAM; 5355 5356 /* Allocate resource for large action */ 5357 buf_len = sizeof(*sw_buf); 5358 sw_buf = (struct ice_aqc_alloc_free_res_elem *) 5359 ice_malloc(hw, buf_len); 5360 if (!sw_buf) 5361 return ICE_ERR_NO_MEMORY; 5362 5363 sw_buf->num_elems = CPU_TO_LE16(1); 5364 5365 /* If num_acts is 1, use ICE_AQC_RES_TYPE_WIDE_TABLE_1. 5366 * If num_acts is 2, use ICE_AQC_RES_TYPE_WIDE_TABLE_3. 5367 * If num_acts is greater than 2, then use 5368 * ICE_AQC_RES_TYPE_WIDE_TABLE_4. 5369 * The num_acts cannot exceed 4. This was ensured at the 5370 * beginning of the function. 5371 */ 5372 if (num_acts == 1) 5373 sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_WIDE_TABLE_1); 5374 else if (num_acts == 2) 5375 sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_WIDE_TABLE_2); 5376 else 5377 sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_WIDE_TABLE_4); 5378 5379 status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, 5380 ice_aqc_opc_alloc_res, NULL); 5381 if (!status) 5382 *l_id = LE16_TO_CPU(sw_buf->elem[0].e.sw_resp); 5383 5384 ice_free(hw, sw_buf); 5385 return status; 5386 } 5387 5388 /** 5389 * ice_add_mac_with_sw_marker - add filter with sw marker 5390 * @hw: pointer to the hardware structure 5391 * @f_info: filter info structure containing the MAC filter information 5392 * @sw_marker: sw marker to tag the Rx descriptor with 5393 */ 5394 enum ice_status 5395 ice_add_mac_with_sw_marker(struct ice_hw *hw, struct ice_fltr_info *f_info, 5396 u16 sw_marker) 5397 { 5398 struct ice_fltr_mgmt_list_entry *m_entry; 5399 struct ice_fltr_list_entry fl_info; 5400 struct ice_sw_recipe *recp_list; 5401 struct LIST_HEAD_TYPE l_head; 5402 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 5403 enum ice_status ret; 5404 bool entry_exists; 5405 u16 lg_act_id; 5406 5407 if (f_info->fltr_act != ICE_FWD_TO_VSI) 5408 return ICE_ERR_PARAM; 5409 5410 if (f_info->lkup_type != ICE_SW_LKUP_MAC) 5411 return ICE_ERR_PARAM; 5412 5413 if (sw_marker == ICE_INVAL_SW_MARKER_ID) 5414 return ICE_ERR_PARAM; 5415 5416 if (!ice_is_vsi_valid(hw, f_info->vsi_handle)) 5417 return ICE_ERR_PARAM; 5418 f_info->fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, f_info->vsi_handle); 5419 5420 /* Add filter if it doesn't exist so then the adding of large 5421 * action always results in update 5422 */ 5423 5424 INIT_LIST_HEAD(&l_head); 5425 fl_info.fltr_info = *f_info; 5426 LIST_ADD(&fl_info.list_entry, &l_head); 5427 5428 entry_exists = false; 5429 ret = ice_add_mac_rule(hw, &l_head, hw->switch_info, 5430 hw->port_info->lport); 5431 if (ret == ICE_ERR_ALREADY_EXISTS) 5432 entry_exists = true; 5433 else if (ret) 5434 return ret; 5435 5436 recp_list = &hw->switch_info->recp_list[ICE_SW_LKUP_MAC]; 5437 rule_lock = &recp_list->filt_rule_lock; 5438 ice_acquire_lock(rule_lock); 5439 /* Get the book keeping entry for the filter */ 5440 m_entry = ice_find_rule_entry(&recp_list->filt_rules, f_info); 5441 if (!m_entry) 5442 goto exit_error; 5443 5444 /* If counter action was enabled for this rule then don't enable 5445 * sw marker large action 5446 */ 5447 if (m_entry->counter_index != ICE_INVAL_COUNTER_ID) { 5448 ret = ICE_ERR_PARAM; 5449 goto exit_error; 5450 } 5451 5452 /* if same marker was added before */ 5453 if (m_entry->sw_marker_id == sw_marker) { 5454 ret = ICE_ERR_ALREADY_EXISTS; 5455 goto exit_error; 5456 } 5457 5458 /* Allocate a hardware table entry to hold large act. Three actions 5459 * for marker based large action 5460 */ 5461 ret = ice_alloc_res_lg_act(hw, &lg_act_id, 3); 5462 if (ret) 5463 goto exit_error; 5464 5465 if (lg_act_id == ICE_INVAL_LG_ACT_INDEX) 5466 goto exit_error; 5467 5468 /* Update the switch rule to add the marker action */ 5469 ret = ice_add_marker_act(hw, m_entry, sw_marker, lg_act_id); 5470 if (!ret) { 5471 ice_release_lock(rule_lock); 5472 return ret; 5473 } 5474 5475 exit_error: 5476 ice_release_lock(rule_lock); 5477 /* only remove entry if it did not exist previously */ 5478 if (!entry_exists) 5479 ret = ice_remove_mac(hw, &l_head); 5480 5481 return ret; 5482 } 5483 5484 /** 5485 * ice_add_mac_with_counter - add filter with counter enabled 5486 * @hw: pointer to the hardware structure 5487 * @f_info: pointer to filter info structure containing the MAC filter 5488 * information 5489 */ 5490 enum ice_status 5491 ice_add_mac_with_counter(struct ice_hw *hw, struct ice_fltr_info *f_info) 5492 { 5493 struct ice_fltr_mgmt_list_entry *m_entry; 5494 struct ice_fltr_list_entry fl_info; 5495 struct ice_sw_recipe *recp_list; 5496 struct LIST_HEAD_TYPE l_head; 5497 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 5498 enum ice_status ret; 5499 bool entry_exist; 5500 u16 counter_id; 5501 u16 lg_act_id; 5502 5503 if (f_info->fltr_act != ICE_FWD_TO_VSI) 5504 return ICE_ERR_PARAM; 5505 5506 if (f_info->lkup_type != ICE_SW_LKUP_MAC) 5507 return ICE_ERR_PARAM; 5508 5509 if (!ice_is_vsi_valid(hw, f_info->vsi_handle)) 5510 return ICE_ERR_PARAM; 5511 f_info->fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, f_info->vsi_handle); 5512 recp_list = &hw->switch_info->recp_list[ICE_SW_LKUP_MAC]; 5513 5514 entry_exist = false; 5515 5516 rule_lock = &recp_list->filt_rule_lock; 5517 5518 /* Add filter if it doesn't exist so then the adding of large 5519 * action always results in update 5520 */ 5521 INIT_LIST_HEAD(&l_head); 5522 5523 fl_info.fltr_info = *f_info; 5524 LIST_ADD(&fl_info.list_entry, &l_head); 5525 5526 ret = ice_add_mac_rule(hw, &l_head, hw->switch_info, 5527 hw->port_info->lport); 5528 if (ret == ICE_ERR_ALREADY_EXISTS) 5529 entry_exist = true; 5530 else if (ret) 5531 return ret; 5532 5533 ice_acquire_lock(rule_lock); 5534 m_entry = ice_find_rule_entry(&recp_list->filt_rules, f_info); 5535 if (!m_entry) { 5536 ret = ICE_ERR_BAD_PTR; 5537 goto exit_error; 5538 } 5539 5540 /* Don't enable counter for a filter for which sw marker was enabled */ 5541 if (m_entry->sw_marker_id != ICE_INVAL_SW_MARKER_ID) { 5542 ret = ICE_ERR_PARAM; 5543 goto exit_error; 5544 } 5545 5546 /* If a counter was already enabled then don't need to add again */ 5547 if (m_entry->counter_index != ICE_INVAL_COUNTER_ID) { 5548 ret = ICE_ERR_ALREADY_EXISTS; 5549 goto exit_error; 5550 } 5551 5552 /* Allocate a hardware table entry to VLAN counter */ 5553 ret = ice_alloc_vlan_res_counter(hw, &counter_id); 5554 if (ret) 5555 goto exit_error; 5556 5557 /* Allocate a hardware table entry to hold large act. Two actions for 5558 * counter based large action 5559 */ 5560 ret = ice_alloc_res_lg_act(hw, &lg_act_id, 2); 5561 if (ret) 5562 goto exit_error; 5563 5564 if (lg_act_id == ICE_INVAL_LG_ACT_INDEX) 5565 goto exit_error; 5566 5567 /* Update the switch rule to add the counter action */ 5568 ret = ice_add_counter_act(hw, m_entry, counter_id, lg_act_id); 5569 if (!ret) { 5570 ice_release_lock(rule_lock); 5571 return ret; 5572 } 5573 5574 exit_error: 5575 ice_release_lock(rule_lock); 5576 /* only remove entry if it did not exist previously */ 5577 if (!entry_exist) 5578 ret = ice_remove_mac(hw, &l_head); 5579 5580 return ret; 5581 } 5582 5583 /* This is mapping table entry that maps every word within a given protocol 5584 * structure to the real byte offset as per the specification of that 5585 * protocol header. 5586 * for example dst address is 3 words in ethertype header and corresponding 5587 * bytes are 0, 2, 3 in the actual packet header and src address is at 4, 6, 8 5588 * IMPORTANT: Every structure part of "ice_prot_hdr" union should have a 5589 * matching entry describing its field. This needs to be updated if new 5590 * structure is added to that union. 5591 */ 5592 static const struct ice_prot_ext_tbl_entry ice_prot_ext[ICE_PROTOCOL_LAST] = { 5593 { ICE_MAC_OFOS, { 0, 2, 4, 6, 8, 10, 12 } }, 5594 { ICE_MAC_IL, { 0, 2, 4, 6, 8, 10, 12 } }, 5595 { ICE_ETYPE_OL, { 0 } }, 5596 { ICE_VLAN_OFOS, { 0, 2 } }, 5597 { ICE_IPV4_OFOS, { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18 } }, 5598 { ICE_IPV4_IL, { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18 } }, 5599 { ICE_IPV6_OFOS, { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 5600 26, 28, 30, 32, 34, 36, 38 } }, 5601 { ICE_IPV6_IL, { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 5602 26, 28, 30, 32, 34, 36, 38 } }, 5603 { ICE_TCP_IL, { 0, 2 } }, 5604 { ICE_UDP_OF, { 0, 2 } }, 5605 { ICE_UDP_ILOS, { 0, 2 } }, 5606 { ICE_SCTP_IL, { 0, 2 } }, 5607 { ICE_VXLAN, { 8, 10, 12, 14 } }, 5608 { ICE_GENEVE, { 8, 10, 12, 14 } }, 5609 { ICE_VXLAN_GPE, { 8, 10, 12, 14 } }, 5610 { ICE_NVGRE, { 0, 2, 4, 6 } }, 5611 { ICE_GTP, { 8, 10, 12, 14, 16, 18, 20 } }, 5612 { ICE_PPPOE, { 0, 2, 4, 6 } }, 5613 { ICE_PFCP, { 8, 10, 12, 14, 16, 18, 20, 22 } }, 5614 { ICE_L2TPV3, { 0, 2, 4, 6, 8, 10 } }, 5615 { ICE_ESP, { 0, 2, 4, 6 } }, 5616 { ICE_AH, { 0, 2, 4, 6, 8, 10 } }, 5617 { ICE_NAT_T, { 8, 10, 12, 14 } }, 5618 }; 5619 5620 /* The following table describes preferred grouping of recipes. 5621 * If a recipe that needs to be programmed is a superset or matches one of the 5622 * following combinations, then the recipe needs to be chained as per the 5623 * following policy. 5624 */ 5625 5626 static const struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = { 5627 { ICE_MAC_OFOS, ICE_MAC_OFOS_HW }, 5628 { ICE_MAC_IL, ICE_MAC_IL_HW }, 5629 { ICE_ETYPE_OL, ICE_ETYPE_OL_HW }, 5630 { ICE_VLAN_OFOS, ICE_VLAN_OL_HW }, 5631 { ICE_IPV4_OFOS, ICE_IPV4_OFOS_HW }, 5632 { ICE_IPV4_IL, ICE_IPV4_IL_HW }, 5633 { ICE_IPV6_OFOS, ICE_IPV6_OFOS_HW }, 5634 { ICE_IPV6_IL, ICE_IPV6_IL_HW }, 5635 { ICE_TCP_IL, ICE_TCP_IL_HW }, 5636 { ICE_UDP_OF, ICE_UDP_OF_HW }, 5637 { ICE_UDP_ILOS, ICE_UDP_ILOS_HW }, 5638 { ICE_SCTP_IL, ICE_SCTP_IL_HW }, 5639 { ICE_VXLAN, ICE_UDP_OF_HW }, 5640 { ICE_GENEVE, ICE_UDP_OF_HW }, 5641 { ICE_VXLAN_GPE, ICE_UDP_OF_HW }, 5642 { ICE_NVGRE, ICE_GRE_OF_HW }, 5643 { ICE_GTP, ICE_UDP_OF_HW }, 5644 { ICE_PPPOE, ICE_PPPOE_HW }, 5645 { ICE_PFCP, ICE_UDP_ILOS_HW }, 5646 { ICE_L2TPV3, ICE_L2TPV3_HW }, 5647 { ICE_ESP, ICE_ESP_HW }, 5648 { ICE_AH, ICE_AH_HW }, 5649 { ICE_NAT_T, ICE_UDP_ILOS_HW }, 5650 }; 5651 5652 /** 5653 * ice_find_recp - find a recipe 5654 * @hw: pointer to the hardware structure 5655 * @lkup_exts: extension sequence to match 5656 * 5657 * Returns index of matching recipe, or ICE_MAX_NUM_RECIPES if not found. 5658 */ 5659 static u16 ice_find_recp(struct ice_hw *hw, struct ice_prot_lkup_ext *lkup_exts, 5660 enum ice_sw_tunnel_type tun_type) 5661 { 5662 bool refresh_required = true; 5663 struct ice_sw_recipe *recp; 5664 u8 i; 5665 5666 /* Walk through existing recipes to find a match */ 5667 recp = hw->switch_info->recp_list; 5668 for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) { 5669 /* If recipe was not created for this ID, in SW bookkeeping, 5670 * check if FW has an entry for this recipe. If the FW has an 5671 * entry update it in our SW bookkeeping and continue with the 5672 * matching. 5673 */ 5674 if (!recp[i].recp_created) 5675 if (ice_get_recp_frm_fw(hw, 5676 hw->switch_info->recp_list, i, 5677 &refresh_required)) 5678 continue; 5679 5680 /* Skip inverse action recipes */ 5681 if (recp[i].root_buf && recp[i].root_buf->content.act_ctrl & 5682 ICE_AQ_RECIPE_ACT_INV_ACT) 5683 continue; 5684 5685 /* if number of words we are looking for match */ 5686 if (lkup_exts->n_val_words == recp[i].lkup_exts.n_val_words) { 5687 struct ice_fv_word *ar = recp[i].lkup_exts.fv_words; 5688 struct ice_fv_word *be = lkup_exts->fv_words; 5689 u16 *cr = recp[i].lkup_exts.field_mask; 5690 u16 *de = lkup_exts->field_mask; 5691 bool found = true; 5692 u8 pe, qr; 5693 5694 /* ar, cr, and qr are related to the recipe words, while 5695 * be, de, and pe are related to the lookup words 5696 */ 5697 for (pe = 0; pe < lkup_exts->n_val_words; pe++) { 5698 for (qr = 0; qr < recp[i].lkup_exts.n_val_words; 5699 qr++) { 5700 if (ar[qr].off == be[pe].off && 5701 ar[qr].prot_id == be[pe].prot_id && 5702 cr[qr] == de[pe]) 5703 /* Found the "pe"th word in the 5704 * given recipe 5705 */ 5706 break; 5707 } 5708 /* After walking through all the words in the 5709 * "i"th recipe if "p"th word was not found then 5710 * this recipe is not what we are looking for. 5711 * So break out from this loop and try the next 5712 * recipe 5713 */ 5714 if (qr >= recp[i].lkup_exts.n_val_words) { 5715 found = false; 5716 break; 5717 } 5718 } 5719 /* If for "i"th recipe the found was never set to false 5720 * then it means we found our match 5721 */ 5722 if (tun_type == recp[i].tun_type && found) 5723 return i; /* Return the recipe ID */ 5724 } 5725 } 5726 return ICE_MAX_NUM_RECIPES; 5727 } 5728 5729 /** 5730 * ice_prot_type_to_id - get protocol ID from protocol type 5731 * @type: protocol type 5732 * @id: pointer to variable that will receive the ID 5733 * 5734 * Returns true if found, false otherwise 5735 */ 5736 static bool ice_prot_type_to_id(enum ice_protocol_type type, u8 *id) 5737 { 5738 u8 i; 5739 5740 for (i = 0; i < ARRAY_SIZE(ice_prot_id_tbl); i++) 5741 if (ice_prot_id_tbl[i].type == type) { 5742 *id = ice_prot_id_tbl[i].protocol_id; 5743 return true; 5744 } 5745 return false; 5746 } 5747 5748 /** 5749 * ice_find_valid_words - count valid words 5750 * @rule: advanced rule with lookup information 5751 * @lkup_exts: byte offset extractions of the words that are valid 5752 * 5753 * calculate valid words in a lookup rule using mask value 5754 */ 5755 static u8 5756 ice_fill_valid_words(struct ice_adv_lkup_elem *rule, 5757 struct ice_prot_lkup_ext *lkup_exts) 5758 { 5759 u8 j, word, prot_id, ret_val; 5760 5761 if (!ice_prot_type_to_id(rule->type, &prot_id)) 5762 return 0; 5763 5764 word = lkup_exts->n_val_words; 5765 5766 for (j = 0; j < sizeof(rule->m_u) / sizeof(u16); j++) 5767 if (((u16 *)&rule->m_u)[j] && 5768 rule->type < ARRAY_SIZE(ice_prot_ext)) { 5769 /* No more space to accommodate */ 5770 if (word >= ICE_MAX_CHAIN_WORDS) 5771 return 0; 5772 lkup_exts->fv_words[word].off = 5773 ice_prot_ext[rule->type].offs[j]; 5774 lkup_exts->fv_words[word].prot_id = 5775 ice_prot_id_tbl[rule->type].protocol_id; 5776 lkup_exts->field_mask[word] = 5777 BE16_TO_CPU(((__be16 *)&rule->m_u)[j]); 5778 word++; 5779 } 5780 5781 ret_val = word - lkup_exts->n_val_words; 5782 lkup_exts->n_val_words = word; 5783 5784 return ret_val; 5785 } 5786 5787 /** 5788 * ice_create_first_fit_recp_def - Create a recipe grouping 5789 * @hw: pointer to the hardware structure 5790 * @lkup_exts: an array of protocol header extractions 5791 * @rg_list: pointer to a list that stores new recipe groups 5792 * @recp_cnt: pointer to a variable that stores returned number of recipe groups 5793 * 5794 * Using first fit algorithm, take all the words that are still not done 5795 * and start grouping them in 4-word groups. Each group makes up one 5796 * recipe. 5797 */ 5798 static enum ice_status 5799 ice_create_first_fit_recp_def(struct ice_hw *hw, 5800 struct ice_prot_lkup_ext *lkup_exts, 5801 struct LIST_HEAD_TYPE *rg_list, 5802 u8 *recp_cnt) 5803 { 5804 struct ice_pref_recipe_group *grp = NULL; 5805 u8 j; 5806 5807 *recp_cnt = 0; 5808 5809 if (!lkup_exts->n_val_words) { 5810 struct ice_recp_grp_entry *entry; 5811 5812 entry = (struct ice_recp_grp_entry *) 5813 ice_malloc(hw, sizeof(*entry)); 5814 if (!entry) 5815 return ICE_ERR_NO_MEMORY; 5816 LIST_ADD(&entry->l_entry, rg_list); 5817 grp = &entry->r_group; 5818 (*recp_cnt)++; 5819 grp->n_val_pairs = 0; 5820 } 5821 5822 /* Walk through every word in the rule to check if it is not done. If so 5823 * then this word needs to be part of a new recipe. 5824 */ 5825 for (j = 0; j < lkup_exts->n_val_words; j++) 5826 if (!ice_is_bit_set(lkup_exts->done, j)) { 5827 if (!grp || 5828 grp->n_val_pairs == ICE_NUM_WORDS_RECIPE) { 5829 struct ice_recp_grp_entry *entry; 5830 5831 entry = (struct ice_recp_grp_entry *) 5832 ice_malloc(hw, sizeof(*entry)); 5833 if (!entry) 5834 return ICE_ERR_NO_MEMORY; 5835 LIST_ADD(&entry->l_entry, rg_list); 5836 grp = &entry->r_group; 5837 (*recp_cnt)++; 5838 } 5839 5840 grp->pairs[grp->n_val_pairs].prot_id = 5841 lkup_exts->fv_words[j].prot_id; 5842 grp->pairs[grp->n_val_pairs].off = 5843 lkup_exts->fv_words[j].off; 5844 grp->mask[grp->n_val_pairs] = lkup_exts->field_mask[j]; 5845 grp->n_val_pairs++; 5846 } 5847 5848 return ICE_SUCCESS; 5849 } 5850 5851 /** 5852 * ice_fill_fv_word_index - fill in the field vector indices for a recipe group 5853 * @hw: pointer to the hardware structure 5854 * @fv_list: field vector with the extraction sequence information 5855 * @rg_list: recipe groupings with protocol-offset pairs 5856 * 5857 * Helper function to fill in the field vector indices for protocol-offset 5858 * pairs. These indexes are then ultimately programmed into a recipe. 5859 */ 5860 static enum ice_status 5861 ice_fill_fv_word_index(struct ice_hw *hw, struct LIST_HEAD_TYPE *fv_list, 5862 struct LIST_HEAD_TYPE *rg_list) 5863 { 5864 struct ice_sw_fv_list_entry *fv; 5865 struct ice_recp_grp_entry *rg; 5866 struct ice_fv_word *fv_ext; 5867 5868 if (LIST_EMPTY(fv_list)) 5869 return ICE_SUCCESS; 5870 5871 fv = LIST_FIRST_ENTRY(fv_list, struct ice_sw_fv_list_entry, list_entry); 5872 fv_ext = fv->fv_ptr->ew; 5873 5874 LIST_FOR_EACH_ENTRY(rg, rg_list, ice_recp_grp_entry, l_entry) { 5875 u8 i; 5876 5877 for (i = 0; i < rg->r_group.n_val_pairs; i++) { 5878 struct ice_fv_word *pr; 5879 bool found = false; 5880 u16 mask; 5881 u8 j; 5882 5883 pr = &rg->r_group.pairs[i]; 5884 mask = rg->r_group.mask[i]; 5885 5886 for (j = 0; j < hw->blk[ICE_BLK_SW].es.fvw; j++) 5887 if (fv_ext[j].prot_id == pr->prot_id && 5888 fv_ext[j].off == pr->off) { 5889 found = true; 5890 5891 /* Store index of field vector */ 5892 rg->fv_idx[i] = j; 5893 rg->fv_mask[i] = mask; 5894 break; 5895 } 5896 5897 /* Protocol/offset could not be found, caller gave an 5898 * invalid pair 5899 */ 5900 if (!found) 5901 return ICE_ERR_PARAM; 5902 } 5903 } 5904 5905 return ICE_SUCCESS; 5906 } 5907 5908 /** 5909 * ice_find_free_recp_res_idx - find free result indexes for recipe 5910 * @hw: pointer to hardware structure 5911 * @profiles: bitmap of profiles that will be associated with the new recipe 5912 * @free_idx: pointer to variable to receive the free index bitmap 5913 * 5914 * The algorithm used here is: 5915 * 1. When creating a new recipe, create a set P which contains all 5916 * Profiles that will be associated with our new recipe 5917 * 5918 * 2. For each Profile p in set P: 5919 * a. Add all recipes associated with Profile p into set R 5920 * b. Optional : PossibleIndexes &= profile[p].possibleIndexes 5921 * [initially PossibleIndexes should be 0xFFFFFFFFFFFFFFFF] 5922 * i. Or just assume they all have the same possible indexes: 5923 * 44, 45, 46, 47 5924 * i.e., PossibleIndexes = 0x0000F00000000000 5925 * 5926 * 3. For each Recipe r in set R: 5927 * a. UsedIndexes |= (bitwise or ) recipe[r].res_indexes 5928 * b. FreeIndexes = UsedIndexes ^ PossibleIndexes 5929 * 5930 * FreeIndexes will contain the bits indicating the indexes free for use, 5931 * then the code needs to update the recipe[r].used_result_idx_bits to 5932 * indicate which indexes were selected for use by this recipe. 5933 */ 5934 static u16 5935 ice_find_free_recp_res_idx(struct ice_hw *hw, const ice_bitmap_t *profiles, 5936 ice_bitmap_t *free_idx) 5937 { 5938 ice_declare_bitmap(possible_idx, ICE_MAX_FV_WORDS); 5939 ice_declare_bitmap(recipes, ICE_MAX_NUM_RECIPES); 5940 ice_declare_bitmap(used_idx, ICE_MAX_FV_WORDS); 5941 u16 count = 0; 5942 u16 bit; 5943 5944 ice_zero_bitmap(possible_idx, ICE_MAX_FV_WORDS); 5945 ice_zero_bitmap(recipes, ICE_MAX_NUM_RECIPES); 5946 ice_zero_bitmap(used_idx, ICE_MAX_FV_WORDS); 5947 ice_zero_bitmap(free_idx, ICE_MAX_FV_WORDS); 5948 5949 for (count = 0; count < ICE_MAX_FV_WORDS; count++) 5950 ice_set_bit(count, possible_idx); 5951 5952 /* For each profile we are going to associate the recipe with, add the 5953 * recipes that are associated with that profile. This will give us 5954 * the set of recipes that our recipe may collide with. Also, determine 5955 * what possible result indexes are usable given this set of profiles. 5956 */ 5957 bit = 0; 5958 while (ICE_MAX_NUM_PROFILES > 5959 (bit = ice_find_next_bit(profiles, ICE_MAX_NUM_PROFILES, bit))) { 5960 ice_or_bitmap(recipes, recipes, profile_to_recipe[bit], 5961 ICE_MAX_NUM_RECIPES); 5962 ice_and_bitmap(possible_idx, possible_idx, 5963 hw->switch_info->prof_res_bm[bit], 5964 ICE_MAX_FV_WORDS); 5965 bit++; 5966 } 5967 5968 /* For each recipe that our new recipe may collide with, determine 5969 * which indexes have been used. 5970 */ 5971 for (bit = 0; bit < ICE_MAX_NUM_RECIPES; bit++) 5972 if (ice_is_bit_set(recipes, bit)) { 5973 ice_or_bitmap(used_idx, used_idx, 5974 hw->switch_info->recp_list[bit].res_idxs, 5975 ICE_MAX_FV_WORDS); 5976 } 5977 5978 ice_xor_bitmap(free_idx, used_idx, possible_idx, ICE_MAX_FV_WORDS); 5979 5980 /* return number of free indexes */ 5981 count = 0; 5982 bit = 0; 5983 while (ICE_MAX_FV_WORDS > 5984 (bit = ice_find_next_bit(free_idx, ICE_MAX_FV_WORDS, bit))) { 5985 count++; 5986 bit++; 5987 } 5988 5989 return count; 5990 } 5991 5992 /** 5993 * ice_add_sw_recipe - function to call AQ calls to create switch recipe 5994 * @hw: pointer to hardware structure 5995 * @rm: recipe management list entry 5996 * @profiles: bitmap of profiles that will be associated. 5997 */ 5998 static enum ice_status 5999 ice_add_sw_recipe(struct ice_hw *hw, struct ice_sw_recipe *rm, 6000 ice_bitmap_t *profiles) 6001 { 6002 ice_declare_bitmap(result_idx_bm, ICE_MAX_FV_WORDS); 6003 struct ice_aqc_recipe_data_elem *tmp; 6004 struct ice_aqc_recipe_data_elem *buf; 6005 struct ice_recp_grp_entry *entry; 6006 enum ice_status status; 6007 u16 free_res_idx; 6008 u16 recipe_count; 6009 u8 chain_idx; 6010 u8 recps = 0; 6011 6012 /* When more than one recipe are required, another recipe is needed to 6013 * chain them together. Matching a tunnel metadata ID takes up one of 6014 * the match fields in the chaining recipe reducing the number of 6015 * chained recipes by one. 6016 */ 6017 /* check number of free result indices */ 6018 ice_zero_bitmap(result_idx_bm, ICE_MAX_FV_WORDS); 6019 free_res_idx = ice_find_free_recp_res_idx(hw, profiles, result_idx_bm); 6020 6021 ice_debug(hw, ICE_DBG_SW, "Result idx slots: %d, need %d\n", 6022 free_res_idx, rm->n_grp_count); 6023 6024 if (rm->n_grp_count > 1) { 6025 if (rm->n_grp_count > free_res_idx) 6026 return ICE_ERR_MAX_LIMIT; 6027 6028 rm->n_grp_count++; 6029 } 6030 6031 if (rm->n_grp_count > ICE_MAX_CHAIN_RECIPE) 6032 return ICE_ERR_MAX_LIMIT; 6033 6034 tmp = (struct ice_aqc_recipe_data_elem *)ice_calloc(hw, 6035 ICE_MAX_NUM_RECIPES, 6036 sizeof(*tmp)); 6037 if (!tmp) 6038 return ICE_ERR_NO_MEMORY; 6039 6040 buf = (struct ice_aqc_recipe_data_elem *) 6041 ice_calloc(hw, rm->n_grp_count, sizeof(*buf)); 6042 if (!buf) { 6043 status = ICE_ERR_NO_MEMORY; 6044 goto err_mem; 6045 } 6046 6047 ice_zero_bitmap(rm->r_bitmap, ICE_MAX_NUM_RECIPES); 6048 recipe_count = ICE_MAX_NUM_RECIPES; 6049 status = ice_aq_get_recipe(hw, tmp, &recipe_count, ICE_SW_LKUP_MAC, 6050 NULL); 6051 if (status || recipe_count == 0) 6052 goto err_unroll; 6053 6054 /* Allocate the recipe resources, and configure them according to the 6055 * match fields from protocol headers and extracted field vectors. 6056 */ 6057 chain_idx = ice_find_first_bit(result_idx_bm, ICE_MAX_FV_WORDS); 6058 LIST_FOR_EACH_ENTRY(entry, &rm->rg_list, ice_recp_grp_entry, l_entry) { 6059 u8 i; 6060 6061 status = ice_alloc_recipe(hw, &entry->rid); 6062 if (status) 6063 goto err_unroll; 6064 6065 /* Clear the result index of the located recipe, as this will be 6066 * updated, if needed, later in the recipe creation process. 6067 */ 6068 tmp[0].content.result_indx = 0; 6069 6070 buf[recps] = tmp[0]; 6071 buf[recps].recipe_indx = (u8)entry->rid; 6072 /* if the recipe is a non-root recipe RID should be programmed 6073 * as 0 for the rules to be applied correctly. 6074 */ 6075 buf[recps].content.rid = 0; 6076 ice_memset(&buf[recps].content.lkup_indx, 0, 6077 sizeof(buf[recps].content.lkup_indx), 6078 ICE_NONDMA_MEM); 6079 6080 /* All recipes use look-up index 0 to match switch ID. */ 6081 buf[recps].content.lkup_indx[0] = ICE_AQ_SW_ID_LKUP_IDX; 6082 buf[recps].content.mask[0] = 6083 CPU_TO_LE16(ICE_AQ_SW_ID_LKUP_MASK); 6084 /* Setup lkup_indx 1..4 to INVALID/ignore and set the mask 6085 * to be 0 6086 */ 6087 for (i = 1; i <= ICE_NUM_WORDS_RECIPE; i++) { 6088 buf[recps].content.lkup_indx[i] = 0x80; 6089 buf[recps].content.mask[i] = 0; 6090 } 6091 6092 for (i = 0; i < entry->r_group.n_val_pairs; i++) { 6093 buf[recps].content.lkup_indx[i + 1] = entry->fv_idx[i]; 6094 buf[recps].content.mask[i + 1] = 6095 CPU_TO_LE16(entry->fv_mask[i]); 6096 } 6097 6098 if (rm->n_grp_count > 1) { 6099 /* Checks to see if there really is a valid result index 6100 * that can be used. 6101 */ 6102 if (chain_idx >= ICE_MAX_FV_WORDS) { 6103 ice_debug(hw, ICE_DBG_SW, 6104 "No chain index available\n"); 6105 status = ICE_ERR_MAX_LIMIT; 6106 goto err_unroll; 6107 } 6108 6109 entry->chain_idx = chain_idx; 6110 buf[recps].content.result_indx = 6111 ICE_AQ_RECIPE_RESULT_EN | 6112 ((chain_idx << ICE_AQ_RECIPE_RESULT_DATA_S) & 6113 ICE_AQ_RECIPE_RESULT_DATA_M); 6114 ice_clear_bit(chain_idx, result_idx_bm); 6115 chain_idx = ice_find_first_bit(result_idx_bm, 6116 ICE_MAX_FV_WORDS); 6117 } 6118 6119 /* fill recipe dependencies */ 6120 ice_zero_bitmap((ice_bitmap_t *)buf[recps].recipe_bitmap, 6121 ICE_MAX_NUM_RECIPES); 6122 ice_set_bit(buf[recps].recipe_indx, 6123 (ice_bitmap_t *)buf[recps].recipe_bitmap); 6124 buf[recps].content.act_ctrl_fwd_priority = rm->priority; 6125 recps++; 6126 } 6127 6128 if (rm->n_grp_count == 1) { 6129 rm->root_rid = buf[0].recipe_indx; 6130 ice_set_bit(buf[0].recipe_indx, rm->r_bitmap); 6131 buf[0].content.rid = rm->root_rid | ICE_AQ_RECIPE_ID_IS_ROOT; 6132 if (sizeof(buf[0].recipe_bitmap) >= sizeof(rm->r_bitmap)) { 6133 ice_memcpy(buf[0].recipe_bitmap, rm->r_bitmap, 6134 sizeof(buf[0].recipe_bitmap), 6135 ICE_NONDMA_TO_NONDMA); 6136 } else { 6137 status = ICE_ERR_BAD_PTR; 6138 goto err_unroll; 6139 } 6140 /* Applicable only for ROOT_RECIPE, set the fwd_priority for 6141 * the recipe which is getting created if specified 6142 * by user. Usually any advanced switch filter, which results 6143 * into new extraction sequence, ended up creating a new recipe 6144 * of type ROOT and usually recipes are associated with profiles 6145 * Switch rule referreing newly created recipe, needs to have 6146 * either/or 'fwd' or 'join' priority, otherwise switch rule 6147 * evaluation will not happen correctly. In other words, if 6148 * switch rule to be evaluated on priority basis, then recipe 6149 * needs to have priority, otherwise it will be evaluated last. 6150 */ 6151 buf[0].content.act_ctrl_fwd_priority = rm->priority; 6152 } else { 6153 struct ice_recp_grp_entry *last_chain_entry; 6154 u16 rid, i; 6155 6156 /* Allocate the last recipe that will chain the outcomes of the 6157 * other recipes together 6158 */ 6159 status = ice_alloc_recipe(hw, &rid); 6160 if (status) 6161 goto err_unroll; 6162 6163 buf[recps].recipe_indx = (u8)rid; 6164 buf[recps].content.rid = (u8)rid; 6165 buf[recps].content.rid |= ICE_AQ_RECIPE_ID_IS_ROOT; 6166 /* the new entry created should also be part of rg_list to 6167 * make sure we have complete recipe 6168 */ 6169 last_chain_entry = (struct ice_recp_grp_entry *)ice_malloc(hw, 6170 sizeof(*last_chain_entry)); 6171 if (!last_chain_entry) { 6172 status = ICE_ERR_NO_MEMORY; 6173 goto err_unroll; 6174 } 6175 last_chain_entry->rid = rid; 6176 ice_memset(&buf[recps].content.lkup_indx, 0, 6177 sizeof(buf[recps].content.lkup_indx), 6178 ICE_NONDMA_MEM); 6179 /* All recipes use look-up index 0 to match switch ID. */ 6180 buf[recps].content.lkup_indx[0] = ICE_AQ_SW_ID_LKUP_IDX; 6181 buf[recps].content.mask[0] = 6182 CPU_TO_LE16(ICE_AQ_SW_ID_LKUP_MASK); 6183 for (i = 1; i <= ICE_NUM_WORDS_RECIPE; i++) { 6184 buf[recps].content.lkup_indx[i] = 6185 ICE_AQ_RECIPE_LKUP_IGNORE; 6186 buf[recps].content.mask[i] = 0; 6187 } 6188 6189 i = 1; 6190 /* update r_bitmap with the recp that is used for chaining */ 6191 ice_set_bit(rid, rm->r_bitmap); 6192 /* this is the recipe that chains all the other recipes so it 6193 * should not have a chaining ID to indicate the same 6194 */ 6195 last_chain_entry->chain_idx = ICE_INVAL_CHAIN_IND; 6196 LIST_FOR_EACH_ENTRY(entry, &rm->rg_list, ice_recp_grp_entry, 6197 l_entry) { 6198 last_chain_entry->fv_idx[i] = entry->chain_idx; 6199 buf[recps].content.lkup_indx[i] = entry->chain_idx; 6200 buf[recps].content.mask[i++] = CPU_TO_LE16(0xFFFF); 6201 ice_set_bit(entry->rid, rm->r_bitmap); 6202 } 6203 LIST_ADD(&last_chain_entry->l_entry, &rm->rg_list); 6204 if (sizeof(buf[recps].recipe_bitmap) >= 6205 sizeof(rm->r_bitmap)) { 6206 ice_memcpy(buf[recps].recipe_bitmap, rm->r_bitmap, 6207 sizeof(buf[recps].recipe_bitmap), 6208 ICE_NONDMA_TO_NONDMA); 6209 } else { 6210 status = ICE_ERR_BAD_PTR; 6211 goto err_unroll; 6212 } 6213 buf[recps].content.act_ctrl_fwd_priority = rm->priority; 6214 6215 recps++; 6216 rm->root_rid = (u8)rid; 6217 } 6218 status = ice_acquire_change_lock(hw, ICE_RES_WRITE); 6219 if (status) 6220 goto err_unroll; 6221 6222 status = ice_aq_add_recipe(hw, buf, rm->n_grp_count, NULL); 6223 ice_release_change_lock(hw); 6224 if (status) 6225 goto err_unroll; 6226 6227 /* Every recipe that just got created add it to the recipe 6228 * book keeping list 6229 */ 6230 LIST_FOR_EACH_ENTRY(entry, &rm->rg_list, ice_recp_grp_entry, l_entry) { 6231 struct ice_switch_info *sw = hw->switch_info; 6232 bool is_root, idx_found = false; 6233 struct ice_sw_recipe *recp; 6234 u16 idx, buf_idx = 0; 6235 6236 /* find buffer index for copying some data */ 6237 for (idx = 0; idx < rm->n_grp_count; idx++) 6238 if (buf[idx].recipe_indx == entry->rid) { 6239 buf_idx = idx; 6240 idx_found = true; 6241 } 6242 6243 if (!idx_found) { 6244 status = ICE_ERR_OUT_OF_RANGE; 6245 goto err_unroll; 6246 } 6247 6248 recp = &sw->recp_list[entry->rid]; 6249 is_root = (rm->root_rid == entry->rid); 6250 recp->is_root = is_root; 6251 6252 recp->root_rid = entry->rid; 6253 recp->big_recp = (is_root && rm->n_grp_count > 1); 6254 6255 ice_memcpy(&recp->ext_words, entry->r_group.pairs, 6256 entry->r_group.n_val_pairs * 6257 sizeof(struct ice_fv_word), 6258 ICE_NONDMA_TO_NONDMA); 6259 6260 ice_memcpy(recp->r_bitmap, buf[buf_idx].recipe_bitmap, 6261 sizeof(recp->r_bitmap), ICE_NONDMA_TO_NONDMA); 6262 6263 /* Copy non-result fv index values and masks to recipe. This 6264 * call will also update the result recipe bitmask. 6265 */ 6266 ice_collect_result_idx(&buf[buf_idx], recp); 6267 6268 /* for non-root recipes, also copy to the root, this allows 6269 * easier matching of a complete chained recipe 6270 */ 6271 if (!is_root) 6272 ice_collect_result_idx(&buf[buf_idx], 6273 &sw->recp_list[rm->root_rid]); 6274 6275 recp->n_ext_words = entry->r_group.n_val_pairs; 6276 recp->chain_idx = entry->chain_idx; 6277 recp->priority = buf[buf_idx].content.act_ctrl_fwd_priority; 6278 recp->n_grp_count = rm->n_grp_count; 6279 recp->tun_type = rm->tun_type; 6280 recp->recp_created = true; 6281 } 6282 rm->root_buf = buf; 6283 ice_free(hw, tmp); 6284 return status; 6285 6286 err_unroll: 6287 err_mem: 6288 ice_free(hw, tmp); 6289 ice_free(hw, buf); 6290 return status; 6291 } 6292 6293 /** 6294 * ice_create_recipe_group - creates recipe group 6295 * @hw: pointer to hardware structure 6296 * @rm: recipe management list entry 6297 * @lkup_exts: lookup elements 6298 */ 6299 static enum ice_status 6300 ice_create_recipe_group(struct ice_hw *hw, struct ice_sw_recipe *rm, 6301 struct ice_prot_lkup_ext *lkup_exts) 6302 { 6303 enum ice_status status; 6304 u8 recp_count = 0; 6305 6306 rm->n_grp_count = 0; 6307 6308 /* Create recipes for words that are marked not done by packing them 6309 * as best fit. 6310 */ 6311 status = ice_create_first_fit_recp_def(hw, lkup_exts, 6312 &rm->rg_list, &recp_count); 6313 if (!status) { 6314 rm->n_grp_count += recp_count; 6315 rm->n_ext_words = lkup_exts->n_val_words; 6316 ice_memcpy(&rm->ext_words, lkup_exts->fv_words, 6317 sizeof(rm->ext_words), ICE_NONDMA_TO_NONDMA); 6318 ice_memcpy(rm->word_masks, lkup_exts->field_mask, 6319 sizeof(rm->word_masks), ICE_NONDMA_TO_NONDMA); 6320 } 6321 6322 return status; 6323 } 6324 6325 /** 6326 * ice_get_fv - get field vectors/extraction sequences for spec. lookup types 6327 * @hw: pointer to hardware structure 6328 * @lkups: lookup elements or match criteria for the advanced recipe, one 6329 * structure per protocol header 6330 * @lkups_cnt: number of protocols 6331 * @bm: bitmap of field vectors to consider 6332 * @fv_list: pointer to a list that holds the returned field vectors 6333 */ 6334 static enum ice_status 6335 ice_get_fv(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, u16 lkups_cnt, 6336 ice_bitmap_t *bm, struct LIST_HEAD_TYPE *fv_list) 6337 { 6338 enum ice_status status; 6339 u8 *prot_ids; 6340 u16 i; 6341 6342 if (!lkups_cnt) 6343 return ICE_SUCCESS; 6344 6345 prot_ids = (u8 *)ice_calloc(hw, lkups_cnt, sizeof(*prot_ids)); 6346 if (!prot_ids) 6347 return ICE_ERR_NO_MEMORY; 6348 6349 for (i = 0; i < lkups_cnt; i++) 6350 if (!ice_prot_type_to_id(lkups[i].type, &prot_ids[i])) { 6351 status = ICE_ERR_CFG; 6352 goto free_mem; 6353 } 6354 6355 /* Find field vectors that include all specified protocol types */ 6356 status = ice_get_sw_fv_list(hw, prot_ids, lkups_cnt, bm, fv_list); 6357 6358 free_mem: 6359 ice_free(hw, prot_ids); 6360 return status; 6361 } 6362 6363 /** 6364 * ice_tun_type_match_mask - determine if tun type needs a match mask 6365 * @tun_type: tunnel type 6366 * @mask: mask to be used for the tunnel 6367 */ 6368 static bool ice_tun_type_match_word(enum ice_sw_tunnel_type tun_type, u16 *mask) 6369 { 6370 switch (tun_type) { 6371 case ICE_SW_TUN_VXLAN_GPE: 6372 case ICE_SW_TUN_GENEVE: 6373 case ICE_SW_TUN_VXLAN: 6374 case ICE_SW_TUN_NVGRE: 6375 case ICE_SW_TUN_UDP: 6376 case ICE_ALL_TUNNELS: 6377 *mask = ICE_TUN_FLAG_MASK; 6378 return true; 6379 6380 case ICE_SW_TUN_GENEVE_VLAN: 6381 case ICE_SW_TUN_VXLAN_VLAN: 6382 *mask = ICE_TUN_FLAG_MASK & ~ICE_TUN_FLAG_VLAN_MASK; 6383 return true; 6384 6385 default: 6386 *mask = 0; 6387 return false; 6388 } 6389 } 6390 6391 /** 6392 * ice_add_special_words - Add words that are not protocols, such as metadata 6393 * @rinfo: other information regarding the rule e.g. priority and action info 6394 * @lkup_exts: lookup word structure 6395 */ 6396 static enum ice_status 6397 ice_add_special_words(struct ice_adv_rule_info *rinfo, 6398 struct ice_prot_lkup_ext *lkup_exts) 6399 { 6400 u16 mask; 6401 6402 /* If this is a tunneled packet, then add recipe index to match the 6403 * tunnel bit in the packet metadata flags. 6404 */ 6405 if (ice_tun_type_match_word(rinfo->tun_type, &mask)) { 6406 if (lkup_exts->n_val_words < ICE_MAX_CHAIN_WORDS) { 6407 u8 word = lkup_exts->n_val_words++; 6408 6409 lkup_exts->fv_words[word].prot_id = ICE_META_DATA_ID_HW; 6410 lkup_exts->fv_words[word].off = ICE_TUN_FLAG_MDID_OFF; 6411 lkup_exts->field_mask[word] = mask; 6412 } else { 6413 return ICE_ERR_MAX_LIMIT; 6414 } 6415 } 6416 6417 return ICE_SUCCESS; 6418 } 6419 6420 /* ice_get_compat_fv_bitmap - Get compatible field vector bitmap for rule 6421 * @hw: pointer to hardware structure 6422 * @rinfo: other information regarding the rule e.g. priority and action info 6423 * @bm: pointer to memory for returning the bitmap of field vectors 6424 */ 6425 static void 6426 ice_get_compat_fv_bitmap(struct ice_hw *hw, struct ice_adv_rule_info *rinfo, 6427 ice_bitmap_t *bm) 6428 { 6429 enum ice_prof_type prof_type; 6430 6431 ice_zero_bitmap(bm, ICE_MAX_NUM_PROFILES); 6432 6433 switch (rinfo->tun_type) { 6434 case ICE_NON_TUN: 6435 prof_type = ICE_PROF_NON_TUN; 6436 break; 6437 case ICE_ALL_TUNNELS: 6438 prof_type = ICE_PROF_TUN_ALL; 6439 break; 6440 case ICE_SW_TUN_VXLAN_GPE: 6441 case ICE_SW_TUN_GENEVE: 6442 case ICE_SW_TUN_GENEVE_VLAN: 6443 case ICE_SW_TUN_VXLAN: 6444 case ICE_SW_TUN_VXLAN_VLAN: 6445 case ICE_SW_TUN_UDP: 6446 case ICE_SW_TUN_GTP: 6447 prof_type = ICE_PROF_TUN_UDP; 6448 break; 6449 case ICE_SW_TUN_NVGRE: 6450 prof_type = ICE_PROF_TUN_GRE; 6451 break; 6452 case ICE_SW_TUN_PPPOE: 6453 prof_type = ICE_PROF_TUN_PPPOE; 6454 break; 6455 case ICE_SW_TUN_PPPOE_PAY: 6456 ice_set_bit(ICE_PROFID_PPPOE_PAY, bm); 6457 return; 6458 case ICE_SW_TUN_PPPOE_IPV4: 6459 ice_set_bit(ICE_PROFID_PPPOE_IPV4_OTHER, bm); 6460 ice_set_bit(ICE_PROFID_PPPOE_IPV4_UDP, bm); 6461 ice_set_bit(ICE_PROFID_PPPOE_IPV4_TCP, bm); 6462 return; 6463 case ICE_SW_TUN_PPPOE_IPV4_TCP: 6464 ice_set_bit(ICE_PROFID_PPPOE_IPV4_TCP, bm); 6465 return; 6466 case ICE_SW_TUN_PPPOE_IPV4_UDP: 6467 ice_set_bit(ICE_PROFID_PPPOE_IPV4_UDP, bm); 6468 return; 6469 case ICE_SW_TUN_PPPOE_IPV6: 6470 ice_set_bit(ICE_PROFID_PPPOE_IPV6_OTHER, bm); 6471 ice_set_bit(ICE_PROFID_PPPOE_IPV6_UDP, bm); 6472 ice_set_bit(ICE_PROFID_PPPOE_IPV6_TCP, bm); 6473 return; 6474 case ICE_SW_TUN_PPPOE_IPV6_TCP: 6475 ice_set_bit(ICE_PROFID_PPPOE_IPV6_TCP, bm); 6476 return; 6477 case ICE_SW_TUN_PPPOE_IPV6_UDP: 6478 ice_set_bit(ICE_PROFID_PPPOE_IPV6_UDP, bm); 6479 return; 6480 case ICE_SW_TUN_PROFID_IPV6_ESP: 6481 case ICE_SW_TUN_IPV6_ESP: 6482 ice_set_bit(ICE_PROFID_IPV6_ESP, bm); 6483 return; 6484 case ICE_SW_TUN_PROFID_IPV6_AH: 6485 case ICE_SW_TUN_IPV6_AH: 6486 ice_set_bit(ICE_PROFID_IPV6_AH, bm); 6487 return; 6488 case ICE_SW_TUN_PROFID_MAC_IPV6_L2TPV3: 6489 case ICE_SW_TUN_IPV6_L2TPV3: 6490 ice_set_bit(ICE_PROFID_MAC_IPV6_L2TPV3, bm); 6491 return; 6492 case ICE_SW_TUN_PROFID_IPV6_NAT_T: 6493 case ICE_SW_TUN_IPV6_NAT_T: 6494 ice_set_bit(ICE_PROFID_IPV6_NAT_T, bm); 6495 return; 6496 case ICE_SW_TUN_PROFID_IPV4_PFCP_NODE: 6497 ice_set_bit(ICE_PROFID_IPV4_PFCP_NODE, bm); 6498 return; 6499 case ICE_SW_TUN_PROFID_IPV4_PFCP_SESSION: 6500 ice_set_bit(ICE_PROFID_IPV4_PFCP_SESSION, bm); 6501 return; 6502 case ICE_SW_TUN_PROFID_IPV6_PFCP_NODE: 6503 ice_set_bit(ICE_PROFID_IPV6_PFCP_NODE, bm); 6504 return; 6505 case ICE_SW_TUN_PROFID_IPV6_PFCP_SESSION: 6506 ice_set_bit(ICE_PROFID_IPV6_PFCP_SESSION, bm); 6507 return; 6508 case ICE_SW_TUN_IPV4_NAT_T: 6509 ice_set_bit(ICE_PROFID_IPV4_NAT_T, bm); 6510 return; 6511 case ICE_SW_TUN_IPV4_L2TPV3: 6512 ice_set_bit(ICE_PROFID_MAC_IPV4_L2TPV3, bm); 6513 return; 6514 case ICE_SW_TUN_IPV4_ESP: 6515 ice_set_bit(ICE_PROFID_IPV4_ESP, bm); 6516 return; 6517 case ICE_SW_TUN_IPV4_AH: 6518 ice_set_bit(ICE_PROFID_IPV4_AH, bm); 6519 return; 6520 case ICE_SW_IPV4_TCP: 6521 ice_set_bit(ICE_PROFID_IPV4_TCP, bm); 6522 return; 6523 case ICE_SW_IPV4_UDP: 6524 ice_set_bit(ICE_PROFID_IPV4_UDP, bm); 6525 return; 6526 case ICE_SW_IPV6_TCP: 6527 ice_set_bit(ICE_PROFID_IPV6_TCP, bm); 6528 return; 6529 case ICE_SW_IPV6_UDP: 6530 ice_set_bit(ICE_PROFID_IPV6_UDP, bm); 6531 return; 6532 case ICE_SW_TUN_AND_NON_TUN: 6533 default: 6534 prof_type = ICE_PROF_ALL; 6535 break; 6536 } 6537 6538 ice_get_sw_fv_bitmap(hw, prof_type, bm); 6539 } 6540 6541 /** 6542 * ice_is_prof_rule - determine if rule type is a profile rule 6543 * @type: the rule type 6544 * 6545 * if the rule type is a profile rule, that means that there no field value 6546 * match required, in this case just a profile hit is required. 6547 */ 6548 bool ice_is_prof_rule(enum ice_sw_tunnel_type type) 6549 { 6550 switch (type) { 6551 case ICE_SW_TUN_PROFID_IPV6_ESP: 6552 case ICE_SW_TUN_PROFID_IPV6_AH: 6553 case ICE_SW_TUN_PROFID_MAC_IPV6_L2TPV3: 6554 case ICE_SW_TUN_PROFID_IPV6_NAT_T: 6555 case ICE_SW_TUN_PROFID_IPV4_PFCP_NODE: 6556 case ICE_SW_TUN_PROFID_IPV4_PFCP_SESSION: 6557 case ICE_SW_TUN_PROFID_IPV6_PFCP_NODE: 6558 case ICE_SW_TUN_PROFID_IPV6_PFCP_SESSION: 6559 return true; 6560 default: 6561 break; 6562 } 6563 6564 return false; 6565 } 6566 6567 /** 6568 * ice_add_adv_recipe - Add an advanced recipe that is not part of the default 6569 * @hw: pointer to hardware structure 6570 * @lkups: lookup elements or match criteria for the advanced recipe, one 6571 * structure per protocol header 6572 * @lkups_cnt: number of protocols 6573 * @rinfo: other information regarding the rule e.g. priority and action info 6574 * @rid: return the recipe ID of the recipe created 6575 */ 6576 static enum ice_status 6577 ice_add_adv_recipe(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, 6578 u16 lkups_cnt, struct ice_adv_rule_info *rinfo, u16 *rid) 6579 { 6580 ice_declare_bitmap(fv_bitmap, ICE_MAX_NUM_PROFILES); 6581 ice_declare_bitmap(profiles, ICE_MAX_NUM_PROFILES); 6582 struct ice_prot_lkup_ext *lkup_exts; 6583 struct ice_recp_grp_entry *r_entry; 6584 struct ice_sw_fv_list_entry *fvit; 6585 struct ice_recp_grp_entry *r_tmp; 6586 struct ice_sw_fv_list_entry *tmp; 6587 enum ice_status status = ICE_SUCCESS; 6588 struct ice_sw_recipe *rm; 6589 u8 i; 6590 6591 if (!ice_is_prof_rule(rinfo->tun_type) && !lkups_cnt) 6592 return ICE_ERR_PARAM; 6593 6594 lkup_exts = (struct ice_prot_lkup_ext *) 6595 ice_malloc(hw, sizeof(*lkup_exts)); 6596 if (!lkup_exts) 6597 return ICE_ERR_NO_MEMORY; 6598 6599 /* Determine the number of words to be matched and if it exceeds a 6600 * recipe's restrictions 6601 */ 6602 for (i = 0; i < lkups_cnt; i++) { 6603 u16 count; 6604 6605 if (lkups[i].type >= ICE_PROTOCOL_LAST) { 6606 status = ICE_ERR_CFG; 6607 goto err_free_lkup_exts; 6608 } 6609 6610 count = ice_fill_valid_words(&lkups[i], lkup_exts); 6611 if (!count) { 6612 status = ICE_ERR_CFG; 6613 goto err_free_lkup_exts; 6614 } 6615 } 6616 6617 rm = (struct ice_sw_recipe *)ice_malloc(hw, sizeof(*rm)); 6618 if (!rm) { 6619 status = ICE_ERR_NO_MEMORY; 6620 goto err_free_lkup_exts; 6621 } 6622 6623 /* Get field vectors that contain fields extracted from all the protocol 6624 * headers being programmed. 6625 */ 6626 INIT_LIST_HEAD(&rm->fv_list); 6627 INIT_LIST_HEAD(&rm->rg_list); 6628 6629 /* Get bitmap of field vectors (profiles) that are compatible with the 6630 * rule request; only these will be searched in the subsequent call to 6631 * ice_get_fv. 6632 */ 6633 ice_get_compat_fv_bitmap(hw, rinfo, fv_bitmap); 6634 6635 status = ice_get_fv(hw, lkups, lkups_cnt, fv_bitmap, &rm->fv_list); 6636 if (status) 6637 goto err_unroll; 6638 6639 /* Create any special protocol/offset pairs, such as looking at tunnel 6640 * bits by extracting metadata 6641 */ 6642 status = ice_add_special_words(rinfo, lkup_exts); 6643 if (status) 6644 goto err_free_lkup_exts; 6645 6646 /* Group match words into recipes using preferred recipe grouping 6647 * criteria. 6648 */ 6649 status = ice_create_recipe_group(hw, rm, lkup_exts); 6650 if (status) 6651 goto err_unroll; 6652 6653 /* set the recipe priority if specified */ 6654 rm->priority = (u8)rinfo->priority; 6655 6656 /* Find offsets from the field vector. Pick the first one for all the 6657 * recipes. 6658 */ 6659 status = ice_fill_fv_word_index(hw, &rm->fv_list, &rm->rg_list); 6660 if (status) 6661 goto err_unroll; 6662 6663 /* An empty FV list means to use all the profiles returned in the 6664 * profile bitmap 6665 */ 6666 if (LIST_EMPTY(&rm->fv_list)) { 6667 u16 j; 6668 6669 for (j = 0; j < ICE_MAX_NUM_PROFILES; j++) 6670 if (ice_is_bit_set(fv_bitmap, j)) { 6671 struct ice_sw_fv_list_entry *fvl; 6672 6673 fvl = (struct ice_sw_fv_list_entry *) 6674 ice_malloc(hw, sizeof(*fvl)); 6675 if (!fvl) 6676 goto err_unroll; 6677 fvl->fv_ptr = NULL; 6678 fvl->profile_id = j; 6679 LIST_ADD(&fvl->list_entry, &rm->fv_list); 6680 } 6681 } 6682 6683 /* get bitmap of all profiles the recipe will be associated with */ 6684 ice_zero_bitmap(profiles, ICE_MAX_NUM_PROFILES); 6685 LIST_FOR_EACH_ENTRY(fvit, &rm->fv_list, ice_sw_fv_list_entry, 6686 list_entry) { 6687 ice_debug(hw, ICE_DBG_SW, "profile: %d\n", fvit->profile_id); 6688 ice_set_bit((u16)fvit->profile_id, profiles); 6689 } 6690 6691 /* Look for a recipe which matches our requested fv / mask list */ 6692 *rid = ice_find_recp(hw, lkup_exts, rinfo->tun_type); 6693 if (*rid < ICE_MAX_NUM_RECIPES) 6694 /* Success if found a recipe that match the existing criteria */ 6695 goto err_unroll; 6696 6697 rm->tun_type = rinfo->tun_type; 6698 /* Recipe we need does not exist, add a recipe */ 6699 status = ice_add_sw_recipe(hw, rm, profiles); 6700 if (status) 6701 goto err_unroll; 6702 6703 /* Associate all the recipes created with all the profiles in the 6704 * common field vector. 6705 */ 6706 LIST_FOR_EACH_ENTRY(fvit, &rm->fv_list, ice_sw_fv_list_entry, 6707 list_entry) { 6708 ice_declare_bitmap(r_bitmap, ICE_MAX_NUM_RECIPES); 6709 u16 j; 6710 6711 status = ice_aq_get_recipe_to_profile(hw, fvit->profile_id, 6712 (u8 *)r_bitmap, NULL); 6713 if (status) 6714 goto err_unroll; 6715 6716 ice_or_bitmap(r_bitmap, r_bitmap, rm->r_bitmap, 6717 ICE_MAX_NUM_RECIPES); 6718 status = ice_acquire_change_lock(hw, ICE_RES_WRITE); 6719 if (status) 6720 goto err_unroll; 6721 6722 status = ice_aq_map_recipe_to_profile(hw, fvit->profile_id, 6723 (u8 *)r_bitmap, 6724 NULL); 6725 ice_release_change_lock(hw); 6726 6727 if (status) 6728 goto err_unroll; 6729 6730 /* Update profile to recipe bitmap array */ 6731 ice_cp_bitmap(profile_to_recipe[fvit->profile_id], r_bitmap, 6732 ICE_MAX_NUM_RECIPES); 6733 6734 /* Update recipe to profile bitmap array */ 6735 for (j = 0; j < ICE_MAX_NUM_RECIPES; j++) 6736 if (ice_is_bit_set(r_bitmap, j)) 6737 ice_set_bit((u16)fvit->profile_id, 6738 recipe_to_profile[j]); 6739 } 6740 6741 *rid = rm->root_rid; 6742 ice_memcpy(&hw->switch_info->recp_list[*rid].lkup_exts, 6743 lkup_exts, sizeof(*lkup_exts), ICE_NONDMA_TO_NONDMA); 6744 err_unroll: 6745 LIST_FOR_EACH_ENTRY_SAFE(r_entry, r_tmp, &rm->rg_list, 6746 ice_recp_grp_entry, l_entry) { 6747 LIST_DEL(&r_entry->l_entry); 6748 ice_free(hw, r_entry); 6749 } 6750 6751 LIST_FOR_EACH_ENTRY_SAFE(fvit, tmp, &rm->fv_list, ice_sw_fv_list_entry, 6752 list_entry) { 6753 LIST_DEL(&fvit->list_entry); 6754 ice_free(hw, fvit); 6755 } 6756 6757 if (rm->root_buf) 6758 ice_free(hw, rm->root_buf); 6759 6760 ice_free(hw, rm); 6761 6762 err_free_lkup_exts: 6763 ice_free(hw, lkup_exts); 6764 6765 return status; 6766 } 6767 6768 /** 6769 * ice_find_dummy_packet - find dummy packet by tunnel type 6770 * 6771 * @lkups: lookup elements or match criteria for the advanced recipe, one 6772 * structure per protocol header 6773 * @lkups_cnt: number of protocols 6774 * @tun_type: tunnel type from the match criteria 6775 * @pkt: dummy packet to fill according to filter match criteria 6776 * @pkt_len: packet length of dummy packet 6777 * @offsets: pointer to receive the pointer to the offsets for the packet 6778 */ 6779 static void 6780 ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt, 6781 enum ice_sw_tunnel_type tun_type, const u8 **pkt, 6782 u16 *pkt_len, 6783 const struct ice_dummy_pkt_offsets **offsets) 6784 { 6785 bool tcp = false, udp = false, ipv6 = false, vlan = false; 6786 bool gre = false; 6787 u16 i; 6788 6789 for (i = 0; i < lkups_cnt; i++) { 6790 if (lkups[i].type == ICE_UDP_ILOS) 6791 udp = true; 6792 else if (lkups[i].type == ICE_TCP_IL) 6793 tcp = true; 6794 else if (lkups[i].type == ICE_IPV6_OFOS) 6795 ipv6 = true; 6796 else if (lkups[i].type == ICE_VLAN_OFOS) 6797 vlan = true; 6798 else if (lkups[i].type == ICE_IPV4_OFOS && 6799 lkups[i].h_u.ipv4_hdr.protocol == 6800 ICE_IPV4_NVGRE_PROTO_ID && 6801 lkups[i].m_u.ipv4_hdr.protocol == 6802 0xFF) 6803 gre = true; 6804 else if (lkups[i].type == ICE_PPPOE && 6805 lkups[i].h_u.pppoe_hdr.ppp_prot_id == 6806 CPU_TO_BE16(ICE_PPP_IPV6_PROTO_ID) && 6807 lkups[i].m_u.pppoe_hdr.ppp_prot_id == 6808 0xFFFF) 6809 ipv6 = true; 6810 else if (lkups[i].type == ICE_ETYPE_OL && 6811 lkups[i].h_u.ethertype.ethtype_id == 6812 CPU_TO_BE16(ICE_IPV6_ETHER_ID) && 6813 lkups[i].m_u.ethertype.ethtype_id == 6814 0xFFFF) 6815 ipv6 = true; 6816 else if (lkups[i].type == ICE_IPV4_IL && 6817 lkups[i].h_u.ipv4_hdr.protocol == 6818 ICE_TCP_PROTO_ID && 6819 lkups[i].m_u.ipv4_hdr.protocol == 6820 0xFF) 6821 tcp = true; 6822 } 6823 6824 if (tun_type == ICE_SW_TUN_IPV4_ESP) { 6825 *pkt = dummy_ipv4_esp_pkt; 6826 *pkt_len = sizeof(dummy_ipv4_esp_pkt); 6827 *offsets = dummy_ipv4_esp_packet_offsets; 6828 return; 6829 } 6830 6831 if (tun_type == ICE_SW_TUN_IPV6_ESP) { 6832 *pkt = dummy_ipv6_esp_pkt; 6833 *pkt_len = sizeof(dummy_ipv6_esp_pkt); 6834 *offsets = dummy_ipv6_esp_packet_offsets; 6835 return; 6836 } 6837 6838 if (tun_type == ICE_SW_TUN_IPV4_AH) { 6839 *pkt = dummy_ipv4_ah_pkt; 6840 *pkt_len = sizeof(dummy_ipv4_ah_pkt); 6841 *offsets = dummy_ipv4_ah_packet_offsets; 6842 return; 6843 } 6844 6845 if (tun_type == ICE_SW_TUN_IPV6_AH) { 6846 *pkt = dummy_ipv6_ah_pkt; 6847 *pkt_len = sizeof(dummy_ipv6_ah_pkt); 6848 *offsets = dummy_ipv6_ah_packet_offsets; 6849 return; 6850 } 6851 6852 if (tun_type == ICE_SW_TUN_IPV4_NAT_T) { 6853 *pkt = dummy_ipv4_nat_pkt; 6854 *pkt_len = sizeof(dummy_ipv4_nat_pkt); 6855 *offsets = dummy_ipv4_nat_packet_offsets; 6856 return; 6857 } 6858 6859 if (tun_type == ICE_SW_TUN_IPV6_NAT_T) { 6860 *pkt = dummy_ipv6_nat_pkt; 6861 *pkt_len = sizeof(dummy_ipv6_nat_pkt); 6862 *offsets = dummy_ipv6_nat_packet_offsets; 6863 return; 6864 } 6865 6866 if (tun_type == ICE_SW_TUN_IPV4_L2TPV3) { 6867 *pkt = dummy_ipv4_l2tpv3_pkt; 6868 *pkt_len = sizeof(dummy_ipv4_l2tpv3_pkt); 6869 *offsets = dummy_ipv4_l2tpv3_packet_offsets; 6870 return; 6871 } 6872 6873 if (tun_type == ICE_SW_TUN_IPV6_L2TPV3) { 6874 *pkt = dummy_ipv6_l2tpv3_pkt; 6875 *pkt_len = sizeof(dummy_ipv6_l2tpv3_pkt); 6876 *offsets = dummy_ipv6_l2tpv3_packet_offsets; 6877 return; 6878 } 6879 6880 if (tun_type == ICE_SW_TUN_GTP) { 6881 *pkt = dummy_udp_gtp_packet; 6882 *pkt_len = sizeof(dummy_udp_gtp_packet); 6883 *offsets = dummy_udp_gtp_packet_offsets; 6884 return; 6885 } 6886 6887 if (tun_type == ICE_SW_TUN_PPPOE && ipv6) { 6888 *pkt = dummy_pppoe_ipv6_packet; 6889 *pkt_len = sizeof(dummy_pppoe_ipv6_packet); 6890 *offsets = dummy_pppoe_packet_offsets; 6891 return; 6892 } else if (tun_type == ICE_SW_TUN_PPPOE || 6893 tun_type == ICE_SW_TUN_PPPOE_PAY) { 6894 *pkt = dummy_pppoe_ipv4_packet; 6895 *pkt_len = sizeof(dummy_pppoe_ipv4_packet); 6896 *offsets = dummy_pppoe_packet_offsets; 6897 return; 6898 } 6899 6900 if (tun_type == ICE_SW_TUN_PPPOE_IPV4) { 6901 *pkt = dummy_pppoe_ipv4_packet; 6902 *pkt_len = sizeof(dummy_pppoe_ipv4_packet); 6903 *offsets = dummy_pppoe_packet_ipv4_offsets; 6904 return; 6905 } 6906 6907 if (tun_type == ICE_SW_TUN_PPPOE_IPV4_TCP) { 6908 *pkt = dummy_pppoe_ipv4_tcp_packet; 6909 *pkt_len = sizeof(dummy_pppoe_ipv4_tcp_packet); 6910 *offsets = dummy_pppoe_ipv4_tcp_packet_offsets; 6911 return; 6912 } 6913 6914 if (tun_type == ICE_SW_TUN_PPPOE_IPV4_UDP) { 6915 *pkt = dummy_pppoe_ipv4_udp_packet; 6916 *pkt_len = sizeof(dummy_pppoe_ipv4_udp_packet); 6917 *offsets = dummy_pppoe_ipv4_udp_packet_offsets; 6918 return; 6919 } 6920 6921 if (tun_type == ICE_SW_TUN_PPPOE_IPV6) { 6922 *pkt = dummy_pppoe_ipv6_packet; 6923 *pkt_len = sizeof(dummy_pppoe_ipv6_packet); 6924 *offsets = dummy_pppoe_packet_ipv6_offsets; 6925 return; 6926 } 6927 6928 if (tun_type == ICE_SW_TUN_PPPOE_IPV6_TCP) { 6929 *pkt = dummy_pppoe_ipv6_tcp_packet; 6930 *pkt_len = sizeof(dummy_pppoe_ipv6_tcp_packet); 6931 *offsets = dummy_pppoe_packet_ipv6_tcp_offsets; 6932 return; 6933 } 6934 6935 if (tun_type == ICE_SW_TUN_PPPOE_IPV6_UDP) { 6936 *pkt = dummy_pppoe_ipv6_udp_packet; 6937 *pkt_len = sizeof(dummy_pppoe_ipv6_udp_packet); 6938 *offsets = dummy_pppoe_packet_ipv6_udp_offsets; 6939 return; 6940 } 6941 6942 if (tun_type == ICE_SW_IPV4_TCP) { 6943 *pkt = dummy_tcp_packet; 6944 *pkt_len = sizeof(dummy_tcp_packet); 6945 *offsets = dummy_tcp_packet_offsets; 6946 return; 6947 } 6948 6949 if (tun_type == ICE_SW_IPV4_UDP) { 6950 *pkt = dummy_udp_packet; 6951 *pkt_len = sizeof(dummy_udp_packet); 6952 *offsets = dummy_udp_packet_offsets; 6953 return; 6954 } 6955 6956 if (tun_type == ICE_SW_IPV6_TCP) { 6957 *pkt = dummy_tcp_ipv6_packet; 6958 *pkt_len = sizeof(dummy_tcp_ipv6_packet); 6959 *offsets = dummy_tcp_ipv6_packet_offsets; 6960 return; 6961 } 6962 6963 if (tun_type == ICE_SW_IPV6_UDP) { 6964 *pkt = dummy_udp_ipv6_packet; 6965 *pkt_len = sizeof(dummy_udp_ipv6_packet); 6966 *offsets = dummy_udp_ipv6_packet_offsets; 6967 return; 6968 } 6969 6970 if (tun_type == ICE_ALL_TUNNELS) { 6971 *pkt = dummy_gre_udp_packet; 6972 *pkt_len = sizeof(dummy_gre_udp_packet); 6973 *offsets = dummy_gre_udp_packet_offsets; 6974 return; 6975 } 6976 6977 if (tun_type == ICE_SW_TUN_NVGRE || gre) { 6978 if (tcp) { 6979 *pkt = dummy_gre_tcp_packet; 6980 *pkt_len = sizeof(dummy_gre_tcp_packet); 6981 *offsets = dummy_gre_tcp_packet_offsets; 6982 return; 6983 } 6984 6985 *pkt = dummy_gre_udp_packet; 6986 *pkt_len = sizeof(dummy_gre_udp_packet); 6987 *offsets = dummy_gre_udp_packet_offsets; 6988 return; 6989 } 6990 6991 if (tun_type == ICE_SW_TUN_VXLAN || tun_type == ICE_SW_TUN_GENEVE || 6992 tun_type == ICE_SW_TUN_VXLAN_GPE || tun_type == ICE_SW_TUN_UDP || 6993 tun_type == ICE_SW_TUN_GENEVE_VLAN || 6994 tun_type == ICE_SW_TUN_VXLAN_VLAN) { 6995 if (tcp) { 6996 *pkt = dummy_udp_tun_tcp_packet; 6997 *pkt_len = sizeof(dummy_udp_tun_tcp_packet); 6998 *offsets = dummy_udp_tun_tcp_packet_offsets; 6999 return; 7000 } 7001 7002 *pkt = dummy_udp_tun_udp_packet; 7003 *pkt_len = sizeof(dummy_udp_tun_udp_packet); 7004 *offsets = dummy_udp_tun_udp_packet_offsets; 7005 return; 7006 } 7007 7008 if (udp && !ipv6) { 7009 if (vlan) { 7010 *pkt = dummy_vlan_udp_packet; 7011 *pkt_len = sizeof(dummy_vlan_udp_packet); 7012 *offsets = dummy_vlan_udp_packet_offsets; 7013 return; 7014 } 7015 *pkt = dummy_udp_packet; 7016 *pkt_len = sizeof(dummy_udp_packet); 7017 *offsets = dummy_udp_packet_offsets; 7018 return; 7019 } else if (udp && ipv6) { 7020 if (vlan) { 7021 *pkt = dummy_vlan_udp_ipv6_packet; 7022 *pkt_len = sizeof(dummy_vlan_udp_ipv6_packet); 7023 *offsets = dummy_vlan_udp_ipv6_packet_offsets; 7024 return; 7025 } 7026 *pkt = dummy_udp_ipv6_packet; 7027 *pkt_len = sizeof(dummy_udp_ipv6_packet); 7028 *offsets = dummy_udp_ipv6_packet_offsets; 7029 return; 7030 } else if ((tcp && ipv6) || ipv6) { 7031 if (vlan) { 7032 *pkt = dummy_vlan_tcp_ipv6_packet; 7033 *pkt_len = sizeof(dummy_vlan_tcp_ipv6_packet); 7034 *offsets = dummy_vlan_tcp_ipv6_packet_offsets; 7035 return; 7036 } 7037 *pkt = dummy_tcp_ipv6_packet; 7038 *pkt_len = sizeof(dummy_tcp_ipv6_packet); 7039 *offsets = dummy_tcp_ipv6_packet_offsets; 7040 return; 7041 } 7042 7043 if (vlan) { 7044 *pkt = dummy_vlan_tcp_packet; 7045 *pkt_len = sizeof(dummy_vlan_tcp_packet); 7046 *offsets = dummy_vlan_tcp_packet_offsets; 7047 } else { 7048 *pkt = dummy_tcp_packet; 7049 *pkt_len = sizeof(dummy_tcp_packet); 7050 *offsets = dummy_tcp_packet_offsets; 7051 } 7052 } 7053 7054 /** 7055 * ice_fill_adv_dummy_packet - fill a dummy packet with given match criteria 7056 * 7057 * @lkups: lookup elements or match criteria for the advanced recipe, one 7058 * structure per protocol header 7059 * @lkups_cnt: number of protocols 7060 * @s_rule: stores rule information from the match criteria 7061 * @dummy_pkt: dummy packet to fill according to filter match criteria 7062 * @pkt_len: packet length of dummy packet 7063 * @offsets: offset info for the dummy packet 7064 */ 7065 static enum ice_status 7066 ice_fill_adv_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt, 7067 struct ice_aqc_sw_rules_elem *s_rule, 7068 const u8 *dummy_pkt, u16 pkt_len, 7069 const struct ice_dummy_pkt_offsets *offsets) 7070 { 7071 u8 *pkt; 7072 u16 i; 7073 7074 /* Start with a packet with a pre-defined/dummy content. Then, fill 7075 * in the header values to be looked up or matched. 7076 */ 7077 pkt = s_rule->pdata.lkup_tx_rx.hdr; 7078 7079 ice_memcpy(pkt, dummy_pkt, pkt_len, ICE_NONDMA_TO_NONDMA); 7080 7081 for (i = 0; i < lkups_cnt; i++) { 7082 enum ice_protocol_type type; 7083 u16 offset = 0, len = 0, j; 7084 bool found = false; 7085 7086 /* find the start of this layer; it should be found since this 7087 * was already checked when search for the dummy packet 7088 */ 7089 type = lkups[i].type; 7090 for (j = 0; offsets[j].type != ICE_PROTOCOL_LAST; j++) { 7091 if (type == offsets[j].type) { 7092 offset = offsets[j].offset; 7093 found = true; 7094 break; 7095 } 7096 } 7097 /* this should never happen in a correct calling sequence */ 7098 if (!found) 7099 return ICE_ERR_PARAM; 7100 7101 switch (lkups[i].type) { 7102 case ICE_MAC_OFOS: 7103 case ICE_MAC_IL: 7104 len = sizeof(struct ice_ether_hdr); 7105 break; 7106 case ICE_ETYPE_OL: 7107 len = sizeof(struct ice_ethtype_hdr); 7108 break; 7109 case ICE_VLAN_OFOS: 7110 len = sizeof(struct ice_vlan_hdr); 7111 break; 7112 case ICE_IPV4_OFOS: 7113 case ICE_IPV4_IL: 7114 len = sizeof(struct ice_ipv4_hdr); 7115 break; 7116 case ICE_IPV6_OFOS: 7117 case ICE_IPV6_IL: 7118 len = sizeof(struct ice_ipv6_hdr); 7119 break; 7120 case ICE_TCP_IL: 7121 case ICE_UDP_OF: 7122 case ICE_UDP_ILOS: 7123 len = sizeof(struct ice_l4_hdr); 7124 break; 7125 case ICE_SCTP_IL: 7126 len = sizeof(struct ice_sctp_hdr); 7127 break; 7128 case ICE_NVGRE: 7129 len = sizeof(struct ice_nvgre); 7130 break; 7131 case ICE_VXLAN: 7132 case ICE_GENEVE: 7133 case ICE_VXLAN_GPE: 7134 len = sizeof(struct ice_udp_tnl_hdr); 7135 break; 7136 7137 case ICE_GTP: 7138 len = sizeof(struct ice_udp_gtp_hdr); 7139 break; 7140 case ICE_PPPOE: 7141 len = sizeof(struct ice_pppoe_hdr); 7142 break; 7143 case ICE_ESP: 7144 len = sizeof(struct ice_esp_hdr); 7145 break; 7146 case ICE_NAT_T: 7147 len = sizeof(struct ice_nat_t_hdr); 7148 break; 7149 case ICE_AH: 7150 len = sizeof(struct ice_ah_hdr); 7151 break; 7152 case ICE_L2TPV3: 7153 len = sizeof(struct ice_l2tpv3_sess_hdr); 7154 break; 7155 default: 7156 return ICE_ERR_PARAM; 7157 } 7158 7159 /* the length should be a word multiple */ 7160 if (len % ICE_BYTES_PER_WORD) 7161 return ICE_ERR_CFG; 7162 7163 /* We have the offset to the header start, the length, the 7164 * caller's header values and mask. Use this information to 7165 * copy the data into the dummy packet appropriately based on 7166 * the mask. Note that we need to only write the bits as 7167 * indicated by the mask to make sure we don't improperly write 7168 * over any significant packet data. 7169 */ 7170 for (j = 0; j < len / sizeof(u16); j++) 7171 if (((u16 *)&lkups[i].m_u)[j]) 7172 ((u16 *)(pkt + offset))[j] = 7173 (((u16 *)(pkt + offset))[j] & 7174 ~((u16 *)&lkups[i].m_u)[j]) | 7175 (((u16 *)&lkups[i].h_u)[j] & 7176 ((u16 *)&lkups[i].m_u)[j]); 7177 } 7178 7179 s_rule->pdata.lkup_tx_rx.hdr_len = CPU_TO_LE16(pkt_len); 7180 7181 return ICE_SUCCESS; 7182 } 7183 7184 /** 7185 * ice_fill_adv_packet_tun - fill dummy packet with udp tunnel port 7186 * @hw: pointer to the hardware structure 7187 * @tun_type: tunnel type 7188 * @pkt: dummy packet to fill in 7189 * @offsets: offset info for the dummy packet 7190 */ 7191 static enum ice_status 7192 ice_fill_adv_packet_tun(struct ice_hw *hw, enum ice_sw_tunnel_type tun_type, 7193 u8 *pkt, const struct ice_dummy_pkt_offsets *offsets) 7194 { 7195 u16 open_port, i; 7196 7197 switch (tun_type) { 7198 case ICE_SW_TUN_AND_NON_TUN: 7199 case ICE_SW_TUN_VXLAN_GPE: 7200 case ICE_SW_TUN_VXLAN: 7201 case ICE_SW_TUN_VXLAN_VLAN: 7202 case ICE_SW_TUN_UDP: 7203 if (!ice_get_open_tunnel_port(hw, TNL_VXLAN, &open_port)) 7204 return ICE_ERR_CFG; 7205 break; 7206 7207 case ICE_SW_TUN_GENEVE: 7208 case ICE_SW_TUN_GENEVE_VLAN: 7209 if (!ice_get_open_tunnel_port(hw, TNL_GENEVE, &open_port)) 7210 return ICE_ERR_CFG; 7211 break; 7212 7213 default: 7214 /* Nothing needs to be done for this tunnel type */ 7215 return ICE_SUCCESS; 7216 } 7217 7218 /* Find the outer UDP protocol header and insert the port number */ 7219 for (i = 0; offsets[i].type != ICE_PROTOCOL_LAST; i++) { 7220 if (offsets[i].type == ICE_UDP_OF) { 7221 struct ice_l4_hdr *hdr; 7222 u16 offset; 7223 7224 offset = offsets[i].offset; 7225 hdr = (struct ice_l4_hdr *)&pkt[offset]; 7226 hdr->dst_port = CPU_TO_BE16(open_port); 7227 7228 return ICE_SUCCESS; 7229 } 7230 } 7231 7232 return ICE_ERR_CFG; 7233 } 7234 7235 /** 7236 * ice_find_adv_rule_entry - Search a rule entry 7237 * @hw: pointer to the hardware structure 7238 * @lkups: lookup elements or match criteria for the advanced recipe, one 7239 * structure per protocol header 7240 * @lkups_cnt: number of protocols 7241 * @recp_id: recipe ID for which we are finding the rule 7242 * @rinfo: other information regarding the rule e.g. priority and action info 7243 * 7244 * Helper function to search for a given advance rule entry 7245 * Returns pointer to entry storing the rule if found 7246 */ 7247 static struct ice_adv_fltr_mgmt_list_entry * 7248 ice_find_adv_rule_entry(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, 7249 u16 lkups_cnt, u16 recp_id, 7250 struct ice_adv_rule_info *rinfo) 7251 { 7252 struct ice_adv_fltr_mgmt_list_entry *list_itr; 7253 struct ice_switch_info *sw = hw->switch_info; 7254 int i; 7255 7256 LIST_FOR_EACH_ENTRY(list_itr, &sw->recp_list[recp_id].filt_rules, 7257 ice_adv_fltr_mgmt_list_entry, list_entry) { 7258 bool lkups_matched = true; 7259 7260 if (lkups_cnt != list_itr->lkups_cnt) 7261 continue; 7262 for (i = 0; i < list_itr->lkups_cnt; i++) 7263 if (memcmp(&list_itr->lkups[i], &lkups[i], 7264 sizeof(*lkups))) { 7265 lkups_matched = false; 7266 break; 7267 } 7268 if (rinfo->sw_act.flag == list_itr->rule_info.sw_act.flag && 7269 rinfo->tun_type == list_itr->rule_info.tun_type && 7270 lkups_matched) 7271 return list_itr; 7272 } 7273 return NULL; 7274 } 7275 7276 /** 7277 * ice_adv_add_update_vsi_list 7278 * @hw: pointer to the hardware structure 7279 * @m_entry: pointer to current adv filter management list entry 7280 * @cur_fltr: filter information from the book keeping entry 7281 * @new_fltr: filter information with the new VSI to be added 7282 * 7283 * Call AQ command to add or update previously created VSI list with new VSI. 7284 * 7285 * Helper function to do book keeping associated with adding filter information 7286 * The algorithm to do the booking keeping is described below : 7287 * When a VSI needs to subscribe to a given advanced filter 7288 * if only one VSI has been added till now 7289 * Allocate a new VSI list and add two VSIs 7290 * to this list using switch rule command 7291 * Update the previously created switch rule with the 7292 * newly created VSI list ID 7293 * if a VSI list was previously created 7294 * Add the new VSI to the previously created VSI list set 7295 * using the update switch rule command 7296 */ 7297 static enum ice_status 7298 ice_adv_add_update_vsi_list(struct ice_hw *hw, 7299 struct ice_adv_fltr_mgmt_list_entry *m_entry, 7300 struct ice_adv_rule_info *cur_fltr, 7301 struct ice_adv_rule_info *new_fltr) 7302 { 7303 enum ice_status status; 7304 u16 vsi_list_id = 0; 7305 7306 if (cur_fltr->sw_act.fltr_act == ICE_FWD_TO_Q || 7307 cur_fltr->sw_act.fltr_act == ICE_FWD_TO_QGRP || 7308 cur_fltr->sw_act.fltr_act == ICE_DROP_PACKET) 7309 return ICE_ERR_NOT_IMPL; 7310 7311 if ((new_fltr->sw_act.fltr_act == ICE_FWD_TO_Q || 7312 new_fltr->sw_act.fltr_act == ICE_FWD_TO_QGRP) && 7313 (cur_fltr->sw_act.fltr_act == ICE_FWD_TO_VSI || 7314 cur_fltr->sw_act.fltr_act == ICE_FWD_TO_VSI_LIST)) 7315 return ICE_ERR_NOT_IMPL; 7316 7317 if (m_entry->vsi_count < 2 && !m_entry->vsi_list_info) { 7318 /* Only one entry existed in the mapping and it was not already 7319 * a part of a VSI list. So, create a VSI list with the old and 7320 * new VSIs. 7321 */ 7322 struct ice_fltr_info tmp_fltr; 7323 u16 vsi_handle_arr[2]; 7324 7325 /* A rule already exists with the new VSI being added */ 7326 if (cur_fltr->sw_act.fwd_id.hw_vsi_id == 7327 new_fltr->sw_act.fwd_id.hw_vsi_id) 7328 return ICE_ERR_ALREADY_EXISTS; 7329 7330 vsi_handle_arr[0] = cur_fltr->sw_act.vsi_handle; 7331 vsi_handle_arr[1] = new_fltr->sw_act.vsi_handle; 7332 status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2, 7333 &vsi_list_id, 7334 ICE_SW_LKUP_LAST); 7335 if (status) 7336 return status; 7337 7338 ice_memset(&tmp_fltr, 0, sizeof(tmp_fltr), ICE_NONDMA_MEM); 7339 tmp_fltr.flag = m_entry->rule_info.sw_act.flag; 7340 tmp_fltr.fltr_rule_id = cur_fltr->fltr_rule_id; 7341 tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST; 7342 tmp_fltr.fwd_id.vsi_list_id = vsi_list_id; 7343 tmp_fltr.lkup_type = ICE_SW_LKUP_LAST; 7344 7345 /* Update the previous switch rule of "forward to VSI" to 7346 * "fwd to VSI list" 7347 */ 7348 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr); 7349 if (status) 7350 return status; 7351 7352 cur_fltr->sw_act.fwd_id.vsi_list_id = vsi_list_id; 7353 cur_fltr->sw_act.fltr_act = ICE_FWD_TO_VSI_LIST; 7354 m_entry->vsi_list_info = 7355 ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2, 7356 vsi_list_id); 7357 } else { 7358 u16 vsi_handle = new_fltr->sw_act.vsi_handle; 7359 7360 if (!m_entry->vsi_list_info) 7361 return ICE_ERR_CFG; 7362 7363 /* A rule already exists with the new VSI being added */ 7364 if (ice_is_bit_set(m_entry->vsi_list_info->vsi_map, vsi_handle)) 7365 return ICE_SUCCESS; 7366 7367 /* Update the previously created VSI list set with 7368 * the new VSI ID passed in 7369 */ 7370 vsi_list_id = cur_fltr->sw_act.fwd_id.vsi_list_id; 7371 7372 status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, 7373 vsi_list_id, false, 7374 ice_aqc_opc_update_sw_rules, 7375 ICE_SW_LKUP_LAST); 7376 /* update VSI list mapping info with new VSI ID */ 7377 if (!status) 7378 ice_set_bit(vsi_handle, 7379 m_entry->vsi_list_info->vsi_map); 7380 } 7381 if (!status) 7382 m_entry->vsi_count++; 7383 return status; 7384 } 7385 7386 /** 7387 * ice_add_adv_rule - helper function to create an advanced switch rule 7388 * @hw: pointer to the hardware structure 7389 * @lkups: information on the words that needs to be looked up. All words 7390 * together makes one recipe 7391 * @lkups_cnt: num of entries in the lkups array 7392 * @rinfo: other information related to the rule that needs to be programmed 7393 * @added_entry: this will return recipe_id, rule_id and vsi_handle. should be 7394 * ignored is case of error. 7395 * 7396 * This function can program only 1 rule at a time. The lkups is used to 7397 * describe the all the words that forms the "lookup" portion of the recipe. 7398 * These words can span multiple protocols. Callers to this function need to 7399 * pass in a list of protocol headers with lookup information along and mask 7400 * that determines which words are valid from the given protocol header. 7401 * rinfo describes other information related to this rule such as forwarding 7402 * IDs, priority of this rule, etc. 7403 */ 7404 enum ice_status 7405 ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, 7406 u16 lkups_cnt, struct ice_adv_rule_info *rinfo, 7407 struct ice_rule_query_data *added_entry) 7408 { 7409 struct ice_adv_fltr_mgmt_list_entry *m_entry, *adv_fltr = NULL; 7410 u16 rid = 0, i, pkt_len, rule_buf_sz, vsi_handle; 7411 const struct ice_dummy_pkt_offsets *pkt_offsets; 7412 struct ice_aqc_sw_rules_elem *s_rule = NULL; 7413 struct LIST_HEAD_TYPE *rule_head; 7414 struct ice_switch_info *sw; 7415 enum ice_status status; 7416 const u8 *pkt = NULL; 7417 bool prof_rule; 7418 u16 word_cnt; 7419 u32 act = 0; 7420 u8 q_rgn; 7421 7422 /* Initialize profile to result index bitmap */ 7423 if (!hw->switch_info->prof_res_bm_init) { 7424 hw->switch_info->prof_res_bm_init = 1; 7425 ice_init_prof_result_bm(hw); 7426 } 7427 7428 prof_rule = ice_is_prof_rule(rinfo->tun_type); 7429 if (!prof_rule && !lkups_cnt) 7430 return ICE_ERR_PARAM; 7431 7432 /* get # of words we need to match */ 7433 word_cnt = 0; 7434 for (i = 0; i < lkups_cnt; i++) { 7435 u16 j, *ptr; 7436 7437 ptr = (u16 *)&lkups[i].m_u; 7438 for (j = 0; j < sizeof(lkups->m_u) / sizeof(u16); j++) 7439 if (ptr[j] != 0) 7440 word_cnt++; 7441 } 7442 7443 if (prof_rule) { 7444 if (word_cnt > ICE_MAX_CHAIN_WORDS) 7445 return ICE_ERR_PARAM; 7446 } else { 7447 if (!word_cnt || word_cnt > ICE_MAX_CHAIN_WORDS) 7448 return ICE_ERR_PARAM; 7449 } 7450 7451 /* make sure that we can locate a dummy packet */ 7452 ice_find_dummy_packet(lkups, lkups_cnt, rinfo->tun_type, &pkt, &pkt_len, 7453 &pkt_offsets); 7454 if (!pkt) { 7455 status = ICE_ERR_PARAM; 7456 goto err_ice_add_adv_rule; 7457 } 7458 7459 if (!(rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI || 7460 rinfo->sw_act.fltr_act == ICE_FWD_TO_Q || 7461 rinfo->sw_act.fltr_act == ICE_FWD_TO_QGRP || 7462 rinfo->sw_act.fltr_act == ICE_DROP_PACKET)) 7463 return ICE_ERR_CFG; 7464 7465 vsi_handle = rinfo->sw_act.vsi_handle; 7466 if (!ice_is_vsi_valid(hw, vsi_handle)) 7467 return ICE_ERR_PARAM; 7468 7469 if (rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI) 7470 rinfo->sw_act.fwd_id.hw_vsi_id = 7471 ice_get_hw_vsi_num(hw, vsi_handle); 7472 if (rinfo->sw_act.flag & ICE_FLTR_TX) 7473 rinfo->sw_act.src = ice_get_hw_vsi_num(hw, vsi_handle); 7474 7475 status = ice_add_adv_recipe(hw, lkups, lkups_cnt, rinfo, &rid); 7476 if (status) 7477 return status; 7478 m_entry = ice_find_adv_rule_entry(hw, lkups, lkups_cnt, rid, rinfo); 7479 if (m_entry) { 7480 /* we have to add VSI to VSI_LIST and increment vsi_count. 7481 * Also Update VSI list so that we can change forwarding rule 7482 * if the rule already exists, we will check if it exists with 7483 * same vsi_id, if not then add it to the VSI list if it already 7484 * exists if not then create a VSI list and add the existing VSI 7485 * ID and the new VSI ID to the list 7486 * We will add that VSI to the list 7487 */ 7488 status = ice_adv_add_update_vsi_list(hw, m_entry, 7489 &m_entry->rule_info, 7490 rinfo); 7491 if (added_entry) { 7492 added_entry->rid = rid; 7493 added_entry->rule_id = m_entry->rule_info.fltr_rule_id; 7494 added_entry->vsi_handle = rinfo->sw_act.vsi_handle; 7495 } 7496 return status; 7497 } 7498 rule_buf_sz = ICE_SW_RULE_RX_TX_NO_HDR_SIZE + pkt_len; 7499 s_rule = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, rule_buf_sz); 7500 if (!s_rule) 7501 return ICE_ERR_NO_MEMORY; 7502 act |= ICE_SINGLE_ACT_LAN_ENABLE; 7503 switch (rinfo->sw_act.fltr_act) { 7504 case ICE_FWD_TO_VSI: 7505 act |= (rinfo->sw_act.fwd_id.hw_vsi_id << 7506 ICE_SINGLE_ACT_VSI_ID_S) & ICE_SINGLE_ACT_VSI_ID_M; 7507 act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_VALID_BIT; 7508 break; 7509 case ICE_FWD_TO_Q: 7510 act |= ICE_SINGLE_ACT_TO_Q; 7511 act |= (rinfo->sw_act.fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) & 7512 ICE_SINGLE_ACT_Q_INDEX_M; 7513 break; 7514 case ICE_FWD_TO_QGRP: 7515 q_rgn = rinfo->sw_act.qgrp_size > 0 ? 7516 (u8)ice_ilog2(rinfo->sw_act.qgrp_size) : 0; 7517 act |= ICE_SINGLE_ACT_TO_Q; 7518 act |= (rinfo->sw_act.fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) & 7519 ICE_SINGLE_ACT_Q_INDEX_M; 7520 act |= (q_rgn << ICE_SINGLE_ACT_Q_REGION_S) & 7521 ICE_SINGLE_ACT_Q_REGION_M; 7522 break; 7523 case ICE_DROP_PACKET: 7524 act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_DROP | 7525 ICE_SINGLE_ACT_VALID_BIT; 7526 break; 7527 default: 7528 status = ICE_ERR_CFG; 7529 goto err_ice_add_adv_rule; 7530 } 7531 7532 /* set the rule LOOKUP type based on caller specified 'RX' 7533 * instead of hardcoding it to be either LOOKUP_TX/RX 7534 * 7535 * for 'RX' set the source to be the port number 7536 * for 'TX' set the source to be the source HW VSI number (determined 7537 * by caller) 7538 */ 7539 if (rinfo->rx) { 7540 s_rule->type = CPU_TO_LE16(ICE_AQC_SW_RULES_T_LKUP_RX); 7541 s_rule->pdata.lkup_tx_rx.src = 7542 CPU_TO_LE16(hw->port_info->lport); 7543 } else { 7544 s_rule->type = CPU_TO_LE16(ICE_AQC_SW_RULES_T_LKUP_TX); 7545 s_rule->pdata.lkup_tx_rx.src = CPU_TO_LE16(rinfo->sw_act.src); 7546 } 7547 7548 s_rule->pdata.lkup_tx_rx.recipe_id = CPU_TO_LE16(rid); 7549 s_rule->pdata.lkup_tx_rx.act = CPU_TO_LE32(act); 7550 7551 status = ice_fill_adv_dummy_packet(lkups, lkups_cnt, s_rule, pkt, 7552 pkt_len, pkt_offsets); 7553 if (status) 7554 goto err_ice_add_adv_rule; 7555 7556 if (rinfo->tun_type != ICE_NON_TUN && 7557 rinfo->tun_type != ICE_SW_TUN_AND_NON_TUN) { 7558 status = ice_fill_adv_packet_tun(hw, rinfo->tun_type, 7559 s_rule->pdata.lkup_tx_rx.hdr, 7560 pkt_offsets); 7561 if (status) 7562 goto err_ice_add_adv_rule; 7563 } 7564 7565 status = ice_aq_sw_rules(hw, (struct ice_aqc_sw_rules *)s_rule, 7566 rule_buf_sz, 1, ice_aqc_opc_add_sw_rules, 7567 NULL); 7568 if (status) 7569 goto err_ice_add_adv_rule; 7570 adv_fltr = (struct ice_adv_fltr_mgmt_list_entry *) 7571 ice_malloc(hw, sizeof(struct ice_adv_fltr_mgmt_list_entry)); 7572 if (!adv_fltr) { 7573 status = ICE_ERR_NO_MEMORY; 7574 goto err_ice_add_adv_rule; 7575 } 7576 7577 adv_fltr->lkups = (struct ice_adv_lkup_elem *) 7578 ice_memdup(hw, lkups, lkups_cnt * sizeof(*lkups), 7579 ICE_NONDMA_TO_NONDMA); 7580 if (!adv_fltr->lkups && !prof_rule) { 7581 status = ICE_ERR_NO_MEMORY; 7582 goto err_ice_add_adv_rule; 7583 } 7584 7585 adv_fltr->lkups_cnt = lkups_cnt; 7586 adv_fltr->rule_info = *rinfo; 7587 adv_fltr->rule_info.fltr_rule_id = 7588 LE16_TO_CPU(s_rule->pdata.lkup_tx_rx.index); 7589 sw = hw->switch_info; 7590 sw->recp_list[rid].adv_rule = true; 7591 rule_head = &sw->recp_list[rid].filt_rules; 7592 7593 if (rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI) 7594 adv_fltr->vsi_count = 1; 7595 7596 /* Add rule entry to book keeping list */ 7597 LIST_ADD(&adv_fltr->list_entry, rule_head); 7598 if (added_entry) { 7599 added_entry->rid = rid; 7600 added_entry->rule_id = adv_fltr->rule_info.fltr_rule_id; 7601 added_entry->vsi_handle = rinfo->sw_act.vsi_handle; 7602 } 7603 err_ice_add_adv_rule: 7604 if (status && adv_fltr) { 7605 ice_free(hw, adv_fltr->lkups); 7606 ice_free(hw, adv_fltr); 7607 } 7608 7609 ice_free(hw, s_rule); 7610 7611 return status; 7612 } 7613 7614 /** 7615 * ice_adv_rem_update_vsi_list 7616 * @hw: pointer to the hardware structure 7617 * @vsi_handle: VSI handle of the VSI to remove 7618 * @fm_list: filter management entry for which the VSI list management needs to 7619 * be done 7620 */ 7621 static enum ice_status 7622 ice_adv_rem_update_vsi_list(struct ice_hw *hw, u16 vsi_handle, 7623 struct ice_adv_fltr_mgmt_list_entry *fm_list) 7624 { 7625 struct ice_vsi_list_map_info *vsi_list_info; 7626 enum ice_sw_lkup_type lkup_type; 7627 enum ice_status status; 7628 u16 vsi_list_id; 7629 7630 if (fm_list->rule_info.sw_act.fltr_act != ICE_FWD_TO_VSI_LIST || 7631 fm_list->vsi_count == 0) 7632 return ICE_ERR_PARAM; 7633 7634 /* A rule with the VSI being removed does not exist */ 7635 if (!ice_is_bit_set(fm_list->vsi_list_info->vsi_map, vsi_handle)) 7636 return ICE_ERR_DOES_NOT_EXIST; 7637 7638 lkup_type = ICE_SW_LKUP_LAST; 7639 vsi_list_id = fm_list->rule_info.sw_act.fwd_id.vsi_list_id; 7640 status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, vsi_list_id, true, 7641 ice_aqc_opc_update_sw_rules, 7642 lkup_type); 7643 if (status) 7644 return status; 7645 7646 fm_list->vsi_count--; 7647 ice_clear_bit(vsi_handle, fm_list->vsi_list_info->vsi_map); 7648 vsi_list_info = fm_list->vsi_list_info; 7649 if (fm_list->vsi_count == 1) { 7650 struct ice_fltr_info tmp_fltr; 7651 u16 rem_vsi_handle; 7652 7653 rem_vsi_handle = ice_find_first_bit(vsi_list_info->vsi_map, 7654 ICE_MAX_VSI); 7655 if (!ice_is_vsi_valid(hw, rem_vsi_handle)) 7656 return ICE_ERR_OUT_OF_RANGE; 7657 7658 /* Make sure VSI list is empty before removing it below */ 7659 status = ice_update_vsi_list_rule(hw, &rem_vsi_handle, 1, 7660 vsi_list_id, true, 7661 ice_aqc_opc_update_sw_rules, 7662 lkup_type); 7663 if (status) 7664 return status; 7665 7666 ice_memset(&tmp_fltr, 0, sizeof(tmp_fltr), ICE_NONDMA_MEM); 7667 tmp_fltr.flag = fm_list->rule_info.sw_act.flag; 7668 tmp_fltr.fltr_rule_id = fm_list->rule_info.fltr_rule_id; 7669 fm_list->rule_info.sw_act.fltr_act = ICE_FWD_TO_VSI; 7670 tmp_fltr.fltr_act = ICE_FWD_TO_VSI; 7671 tmp_fltr.fwd_id.hw_vsi_id = 7672 ice_get_hw_vsi_num(hw, rem_vsi_handle); 7673 fm_list->rule_info.sw_act.fwd_id.hw_vsi_id = 7674 ice_get_hw_vsi_num(hw, rem_vsi_handle); 7675 fm_list->rule_info.sw_act.vsi_handle = rem_vsi_handle; 7676 7677 /* Update the previous switch rule of "MAC forward to VSI" to 7678 * "MAC fwd to VSI list" 7679 */ 7680 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr); 7681 if (status) { 7682 ice_debug(hw, ICE_DBG_SW, 7683 "Failed to update pkt fwd rule to FWD_TO_VSI on HW VSI %d, error %d\n", 7684 tmp_fltr.fwd_id.hw_vsi_id, status); 7685 return status; 7686 } 7687 fm_list->vsi_list_info->ref_cnt--; 7688 7689 /* Remove the VSI list since it is no longer used */ 7690 status = ice_remove_vsi_list_rule(hw, vsi_list_id, lkup_type); 7691 if (status) { 7692 ice_debug(hw, ICE_DBG_SW, 7693 "Failed to remove VSI list %d, error %d\n", 7694 vsi_list_id, status); 7695 return status; 7696 } 7697 7698 LIST_DEL(&vsi_list_info->list_entry); 7699 ice_free(hw, vsi_list_info); 7700 fm_list->vsi_list_info = NULL; 7701 } 7702 7703 return status; 7704 } 7705 7706 /** 7707 * ice_rem_adv_rule - removes existing advanced switch rule 7708 * @hw: pointer to the hardware structure 7709 * @lkups: information on the words that needs to be looked up. All words 7710 * together makes one recipe 7711 * @lkups_cnt: num of entries in the lkups array 7712 * @rinfo: Its the pointer to the rule information for the rule 7713 * 7714 * This function can be used to remove 1 rule at a time. The lkups is 7715 * used to describe all the words that forms the "lookup" portion of the 7716 * rule. These words can span multiple protocols. Callers to this function 7717 * need to pass in a list of protocol headers with lookup information along 7718 * and mask that determines which words are valid from the given protocol 7719 * header. rinfo describes other information related to this rule such as 7720 * forwarding IDs, priority of this rule, etc. 7721 */ 7722 enum ice_status 7723 ice_rem_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, 7724 u16 lkups_cnt, struct ice_adv_rule_info *rinfo) 7725 { 7726 struct ice_adv_fltr_mgmt_list_entry *list_elem; 7727 struct ice_prot_lkup_ext lkup_exts; 7728 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 7729 enum ice_status status = ICE_SUCCESS; 7730 bool remove_rule = false; 7731 u16 i, rid, vsi_handle; 7732 7733 ice_memset(&lkup_exts, 0, sizeof(lkup_exts), ICE_NONDMA_MEM); 7734 for (i = 0; i < lkups_cnt; i++) { 7735 u16 count; 7736 7737 if (lkups[i].type >= ICE_PROTOCOL_LAST) 7738 return ICE_ERR_CFG; 7739 7740 count = ice_fill_valid_words(&lkups[i], &lkup_exts); 7741 if (!count) 7742 return ICE_ERR_CFG; 7743 } 7744 7745 /* Create any special protocol/offset pairs, such as looking at tunnel 7746 * bits by extracting metadata 7747 */ 7748 status = ice_add_special_words(rinfo, &lkup_exts); 7749 if (status) 7750 return status; 7751 7752 rid = ice_find_recp(hw, &lkup_exts, rinfo->tun_type); 7753 /* If did not find a recipe that match the existing criteria */ 7754 if (rid == ICE_MAX_NUM_RECIPES) 7755 return ICE_ERR_PARAM; 7756 7757 rule_lock = &hw->switch_info->recp_list[rid].filt_rule_lock; 7758 list_elem = ice_find_adv_rule_entry(hw, lkups, lkups_cnt, rid, rinfo); 7759 /* the rule is already removed */ 7760 if (!list_elem) 7761 return ICE_SUCCESS; 7762 ice_acquire_lock(rule_lock); 7763 if (list_elem->rule_info.sw_act.fltr_act != ICE_FWD_TO_VSI_LIST) { 7764 remove_rule = true; 7765 } else if (list_elem->vsi_count > 1) { 7766 remove_rule = false; 7767 vsi_handle = rinfo->sw_act.vsi_handle; 7768 status = ice_adv_rem_update_vsi_list(hw, vsi_handle, list_elem); 7769 } else { 7770 vsi_handle = rinfo->sw_act.vsi_handle; 7771 status = ice_adv_rem_update_vsi_list(hw, vsi_handle, list_elem); 7772 if (status) { 7773 ice_release_lock(rule_lock); 7774 return status; 7775 } 7776 if (list_elem->vsi_count == 0) 7777 remove_rule = true; 7778 } 7779 ice_release_lock(rule_lock); 7780 if (remove_rule) { 7781 struct ice_aqc_sw_rules_elem *s_rule; 7782 u16 rule_buf_sz; 7783 7784 rule_buf_sz = ICE_SW_RULE_RX_TX_NO_HDR_SIZE; 7785 s_rule = 7786 (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, 7787 rule_buf_sz); 7788 if (!s_rule) 7789 return ICE_ERR_NO_MEMORY; 7790 s_rule->pdata.lkup_tx_rx.act = 0; 7791 s_rule->pdata.lkup_tx_rx.index = 7792 CPU_TO_LE16(list_elem->rule_info.fltr_rule_id); 7793 s_rule->pdata.lkup_tx_rx.hdr_len = 0; 7794 status = ice_aq_sw_rules(hw, (struct ice_aqc_sw_rules *)s_rule, 7795 rule_buf_sz, 1, 7796 ice_aqc_opc_remove_sw_rules, NULL); 7797 if (status == ICE_SUCCESS || status == ICE_ERR_DOES_NOT_EXIST) { 7798 struct ice_switch_info *sw = hw->switch_info; 7799 7800 ice_acquire_lock(rule_lock); 7801 LIST_DEL(&list_elem->list_entry); 7802 ice_free(hw, list_elem->lkups); 7803 ice_free(hw, list_elem); 7804 ice_release_lock(rule_lock); 7805 if (LIST_EMPTY(&sw->recp_list[rid].filt_rules)) 7806 sw->recp_list[rid].adv_rule = false; 7807 } 7808 ice_free(hw, s_rule); 7809 } 7810 return status; 7811 } 7812 7813 /** 7814 * ice_rem_adv_rule_by_id - removes existing advanced switch rule by ID 7815 * @hw: pointer to the hardware structure 7816 * @remove_entry: data struct which holds rule_id, VSI handle and recipe ID 7817 * 7818 * This function is used to remove 1 rule at a time. The removal is based on 7819 * the remove_entry parameter. This function will remove rule for a given 7820 * vsi_handle with a given rule_id which is passed as parameter in remove_entry 7821 */ 7822 enum ice_status 7823 ice_rem_adv_rule_by_id(struct ice_hw *hw, 7824 struct ice_rule_query_data *remove_entry) 7825 { 7826 struct ice_adv_fltr_mgmt_list_entry *list_itr; 7827 struct LIST_HEAD_TYPE *list_head; 7828 struct ice_adv_rule_info rinfo; 7829 struct ice_switch_info *sw; 7830 7831 sw = hw->switch_info; 7832 if (!sw->recp_list[remove_entry->rid].recp_created) 7833 return ICE_ERR_PARAM; 7834 list_head = &sw->recp_list[remove_entry->rid].filt_rules; 7835 LIST_FOR_EACH_ENTRY(list_itr, list_head, ice_adv_fltr_mgmt_list_entry, 7836 list_entry) { 7837 if (list_itr->rule_info.fltr_rule_id == 7838 remove_entry->rule_id) { 7839 rinfo = list_itr->rule_info; 7840 rinfo.sw_act.vsi_handle = remove_entry->vsi_handle; 7841 return ice_rem_adv_rule(hw, list_itr->lkups, 7842 list_itr->lkups_cnt, &rinfo); 7843 } 7844 } 7845 /* either list is empty or unable to find rule */ 7846 return ICE_ERR_DOES_NOT_EXIST; 7847 } 7848 7849 /** 7850 * ice_rem_adv_for_vsi - removes existing advanced switch rules for a 7851 * given VSI handle 7852 * @hw: pointer to the hardware structure 7853 * @vsi_handle: VSI handle for which we are supposed to remove all the rules. 7854 * 7855 * This function is used to remove all the rules for a given VSI and as soon 7856 * as removing a rule fails, it will return immediately with the error code, 7857 * else it will return ICE_SUCCESS 7858 */ 7859 enum ice_status ice_rem_adv_rule_for_vsi(struct ice_hw *hw, u16 vsi_handle) 7860 { 7861 struct ice_adv_fltr_mgmt_list_entry *list_itr; 7862 struct ice_vsi_list_map_info *map_info; 7863 struct LIST_HEAD_TYPE *list_head; 7864 struct ice_adv_rule_info rinfo; 7865 struct ice_switch_info *sw; 7866 enum ice_status status; 7867 u16 vsi_list_id = 0; 7868 u8 rid; 7869 7870 sw = hw->switch_info; 7871 for (rid = 0; rid < ICE_MAX_NUM_RECIPES; rid++) { 7872 if (!sw->recp_list[rid].recp_created) 7873 continue; 7874 if (!sw->recp_list[rid].adv_rule) 7875 continue; 7876 list_head = &sw->recp_list[rid].filt_rules; 7877 map_info = NULL; 7878 LIST_FOR_EACH_ENTRY(list_itr, list_head, 7879 ice_adv_fltr_mgmt_list_entry, list_entry) { 7880 map_info = ice_find_vsi_list_entry(&sw->recp_list[rid], 7881 vsi_handle, 7882 &vsi_list_id); 7883 if (!map_info) 7884 continue; 7885 rinfo = list_itr->rule_info; 7886 rinfo.sw_act.vsi_handle = vsi_handle; 7887 status = ice_rem_adv_rule(hw, list_itr->lkups, 7888 list_itr->lkups_cnt, &rinfo); 7889 if (status) 7890 return status; 7891 map_info = NULL; 7892 } 7893 } 7894 return ICE_SUCCESS; 7895 } 7896 7897 /** 7898 * ice_replay_fltr - Replay all the filters stored by a specific list head 7899 * @hw: pointer to the hardware structure 7900 * @list_head: list for which filters needs to be replayed 7901 * @recp_id: Recipe ID for which rules need to be replayed 7902 */ 7903 static enum ice_status 7904 ice_replay_fltr(struct ice_hw *hw, u8 recp_id, struct LIST_HEAD_TYPE *list_head) 7905 { 7906 struct ice_fltr_mgmt_list_entry *itr; 7907 enum ice_status status = ICE_SUCCESS; 7908 struct ice_sw_recipe *recp_list; 7909 u8 lport = hw->port_info->lport; 7910 struct LIST_HEAD_TYPE l_head; 7911 7912 if (LIST_EMPTY(list_head)) 7913 return status; 7914 7915 recp_list = &hw->switch_info->recp_list[recp_id]; 7916 /* Move entries from the given list_head to a temporary l_head so that 7917 * they can be replayed. Otherwise when trying to re-add the same 7918 * filter, the function will return already exists 7919 */ 7920 LIST_REPLACE_INIT(list_head, &l_head); 7921 7922 /* Mark the given list_head empty by reinitializing it so filters 7923 * could be added again by *handler 7924 */ 7925 LIST_FOR_EACH_ENTRY(itr, &l_head, ice_fltr_mgmt_list_entry, 7926 list_entry) { 7927 struct ice_fltr_list_entry f_entry; 7928 7929 f_entry.fltr_info = itr->fltr_info; 7930 if (itr->vsi_count < 2 && recp_id != ICE_SW_LKUP_VLAN) { 7931 status = ice_add_rule_internal(hw, recp_list, lport, 7932 &f_entry); 7933 if (status != ICE_SUCCESS) 7934 goto end; 7935 continue; 7936 } 7937 7938 /* Add a filter per VSI separately */ 7939 while (1) { 7940 u16 vsi_handle; 7941 7942 vsi_handle = 7943 ice_find_first_bit(itr->vsi_list_info->vsi_map, 7944 ICE_MAX_VSI); 7945 if (!ice_is_vsi_valid(hw, vsi_handle)) 7946 break; 7947 7948 ice_clear_bit(vsi_handle, itr->vsi_list_info->vsi_map); 7949 f_entry.fltr_info.vsi_handle = vsi_handle; 7950 f_entry.fltr_info.fwd_id.hw_vsi_id = 7951 ice_get_hw_vsi_num(hw, vsi_handle); 7952 f_entry.fltr_info.fltr_act = ICE_FWD_TO_VSI; 7953 if (recp_id == ICE_SW_LKUP_VLAN) 7954 status = ice_add_vlan_internal(hw, recp_list, 7955 &f_entry); 7956 else 7957 status = ice_add_rule_internal(hw, recp_list, 7958 lport, 7959 &f_entry); 7960 if (status != ICE_SUCCESS) 7961 goto end; 7962 } 7963 } 7964 end: 7965 /* Clear the filter management list */ 7966 ice_rem_sw_rule_info(hw, &l_head); 7967 return status; 7968 } 7969 7970 /** 7971 * ice_replay_all_fltr - replay all filters stored in bookkeeping lists 7972 * @hw: pointer to the hardware structure 7973 * 7974 * NOTE: This function does not clean up partially added filters on error. 7975 * It is up to caller of the function to issue a reset or fail early. 7976 */ 7977 enum ice_status ice_replay_all_fltr(struct ice_hw *hw) 7978 { 7979 struct ice_switch_info *sw = hw->switch_info; 7980 enum ice_status status = ICE_SUCCESS; 7981 u8 i; 7982 7983 for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) { 7984 struct LIST_HEAD_TYPE *head = &sw->recp_list[i].filt_rules; 7985 7986 status = ice_replay_fltr(hw, i, head); 7987 if (status != ICE_SUCCESS) 7988 return status; 7989 } 7990 return status; 7991 } 7992 7993 /** 7994 * ice_replay_vsi_fltr - Replay filters for requested VSI 7995 * @hw: pointer to the hardware structure 7996 * @pi: pointer to port information structure 7997 * @sw: pointer to switch info struct for which function replays filters 7998 * @vsi_handle: driver VSI handle 7999 * @recp_id: Recipe ID for which rules need to be replayed 8000 * @list_head: list for which filters need to be replayed 8001 * 8002 * Replays the filter of recipe recp_id for a VSI represented via vsi_handle. 8003 * It is required to pass valid VSI handle. 8004 */ 8005 static enum ice_status 8006 ice_replay_vsi_fltr(struct ice_hw *hw, struct ice_port_info *pi, 8007 struct ice_switch_info *sw, u16 vsi_handle, u8 recp_id, 8008 struct LIST_HEAD_TYPE *list_head) 8009 { 8010 struct ice_fltr_mgmt_list_entry *itr; 8011 enum ice_status status = ICE_SUCCESS; 8012 struct ice_sw_recipe *recp_list; 8013 u16 hw_vsi_id; 8014 8015 if (LIST_EMPTY(list_head)) 8016 return status; 8017 recp_list = &sw->recp_list[recp_id]; 8018 hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 8019 8020 LIST_FOR_EACH_ENTRY(itr, list_head, ice_fltr_mgmt_list_entry, 8021 list_entry) { 8022 struct ice_fltr_list_entry f_entry; 8023 8024 f_entry.fltr_info = itr->fltr_info; 8025 if (itr->vsi_count < 2 && recp_id != ICE_SW_LKUP_VLAN && 8026 itr->fltr_info.vsi_handle == vsi_handle) { 8027 /* update the src in case it is VSI num */ 8028 if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI) 8029 f_entry.fltr_info.src = hw_vsi_id; 8030 status = ice_add_rule_internal(hw, recp_list, 8031 pi->lport, 8032 &f_entry); 8033 if (status != ICE_SUCCESS) 8034 goto end; 8035 continue; 8036 } 8037 if (!itr->vsi_list_info || 8038 !ice_is_bit_set(itr->vsi_list_info->vsi_map, vsi_handle)) 8039 continue; 8040 /* Clearing it so that the logic can add it back */ 8041 ice_clear_bit(vsi_handle, itr->vsi_list_info->vsi_map); 8042 f_entry.fltr_info.vsi_handle = vsi_handle; 8043 f_entry.fltr_info.fltr_act = ICE_FWD_TO_VSI; 8044 /* update the src in case it is VSI num */ 8045 if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI) 8046 f_entry.fltr_info.src = hw_vsi_id; 8047 if (recp_id == ICE_SW_LKUP_VLAN) 8048 status = ice_add_vlan_internal(hw, recp_list, &f_entry); 8049 else 8050 status = ice_add_rule_internal(hw, recp_list, 8051 pi->lport, 8052 &f_entry); 8053 if (status != ICE_SUCCESS) 8054 goto end; 8055 } 8056 end: 8057 return status; 8058 } 8059 8060 /** 8061 * ice_replay_vsi_adv_rule - Replay advanced rule for requested VSI 8062 * @hw: pointer to the hardware structure 8063 * @vsi_handle: driver VSI handle 8064 * @list_head: list for which filters need to be replayed 8065 * 8066 * Replay the advanced rule for the given VSI. 8067 */ 8068 static enum ice_status 8069 ice_replay_vsi_adv_rule(struct ice_hw *hw, u16 vsi_handle, 8070 struct LIST_HEAD_TYPE *list_head) 8071 { 8072 struct ice_rule_query_data added_entry = { 0 }; 8073 struct ice_adv_fltr_mgmt_list_entry *adv_fltr; 8074 enum ice_status status = ICE_SUCCESS; 8075 8076 if (LIST_EMPTY(list_head)) 8077 return status; 8078 LIST_FOR_EACH_ENTRY(adv_fltr, list_head, ice_adv_fltr_mgmt_list_entry, 8079 list_entry) { 8080 struct ice_adv_rule_info *rinfo = &adv_fltr->rule_info; 8081 u16 lk_cnt = adv_fltr->lkups_cnt; 8082 8083 if (vsi_handle != rinfo->sw_act.vsi_handle) 8084 continue; 8085 status = ice_add_adv_rule(hw, adv_fltr->lkups, lk_cnt, rinfo, 8086 &added_entry); 8087 if (status) 8088 break; 8089 } 8090 return status; 8091 } 8092 8093 /** 8094 * ice_replay_vsi_all_fltr - replay all filters stored in bookkeeping lists 8095 * @hw: pointer to the hardware structure 8096 * @pi: pointer to port information structure 8097 * @vsi_handle: driver VSI handle 8098 * 8099 * Replays filters for requested VSI via vsi_handle. 8100 */ 8101 enum ice_status 8102 ice_replay_vsi_all_fltr(struct ice_hw *hw, struct ice_port_info *pi, 8103 u16 vsi_handle) 8104 { 8105 struct ice_switch_info *sw = hw->switch_info; 8106 enum ice_status status; 8107 u8 i; 8108 8109 /* Update the recipes that were created */ 8110 for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) { 8111 struct LIST_HEAD_TYPE *head; 8112 8113 head = &sw->recp_list[i].filt_replay_rules; 8114 if (!sw->recp_list[i].adv_rule) 8115 status = ice_replay_vsi_fltr(hw, pi, sw, vsi_handle, i, 8116 head); 8117 else 8118 status = ice_replay_vsi_adv_rule(hw, vsi_handle, head); 8119 if (status != ICE_SUCCESS) 8120 return status; 8121 } 8122 8123 return ICE_SUCCESS; 8124 } 8125 8126 /** 8127 * ice_rm_all_sw_replay_rule - helper function to delete filter replay rules 8128 * @hw: pointer to the HW struct 8129 * @sw: pointer to switch info struct for which function removes filters 8130 * 8131 * Deletes the filter replay rules for given switch 8132 */ 8133 void ice_rm_sw_replay_rule_info(struct ice_hw *hw, struct ice_switch_info *sw) 8134 { 8135 u8 i; 8136 8137 if (!sw) 8138 return; 8139 8140 for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) { 8141 if (!LIST_EMPTY(&sw->recp_list[i].filt_replay_rules)) { 8142 struct LIST_HEAD_TYPE *l_head; 8143 8144 l_head = &sw->recp_list[i].filt_replay_rules; 8145 if (!sw->recp_list[i].adv_rule) 8146 ice_rem_sw_rule_info(hw, l_head); 8147 else 8148 ice_rem_adv_rule_info(hw, l_head); 8149 } 8150 } 8151 } 8152 8153 /** 8154 * ice_rm_all_sw_replay_rule_info - deletes filter replay rules 8155 * @hw: pointer to the HW struct 8156 * 8157 * Deletes the filter replay rules. 8158 */ 8159 void ice_rm_all_sw_replay_rule_info(struct ice_hw *hw) 8160 { 8161 ice_rm_sw_replay_rule_info(hw, hw->switch_info); 8162 } 8163