| /* |
| * Copyright(c) 2017 Intel Corporation. |
| * |
| * This file is provided under a dual BSD/GPLv2 license. When using or |
| * redistributing this file, you may do so under either license. |
| * |
| * GPL LICENSE SUMMARY |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of version 2 of the GNU General Public License as |
| * published by the Free Software Foundation. |
| * |
| * This program is distributed in the hope that it will be useful, but |
| * WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * General Public License for more details. |
| * |
| * BSD LICENSE |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * - Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * - Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * - Neither the name of Intel Corporation nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| */ |
| |
| /* |
| * This file contains OPA VNIC EMA Interface functions. |
| */ |
| |
| #include "opa_vnic_internal.h" |
| |
| /** |
| * opa_vnic_vema_report_event - sent trap to report the specified event |
| * @adapter: vnic port adapter |
| * @event: event to be reported |
| * |
| * This function calls vema api to sent a trap for the given event. |
| */ |
| void opa_vnic_vema_report_event(struct opa_vnic_adapter *adapter, u8 event) |
| { |
| struct __opa_veswport_info *info = &adapter->info; |
| struct __opa_veswport_trap trap_data; |
| |
| trap_data.fabric_id = info->vesw.fabric_id; |
| trap_data.veswid = info->vesw.vesw_id; |
| trap_data.veswportnum = info->vport.port_num; |
| trap_data.opaportnum = adapter->port_num; |
| trap_data.veswportindex = adapter->vport_num; |
| trap_data.opcode = event; |
| |
| opa_vnic_vema_send_trap(adapter, &trap_data, info->vport.encap_slid); |
| } |
| |
| /** |
| * opa_vnic_get_error_counters - get summary counters |
| * @adapter: vnic port adapter |
| * @cntrs: pointer to destination summary counters structure |
| * |
| * This function populates the summary counters that is maintained by the |
| * given adapter to destination address provided. |
| */ |
| void opa_vnic_get_summary_counters(struct opa_vnic_adapter *adapter, |
| struct opa_veswport_summary_counters *cntrs) |
| { |
| struct opa_vnic_stats vstats; |
| __be64 *dst; |
| u64 *src; |
| |
| memset(&vstats, 0, sizeof(vstats)); |
| spin_lock(&adapter->stats_lock); |
| adapter->rn_ops->ndo_get_stats64(adapter->netdev, &vstats.netstats); |
| spin_unlock(&adapter->stats_lock); |
| |
| cntrs->vp_instance = cpu_to_be16(adapter->vport_num); |
| cntrs->vesw_id = cpu_to_be16(adapter->info.vesw.vesw_id); |
| cntrs->veswport_num = cpu_to_be32(adapter->port_num); |
| |
| cntrs->tx_errors = cpu_to_be64(vstats.netstats.tx_errors); |
| cntrs->rx_errors = cpu_to_be64(vstats.netstats.rx_errors); |
| cntrs->tx_packets = cpu_to_be64(vstats.netstats.tx_packets); |
| cntrs->rx_packets = cpu_to_be64(vstats.netstats.rx_packets); |
| cntrs->tx_bytes = cpu_to_be64(vstats.netstats.tx_bytes); |
| cntrs->rx_bytes = cpu_to_be64(vstats.netstats.rx_bytes); |
| |
| /* |
| * This loop depends on layout of |
| * opa_veswport_summary_counters opa_vnic_stats structures. |
| */ |
| for (dst = &cntrs->tx_unicast, src = &vstats.tx_grp.unicast; |
| dst < &cntrs->reserved[0]; dst++, src++) { |
| *dst = cpu_to_be64(*src); |
| } |
| } |
| |
| /** |
| * opa_vnic_get_error_counters - get error counters |
| * @adapter: vnic port adapter |
| * @cntrs: pointer to destination error counters structure |
| * |
| * This function populates the error counters that is maintained by the |
| * given adapter to destination address provided. |
| */ |
| void opa_vnic_get_error_counters(struct opa_vnic_adapter *adapter, |
| struct opa_veswport_error_counters *cntrs) |
| { |
| struct opa_vnic_stats vstats; |
| |
| memset(&vstats, 0, sizeof(vstats)); |
| spin_lock(&adapter->stats_lock); |
| adapter->rn_ops->ndo_get_stats64(adapter->netdev, &vstats.netstats); |
| spin_unlock(&adapter->stats_lock); |
| |
| cntrs->vp_instance = cpu_to_be16(adapter->vport_num); |
| cntrs->vesw_id = cpu_to_be16(adapter->info.vesw.vesw_id); |
| cntrs->veswport_num = cpu_to_be32(adapter->port_num); |
| |
| cntrs->tx_errors = cpu_to_be64(vstats.netstats.tx_errors); |
| cntrs->rx_errors = cpu_to_be64(vstats.netstats.rx_errors); |
| cntrs->tx_dlid_zero = cpu_to_be64(vstats.tx_dlid_zero); |
| cntrs->tx_drop_state = cpu_to_be64(vstats.tx_drop_state); |
| cntrs->tx_logic = cpu_to_be64(vstats.netstats.tx_fifo_errors + |
| vstats.netstats.tx_carrier_errors); |
| |
| cntrs->rx_bad_veswid = cpu_to_be64(vstats.netstats.rx_nohandler); |
| cntrs->rx_runt = cpu_to_be64(vstats.rx_runt); |
| cntrs->rx_oversize = cpu_to_be64(vstats.rx_oversize); |
| cntrs->rx_drop_state = cpu_to_be64(vstats.rx_drop_state); |
| cntrs->rx_logic = cpu_to_be64(vstats.netstats.rx_fifo_errors); |
| } |
| |
| /** |
| * opa_vnic_get_vesw_info -- Get the vesw information |
| * @adapter: vnic port adapter |
| * @info: pointer to destination vesw info structure |
| * |
| * This function copies the vesw info that is maintained by the |
| * given adapter to destination address provided. |
| */ |
| void opa_vnic_get_vesw_info(struct opa_vnic_adapter *adapter, |
| struct opa_vesw_info *info) |
| { |
| struct __opa_vesw_info *src = &adapter->info.vesw; |
| int i; |
| |
| info->fabric_id = cpu_to_be16(src->fabric_id); |
| info->vesw_id = cpu_to_be16(src->vesw_id); |
| memcpy(info->rsvd0, src->rsvd0, ARRAY_SIZE(src->rsvd0)); |
| info->def_port_mask = cpu_to_be16(src->def_port_mask); |
| memcpy(info->rsvd1, src->rsvd1, ARRAY_SIZE(src->rsvd1)); |
| info->pkey = cpu_to_be16(src->pkey); |
| |
| memcpy(info->rsvd2, src->rsvd2, ARRAY_SIZE(src->rsvd2)); |
| info->u_mcast_dlid = cpu_to_be32(src->u_mcast_dlid); |
| for (i = 0; i < OPA_VESW_MAX_NUM_DEF_PORT; i++) |
| info->u_ucast_dlid[i] = cpu_to_be32(src->u_ucast_dlid[i]); |
| |
| info->rc = cpu_to_be32(src->rc); |
| |
| memcpy(info->rsvd3, src->rsvd3, ARRAY_SIZE(src->rsvd3)); |
| info->eth_mtu = cpu_to_be16(src->eth_mtu); |
| memcpy(info->rsvd4, src->rsvd4, ARRAY_SIZE(src->rsvd4)); |
| } |
| |
| /** |
| * opa_vnic_set_vesw_info -- Set the vesw information |
| * @adapter: vnic port adapter |
| * @info: pointer to vesw info structure |
| * |
| * This function updates the vesw info that is maintained by the |
| * given adapter with vesw info provided. Reserved fields are stored |
| * and returned back to EM as is. |
| */ |
| void opa_vnic_set_vesw_info(struct opa_vnic_adapter *adapter, |
| struct opa_vesw_info *info) |
| { |
| struct __opa_vesw_info *dst = &adapter->info.vesw; |
| int i; |
| |
| dst->fabric_id = be16_to_cpu(info->fabric_id); |
| dst->vesw_id = be16_to_cpu(info->vesw_id); |
| memcpy(dst->rsvd0, info->rsvd0, ARRAY_SIZE(info->rsvd0)); |
| dst->def_port_mask = be16_to_cpu(info->def_port_mask); |
| memcpy(dst->rsvd1, info->rsvd1, ARRAY_SIZE(info->rsvd1)); |
| dst->pkey = be16_to_cpu(info->pkey); |
| |
| memcpy(dst->rsvd2, info->rsvd2, ARRAY_SIZE(info->rsvd2)); |
| dst->u_mcast_dlid = be32_to_cpu(info->u_mcast_dlid); |
| for (i = 0; i < OPA_VESW_MAX_NUM_DEF_PORT; i++) |
| dst->u_ucast_dlid[i] = be32_to_cpu(info->u_ucast_dlid[i]); |
| |
| dst->rc = be32_to_cpu(info->rc); |
| |
| memcpy(dst->rsvd3, info->rsvd3, ARRAY_SIZE(info->rsvd3)); |
| dst->eth_mtu = be16_to_cpu(info->eth_mtu); |
| memcpy(dst->rsvd4, info->rsvd4, ARRAY_SIZE(info->rsvd4)); |
| } |
| |
| /** |
| * opa_vnic_get_per_veswport_info -- Get the vesw per port information |
| * @adapter: vnic port adapter |
| * @info: pointer to destination vport info structure |
| * |
| * This function copies the vesw per port info that is maintained by the |
| * given adapter to destination address provided. |
| * Note that the read only fields are not copied. |
| */ |
| void opa_vnic_get_per_veswport_info(struct opa_vnic_adapter *adapter, |
| struct opa_per_veswport_info *info) |
| { |
| struct __opa_per_veswport_info *src = &adapter->info.vport; |
| |
| info->port_num = cpu_to_be32(src->port_num); |
| info->eth_link_status = src->eth_link_status; |
| memcpy(info->rsvd0, src->rsvd0, ARRAY_SIZE(src->rsvd0)); |
| |
| memcpy(info->base_mac_addr, src->base_mac_addr, |
| ARRAY_SIZE(info->base_mac_addr)); |
| info->config_state = src->config_state; |
| info->oper_state = src->oper_state; |
| info->max_mac_tbl_ent = cpu_to_be16(src->max_mac_tbl_ent); |
| info->max_smac_ent = cpu_to_be16(src->max_smac_ent); |
| info->mac_tbl_digest = cpu_to_be32(src->mac_tbl_digest); |
| memcpy(info->rsvd1, src->rsvd1, ARRAY_SIZE(src->rsvd1)); |
| |
| info->encap_slid = cpu_to_be32(src->encap_slid); |
| memcpy(info->pcp_to_sc_uc, src->pcp_to_sc_uc, |
| ARRAY_SIZE(info->pcp_to_sc_uc)); |
| memcpy(info->pcp_to_vl_uc, src->pcp_to_vl_uc, |
| ARRAY_SIZE(info->pcp_to_vl_uc)); |
| memcpy(info->pcp_to_sc_mc, src->pcp_to_sc_mc, |
| ARRAY_SIZE(info->pcp_to_sc_mc)); |
| memcpy(info->pcp_to_vl_mc, src->pcp_to_vl_mc, |
| ARRAY_SIZE(info->pcp_to_vl_mc)); |
| info->non_vlan_sc_uc = src->non_vlan_sc_uc; |
| info->non_vlan_vl_uc = src->non_vlan_vl_uc; |
| info->non_vlan_sc_mc = src->non_vlan_sc_mc; |
| info->non_vlan_vl_mc = src->non_vlan_vl_mc; |
| memcpy(info->rsvd2, src->rsvd2, ARRAY_SIZE(src->rsvd2)); |
| |
| info->uc_macs_gen_count = cpu_to_be16(src->uc_macs_gen_count); |
| info->mc_macs_gen_count = cpu_to_be16(src->mc_macs_gen_count); |
| memcpy(info->rsvd3, src->rsvd3, ARRAY_SIZE(src->rsvd3)); |
| } |
| |
| /** |
| * opa_vnic_set_per_veswport_info -- Set vesw per port information |
| * @adapter: vnic port adapter |
| * @info: pointer to vport info structure |
| * |
| * This function updates the vesw per port info that is maintained by the |
| * given adapter with vesw per port info provided. Reserved fields are |
| * stored and returned back to EM as is. |
| */ |
| void opa_vnic_set_per_veswport_info(struct opa_vnic_adapter *adapter, |
| struct opa_per_veswport_info *info) |
| { |
| struct __opa_per_veswport_info *dst = &adapter->info.vport; |
| |
| dst->port_num = be32_to_cpu(info->port_num); |
| memcpy(dst->rsvd0, info->rsvd0, ARRAY_SIZE(info->rsvd0)); |
| |
| memcpy(dst->base_mac_addr, info->base_mac_addr, |
| ARRAY_SIZE(dst->base_mac_addr)); |
| dst->config_state = info->config_state; |
| memcpy(dst->rsvd1, info->rsvd1, ARRAY_SIZE(info->rsvd1)); |
| |
| dst->encap_slid = be32_to_cpu(info->encap_slid); |
| memcpy(dst->pcp_to_sc_uc, info->pcp_to_sc_uc, |
| ARRAY_SIZE(dst->pcp_to_sc_uc)); |
| memcpy(dst->pcp_to_vl_uc, info->pcp_to_vl_uc, |
| ARRAY_SIZE(dst->pcp_to_vl_uc)); |
| memcpy(dst->pcp_to_sc_mc, info->pcp_to_sc_mc, |
| ARRAY_SIZE(dst->pcp_to_sc_mc)); |
| memcpy(dst->pcp_to_vl_mc, info->pcp_to_vl_mc, |
| ARRAY_SIZE(dst->pcp_to_vl_mc)); |
| dst->non_vlan_sc_uc = info->non_vlan_sc_uc; |
| dst->non_vlan_vl_uc = info->non_vlan_vl_uc; |
| dst->non_vlan_sc_mc = info->non_vlan_sc_mc; |
| dst->non_vlan_vl_mc = info->non_vlan_vl_mc; |
| memcpy(dst->rsvd2, info->rsvd2, ARRAY_SIZE(info->rsvd2)); |
| memcpy(dst->rsvd3, info->rsvd3, ARRAY_SIZE(info->rsvd3)); |
| } |
| |
| /** |
| * opa_vnic_query_mcast_macs - query multicast mac list |
| * @adapter: vnic port adapter |
| * @macs: pointer mac list |
| * |
| * This function populates the provided mac list with the configured |
| * multicast addresses in the adapter. |
| */ |
| void opa_vnic_query_mcast_macs(struct opa_vnic_adapter *adapter, |
| struct opa_veswport_iface_macs *macs) |
| { |
| u16 start_idx, num_macs, idx = 0, count = 0; |
| struct netdev_hw_addr *ha; |
| |
| start_idx = be16_to_cpu(macs->start_idx); |
| num_macs = be16_to_cpu(macs->num_macs_in_msg); |
| netdev_for_each_mc_addr(ha, adapter->netdev) { |
| struct opa_vnic_iface_mac_entry *entry = &macs->entry[count]; |
| |
| if (start_idx > idx++) |
| continue; |
| else if (num_macs == count) |
| break; |
| memcpy(entry, ha->addr, sizeof(*entry)); |
| count++; |
| } |
| |
| macs->tot_macs_in_lst = cpu_to_be16(netdev_mc_count(adapter->netdev)); |
| macs->num_macs_in_msg = cpu_to_be16(count); |
| macs->gen_count = cpu_to_be16(adapter->info.vport.mc_macs_gen_count); |
| } |
| |
| /** |
| * opa_vnic_query_ucast_macs - query unicast mac list |
| * @adapter: vnic port adapter |
| * @macs: pointer mac list |
| * |
| * This function populates the provided mac list with the configured |
| * unicast addresses in the adapter. |
| */ |
| void opa_vnic_query_ucast_macs(struct opa_vnic_adapter *adapter, |
| struct opa_veswport_iface_macs *macs) |
| { |
| u16 start_idx, tot_macs, num_macs, idx = 0, count = 0, em_macs = 0; |
| struct netdev_hw_addr *ha; |
| |
| start_idx = be16_to_cpu(macs->start_idx); |
| num_macs = be16_to_cpu(macs->num_macs_in_msg); |
| /* loop through dev_addrs list first */ |
| for_each_dev_addr(adapter->netdev, ha) { |
| struct opa_vnic_iface_mac_entry *entry = &macs->entry[count]; |
| |
| /* Do not include EM specified MAC address */ |
| if (!memcmp(adapter->info.vport.base_mac_addr, ha->addr, |
| ARRAY_SIZE(adapter->info.vport.base_mac_addr))) { |
| em_macs++; |
| continue; |
| } |
| |
| if (start_idx > idx++) |
| continue; |
| else if (num_macs == count) |
| break; |
| memcpy(entry, ha->addr, sizeof(*entry)); |
| count++; |
| } |
| |
| /* loop through uc list */ |
| netdev_for_each_uc_addr(ha, adapter->netdev) { |
| struct opa_vnic_iface_mac_entry *entry = &macs->entry[count]; |
| |
| if (start_idx > idx++) |
| continue; |
| else if (num_macs == count) |
| break; |
| memcpy(entry, ha->addr, sizeof(*entry)); |
| count++; |
| } |
| |
| tot_macs = netdev_hw_addr_list_count(&adapter->netdev->dev_addrs) + |
| netdev_uc_count(adapter->netdev) - em_macs; |
| macs->tot_macs_in_lst = cpu_to_be16(tot_macs); |
| macs->num_macs_in_msg = cpu_to_be16(count); |
| macs->gen_count = cpu_to_be16(adapter->info.vport.uc_macs_gen_count); |
| } |