| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * IBM Power Virtual Ethernet Device Driver |
|---|
| 3 | | - * |
|---|
| 4 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 5 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 6 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 7 | | - * (at your option) any later version. |
|---|
| 8 | | - * |
|---|
| 9 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 10 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 11 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 12 | | - * GNU General Public License for more details. |
|---|
| 13 | | - * |
|---|
| 14 | | - * You should have received a copy of the GNU General Public License |
|---|
| 15 | | - * along with this program; if not, see <http://www.gnu.org/licenses/>. |
|---|
| 16 | 4 | * |
|---|
| 17 | 5 | * Copyright (C) IBM Corporation, 2003, 2010 |
|---|
| 18 | 6 | * |
|---|
| .. | .. |
|---|
| 24 | 12 | */ |
|---|
| 25 | 13 | |
|---|
| 26 | 14 | #include <linux/module.h> |
|---|
| 27 | | -#include <linux/moduleparam.h> |
|---|
| 28 | 15 | #include <linux/types.h> |
|---|
| 29 | 16 | #include <linux/errno.h> |
|---|
| 30 | 17 | #include <linux/dma-mapping.h> |
|---|
| .. | .. |
|---|
| 94 | 81 | #define IBMVETH_STAT_OFF(stat) offsetof(struct ibmveth_adapter, stat) |
|---|
| 95 | 82 | #define IBMVETH_GET_STAT(a, off) *((u64 *)(((unsigned long)(a)) + off)) |
|---|
| 96 | 83 | |
|---|
| 97 | | -struct ibmveth_stat ibmveth_stats[] = { |
|---|
| 84 | +static struct ibmveth_stat ibmveth_stats[] = { |
|---|
| 98 | 85 | { "replenish_task_cycles", IBMVETH_STAT_OFF(replenish_task_cycles) }, |
|---|
| 99 | 86 | { "replenish_no_mem", IBMVETH_STAT_OFF(replenish_no_mem) }, |
|---|
| 100 | 87 | { "replenish_add_buff_failure", |
|---|
| .. | .. |
|---|
| 725 | 712 | return 0; |
|---|
| 726 | 713 | } |
|---|
| 727 | 714 | |
|---|
| 728 | | -static int netdev_get_link_ksettings(struct net_device *dev, |
|---|
| 729 | | - struct ethtool_link_ksettings *cmd) |
|---|
| 715 | +static int ibmveth_set_link_ksettings(struct net_device *dev, |
|---|
| 716 | + const struct ethtool_link_ksettings *cmd) |
|---|
| 730 | 717 | { |
|---|
| 731 | | - u32 supported, advertising; |
|---|
| 718 | + struct ibmveth_adapter *adapter = netdev_priv(dev); |
|---|
| 732 | 719 | |
|---|
| 733 | | - supported = (SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | |
|---|
| 734 | | - SUPPORTED_FIBRE); |
|---|
| 735 | | - advertising = (ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg | |
|---|
| 736 | | - ADVERTISED_FIBRE); |
|---|
| 737 | | - cmd->base.speed = SPEED_1000; |
|---|
| 738 | | - cmd->base.duplex = DUPLEX_FULL; |
|---|
| 739 | | - cmd->base.port = PORT_FIBRE; |
|---|
| 740 | | - cmd->base.phy_address = 0; |
|---|
| 741 | | - cmd->base.autoneg = AUTONEG_ENABLE; |
|---|
| 720 | + return ethtool_virtdev_set_link_ksettings(dev, cmd, |
|---|
| 721 | + &adapter->speed, |
|---|
| 722 | + &adapter->duplex); |
|---|
| 723 | +} |
|---|
| 742 | 724 | |
|---|
| 743 | | - ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, |
|---|
| 744 | | - supported); |
|---|
| 745 | | - ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising, |
|---|
| 746 | | - advertising); |
|---|
| 725 | +static int ibmveth_get_link_ksettings(struct net_device *dev, |
|---|
| 726 | + struct ethtool_link_ksettings *cmd) |
|---|
| 727 | +{ |
|---|
| 728 | + struct ibmveth_adapter *adapter = netdev_priv(dev); |
|---|
| 729 | + |
|---|
| 730 | + cmd->base.speed = adapter->speed; |
|---|
| 731 | + cmd->base.duplex = adapter->duplex; |
|---|
| 732 | + cmd->base.port = PORT_OTHER; |
|---|
| 747 | 733 | |
|---|
| 748 | 734 | return 0; |
|---|
| 735 | +} |
|---|
| 736 | + |
|---|
| 737 | +static void ibmveth_init_link_settings(struct net_device *dev) |
|---|
| 738 | +{ |
|---|
| 739 | + struct ibmveth_adapter *adapter = netdev_priv(dev); |
|---|
| 740 | + |
|---|
| 741 | + adapter->speed = SPEED_1000; |
|---|
| 742 | + adapter->duplex = DUPLEX_FULL; |
|---|
| 749 | 743 | } |
|---|
| 750 | 744 | |
|---|
| 751 | 745 | static void netdev_get_drvinfo(struct net_device *dev, |
|---|
| .. | .. |
|---|
| 978 | 972 | } |
|---|
| 979 | 973 | |
|---|
| 980 | 974 | static const struct ethtool_ops netdev_ethtool_ops = { |
|---|
| 981 | | - .get_drvinfo = netdev_get_drvinfo, |
|---|
| 982 | | - .get_link = ethtool_op_get_link, |
|---|
| 983 | | - .get_strings = ibmveth_get_strings, |
|---|
| 984 | | - .get_sset_count = ibmveth_get_sset_count, |
|---|
| 985 | | - .get_ethtool_stats = ibmveth_get_ethtool_stats, |
|---|
| 986 | | - .get_link_ksettings = netdev_get_link_ksettings, |
|---|
| 975 | + .get_drvinfo = netdev_get_drvinfo, |
|---|
| 976 | + .get_link = ethtool_op_get_link, |
|---|
| 977 | + .get_strings = ibmveth_get_strings, |
|---|
| 978 | + .get_sset_count = ibmveth_get_sset_count, |
|---|
| 979 | + .get_ethtool_stats = ibmveth_get_ethtool_stats, |
|---|
| 980 | + .get_link_ksettings = ibmveth_get_link_ksettings, |
|---|
| 981 | + .set_link_ksettings = ibmveth_set_link_ksettings, |
|---|
| 987 | 982 | }; |
|---|
| 988 | 983 | |
|---|
| 989 | 984 | static int ibmveth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) |
|---|
| 990 | 985 | { |
|---|
| 991 | 986 | return -EOPNOTSUPP; |
|---|
| 992 | 987 | } |
|---|
| 993 | | - |
|---|
| 994 | | -#define page_offset(v) ((unsigned long)(v) & ((1 << 12) - 1)) |
|---|
| 995 | 988 | |
|---|
| 996 | 989 | static int ibmveth_send(struct ibmveth_adapter *adapter, |
|---|
| 997 | 990 | union ibmveth_buf_desc *descs, unsigned long mss) |
|---|
| .. | .. |
|---|
| 1024 | 1017 | return 0; |
|---|
| 1025 | 1018 | } |
|---|
| 1026 | 1019 | |
|---|
| 1020 | +static int ibmveth_is_packet_unsupported(struct sk_buff *skb, |
|---|
| 1021 | + struct net_device *netdev) |
|---|
| 1022 | +{ |
|---|
| 1023 | + struct ethhdr *ether_header; |
|---|
| 1024 | + int ret = 0; |
|---|
| 1025 | + |
|---|
| 1026 | + ether_header = eth_hdr(skb); |
|---|
| 1027 | + |
|---|
| 1028 | + if (ether_addr_equal(ether_header->h_dest, netdev->dev_addr)) { |
|---|
| 1029 | + netdev_dbg(netdev, "veth doesn't support loopback packets, dropping packet.\n"); |
|---|
| 1030 | + netdev->stats.tx_dropped++; |
|---|
| 1031 | + ret = -EOPNOTSUPP; |
|---|
| 1032 | + } |
|---|
| 1033 | + |
|---|
| 1034 | + return ret; |
|---|
| 1035 | +} |
|---|
| 1036 | + |
|---|
| 1027 | 1037 | static netdev_tx_t ibmveth_start_xmit(struct sk_buff *skb, |
|---|
| 1028 | 1038 | struct net_device *netdev) |
|---|
| 1029 | 1039 | { |
|---|
| .. | .. |
|---|
| 1034 | 1044 | int force_bounce = 0; |
|---|
| 1035 | 1045 | dma_addr_t dma_addr; |
|---|
| 1036 | 1046 | unsigned long mss = 0; |
|---|
| 1047 | + |
|---|
| 1048 | + if (ibmveth_is_packet_unsupported(skb, netdev)) |
|---|
| 1049 | + goto out; |
|---|
| 1037 | 1050 | |
|---|
| 1038 | 1051 | /* veth doesn't handle frag_list, so linearize the skb. |
|---|
| 1039 | 1052 | * When GRO is enabled SKB's can have frag_list. |
|---|
| .. | .. |
|---|
| 1672 | 1685 | adapter->netdev = netdev; |
|---|
| 1673 | 1686 | adapter->mcastFilterSize = be32_to_cpu(*mcastFilterSize_p); |
|---|
| 1674 | 1687 | adapter->pool_config = 0; |
|---|
| 1688 | + ibmveth_init_link_settings(netdev); |
|---|
| 1675 | 1689 | |
|---|
| 1676 | 1690 | netif_napi_add(netdev, &adapter->napi, ibmveth_poll, 16); |
|---|
| 1677 | 1691 | |
|---|