New upstream version 18.08
[deb_dpdk.git] / drivers / net / sfc / sfc_filter.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright (c) 2017-2018 Solarflare Communications Inc.
4  * All rights reserved.
5  *
6  * This software was jointly developed between OKTET Labs (under contract
7  * for Solarflare) and Solarflare Communications, Inc.
8  */
9
10 #include <rte_common.h>
11
12 #include "efx.h"
13
14 #include "sfc.h"
15 #include "sfc_log.h"
16
17 boolean_t
18 sfc_filter_is_match_supported(struct sfc_adapter *sa, uint32_t match)
19 {
20         struct sfc_filter *filter = &sa->filter;
21         size_t i;
22
23         for (i = 0; i < filter->supported_match_num; ++i) {
24                 if (match == filter->supported_match[i])
25                         return B_TRUE;
26         }
27
28         return B_FALSE;
29 }
30
31 static int
32 sfc_filter_cache_match_supported(struct sfc_adapter *sa)
33 {
34         struct sfc_filter *filter = &sa->filter;
35         size_t num = filter->supported_match_num;
36         uint32_t *buf = filter->supported_match;
37         unsigned int retry;
38         int rc;
39
40         /* Just a guess of possibly sufficient entries */
41         if (num == 0)
42                 num = 16;
43
44         for (retry = 0; retry < 2; ++retry) {
45                 if (num != filter->supported_match_num) {
46                         rc = ENOMEM;
47                         buf = rte_realloc(buf, num * sizeof(*buf), 0);
48                         if (buf == NULL)
49                                 goto fail_realloc;
50                 }
51
52                 rc = efx_filter_supported_filters(sa->nic, buf, num, &num);
53                 if (rc == 0) {
54                         filter->supported_match_num = num;
55                         filter->supported_match = buf;
56
57                         return 0;
58                 } else if (rc != ENOSPC) {
59                         goto fail_efx_filter_supported_filters;
60                 }
61         }
62
63         SFC_ASSERT(rc == ENOSPC);
64
65 fail_efx_filter_supported_filters:
66 fail_realloc:
67         /* Original pointer is not freed by rte_realloc() on failure */
68         rte_free(buf);
69         filter->supported_match = NULL;
70         filter->supported_match_num = 0;
71         return rc;
72 }
73
74 int
75 sfc_filter_attach(struct sfc_adapter *sa)
76 {
77         int rc;
78         unsigned int i;
79
80         sfc_log_init(sa, "entry");
81
82         rc = efx_filter_init(sa->nic);
83         if (rc != 0)
84                 goto fail_filter_init;
85
86         rc = sfc_filter_cache_match_supported(sa);
87         if (rc != 0)
88                 goto fail_cache_match_supported;
89
90         efx_filter_fini(sa->nic);
91
92         sa->filter.supports_ip_proto_or_addr_filter = B_FALSE;
93         sa->filter.supports_rem_or_local_port_filter = B_FALSE;
94         for (i = 0; i < sa->filter.supported_match_num; ++i) {
95                 if (sa->filter.supported_match[i] &
96                     (EFX_FILTER_MATCH_IP_PROTO | EFX_FILTER_MATCH_LOC_HOST |
97                      EFX_FILTER_MATCH_REM_HOST))
98                         sa->filter.supports_ip_proto_or_addr_filter = B_TRUE;
99
100                 if (sa->filter.supported_match[i] &
101                     (EFX_FILTER_MATCH_LOC_PORT | EFX_FILTER_MATCH_REM_PORT))
102                         sa->filter.supports_rem_or_local_port_filter = B_TRUE;
103         }
104
105         sfc_log_init(sa, "done");
106
107         return 0;
108
109 fail_cache_match_supported:
110         efx_filter_fini(sa->nic);
111
112 fail_filter_init:
113         sfc_log_init(sa, "failed %d", rc);
114         return rc;
115 }
116
117 void
118 sfc_filter_detach(struct sfc_adapter *sa)
119 {
120         struct sfc_filter *filter = &sa->filter;
121
122         sfc_log_init(sa, "entry");
123
124         rte_free(filter->supported_match);
125         filter->supported_match = NULL;
126         filter->supported_match_num = 0;
127
128         sfc_log_init(sa, "done");
129 }