linux/drivers/net/ethernet/aquantia/atlantic/aq_filters.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/* Copyright (C) 2014-2017 aQuantia Corporation. */
   3
   4/* File aq_filters.c: RX filters related functions. */
   5
   6#include "aq_filters.h"
   7
   8static bool __must_check
   9aq_rule_is_approve(struct ethtool_rx_flow_spec *fsp)
  10{
  11        if (fsp->flow_type & FLOW_MAC_EXT)
  12                return false;
  13
  14        switch (fsp->flow_type & ~FLOW_EXT) {
  15        case ETHER_FLOW:
  16        case TCP_V4_FLOW:
  17        case UDP_V4_FLOW:
  18        case SCTP_V4_FLOW:
  19        case TCP_V6_FLOW:
  20        case UDP_V6_FLOW:
  21        case SCTP_V6_FLOW:
  22        case IPV4_FLOW:
  23        case IPV6_FLOW:
  24                return true;
  25        case IP_USER_FLOW:
  26                switch (fsp->h_u.usr_ip4_spec.proto) {
  27                case IPPROTO_TCP:
  28                case IPPROTO_UDP:
  29                case IPPROTO_SCTP:
  30                case IPPROTO_IP:
  31                        return true;
  32                default:
  33                        return false;
  34                        }
  35        case IPV6_USER_FLOW:
  36                switch (fsp->h_u.usr_ip6_spec.l4_proto) {
  37                case IPPROTO_TCP:
  38                case IPPROTO_UDP:
  39                case IPPROTO_SCTP:
  40                case IPPROTO_IP:
  41                        return true;
  42                default:
  43                        return false;
  44                        }
  45        default:
  46                return false;
  47        }
  48
  49        return false;
  50}
  51
  52static bool __must_check
  53aq_match_filter(struct ethtool_rx_flow_spec *fsp1,
  54                struct ethtool_rx_flow_spec *fsp2)
  55{
  56        if (fsp1->flow_type != fsp2->flow_type ||
  57            memcmp(&fsp1->h_u, &fsp2->h_u, sizeof(fsp2->h_u)) ||
  58            memcmp(&fsp1->h_ext, &fsp2->h_ext, sizeof(fsp2->h_ext)) ||
  59            memcmp(&fsp1->m_u, &fsp2->m_u, sizeof(fsp2->m_u)) ||
  60            memcmp(&fsp1->m_ext, &fsp2->m_ext, sizeof(fsp2->m_ext)))
  61                return false;
  62
  63        return true;
  64}
  65
  66static bool __must_check
  67aq_rule_already_exists(struct aq_nic_s *aq_nic,
  68                       struct ethtool_rx_flow_spec *fsp)
  69{
  70        struct aq_rx_filter *rule;
  71        struct hlist_node *aq_node2;
  72        struct aq_hw_rx_fltrs_s *rx_fltrs = aq_get_hw_rx_fltrs(aq_nic);
  73
  74        hlist_for_each_entry_safe(rule, aq_node2,
  75                                  &rx_fltrs->filter_list, aq_node) {
  76                if (rule->aq_fsp.location == fsp->location)
  77                        continue;
  78                if (aq_match_filter(&rule->aq_fsp, fsp)) {
  79                        netdev_err(aq_nic->ndev,
  80                                   "ethtool: This filter is already set\n");
  81                        return true;
  82                }
  83        }
  84
  85        return false;
  86}
  87
  88static int aq_check_approve_fl3l4(struct aq_nic_s *aq_nic,
  89                                  struct aq_hw_rx_fltrs_s *rx_fltrs,
  90                                  struct ethtool_rx_flow_spec *fsp)
  91{
  92        if (fsp->location < AQ_RX_FIRST_LOC_FL3L4 ||
  93            fsp->location > AQ_RX_LAST_LOC_FL3L4) {
  94                netdev_err(aq_nic->ndev,
  95                           "ethtool: location must be in range [%d, %d]",
  96                           AQ_RX_FIRST_LOC_FL3L4,
  97                           AQ_RX_LAST_LOC_FL3L4);
  98                return -EINVAL;
  99        }
 100        if (rx_fltrs->fl3l4.is_ipv6 && rx_fltrs->fl3l4.active_ipv4) {
 101                rx_fltrs->fl3l4.is_ipv6 = false;
 102                netdev_err(aq_nic->ndev,
 103                           "ethtool: mixing ipv4 and ipv6 is not allowed");
 104                return -EINVAL;
 105        } else if (!rx_fltrs->fl3l4.is_ipv6 && rx_fltrs->fl3l4.active_ipv6) {
 106                rx_fltrs->fl3l4.is_ipv6 = true;
 107                netdev_err(aq_nic->ndev,
 108                           "ethtool: mixing ipv4 and ipv6 is not allowed");
 109                return -EINVAL;
 110        } else if (rx_fltrs->fl3l4.is_ipv6                    &&
 111                   fsp->location != AQ_RX_FIRST_LOC_FL3L4 + 4 &&
 112                   fsp->location != AQ_RX_FIRST_LOC_FL3L4) {
 113                netdev_err(aq_nic->ndev,
 114                           "ethtool: The specified location for ipv6 must be %d or %d",
 115                           AQ_RX_FIRST_LOC_FL3L4, AQ_RX_FIRST_LOC_FL3L4 + 4);
 116                return -EINVAL;
 117        }
 118
 119        return 0;
 120}
 121
 122static int __must_check
 123aq_check_approve_fl2(struct aq_nic_s *aq_nic,
 124                     struct aq_hw_rx_fltrs_s *rx_fltrs,
 125                     struct ethtool_rx_flow_spec *fsp)
 126{
 127        if (fsp->location < AQ_RX_FIRST_LOC_FETHERT ||
 128            fsp->location > AQ_RX_LAST_LOC_FETHERT) {
 129                netdev_err(aq_nic->ndev,
 130                           "ethtool: location must be in range [%d, %d]",
 131                           AQ_RX_FIRST_LOC_FETHERT,
 132                           AQ_RX_LAST_LOC_FETHERT);
 133                return -EINVAL;
 134        }
 135
 136        if (be16_to_cpu(fsp->m_ext.vlan_tci) == VLAN_PRIO_MASK &&
 137            fsp->m_u.ether_spec.h_proto == 0U) {
 138                netdev_err(aq_nic->ndev,
 139                           "ethtool: proto (ether_type) parameter must be specified");
 140                return -EINVAL;
 141        }
 142
 143        return 0;
 144}
 145
 146static int __must_check
 147aq_check_approve_fvlan(struct aq_nic_s *aq_nic,
 148                       struct aq_hw_rx_fltrs_s *rx_fltrs,
 149                       struct ethtool_rx_flow_spec *fsp)
 150{
 151        if (fsp->location < AQ_RX_FIRST_LOC_FVLANID ||
 152            fsp->location > AQ_RX_LAST_LOC_FVLANID) {
 153                netdev_err(aq_nic->ndev,
 154                           "ethtool: location must be in range [%d, %d]",
 155                           AQ_RX_FIRST_LOC_FVLANID,
 156                           AQ_RX_LAST_LOC_FVLANID);
 157                return -EINVAL;
 158        }
 159
 160        if ((aq_nic->ndev->features & NETIF_F_HW_VLAN_CTAG_FILTER) &&
 161            (!test_bit(be16_to_cpu(fsp->h_ext.vlan_tci),
 162                       aq_nic->active_vlans))) {
 163                netdev_err(aq_nic->ndev,
 164                           "ethtool: unknown vlan-id specified");
 165                return -EINVAL;
 166        }
 167
 168        if (fsp->ring_cookie > aq_nic->aq_nic_cfg.num_rss_queues) {
 169                netdev_err(aq_nic->ndev,
 170                           "ethtool: queue number must be in range [0, %d]",
 171                           aq_nic->aq_nic_cfg.num_rss_queues - 1);
 172                return -EINVAL;
 173        }
 174        return 0;
 175}
 176
 177static int __must_check
 178aq_check_filter(struct aq_nic_s *aq_nic,
 179                struct ethtool_rx_flow_spec *fsp)
 180{
 181        int err = 0;
 182        struct aq_hw_rx_fltrs_s *rx_fltrs = aq_get_hw_rx_fltrs(aq_nic);
 183
 184        if (fsp->flow_type & FLOW_EXT) {
 185                if (be16_to_cpu(fsp->m_ext.vlan_tci) == VLAN_VID_MASK) {
 186                        err = aq_check_approve_fvlan(aq_nic, rx_fltrs, fsp);
 187                } else if (be16_to_cpu(fsp->m_ext.vlan_tci) == VLAN_PRIO_MASK) {
 188                        err = aq_check_approve_fl2(aq_nic, rx_fltrs, fsp);
 189                } else {
 190                        netdev_err(aq_nic->ndev,
 191                                   "ethtool: invalid vlan mask 0x%x specified",
 192                                   be16_to_cpu(fsp->m_ext.vlan_tci));
 193                        err = -EINVAL;
 194                }
 195        } else {
 196                switch (fsp->flow_type & ~FLOW_EXT) {
 197                case ETHER_FLOW:
 198                        err = aq_check_approve_fl2(aq_nic, rx_fltrs, fsp);
 199                        break;
 200                case TCP_V4_FLOW:
 201                case UDP_V4_FLOW:
 202                case SCTP_V4_FLOW:
 203                case IPV4_FLOW:
 204                case IP_USER_FLOW:
 205                        rx_fltrs->fl3l4.is_ipv6 = false;
 206                        err = aq_check_approve_fl3l4(aq_nic, rx_fltrs, fsp);
 207                        break;
 208                case TCP_V6_FLOW:
 209                case UDP_V6_FLOW:
 210                case SCTP_V6_FLOW:
 211                case IPV6_FLOW:
 212                case IPV6_USER_FLOW:
 213                        rx_fltrs->fl3l4.is_ipv6 = true;
 214                        err = aq_check_approve_fl3l4(aq_nic, rx_fltrs, fsp);
 215                        break;
 216                default:
 217                        netdev_err(aq_nic->ndev,
 218                                   "ethtool: unknown flow-type specified");
 219                        err = -EINVAL;
 220                }
 221        }
 222
 223        return err;
 224}
 225
 226static bool __must_check
 227aq_rule_is_not_support(struct aq_nic_s *aq_nic,
 228                       struct ethtool_rx_flow_spec *fsp)
 229{
 230        bool rule_is_not_support = false;
 231
 232        if (!(aq_nic->ndev->features & NETIF_F_NTUPLE)) {
 233                netdev_err(aq_nic->ndev,
 234                           "ethtool: Please, to enable the RX flow control:\n"
 235                           "ethtool -K %s ntuple on\n", aq_nic->ndev->name);
 236                rule_is_not_support = true;
 237        } else if (!aq_rule_is_approve(fsp)) {
 238                netdev_err(aq_nic->ndev,
 239                           "ethtool: The specified flow type is not supported\n");
 240                rule_is_not_support = true;
 241        } else if ((fsp->flow_type & ~FLOW_EXT) != ETHER_FLOW &&
 242                   (fsp->h_u.tcp_ip4_spec.tos ||
 243                    fsp->h_u.tcp_ip6_spec.tclass)) {
 244                netdev_err(aq_nic->ndev,
 245                           "ethtool: The specified tos tclass are not supported\n");
 246                rule_is_not_support = true;
 247        } else if (fsp->flow_type & FLOW_MAC_EXT) {
 248                netdev_err(aq_nic->ndev,
 249                           "ethtool: MAC_EXT is not supported");
 250                rule_is_not_support = true;
 251        }
 252
 253        return rule_is_not_support;
 254}
 255
 256static bool __must_check
 257aq_rule_is_not_correct(struct aq_nic_s *aq_nic,
 258                       struct ethtool_rx_flow_spec *fsp)
 259{
 260        bool rule_is_not_correct = false;
 261
 262        if (!aq_nic) {
 263                rule_is_not_correct = true;
 264        } else if (fsp->location > AQ_RX_MAX_RXNFC_LOC) {
 265                netdev_err(aq_nic->ndev,
 266                           "ethtool: The specified number %u rule is invalid\n",
 267                           fsp->location);
 268                rule_is_not_correct = true;
 269        } else if (aq_check_filter(aq_nic, fsp)) {
 270                rule_is_not_correct = true;
 271        } else if (fsp->ring_cookie != RX_CLS_FLOW_DISC) {
 272                if (fsp->ring_cookie >= aq_nic->aq_nic_cfg.num_rss_queues) {
 273                        netdev_err(aq_nic->ndev,
 274                                   "ethtool: The specified action is invalid.\n"
 275                                   "Maximum allowable value action is %u.\n",
 276                                   aq_nic->aq_nic_cfg.num_rss_queues - 1);
 277                        rule_is_not_correct = true;
 278                }
 279        }
 280
 281        return rule_is_not_correct;
 282}
 283
 284static int __must_check
 285aq_check_rule(struct aq_nic_s *aq_nic,
 286              struct ethtool_rx_flow_spec *fsp)
 287{
 288        int err = 0;
 289
 290        if (aq_rule_is_not_correct(aq_nic, fsp))
 291                err = -EINVAL;
 292        else if (aq_rule_is_not_support(aq_nic, fsp))
 293                err = -EOPNOTSUPP;
 294        else if (aq_rule_already_exists(aq_nic, fsp))
 295                err = -EEXIST;
 296
 297        return err;
 298}
 299
 300static void aq_set_data_fl2(struct aq_nic_s *aq_nic,
 301                            struct aq_rx_filter *aq_rx_fltr,
 302                            struct aq_rx_filter_l2 *data, bool add)
 303{
 304        const struct ethtool_rx_flow_spec *fsp = &aq_rx_fltr->aq_fsp;
 305
 306        memset(data, 0, sizeof(*data));
 307
 308        data->location = fsp->location - AQ_RX_FIRST_LOC_FETHERT;
 309
 310        if (fsp->ring_cookie != RX_CLS_FLOW_DISC)
 311                data->queue = fsp->ring_cookie;
 312        else
 313                data->queue = -1;
 314
 315        data->ethertype = be16_to_cpu(fsp->h_u.ether_spec.h_proto);
 316        data->user_priority_en = be16_to_cpu(fsp->m_ext.vlan_tci)
 317                                 == VLAN_PRIO_MASK;
 318        data->user_priority = (be16_to_cpu(fsp->h_ext.vlan_tci)
 319                               & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
 320}
 321
 322static int aq_add_del_fether(struct aq_nic_s *aq_nic,
 323                             struct aq_rx_filter *aq_rx_fltr, bool add)
 324{
 325        struct aq_rx_filter_l2 data;
 326        struct aq_hw_s *aq_hw = aq_nic->aq_hw;
 327        const struct aq_hw_ops *aq_hw_ops = aq_nic->aq_hw_ops;
 328
 329        aq_set_data_fl2(aq_nic, aq_rx_fltr, &data, add);
 330
 331        if (unlikely(!aq_hw_ops->hw_filter_l2_set))
 332                return -EOPNOTSUPP;
 333        if (unlikely(!aq_hw_ops->hw_filter_l2_clear))
 334                return -EOPNOTSUPP;
 335
 336        if (add)
 337                return aq_hw_ops->hw_filter_l2_set(aq_hw, &data);
 338        else
 339                return aq_hw_ops->hw_filter_l2_clear(aq_hw, &data);
 340}
 341
 342static bool aq_fvlan_is_busy(struct aq_rx_filter_vlan *aq_vlans, int vlan)
 343{
 344        int i;
 345
 346        for (i = 0; i < AQ_VLAN_MAX_FILTERS; ++i) {
 347                if (aq_vlans[i].enable &&
 348                    aq_vlans[i].queue != AQ_RX_QUEUE_NOT_ASSIGNED &&
 349                    aq_vlans[i].vlan_id == vlan) {
 350                        return true;
 351                }
 352        }
 353
 354        return false;
 355}
 356
 357/* Function rebuilds array of vlan filters so that filters with assigned
 358 * queue have a precedence over just vlans on the interface.
 359 */
 360static void aq_fvlan_rebuild(struct aq_nic_s *aq_nic,
 361                             unsigned long *active_vlans,
 362                             struct aq_rx_filter_vlan *aq_vlans)
 363{
 364        bool vlan_busy = false;
 365        int vlan = -1;
 366        int i;
 367
 368        for (i = 0; i < AQ_VLAN_MAX_FILTERS; ++i) {
 369                if (aq_vlans[i].enable &&
 370                    aq_vlans[i].queue != AQ_RX_QUEUE_NOT_ASSIGNED)
 371                        continue;
 372                do {
 373                        vlan = find_next_bit(active_vlans,
 374                                             VLAN_N_VID,
 375                                             vlan + 1);
 376                        if (vlan == VLAN_N_VID) {
 377                                aq_vlans[i].enable = 0U;
 378                                aq_vlans[i].queue = AQ_RX_QUEUE_NOT_ASSIGNED;
 379                                aq_vlans[i].vlan_id = 0;
 380                                continue;
 381                        }
 382
 383                        vlan_busy = aq_fvlan_is_busy(aq_vlans, vlan);
 384                        if (!vlan_busy) {
 385                                aq_vlans[i].enable = 1U;
 386                                aq_vlans[i].queue = AQ_RX_QUEUE_NOT_ASSIGNED;
 387                                aq_vlans[i].vlan_id = vlan;
 388                        }
 389                } while (vlan_busy && vlan != VLAN_N_VID);
 390        }
 391}
 392
 393static int aq_set_data_fvlan(struct aq_nic_s *aq_nic,
 394                             struct aq_rx_filter *aq_rx_fltr,
 395                             struct aq_rx_filter_vlan *aq_vlans, bool add)
 396{
 397        const struct ethtool_rx_flow_spec *fsp = &aq_rx_fltr->aq_fsp;
 398        int location = fsp->location - AQ_RX_FIRST_LOC_FVLANID;
 399        int i;
 400
 401        memset(&aq_vlans[location], 0, sizeof(aq_vlans[location]));
 402
 403        if (!add)
 404                return 0;
 405
 406        /* remove vlan if it was in table without queue assignment */
 407        for (i = 0; i < AQ_VLAN_MAX_FILTERS; ++i) {
 408                if (aq_vlans[i].vlan_id ==
 409                   (be16_to_cpu(fsp->h_ext.vlan_tci) & VLAN_VID_MASK)) {
 410                        aq_vlans[i].enable = false;
 411                }
 412        }
 413
 414        aq_vlans[location].location = location;
 415        aq_vlans[location].vlan_id = be16_to_cpu(fsp->h_ext.vlan_tci)
 416                                     & VLAN_VID_MASK;
 417        aq_vlans[location].queue = fsp->ring_cookie & 0x1FU;
 418        aq_vlans[location].enable = 1U;
 419
 420        return 0;
 421}
 422
 423int aq_del_fvlan_by_vlan(struct aq_nic_s *aq_nic, u16 vlan_id)
 424{
 425        struct aq_hw_rx_fltrs_s *rx_fltrs = aq_get_hw_rx_fltrs(aq_nic);
 426        struct aq_rx_filter *rule = NULL;
 427        struct hlist_node *aq_node2;
 428
 429        hlist_for_each_entry_safe(rule, aq_node2,
 430                                  &rx_fltrs->filter_list, aq_node) {
 431                if (be16_to_cpu(rule->aq_fsp.h_ext.vlan_tci) == vlan_id)
 432                        break;
 433        }
 434        if (rule && rule->type == aq_rx_filter_vlan &&
 435            be16_to_cpu(rule->aq_fsp.h_ext.vlan_tci) == vlan_id) {
 436                struct ethtool_rxnfc cmd;
 437
 438                cmd.fs.location = rule->aq_fsp.location;
 439                return aq_del_rxnfc_rule(aq_nic, &cmd);
 440        }
 441
 442        return -ENOENT;
 443}
 444
 445static int aq_add_del_fvlan(struct aq_nic_s *aq_nic,
 446                            struct aq_rx_filter *aq_rx_fltr, bool add)
 447{
 448        const struct aq_hw_ops *aq_hw_ops = aq_nic->aq_hw_ops;
 449
 450        if (unlikely(!aq_hw_ops->hw_filter_vlan_set))
 451                return -EOPNOTSUPP;
 452
 453        aq_set_data_fvlan(aq_nic,
 454                          aq_rx_fltr,
 455                          aq_nic->aq_hw_rx_fltrs.fl2.aq_vlans,
 456                          add);
 457
 458        return aq_filters_vlans_update(aq_nic);
 459}
 460
 461static int aq_set_data_fl3l4(struct aq_nic_s *aq_nic,
 462                             struct aq_rx_filter *aq_rx_fltr,
 463                             struct aq_rx_filter_l3l4 *data, bool add)
 464{
 465        struct aq_hw_rx_fltrs_s *rx_fltrs = aq_get_hw_rx_fltrs(aq_nic);
 466        const struct ethtool_rx_flow_spec *fsp = &aq_rx_fltr->aq_fsp;
 467
 468        memset(data, 0, sizeof(*data));
 469
 470        data->is_ipv6 = rx_fltrs->fl3l4.is_ipv6;
 471        data->location = HW_ATL_GET_REG_LOCATION_FL3L4(fsp->location);
 472
 473        if (!add) {
 474                if (!data->is_ipv6)
 475                        rx_fltrs->fl3l4.active_ipv4 &= ~BIT(data->location);
 476                else
 477                        rx_fltrs->fl3l4.active_ipv6 &=
 478                                ~BIT((data->location) / 4);
 479
 480                return 0;
 481        }
 482
 483        data->cmd |= HW_ATL_RX_ENABLE_FLTR_L3L4;
 484
 485        switch (fsp->flow_type) {
 486        case TCP_V4_FLOW:
 487        case TCP_V6_FLOW:
 488                data->cmd |= HW_ATL_RX_ENABLE_CMP_PROT_L4;
 489                break;
 490        case UDP_V4_FLOW:
 491        case UDP_V6_FLOW:
 492                data->cmd |= HW_ATL_RX_UDP;
 493                data->cmd |= HW_ATL_RX_ENABLE_CMP_PROT_L4;
 494                break;
 495        case SCTP_V4_FLOW:
 496        case SCTP_V6_FLOW:
 497                data->cmd |= HW_ATL_RX_SCTP;
 498                data->cmd |= HW_ATL_RX_ENABLE_CMP_PROT_L4;
 499                break;
 500        default:
 501                break;
 502        }
 503
 504        if (!data->is_ipv6) {
 505                data->ip_src[0] =
 506                        ntohl(fsp->h_u.tcp_ip4_spec.ip4src);
 507                data->ip_dst[0] =
 508                        ntohl(fsp->h_u.tcp_ip4_spec.ip4dst);
 509                rx_fltrs->fl3l4.active_ipv4 |= BIT(data->location);
 510        } else {
 511                int i;
 512
 513                rx_fltrs->fl3l4.active_ipv6 |= BIT((data->location) / 4);
 514                for (i = 0; i < HW_ATL_RX_CNT_REG_ADDR_IPV6; ++i) {
 515                        data->ip_dst[i] =
 516                                ntohl(fsp->h_u.tcp_ip6_spec.ip6dst[i]);
 517                        data->ip_src[i] =
 518                                ntohl(fsp->h_u.tcp_ip6_spec.ip6src[i]);
 519                }
 520                data->cmd |= HW_ATL_RX_ENABLE_L3_IPV6;
 521        }
 522        if (fsp->flow_type != IP_USER_FLOW &&
 523            fsp->flow_type != IPV6_USER_FLOW) {
 524                if (!data->is_ipv6) {
 525                        data->p_dst =
 526                                ntohs(fsp->h_u.tcp_ip4_spec.pdst);
 527                        data->p_src =
 528                                ntohs(fsp->h_u.tcp_ip4_spec.psrc);
 529                } else {
 530                        data->p_dst =
 531                                ntohs(fsp->h_u.tcp_ip6_spec.pdst);
 532                        data->p_src =
 533                                ntohs(fsp->h_u.tcp_ip6_spec.psrc);
 534                }
 535        }
 536        if (data->ip_src[0] && !data->is_ipv6)
 537                data->cmd |= HW_ATL_RX_ENABLE_CMP_SRC_ADDR_L3;
 538        if (data->ip_dst[0] && !data->is_ipv6)
 539                data->cmd |= HW_ATL_RX_ENABLE_CMP_DEST_ADDR_L3;
 540        if (data->p_dst)
 541                data->cmd |= HW_ATL_RX_ENABLE_CMP_DEST_PORT_L4;
 542        if (data->p_src)
 543                data->cmd |= HW_ATL_RX_ENABLE_CMP_SRC_PORT_L4;
 544        if (fsp->ring_cookie != RX_CLS_FLOW_DISC) {
 545                data->cmd |= HW_ATL_RX_HOST << HW_ATL_RX_ACTION_FL3F4_SHIFT;
 546                data->cmd |= fsp->ring_cookie << HW_ATL_RX_QUEUE_FL3L4_SHIFT;
 547                data->cmd |= HW_ATL_RX_ENABLE_QUEUE_L3L4;
 548        } else {
 549                data->cmd |= HW_ATL_RX_DISCARD << HW_ATL_RX_ACTION_FL3F4_SHIFT;
 550        }
 551
 552        return 0;
 553}
 554
 555static int aq_set_fl3l4(struct aq_hw_s *aq_hw,
 556                        const struct aq_hw_ops *aq_hw_ops,
 557                        struct aq_rx_filter_l3l4 *data)
 558{
 559        if (unlikely(!aq_hw_ops->hw_filter_l3l4_set))
 560                return -EOPNOTSUPP;
 561
 562        return aq_hw_ops->hw_filter_l3l4_set(aq_hw, data);
 563}
 564
 565static int aq_add_del_fl3l4(struct aq_nic_s *aq_nic,
 566                            struct aq_rx_filter *aq_rx_fltr, bool add)
 567{
 568        const struct aq_hw_ops *aq_hw_ops = aq_nic->aq_hw_ops;
 569        struct aq_hw_s *aq_hw = aq_nic->aq_hw;
 570        struct aq_rx_filter_l3l4 data;
 571
 572        if (unlikely(aq_rx_fltr->aq_fsp.location < AQ_RX_FIRST_LOC_FL3L4 ||
 573                     aq_rx_fltr->aq_fsp.location > AQ_RX_LAST_LOC_FL3L4  ||
 574                     aq_set_data_fl3l4(aq_nic, aq_rx_fltr, &data, add)))
 575                return -EINVAL;
 576
 577        return aq_set_fl3l4(aq_hw, aq_hw_ops, &data);
 578}
 579
 580static int aq_add_del_rule(struct aq_nic_s *aq_nic,
 581                           struct aq_rx_filter *aq_rx_fltr, bool add)
 582{
 583        int err = -EINVAL;
 584
 585        if (aq_rx_fltr->aq_fsp.flow_type & FLOW_EXT) {
 586                if (be16_to_cpu(aq_rx_fltr->aq_fsp.m_ext.vlan_tci)
 587                    == VLAN_VID_MASK) {
 588                        aq_rx_fltr->type = aq_rx_filter_vlan;
 589                        err = aq_add_del_fvlan(aq_nic, aq_rx_fltr, add);
 590                } else if (be16_to_cpu(aq_rx_fltr->aq_fsp.m_ext.vlan_tci)
 591                        == VLAN_PRIO_MASK) {
 592                        aq_rx_fltr->type = aq_rx_filter_ethertype;
 593                        err = aq_add_del_fether(aq_nic, aq_rx_fltr, add);
 594                }
 595        } else {
 596                switch (aq_rx_fltr->aq_fsp.flow_type & ~FLOW_EXT) {
 597                case ETHER_FLOW:
 598                        aq_rx_fltr->type = aq_rx_filter_ethertype;
 599                        err = aq_add_del_fether(aq_nic, aq_rx_fltr, add);
 600                        break;
 601                case TCP_V4_FLOW:
 602                case UDP_V4_FLOW:
 603                case SCTP_V4_FLOW:
 604                case IP_USER_FLOW:
 605                case TCP_V6_FLOW:
 606                case UDP_V6_FLOW:
 607                case SCTP_V6_FLOW:
 608                case IPV6_USER_FLOW:
 609                        aq_rx_fltr->type = aq_rx_filter_l3l4;
 610                        err = aq_add_del_fl3l4(aq_nic, aq_rx_fltr, add);
 611                        break;
 612                default:
 613                        err = -EINVAL;
 614                        break;
 615                }
 616        }
 617
 618        return err;
 619}
 620
 621static int aq_update_table_filters(struct aq_nic_s *aq_nic,
 622                                   struct aq_rx_filter *aq_rx_fltr, u16 index,
 623                                   struct ethtool_rxnfc *cmd)
 624{
 625        struct aq_hw_rx_fltrs_s *rx_fltrs = aq_get_hw_rx_fltrs(aq_nic);
 626        struct aq_rx_filter *rule = NULL, *parent = NULL;
 627        struct hlist_node *aq_node2;
 628        int err = -EINVAL;
 629
 630        hlist_for_each_entry_safe(rule, aq_node2,
 631                                  &rx_fltrs->filter_list, aq_node) {
 632                if (rule->aq_fsp.location >= index)
 633                        break;
 634                parent = rule;
 635        }
 636
 637        if (rule && rule->aq_fsp.location == index) {
 638                err = aq_add_del_rule(aq_nic, rule, false);
 639                hlist_del(&rule->aq_node);
 640                kfree(rule);
 641                --rx_fltrs->active_filters;
 642        }
 643
 644        if (unlikely(!aq_rx_fltr))
 645                return err;
 646
 647        INIT_HLIST_NODE(&aq_rx_fltr->aq_node);
 648
 649        if (parent)
 650                hlist_add_behind(&aq_rx_fltr->aq_node, &parent->aq_node);
 651        else
 652                hlist_add_head(&aq_rx_fltr->aq_node, &rx_fltrs->filter_list);
 653
 654        ++rx_fltrs->active_filters;
 655
 656        return 0;
 657}
 658
 659u16 aq_get_rxnfc_count_all_rules(struct aq_nic_s *aq_nic)
 660{
 661        struct aq_hw_rx_fltrs_s *rx_fltrs = aq_get_hw_rx_fltrs(aq_nic);
 662
 663        return rx_fltrs->active_filters;
 664}
 665
 666struct aq_hw_rx_fltrs_s *aq_get_hw_rx_fltrs(struct aq_nic_s *aq_nic)
 667{
 668        return &aq_nic->aq_hw_rx_fltrs;
 669}
 670
 671int aq_add_rxnfc_rule(struct aq_nic_s *aq_nic, const struct ethtool_rxnfc *cmd)
 672{
 673        struct aq_hw_rx_fltrs_s *rx_fltrs = aq_get_hw_rx_fltrs(aq_nic);
 674        struct ethtool_rx_flow_spec *fsp =
 675                (struct ethtool_rx_flow_spec *)&cmd->fs;
 676        struct aq_rx_filter *aq_rx_fltr;
 677        int err = 0;
 678
 679        err = aq_check_rule(aq_nic, fsp);
 680        if (err)
 681                goto err_exit;
 682
 683        aq_rx_fltr = kzalloc(sizeof(*aq_rx_fltr), GFP_KERNEL);
 684        if (unlikely(!aq_rx_fltr)) {
 685                err = -ENOMEM;
 686                goto err_exit;
 687        }
 688
 689        memcpy(&aq_rx_fltr->aq_fsp, fsp, sizeof(*fsp));
 690
 691        err = aq_update_table_filters(aq_nic, aq_rx_fltr, fsp->location, NULL);
 692        if (unlikely(err))
 693                goto err_free;
 694
 695        err = aq_add_del_rule(aq_nic, aq_rx_fltr, true);
 696        if (unlikely(err)) {
 697                hlist_del(&aq_rx_fltr->aq_node);
 698                --rx_fltrs->active_filters;
 699                goto err_free;
 700        }
 701
 702        return 0;
 703
 704err_free:
 705        kfree(aq_rx_fltr);
 706err_exit:
 707        return err;
 708}
 709
 710int aq_del_rxnfc_rule(struct aq_nic_s *aq_nic, const struct ethtool_rxnfc *cmd)
 711{
 712        struct aq_hw_rx_fltrs_s *rx_fltrs = aq_get_hw_rx_fltrs(aq_nic);
 713        struct aq_rx_filter *rule = NULL;
 714        struct hlist_node *aq_node2;
 715        int err = -EINVAL;
 716
 717        hlist_for_each_entry_safe(rule, aq_node2,
 718                                  &rx_fltrs->filter_list, aq_node) {
 719                if (rule->aq_fsp.location == cmd->fs.location)
 720                        break;
 721        }
 722
 723        if (rule && rule->aq_fsp.location == cmd->fs.location) {
 724                err = aq_add_del_rule(aq_nic, rule, false);
 725                hlist_del(&rule->aq_node);
 726                kfree(rule);
 727                --rx_fltrs->active_filters;
 728        }
 729        return err;
 730}
 731
 732int aq_get_rxnfc_rule(struct aq_nic_s *aq_nic, struct ethtool_rxnfc *cmd)
 733{
 734        struct aq_hw_rx_fltrs_s *rx_fltrs = aq_get_hw_rx_fltrs(aq_nic);
 735        struct ethtool_rx_flow_spec *fsp =
 736                        (struct ethtool_rx_flow_spec *)&cmd->fs;
 737        struct aq_rx_filter *rule = NULL;
 738        struct hlist_node *aq_node2;
 739
 740        hlist_for_each_entry_safe(rule, aq_node2,
 741                                  &rx_fltrs->filter_list, aq_node)
 742                if (fsp->location <= rule->aq_fsp.location)
 743                        break;
 744
 745        if (unlikely(!rule || fsp->location != rule->aq_fsp.location))
 746                return -EINVAL;
 747
 748        memcpy(fsp, &rule->aq_fsp, sizeof(*fsp));
 749
 750        return 0;
 751}
 752
 753int aq_get_rxnfc_all_rules(struct aq_nic_s *aq_nic, struct ethtool_rxnfc *cmd,
 754                           u32 *rule_locs)
 755{
 756        struct aq_hw_rx_fltrs_s *rx_fltrs = aq_get_hw_rx_fltrs(aq_nic);
 757        struct hlist_node *aq_node2;
 758        struct aq_rx_filter *rule;
 759        int count = 0;
 760
 761        cmd->data = aq_get_rxnfc_count_all_rules(aq_nic);
 762
 763        hlist_for_each_entry_safe(rule, aq_node2,
 764                                  &rx_fltrs->filter_list, aq_node) {
 765                if (unlikely(count == cmd->rule_cnt))
 766                        return -EMSGSIZE;
 767
 768                rule_locs[count++] = rule->aq_fsp.location;
 769        }
 770
 771        cmd->rule_cnt = count;
 772
 773        return 0;
 774}
 775
 776int aq_clear_rxnfc_all_rules(struct aq_nic_s *aq_nic)
 777{
 778        struct aq_hw_rx_fltrs_s *rx_fltrs = aq_get_hw_rx_fltrs(aq_nic);
 779        struct hlist_node *aq_node2;
 780        struct aq_rx_filter *rule;
 781        int err = 0;
 782
 783        hlist_for_each_entry_safe(rule, aq_node2,
 784                                  &rx_fltrs->filter_list, aq_node) {
 785                err = aq_add_del_rule(aq_nic, rule, false);
 786                if (err)
 787                        goto err_exit;
 788                hlist_del(&rule->aq_node);
 789                kfree(rule);
 790                --rx_fltrs->active_filters;
 791        }
 792
 793err_exit:
 794        return err;
 795}
 796
 797int aq_reapply_rxnfc_all_rules(struct aq_nic_s *aq_nic)
 798{
 799        struct aq_hw_rx_fltrs_s *rx_fltrs = aq_get_hw_rx_fltrs(aq_nic);
 800        struct hlist_node *aq_node2;
 801        struct aq_rx_filter *rule;
 802        int err = 0;
 803
 804        hlist_for_each_entry_safe(rule, aq_node2,
 805                                  &rx_fltrs->filter_list, aq_node) {
 806                err = aq_add_del_rule(aq_nic, rule, true);
 807                if (err)
 808                        goto err_exit;
 809        }
 810
 811err_exit:
 812        return err;
 813}
 814
 815int aq_filters_vlans_update(struct aq_nic_s *aq_nic)
 816{
 817        const struct aq_hw_ops *aq_hw_ops = aq_nic->aq_hw_ops;
 818        struct aq_hw_s *aq_hw = aq_nic->aq_hw;
 819        int hweight = 0;
 820        int err = 0;
 821        int i;
 822
 823        if (unlikely(!aq_hw_ops->hw_filter_vlan_set))
 824                return -EOPNOTSUPP;
 825        if (unlikely(!aq_hw_ops->hw_filter_vlan_ctrl))
 826                return -EOPNOTSUPP;
 827
 828        aq_fvlan_rebuild(aq_nic, aq_nic->active_vlans,
 829                         aq_nic->aq_hw_rx_fltrs.fl2.aq_vlans);
 830
 831        if (aq_nic->ndev->features & NETIF_F_HW_VLAN_CTAG_FILTER) {
 832                for (i = 0; i < BITS_TO_LONGS(VLAN_N_VID); i++)
 833                        hweight += hweight_long(aq_nic->active_vlans[i]);
 834
 835                err = aq_hw_ops->hw_filter_vlan_ctrl(aq_hw, false);
 836                if (err)
 837                        return err;
 838        }
 839
 840        err = aq_hw_ops->hw_filter_vlan_set(aq_hw,
 841                                            aq_nic->aq_hw_rx_fltrs.fl2.aq_vlans
 842                                           );
 843        if (err)
 844                return err;
 845
 846        if (aq_nic->ndev->features & NETIF_F_HW_VLAN_CTAG_FILTER) {
 847                if (hweight <= AQ_VLAN_MAX_FILTERS && hweight > 0) {
 848                        err = aq_hw_ops->hw_filter_vlan_ctrl(aq_hw,
 849                                !(aq_nic->packet_filter & IFF_PROMISC));
 850                        aq_nic->aq_nic_cfg.is_vlan_force_promisc = false;
 851                } else {
 852                /* otherwise left in promiscue mode */
 853                        aq_nic->aq_nic_cfg.is_vlan_force_promisc = true;
 854                }
 855        }
 856
 857        return err;
 858}
 859
 860int aq_filters_vlan_offload_off(struct aq_nic_s *aq_nic)
 861{
 862        const struct aq_hw_ops *aq_hw_ops = aq_nic->aq_hw_ops;
 863        struct aq_hw_s *aq_hw = aq_nic->aq_hw;
 864        int err = 0;
 865
 866        memset(aq_nic->active_vlans, 0, sizeof(aq_nic->active_vlans));
 867        aq_fvlan_rebuild(aq_nic, aq_nic->active_vlans,
 868                         aq_nic->aq_hw_rx_fltrs.fl2.aq_vlans);
 869
 870        if (unlikely(!aq_hw_ops->hw_filter_vlan_set))
 871                return -EOPNOTSUPP;
 872        if (unlikely(!aq_hw_ops->hw_filter_vlan_ctrl))
 873                return -EOPNOTSUPP;
 874
 875        aq_nic->aq_nic_cfg.is_vlan_force_promisc = true;
 876        err = aq_hw_ops->hw_filter_vlan_ctrl(aq_hw, false);
 877        if (err)
 878                return err;
 879        err = aq_hw_ops->hw_filter_vlan_set(aq_hw,
 880                                            aq_nic->aq_hw_rx_fltrs.fl2.aq_vlans
 881                                           );
 882        return err;
 883}
 884