]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/infiniband/ulp/opa_vnic/opa_vnic_vema_iface.c
IB/opa_vnic: Use spinlock instead of mutex for stats_lock
[karo-tx-linux.git] / drivers / infiniband / ulp / opa_vnic / opa_vnic_vema_iface.c
1 /*
2  * Copyright(c) 2017 Intel Corporation.
3  *
4  * This file is provided under a dual BSD/GPLv2 license.  When using or
5  * redistributing this file, you may do so under either license.
6  *
7  * GPL LICENSE SUMMARY
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of version 2 of the GNU General Public License as
11  * published by the Free Software Foundation.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * BSD LICENSE
19  *
20  * Redistribution and use in source and binary forms, with or without
21  * modification, are permitted provided that the following conditions
22  * are met:
23  *
24  *  - Redistributions of source code must retain the above copyright
25  *    notice, this list of conditions and the following disclaimer.
26  *  - Redistributions in binary form must reproduce the above copyright
27  *    notice, this list of conditions and the following disclaimer in
28  *    the documentation and/or other materials provided with the
29  *    distribution.
30  *  - Neither the name of Intel Corporation nor the names of its
31  *    contributors may be used to endorse or promote products derived
32  *    from this software without specific prior written permission.
33  *
34  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
35  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
36  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
37  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
38  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
39  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
40  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
41  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
42  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
43  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
44  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45  *
46  */
47
48 /*
49  * This file contains OPA VNIC EMA Interface functions.
50  */
51
52 #include "opa_vnic_internal.h"
53
54 /**
55  * opa_vnic_vema_report_event - sent trap to report the specified event
56  * @adapter: vnic port adapter
57  * @event: event to be reported
58  *
59  * This function calls vema api to sent a trap for the given event.
60  */
61 void opa_vnic_vema_report_event(struct opa_vnic_adapter *adapter, u8 event)
62 {
63         struct __opa_veswport_info *info = &adapter->info;
64         struct __opa_veswport_trap trap_data;
65
66         trap_data.fabric_id = info->vesw.fabric_id;
67         trap_data.veswid = info->vesw.vesw_id;
68         trap_data.veswportnum = info->vport.port_num;
69         trap_data.opaportnum = adapter->port_num;
70         trap_data.veswportindex = adapter->vport_num;
71         trap_data.opcode = event;
72
73         opa_vnic_vema_send_trap(adapter, &trap_data, info->vport.encap_slid);
74 }
75
76 /**
77  * opa_vnic_get_error_counters - get summary counters
78  * @adapter: vnic port adapter
79  * @cntrs: pointer to destination summary counters structure
80  *
81  * This function populates the summary counters that is maintained by the
82  * given adapter to destination address provided.
83  */
84 void opa_vnic_get_summary_counters(struct opa_vnic_adapter *adapter,
85                                    struct opa_veswport_summary_counters *cntrs)
86 {
87         struct opa_vnic_stats vstats;
88         __be64 *dst;
89         u64 *src;
90
91         memset(&vstats, 0, sizeof(vstats));
92         spin_lock(&adapter->stats_lock);
93         adapter->rn_ops->ndo_get_stats64(adapter->netdev, &vstats.netstats);
94         spin_unlock(&adapter->stats_lock);
95
96         cntrs->vp_instance = cpu_to_be16(adapter->vport_num);
97         cntrs->vesw_id = cpu_to_be16(adapter->info.vesw.vesw_id);
98         cntrs->veswport_num = cpu_to_be32(adapter->port_num);
99
100         cntrs->tx_errors = cpu_to_be64(vstats.netstats.tx_errors);
101         cntrs->rx_errors = cpu_to_be64(vstats.netstats.rx_errors);
102         cntrs->tx_packets = cpu_to_be64(vstats.netstats.tx_packets);
103         cntrs->rx_packets = cpu_to_be64(vstats.netstats.rx_packets);
104         cntrs->tx_bytes = cpu_to_be64(vstats.netstats.tx_bytes);
105         cntrs->rx_bytes = cpu_to_be64(vstats.netstats.rx_bytes);
106
107         /*
108          * This loop depends on layout of
109          * opa_veswport_summary_counters opa_vnic_stats structures.
110          */
111         for (dst = &cntrs->tx_unicast, src = &vstats.tx_grp.unicast;
112              dst < &cntrs->reserved[0]; dst++, src++) {
113                 *dst = cpu_to_be64(*src);
114         }
115 }
116
117 /**
118  * opa_vnic_get_error_counters - get error counters
119  * @adapter: vnic port adapter
120  * @cntrs: pointer to destination error counters structure
121  *
122  * This function populates the error counters that is maintained by the
123  * given adapter to destination address provided.
124  */
125 void opa_vnic_get_error_counters(struct opa_vnic_adapter *adapter,
126                                  struct opa_veswport_error_counters *cntrs)
127 {
128         struct opa_vnic_stats vstats;
129
130         memset(&vstats, 0, sizeof(vstats));
131         spin_lock(&adapter->stats_lock);
132         adapter->rn_ops->ndo_get_stats64(adapter->netdev, &vstats.netstats);
133         spin_unlock(&adapter->stats_lock);
134
135         cntrs->vp_instance = cpu_to_be16(adapter->vport_num);
136         cntrs->vesw_id = cpu_to_be16(adapter->info.vesw.vesw_id);
137         cntrs->veswport_num = cpu_to_be32(adapter->port_num);
138
139         cntrs->tx_errors = cpu_to_be64(vstats.netstats.tx_errors);
140         cntrs->rx_errors = cpu_to_be64(vstats.netstats.rx_errors);
141         cntrs->tx_dlid_zero = cpu_to_be64(vstats.tx_dlid_zero);
142         cntrs->tx_drop_state = cpu_to_be64(vstats.tx_drop_state);
143         cntrs->tx_logic = cpu_to_be64(vstats.netstats.tx_fifo_errors +
144                                       vstats.netstats.tx_carrier_errors);
145
146         cntrs->rx_bad_veswid = cpu_to_be64(vstats.netstats.rx_nohandler);
147         cntrs->rx_runt = cpu_to_be64(vstats.rx_runt);
148         cntrs->rx_oversize = cpu_to_be64(vstats.rx_oversize);
149         cntrs->rx_drop_state = cpu_to_be64(vstats.rx_drop_state);
150         cntrs->rx_logic = cpu_to_be64(vstats.netstats.rx_fifo_errors);
151 }
152
153 /**
154  * opa_vnic_get_vesw_info -- Get the vesw information
155  * @adapter: vnic port adapter
156  * @info: pointer to destination vesw info structure
157  *
158  * This function copies the vesw info that is maintained by the
159  * given adapter to destination address provided.
160  */
161 void opa_vnic_get_vesw_info(struct opa_vnic_adapter *adapter,
162                             struct opa_vesw_info *info)
163 {
164         struct __opa_vesw_info *src = &adapter->info.vesw;
165         int i;
166
167         info->fabric_id = cpu_to_be16(src->fabric_id);
168         info->vesw_id = cpu_to_be16(src->vesw_id);
169         memcpy(info->rsvd0, src->rsvd0, ARRAY_SIZE(src->rsvd0));
170         info->def_port_mask = cpu_to_be16(src->def_port_mask);
171         memcpy(info->rsvd1, src->rsvd1, ARRAY_SIZE(src->rsvd1));
172         info->pkey = cpu_to_be16(src->pkey);
173
174         memcpy(info->rsvd2, src->rsvd2, ARRAY_SIZE(src->rsvd2));
175         info->u_mcast_dlid = cpu_to_be32(src->u_mcast_dlid);
176         for (i = 0; i < OPA_VESW_MAX_NUM_DEF_PORT; i++)
177                 info->u_ucast_dlid[i] = cpu_to_be32(src->u_ucast_dlid[i]);
178
179         memcpy(info->rsvd3, src->rsvd3, ARRAY_SIZE(src->rsvd3));
180         for (i = 0; i < OPA_VNIC_MAX_NUM_PCP; i++)
181                 info->eth_mtu[i] = cpu_to_be16(src->eth_mtu[i]);
182
183         info->eth_mtu_non_vlan = cpu_to_be16(src->eth_mtu_non_vlan);
184         memcpy(info->rsvd4, src->rsvd4, ARRAY_SIZE(src->rsvd4));
185 }
186
187 /**
188  * opa_vnic_set_vesw_info -- Set the vesw information
189  * @adapter: vnic port adapter
190  * @info: pointer to vesw info structure
191  *
192  * This function updates the vesw info that is maintained by the
193  * given adapter with vesw info provided. Reserved fields are stored
194  * and returned back to EM as is.
195  */
196 void opa_vnic_set_vesw_info(struct opa_vnic_adapter *adapter,
197                             struct opa_vesw_info *info)
198 {
199         struct __opa_vesw_info *dst = &adapter->info.vesw;
200         int i;
201
202         dst->fabric_id = be16_to_cpu(info->fabric_id);
203         dst->vesw_id = be16_to_cpu(info->vesw_id);
204         memcpy(dst->rsvd0, info->rsvd0, ARRAY_SIZE(info->rsvd0));
205         dst->def_port_mask = be16_to_cpu(info->def_port_mask);
206         memcpy(dst->rsvd1, info->rsvd1, ARRAY_SIZE(info->rsvd1));
207         dst->pkey = be16_to_cpu(info->pkey);
208
209         memcpy(dst->rsvd2, info->rsvd2, ARRAY_SIZE(info->rsvd2));
210         dst->u_mcast_dlid = be32_to_cpu(info->u_mcast_dlid);
211         for (i = 0; i < OPA_VESW_MAX_NUM_DEF_PORT; i++)
212                 dst->u_ucast_dlid[i] = be32_to_cpu(info->u_ucast_dlid[i]);
213
214         memcpy(dst->rsvd3, info->rsvd3, ARRAY_SIZE(info->rsvd3));
215         for (i = 0; i < OPA_VNIC_MAX_NUM_PCP; i++)
216                 dst->eth_mtu[i] = be16_to_cpu(info->eth_mtu[i]);
217
218         dst->eth_mtu_non_vlan = be16_to_cpu(info->eth_mtu_non_vlan);
219         memcpy(dst->rsvd4, info->rsvd4, ARRAY_SIZE(info->rsvd4));
220 }
221
222 /**
223  * opa_vnic_get_per_veswport_info -- Get the vesw per port information
224  * @adapter: vnic port adapter
225  * @info: pointer to destination vport info structure
226  *
227  * This function copies the vesw per port info that is maintained by the
228  * given adapter to destination address provided.
229  * Note that the read only fields are not copied.
230  */
231 void opa_vnic_get_per_veswport_info(struct opa_vnic_adapter *adapter,
232                                     struct opa_per_veswport_info *info)
233 {
234         struct __opa_per_veswport_info *src = &adapter->info.vport;
235
236         info->port_num = cpu_to_be32(src->port_num);
237         info->eth_link_status = src->eth_link_status;
238         memcpy(info->rsvd0, src->rsvd0, ARRAY_SIZE(src->rsvd0));
239
240         memcpy(info->base_mac_addr, src->base_mac_addr,
241                ARRAY_SIZE(info->base_mac_addr));
242         info->config_state = src->config_state;
243         info->oper_state = src->oper_state;
244         info->max_mac_tbl_ent = cpu_to_be16(src->max_mac_tbl_ent);
245         info->max_smac_ent = cpu_to_be16(src->max_smac_ent);
246         info->mac_tbl_digest = cpu_to_be32(src->mac_tbl_digest);
247         memcpy(info->rsvd1, src->rsvd1, ARRAY_SIZE(src->rsvd1));
248
249         info->encap_slid = cpu_to_be32(src->encap_slid);
250         memcpy(info->pcp_to_sc_uc, src->pcp_to_sc_uc,
251                ARRAY_SIZE(info->pcp_to_sc_uc));
252         memcpy(info->pcp_to_vl_uc, src->pcp_to_vl_uc,
253                ARRAY_SIZE(info->pcp_to_vl_uc));
254         memcpy(info->pcp_to_sc_mc, src->pcp_to_sc_mc,
255                ARRAY_SIZE(info->pcp_to_sc_mc));
256         memcpy(info->pcp_to_vl_mc, src->pcp_to_vl_mc,
257                ARRAY_SIZE(info->pcp_to_vl_mc));
258         info->non_vlan_sc_uc = src->non_vlan_sc_uc;
259         info->non_vlan_vl_uc = src->non_vlan_vl_uc;
260         info->non_vlan_sc_mc = src->non_vlan_sc_mc;
261         info->non_vlan_vl_mc = src->non_vlan_vl_mc;
262         memcpy(info->rsvd2, src->rsvd2, ARRAY_SIZE(src->rsvd2));
263
264         info->uc_macs_gen_count = cpu_to_be16(src->uc_macs_gen_count);
265         info->mc_macs_gen_count = cpu_to_be16(src->mc_macs_gen_count);
266         memcpy(info->rsvd3, src->rsvd3, ARRAY_SIZE(src->rsvd3));
267 }
268
269 /**
270  * opa_vnic_set_per_veswport_info -- Set vesw per port information
271  * @adapter: vnic port adapter
272  * @info: pointer to vport info structure
273  *
274  * This function updates the vesw per port info that is maintained by the
275  * given adapter with vesw per port info provided. Reserved fields are
276  * stored and returned back to EM as is.
277  */
278 void opa_vnic_set_per_veswport_info(struct opa_vnic_adapter *adapter,
279                                     struct opa_per_veswport_info *info)
280 {
281         struct __opa_per_veswport_info *dst = &adapter->info.vport;
282
283         dst->port_num = be32_to_cpu(info->port_num);
284         memcpy(dst->rsvd0, info->rsvd0, ARRAY_SIZE(info->rsvd0));
285
286         memcpy(dst->base_mac_addr, info->base_mac_addr,
287                ARRAY_SIZE(dst->base_mac_addr));
288         dst->config_state = info->config_state;
289         memcpy(dst->rsvd1, info->rsvd1, ARRAY_SIZE(info->rsvd1));
290
291         dst->encap_slid = be32_to_cpu(info->encap_slid);
292         memcpy(dst->pcp_to_sc_uc, info->pcp_to_sc_uc,
293                ARRAY_SIZE(dst->pcp_to_sc_uc));
294         memcpy(dst->pcp_to_vl_uc, info->pcp_to_vl_uc,
295                ARRAY_SIZE(dst->pcp_to_vl_uc));
296         memcpy(dst->pcp_to_sc_mc, info->pcp_to_sc_mc,
297                ARRAY_SIZE(dst->pcp_to_sc_mc));
298         memcpy(dst->pcp_to_vl_mc, info->pcp_to_vl_mc,
299                ARRAY_SIZE(dst->pcp_to_vl_mc));
300         dst->non_vlan_sc_uc = info->non_vlan_sc_uc;
301         dst->non_vlan_vl_uc = info->non_vlan_vl_uc;
302         dst->non_vlan_sc_mc = info->non_vlan_sc_mc;
303         dst->non_vlan_vl_mc = info->non_vlan_vl_mc;
304         memcpy(dst->rsvd2, info->rsvd2, ARRAY_SIZE(info->rsvd2));
305         memcpy(dst->rsvd3, info->rsvd3, ARRAY_SIZE(info->rsvd3));
306 }
307
308 /**
309  * opa_vnic_query_mcast_macs - query multicast mac list
310  * @adapter: vnic port adapter
311  * @macs: pointer mac list
312  *
313  * This function populates the provided mac list with the configured
314  * multicast addresses in the adapter.
315  */
316 void opa_vnic_query_mcast_macs(struct opa_vnic_adapter *adapter,
317                                struct opa_veswport_iface_macs *macs)
318 {
319         u16 start_idx, num_macs, idx = 0, count = 0;
320         struct netdev_hw_addr *ha;
321
322         start_idx = be16_to_cpu(macs->start_idx);
323         num_macs = be16_to_cpu(macs->num_macs_in_msg);
324         netdev_for_each_mc_addr(ha, adapter->netdev) {
325                 struct opa_vnic_iface_mac_entry *entry = &macs->entry[count];
326
327                 if (start_idx > idx++)
328                         continue;
329                 else if (num_macs == count)
330                         break;
331                 memcpy(entry, ha->addr, sizeof(*entry));
332                 count++;
333         }
334
335         macs->tot_macs_in_lst = cpu_to_be16(netdev_mc_count(adapter->netdev));
336         macs->num_macs_in_msg = cpu_to_be16(count);
337         macs->gen_count = cpu_to_be16(adapter->info.vport.mc_macs_gen_count);
338 }
339
340 /**
341  * opa_vnic_query_ucast_macs - query unicast mac list
342  * @adapter: vnic port adapter
343  * @macs: pointer mac list
344  *
345  * This function populates the provided mac list with the configured
346  * unicast addresses in the adapter.
347  */
348 void opa_vnic_query_ucast_macs(struct opa_vnic_adapter *adapter,
349                                struct opa_veswport_iface_macs *macs)
350 {
351         u16 start_idx, tot_macs, num_macs, idx = 0, count = 0;
352         struct netdev_hw_addr *ha;
353
354         start_idx = be16_to_cpu(macs->start_idx);
355         num_macs = be16_to_cpu(macs->num_macs_in_msg);
356         /* loop through dev_addrs list first */
357         for_each_dev_addr(adapter->netdev, ha) {
358                 struct opa_vnic_iface_mac_entry *entry = &macs->entry[count];
359
360                 /* Do not include EM specified MAC address */
361                 if (!memcmp(adapter->info.vport.base_mac_addr, ha->addr,
362                             ARRAY_SIZE(adapter->info.vport.base_mac_addr)))
363                         continue;
364
365                 if (start_idx > idx++)
366                         continue;
367                 else if (num_macs == count)
368                         break;
369                 memcpy(entry, ha->addr, sizeof(*entry));
370                 count++;
371         }
372
373         /* loop through uc list */
374         netdev_for_each_uc_addr(ha, adapter->netdev) {
375                 struct opa_vnic_iface_mac_entry *entry = &macs->entry[count];
376
377                 if (start_idx > idx++)
378                         continue;
379                 else if (num_macs == count)
380                         break;
381                 memcpy(entry, ha->addr, sizeof(*entry));
382                 count++;
383         }
384
385         tot_macs = netdev_hw_addr_list_count(&adapter->netdev->dev_addrs) +
386                    netdev_uc_count(adapter->netdev);
387         macs->tot_macs_in_lst = cpu_to_be16(tot_macs);
388         macs->num_macs_in_msg = cpu_to_be16(count);
389         macs->gen_count = cpu_to_be16(adapter->info.vport.uc_macs_gen_count);
390 }