i40e/base: support CEE DCBX
[dpdk.git] / lib / librte_pmd_i40e / i40e_fdir.c
index d75b96e..612377a 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
                        I40E_PRTQF_FLX_PIT_DEST_OFF_SHIFT) & \
                        I40E_PRTQF_FLX_PIT_DEST_OFF_MASK))
 
-#define I40E_FDIR_FLOW_TYPES ( \
-       (1 << RTE_ETH_FLOW_TYPE_UDPV4) | \
-       (1 << RTE_ETH_FLOW_TYPE_TCPV4) | \
-       (1 << RTE_ETH_FLOW_TYPE_SCTPV4) | \
-       (1 << RTE_ETH_FLOW_TYPE_IPV4_OTHER) | \
-       (1 << RTE_ETH_FLOW_TYPE_FRAG_IPV4) | \
-       (1 << RTE_ETH_FLOW_TYPE_UDPV6) | \
-       (1 << RTE_ETH_FLOW_TYPE_TCPV6) | \
-       (1 << RTE_ETH_FLOW_TYPE_SCTPV6) | \
-       (1 << RTE_ETH_FLOW_TYPE_IPV6_OTHER) | \
-       (1 << RTE_ETH_FLOW_TYPE_FRAG_IPV6))
+#define I40E_FDIR_FLOWS ( \
+       (1 << RTE_ETH_FLOW_FRAG_IPV4) | \
+       (1 << RTE_ETH_FLOW_NONFRAG_IPV4_UDP) | \
+       (1 << RTE_ETH_FLOW_NONFRAG_IPV4_TCP) | \
+       (1 << RTE_ETH_FLOW_NONFRAG_IPV4_SCTP) | \
+       (1 << RTE_ETH_FLOW_NONFRAG_IPV4_OTHER) | \
+       (1 << RTE_ETH_FLOW_FRAG_IPV6) | \
+       (1 << RTE_ETH_FLOW_NONFRAG_IPV6_UDP) | \
+       (1 << RTE_ETH_FLOW_NONFRAG_IPV6_TCP) | \
+       (1 << RTE_ETH_FLOW_NONFRAG_IPV6_SCTP) | \
+       (1 << RTE_ETH_FLOW_NONFRAG_IPV6_OTHER))
 
 #define I40E_FLEX_WORD_MASK(off) (0x80 >> (off))
 
@@ -196,6 +196,11 @@ i40e_fdir_setup(struct i40e_pf *pf)
        const struct rte_memzone *mz = NULL;
        struct rte_eth_dev *eth_dev = pf->adapter->eth_dev;
 
+       if ((pf->flags & I40E_FLAG_FDIR) == 0) {
+               PMD_INIT_LOG(ERR, "HW doesn't support FDIR");
+               return I40E_NOT_SUPPORTED;
+       }
+
        PMD_DRV_LOG(INFO, "FDIR HW Capabilities: num_filters_guaranteed = %u,"
                        " num_filters_best_effort = %u.",
                        hw->func_caps.fd_filters_guaranteed,
@@ -203,9 +208,8 @@ i40e_fdir_setup(struct i40e_pf *pf)
 
        vsi = pf->fdir.fdir_vsi;
        if (vsi) {
-               PMD_DRV_LOG(ERR, "FDIR vsi pointer needs "
-                                "to be null before creation.");
-               return I40E_ERR_BAD_PTR;
+               PMD_DRV_LOG(INFO, "FDIR initialization has been done.");
+               return I40E_SUCCESS;
        }
        /* make new FDIR VSI */
        vsi = i40e_vsi_setup(pf, I40E_VSI_FDIR, pf->main_vsi, 0);
@@ -302,6 +306,8 @@ i40e_fdir_teardown(struct i40e_pf *pf)
        struct i40e_vsi *vsi;
 
        vsi = pf->fdir.fdir_vsi;
+       if (!vsi)
+               return;
        i40e_switch_tx_queue(hw, vsi->base_queue, FALSE);
        i40e_switch_rx_queue(hw, vsi->base_queue, FALSE);
        i40e_dev_rx_queue_release(pf->fdir.rxq);
@@ -396,28 +402,27 @@ i40e_srcoff_to_flx_pit(const uint16_t *src_offset,
 
        while (j < I40E_FDIR_MAX_FLEX_LEN) {
                size = 1;
-               for (; j < I40E_FDIR_MAX_FLEX_LEN; j++) {
+               for (; j < I40E_FDIR_MAX_FLEX_LEN - 1; j++) {
                        if (src_offset[j + 1] == src_offset[j] + 1)
                                size++;
-                       else {
-                               src_tmp = src_offset[j] + 1 - size;
-                               /* the flex_pit need to be sort by scr_offset */
-                               for (i = 0; i < num; i++) {
-                                       if (src_tmp < flex_pit[i].src_offset)
-                                               break;
-                               }
-                               /* if insert required, move backward */
-                               for (k = num; k > i; k--)
-                                       flex_pit[k] = flex_pit[k - 1];
-                               /* insert */
-                               flex_pit[i].dst_offset = j + 1 - size;
-                               flex_pit[i].src_offset = src_tmp;
-                               flex_pit[i].size = size;
-                               j++;
-                               num++;
+                       else
+                               break;
+               }
+               src_tmp = src_offset[j] + 1 - size;
+               /* the flex_pit need to be sort by src_offset */
+               for (i = 0; i < num; i++) {
+                       if (src_tmp < flex_pit[i].src_offset)
                                break;
-                       }
                }
+               /* if insert required, move backward */
+               for (k = num; k > i; k--)
+                       flex_pit[k] = flex_pit[k - 1];
+               /* insert */
+               flex_pit[i].dst_offset = j + 1 - size;
+               flex_pit[i].src_offset = src_tmp;
+               flex_pit[i].size = size;
+               j++;
+               num++;
        }
        return num;
 }
@@ -492,13 +497,13 @@ i40e_check_fdir_flex_conf(const struct rte_eth_fdir_flex_conf *conf)
        }
 
        /* check flex mask setting configuration */
-       if (conf->nb_flexmasks > RTE_ETH_FLOW_TYPE_FRAG_IPV6) {
+       if (conf->nb_flexmasks >= RTE_ETH_FLOW_MAX) {
                PMD_DRV_LOG(ERR, "invalid number of flex masks.");
                return -EINVAL;
        }
        for (i = 0; i < conf->nb_flexmasks; i++) {
                flex_mask = &conf->flex_mask[i];
-               if (!I40E_VALID_FLOW_TYPE(flex_mask->flow_type)) {
+               if (!I40E_VALID_FLOW(flex_mask->flow_type)) {
                        PMD_DRV_LOG(WARNING, "invalid flow type.");
                        return -EINVAL;
                }
@@ -653,37 +658,26 @@ i40e_fdir_configure(struct rte_eth_dev *dev)
                }
        }
 
+       /* enable FDIR filter */
        val = I40E_READ_REG(hw, I40E_PFQF_CTL_0);
-       if ((pf->flags & I40E_FLAG_FDIR) &&
-               dev->data->dev_conf.fdir_conf.mode == RTE_FDIR_MODE_PERFECT) {
-               /* enable FDIR filter */
-               val |= I40E_PFQF_CTL_0_FD_ENA_MASK;
-               I40E_WRITE_REG(hw, I40E_PFQF_CTL_0, val);
+       val |= I40E_PFQF_CTL_0_FD_ENA_MASK;
+       I40E_WRITE_REG(hw, I40E_PFQF_CTL_0, val);
 
-               i40e_init_flx_pld(pf); /* set flex config to default value */
+       i40e_init_flx_pld(pf); /* set flex config to default value */
 
-               conf = &dev->data->dev_conf.fdir_conf.flex_conf;
-               ret = i40e_check_fdir_flex_conf(conf);
-               if (ret < 0) {
-                       PMD_DRV_LOG(ERR, " invalid configuration arguments.");
-                       return -EINVAL;
-               }
-               /* configure flex payload */
-               for (i = 0; i < conf->nb_payloads; i++)
-                       i40e_set_flx_pld_cfg(pf, &conf->flex_set[i]);
-               /* configure flex mask*/
-               for (i = 0; i < conf->nb_flexmasks; i++) {
-                       pctype = i40e_flowtype_to_pctype(
-                               conf->flex_mask[i].flow_type);
-                       i40e_set_flex_mask_on_pctype(pf,
-                                       pctype,
-                                       &conf->flex_mask[i]);
-               }
-       } else {
-               /* disable FDIR filter */
-               val &= ~I40E_PFQF_CTL_0_FD_ENA_MASK;
-               I40E_WRITE_REG(hw, I40E_PFQF_CTL_0, val);
-               pf->flags &= ~I40E_FLAG_FDIR;
+       conf = &dev->data->dev_conf.fdir_conf.flex_conf;
+       ret = i40e_check_fdir_flex_conf(conf);
+       if (ret < 0) {
+               PMD_DRV_LOG(ERR, " invalid configuration arguments.");
+               return -EINVAL;
+       }
+       /* configure flex payload */
+       for (i = 0; i < conf->nb_payloads; i++)
+               i40e_set_flx_pld_cfg(pf, &conf->flex_set[i]);
+       /* configure flex mask*/
+       for (i = 0; i < conf->nb_flexmasks; i++) {
+               pctype = i40e_flowtype_to_pctype(conf->flex_mask[i].flow_type);
+               i40e_set_flex_mask_on_pctype(pf, pctype, &conf->flex_mask[i]);
        }
 
        return ret;
@@ -697,24 +691,24 @@ i40e_fdir_fill_eth_ip_head(const struct rte_eth_fdir_input *fdir_input,
        struct ipv4_hdr *ip;
        struct ipv6_hdr *ip6;
        static const uint8_t next_proto[] = {
-               [RTE_ETH_FLOW_TYPE_UDPV4] = IPPROTO_UDP,
-               [RTE_ETH_FLOW_TYPE_TCPV4] = IPPROTO_TCP,
-               [RTE_ETH_FLOW_TYPE_SCTPV4] = IPPROTO_SCTP,
-               [RTE_ETH_FLOW_TYPE_IPV4_OTHER] = IPPROTO_IP,
-               [RTE_ETH_FLOW_TYPE_FRAG_IPV4] = IPPROTO_IP,
-               [RTE_ETH_FLOW_TYPE_UDPV6] = IPPROTO_UDP,
-               [RTE_ETH_FLOW_TYPE_TCPV6] = IPPROTO_TCP,
-               [RTE_ETH_FLOW_TYPE_SCTPV6] = IPPROTO_SCTP,
-               [RTE_ETH_FLOW_TYPE_IPV6_OTHER] = IPPROTO_NONE,
-               [RTE_ETH_FLOW_TYPE_FRAG_IPV6] = IPPROTO_NONE,
+               [RTE_ETH_FLOW_FRAG_IPV4] = IPPROTO_IP,
+               [RTE_ETH_FLOW_NONFRAG_IPV4_TCP] = IPPROTO_TCP,
+               [RTE_ETH_FLOW_NONFRAG_IPV4_UDP] = IPPROTO_UDP,
+               [RTE_ETH_FLOW_NONFRAG_IPV4_SCTP] = IPPROTO_SCTP,
+               [RTE_ETH_FLOW_NONFRAG_IPV4_OTHER] = IPPROTO_IP,
+               [RTE_ETH_FLOW_FRAG_IPV6] = IPPROTO_NONE,
+               [RTE_ETH_FLOW_NONFRAG_IPV6_TCP] = IPPROTO_TCP,
+               [RTE_ETH_FLOW_NONFRAG_IPV6_UDP] = IPPROTO_UDP,
+               [RTE_ETH_FLOW_NONFRAG_IPV6_SCTP] = IPPROTO_SCTP,
+               [RTE_ETH_FLOW_NONFRAG_IPV6_OTHER] = IPPROTO_NONE,
        };
 
        switch (fdir_input->flow_type) {
-       case RTE_ETH_FLOW_TYPE_UDPV4:
-       case RTE_ETH_FLOW_TYPE_TCPV4:
-       case RTE_ETH_FLOW_TYPE_SCTPV4:
-       case RTE_ETH_FLOW_TYPE_IPV4_OTHER:
-       case RTE_ETH_FLOW_TYPE_FRAG_IPV4:
+       case RTE_ETH_FLOW_NONFRAG_IPV4_TCP:
+       case RTE_ETH_FLOW_NONFRAG_IPV4_UDP:
+       case RTE_ETH_FLOW_NONFRAG_IPV4_SCTP:
+       case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER:
+       case RTE_ETH_FLOW_FRAG_IPV4:
                ip = (struct ipv4_hdr *)(raw_pkt + sizeof(struct ether_hdr));
 
                ether->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
@@ -731,11 +725,11 @@ i40e_fdir_fill_eth_ip_head(const struct rte_eth_fdir_input *fdir_input,
                ip->dst_addr = fdir_input->flow.ip4_flow.src_ip;
                ip->next_proto_id = next_proto[fdir_input->flow_type];
                break;
-       case RTE_ETH_FLOW_TYPE_UDPV6:
-       case RTE_ETH_FLOW_TYPE_TCPV6:
-       case RTE_ETH_FLOW_TYPE_SCTPV6:
-       case RTE_ETH_FLOW_TYPE_IPV6_OTHER:
-       case RTE_ETH_FLOW_TYPE_FRAG_IPV6:
+       case RTE_ETH_FLOW_NONFRAG_IPV6_TCP:
+       case RTE_ETH_FLOW_NONFRAG_IPV6_UDP:
+       case RTE_ETH_FLOW_NONFRAG_IPV6_SCTP:
+       case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER:
+       case RTE_ETH_FLOW_FRAG_IPV6:
                ip6 = (struct ipv6_hdr *)(raw_pkt + sizeof(struct ether_hdr));
 
                ether->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
@@ -751,10 +745,10 @@ i40e_fdir_fill_eth_ip_head(const struct rte_eth_fdir_input *fdir_input,
                 * to the expected received packets.
                 */
                rte_memcpy(&(ip6->src_addr),
-                          &(fdir_input->flow.ip6_flow.dst_ip),
+                          &(fdir_input->flow.ipv6_flow.dst_ip),
                           IPV6_ADDR_LEN);
                rte_memcpy(&(ip6->dst_addr),
-                          &(fdir_input->flow.ip6_flow.src_ip),
+                          &(fdir_input->flow.ipv6_flow.src_ip),
                           IPV6_ADDR_LEN);
                ip6->proto = next_proto[fdir_input->flow_type];
                break;
@@ -789,7 +783,7 @@ i40e_fdir_construct_pkt(struct i40e_pf *pf,
 
        /* fill the L4 head */
        switch (fdir_input->flow_type) {
-       case RTE_ETH_FLOW_TYPE_UDPV4:
+       case RTE_ETH_FLOW_NONFRAG_IPV4_UDP:
                udp = (struct udp_hdr *)(raw_pkt + sizeof(struct ether_hdr) +
                                sizeof(struct ipv4_hdr));
                payload = (unsigned char *)udp + sizeof(struct udp_hdr);
@@ -803,7 +797,7 @@ i40e_fdir_construct_pkt(struct i40e_pf *pf,
                udp->dgram_len = rte_cpu_to_be_16(I40E_FDIR_UDP_DEFAULT_LEN);
                break;
 
-       case RTE_ETH_FLOW_TYPE_TCPV4:
+       case RTE_ETH_FLOW_NONFRAG_IPV4_TCP:
                tcp = (struct tcp_hdr *)(raw_pkt + sizeof(struct ether_hdr) +
                                         sizeof(struct ipv4_hdr));
                payload = (unsigned char *)tcp + sizeof(struct tcp_hdr);
@@ -817,21 +811,21 @@ i40e_fdir_construct_pkt(struct i40e_pf *pf,
                tcp->data_off = I40E_FDIR_TCP_DEFAULT_DATAOFF;
                break;
 
-       case RTE_ETH_FLOW_TYPE_SCTPV4:
+       case RTE_ETH_FLOW_NONFRAG_IPV4_SCTP:
                sctp = (struct sctp_hdr *)(raw_pkt + sizeof(struct ether_hdr) +
                                           sizeof(struct ipv4_hdr));
                payload = (unsigned char *)sctp + sizeof(struct sctp_hdr);
                sctp->tag = fdir_input->flow.sctp4_flow.verify_tag;
                break;
 
-       case RTE_ETH_FLOW_TYPE_IPV4_OTHER:
-       case RTE_ETH_FLOW_TYPE_FRAG_IPV4:
+       case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER:
+       case RTE_ETH_FLOW_FRAG_IPV4:
                payload = raw_pkt + sizeof(struct ether_hdr) +
                          sizeof(struct ipv4_hdr);
                set_idx = I40E_FLXPLD_L3_IDX;
                break;
 
-       case RTE_ETH_FLOW_TYPE_UDPV6:
+       case RTE_ETH_FLOW_NONFRAG_IPV6_UDP:
                udp = (struct udp_hdr *)(raw_pkt + sizeof(struct ether_hdr) +
                                         sizeof(struct ipv6_hdr));
                payload = (unsigned char *)udp + sizeof(struct udp_hdr);
@@ -845,7 +839,7 @@ i40e_fdir_construct_pkt(struct i40e_pf *pf,
                udp->dgram_len = rte_cpu_to_be_16(I40E_FDIR_IPv6_PAYLOAD_LEN);
                break;
 
-       case RTE_ETH_FLOW_TYPE_TCPV6:
+       case RTE_ETH_FLOW_NONFRAG_IPV6_TCP:
                tcp = (struct tcp_hdr *)(raw_pkt + sizeof(struct ether_hdr) +
                                         sizeof(struct ipv6_hdr));
                payload = (unsigned char *)tcp + sizeof(struct tcp_hdr);
@@ -859,15 +853,15 @@ i40e_fdir_construct_pkt(struct i40e_pf *pf,
                tcp->dst_port = fdir_input->flow.udp6_flow.src_port;
                break;
 
-       case RTE_ETH_FLOW_TYPE_SCTPV6:
+       case RTE_ETH_FLOW_NONFRAG_IPV6_SCTP:
                sctp = (struct sctp_hdr *)(raw_pkt + sizeof(struct ether_hdr) +
                                           sizeof(struct ipv6_hdr));
                payload = (unsigned char *)sctp + sizeof(struct sctp_hdr);
                sctp->tag = fdir_input->flow.sctp6_flow.verify_tag;
                break;
 
-       case RTE_ETH_FLOW_TYPE_IPV6_OTHER:
-       case RTE_ETH_FLOW_TYPE_FRAG_IPV6:
+       case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER:
+       case RTE_ETH_FLOW_FRAG_IPV6:
                payload = raw_pkt + sizeof(struct ether_hdr) +
                          sizeof(struct ipv6_hdr);
                set_idx = I40E_FLXPLD_L3_IDX;
@@ -982,11 +976,13 @@ i40e_add_del_fdir_filter(struct rte_eth_dev *dev,
        enum i40e_filter_pctype pctype;
        int ret = 0;
 
-       if (!(pf->flags & I40E_FLAG_FDIR)) {
-               PMD_DRV_LOG(ERR, "FDIR is not enabled.");
+       if (dev->data->dev_conf.fdir_conf.mode != RTE_FDIR_MODE_PERFECT) {
+               PMD_DRV_LOG(ERR, "FDIR is not enabled, please"
+                       " check the mode in fdir_conf.");
                return -ENOTSUP;
        }
-       if (!I40E_VALID_FLOW_TYPE(filter->input.flow_type)) {
+
+       if (!I40E_VALID_FLOW(filter->input.flow_type)) {
                PMD_DRV_LOG(ERR, "invalid flow_type input.");
                return -EINVAL;
        }
@@ -1217,7 +1213,7 @@ i40e_fdir_info_get_flex_mask(struct i40e_pf *pf,
 {
        struct i40e_fdir_flex_mask *mask;
        struct rte_eth_fdir_flex_mask *ptr = flex_mask;
-       enum rte_eth_flow_type flow_type;
+       uint16_t flow_type;
        uint8_t i, j;
        uint16_t off_bytes, mask_tmp;
 
@@ -1263,14 +1259,17 @@ i40e_fdir_info_get(struct rte_eth_dev *dev, struct rte_eth_fdir_info *fdir)
        uint16_t num_flex_set = 0;
        uint16_t num_flex_mask = 0;
 
-       fdir->mode = (pf->flags & I40E_FLAG_FDIR) ?
-                       RTE_FDIR_MODE_PERFECT : RTE_FDIR_MODE_NONE;
+       if (dev->data->dev_conf.fdir_conf.mode == RTE_FDIR_MODE_PERFECT)
+               fdir->mode = RTE_FDIR_MODE_PERFECT;
+       else
+               fdir->mode = RTE_FDIR_MODE_NONE;
+
        fdir->guarant_spc =
                (uint32_t)hw->func_caps.fd_filters_guaranteed;
        fdir->best_spc =
                (uint32_t)hw->func_caps.fd_filters_best_effort;
        fdir->max_flexpayload = I40E_FDIR_MAX_FLEX_LEN;
-       fdir->flow_types_mask[0] = I40E_FDIR_FLOW_TYPES;
+       fdir->flow_types_mask[0] = I40E_FDIR_FLOWS;
        fdir->flex_payload_unit = sizeof(uint16_t);
        fdir->flex_bitmask_unit = sizeof(uint16_t);
        fdir->max_flex_payload_segment_num = I40E_MAX_FLXPLD_FIED;
@@ -1324,11 +1323,11 @@ i40e_fdir_ctrl_func(struct rte_eth_dev *dev,
        struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
        int ret = 0;
 
-       if (filter_op == RTE_ETH_FILTER_NOP) {
-               if (!(pf->flags & I40E_FLAG_FDIR))
-                       ret = -ENOTSUP;
-               return ret;
-       }
+       if ((pf->flags & I40E_FLAG_FDIR) == 0)
+               return -ENOTSUP;
+
+       if (filter_op == RTE_ETH_FILTER_NOP)
+               return 0;
 
        if (arg == NULL && filter_op != RTE_ETH_FILTER_FLUSH)
                return -EINVAL;