diff options
Diffstat (limited to 'drivers/net/ethernet/ibm/ibmvnic.c')
-rw-r--r-- | drivers/net/ethernet/ibm/ibmvnic.c | 151 |
1 files changed, 97 insertions, 54 deletions
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 4f0daf67b18d..c9d5d0a7fbf1 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -1428,7 +1428,7 @@ static int ibmvnic_xmit_workarounds(struct sk_buff *skb, return 0; } -static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev) +static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev) { struct ibmvnic_adapter *adapter = netdev_priv(netdev); int queue_num = skb_get_queue_mapping(skb); @@ -1452,7 +1452,7 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev) u64 *handle_array; int index = 0; u8 proto = 0; - int ret = 0; + netdev_tx_t ret = NETDEV_TX_OK; if (adapter->resetting) { if (!netif_subqueue_stopped(netdev, skb)) @@ -1545,7 +1545,7 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev) tx_crq.v1.sge_len = cpu_to_be32(skb->len); tx_crq.v1.ioba = cpu_to_be64(data_dma_addr); - if (adapter->vlan_header_insertion) { + if (adapter->vlan_header_insertion && skb_vlan_tag_present(skb)) { tx_crq.v1.flags2 |= IBMVNIC_TX_VLAN_INSERT; tx_crq.v1.vlan_id = cpu_to_be16(skb->vlan_tci); } @@ -2207,19 +2207,6 @@ restart_poll: return frames_processed; } -#ifdef CONFIG_NET_POLL_CONTROLLER -static void ibmvnic_netpoll_controller(struct net_device *dev) -{ - struct ibmvnic_adapter *adapter = netdev_priv(dev); - int i; - - replenish_pools(netdev_priv(dev)); - for (i = 0; i < adapter->req_rx_queues; i++) - ibmvnic_interrupt_rx(adapter->rx_scrq[i]->irq, - adapter->rx_scrq[i]); -} -#endif - static int wait_for_reset(struct ibmvnic_adapter *adapter) { int rc, ret; @@ -2292,9 +2279,6 @@ static const struct net_device_ops ibmvnic_netdev_ops = { .ndo_set_mac_address = ibmvnic_set_mac, .ndo_validate_addr = eth_validate_addr, .ndo_tx_timeout = ibmvnic_tx_timeout, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = ibmvnic_netpoll_controller, -#endif .ndo_change_mtu = ibmvnic_change_mtu, .ndo_features_check = ibmvnic_features_check, }; @@ -2364,8 +2348,13 @@ static void ibmvnic_get_ringparam(struct net_device *netdev, { struct ibmvnic_adapter *adapter = netdev_priv(netdev); - ring->rx_max_pending = adapter->max_rx_add_entries_per_subcrq; - ring->tx_max_pending = adapter->max_tx_entries_per_subcrq; + if (adapter->priv_flags & IBMVNIC_USE_SERVER_MAXES) { + ring->rx_max_pending = adapter->max_rx_add_entries_per_subcrq; + ring->tx_max_pending = adapter->max_tx_entries_per_subcrq; + } else { + ring->rx_max_pending = IBMVNIC_MAX_QUEUE_SZ; + ring->tx_max_pending = IBMVNIC_MAX_QUEUE_SZ; + } ring->rx_mini_max_pending = 0; ring->rx_jumbo_max_pending = 0; ring->rx_pending = adapter->req_rx_add_entries_per_subcrq; @@ -2378,21 +2367,23 @@ static int ibmvnic_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) { struct ibmvnic_adapter *adapter = netdev_priv(netdev); + int ret; - if (ring->rx_pending > adapter->max_rx_add_entries_per_subcrq || - ring->tx_pending > adapter->max_tx_entries_per_subcrq) { - netdev_err(netdev, "Invalid request.\n"); - netdev_err(netdev, "Max tx buffers = %llu\n", - adapter->max_rx_add_entries_per_subcrq); - netdev_err(netdev, "Max rx buffers = %llu\n", - adapter->max_tx_entries_per_subcrq); - return -EINVAL; - } - + ret = 0; adapter->desired.rx_entries = ring->rx_pending; adapter->desired.tx_entries = ring->tx_pending; - return wait_for_reset(adapter); + ret = wait_for_reset(adapter); + + if (!ret && + (adapter->req_rx_add_entries_per_subcrq != ring->rx_pending || + adapter->req_tx_entries_per_subcrq != ring->tx_pending)) + netdev_info(netdev, + "Could not match full ringsize request. Requested: RX %d, TX %d; Allowed: RX %llu, TX %llu\n", + ring->rx_pending, ring->tx_pending, + adapter->req_rx_add_entries_per_subcrq, + adapter->req_tx_entries_per_subcrq); + return ret; } static void ibmvnic_get_channels(struct net_device *netdev, @@ -2400,8 +2391,14 @@ static void ibmvnic_get_channels(struct net_device *netdev, { struct ibmvnic_adapter *adapter = netdev_priv(netdev); - channels->max_rx = adapter->max_rx_queues; - channels->max_tx = adapter->max_tx_queues; + if (adapter->priv_flags & IBMVNIC_USE_SERVER_MAXES) { + channels->max_rx = adapter->max_rx_queues; + channels->max_tx = adapter->max_tx_queues; + } else { + channels->max_rx = IBMVNIC_MAX_QUEUES; + channels->max_tx = IBMVNIC_MAX_QUEUES; + } + channels->max_other = 0; channels->max_combined = 0; channels->rx_count = adapter->req_rx_queues; @@ -2414,11 +2411,23 @@ static int ibmvnic_set_channels(struct net_device *netdev, struct ethtool_channels *channels) { struct ibmvnic_adapter *adapter = netdev_priv(netdev); + int ret; + ret = 0; adapter->desired.rx_queues = channels->rx_count; adapter->desired.tx_queues = channels->tx_count; - return wait_for_reset(adapter); + ret = wait_for_reset(adapter); + + if (!ret && + (adapter->req_rx_queues != channels->rx_count || + adapter->req_tx_queues != channels->tx_count)) + netdev_info(netdev, + "Could not match full channels request. Requested: RX %d, TX %d; Allowed: RX %llu, TX %llu\n", + channels->rx_count, channels->tx_count, + adapter->req_rx_queues, adapter->req_tx_queues); + return ret; + } static void ibmvnic_get_strings(struct net_device *dev, u32 stringset, u8 *data) @@ -2426,32 +2435,43 @@ static void ibmvnic_get_strings(struct net_device *dev, u32 stringset, u8 *data) struct ibmvnic_adapter *adapter = netdev_priv(dev); int i; - if (stringset != ETH_SS_STATS) - return; + switch (stringset) { + case ETH_SS_STATS: + for (i = 0; i < ARRAY_SIZE(ibmvnic_stats); + i++, data += ETH_GSTRING_LEN) + memcpy(data, ibmvnic_stats[i].name, ETH_GSTRING_LEN); - for (i = 0; i < ARRAY_SIZE(ibmvnic_stats); i++, data += ETH_GSTRING_LEN) - memcpy(data, ibmvnic_stats[i].name, ETH_GSTRING_LEN); + for (i = 0; i < adapter->req_tx_queues; i++) { + snprintf(data, ETH_GSTRING_LEN, "tx%d_packets", i); + data += ETH_GSTRING_LEN; - for (i = 0; i < adapter->req_tx_queues; i++) { - snprintf(data, ETH_GSTRING_LEN, "tx%d_packets", i); - data += ETH_GSTRING_LEN; + snprintf(data, ETH_GSTRING_LEN, "tx%d_bytes", i); + data += ETH_GSTRING_LEN; - snprintf(data, ETH_GSTRING_LEN, "tx%d_bytes", i); - data += ETH_GSTRING_LEN; + snprintf(data, ETH_GSTRING_LEN, + "tx%d_dropped_packets", i); + data += ETH_GSTRING_LEN; + } - snprintf(data, ETH_GSTRING_LEN, "tx%d_dropped_packets", i); - data += ETH_GSTRING_LEN; - } + for (i = 0; i < adapter->req_rx_queues; i++) { + snprintf(data, ETH_GSTRING_LEN, "rx%d_packets", i); + data += ETH_GSTRING_LEN; - for (i = 0; i < adapter->req_rx_queues; i++) { - snprintf(data, ETH_GSTRING_LEN, "rx%d_packets", i); - data += ETH_GSTRING_LEN; + snprintf(data, ETH_GSTRING_LEN, "rx%d_bytes", i); + data += ETH_GSTRING_LEN; - snprintf(data, ETH_GSTRING_LEN, "rx%d_bytes", i); - data += ETH_GSTRING_LEN; + snprintf(data, ETH_GSTRING_LEN, "rx%d_interrupts", i); + data += ETH_GSTRING_LEN; + } + break; - snprintf(data, ETH_GSTRING_LEN, "rx%d_interrupts", i); - data += ETH_GSTRING_LEN; + case ETH_SS_PRIV_FLAGS: + for (i = 0; i < ARRAY_SIZE(ibmvnic_priv_flags); i++) + strcpy(data + i * ETH_GSTRING_LEN, + ibmvnic_priv_flags[i]); + break; + default: + return; } } @@ -2464,6 +2484,8 @@ static int ibmvnic_get_sset_count(struct net_device *dev, int sset) return ARRAY_SIZE(ibmvnic_stats) + adapter->req_tx_queues * NUM_TX_STATS + adapter->req_rx_queues * NUM_RX_STATS; + case ETH_SS_PRIV_FLAGS: + return ARRAY_SIZE(ibmvnic_priv_flags); default: return -EOPNOTSUPP; } @@ -2514,6 +2536,25 @@ static void ibmvnic_get_ethtool_stats(struct net_device *dev, } } +static u32 ibmvnic_get_priv_flags(struct net_device *netdev) +{ + struct ibmvnic_adapter *adapter = netdev_priv(netdev); + + return adapter->priv_flags; +} + +static int ibmvnic_set_priv_flags(struct net_device *netdev, u32 flags) +{ + struct ibmvnic_adapter *adapter = netdev_priv(netdev); + bool which_maxes = !!(flags & IBMVNIC_USE_SERVER_MAXES); + + if (which_maxes) + adapter->priv_flags |= IBMVNIC_USE_SERVER_MAXES; + else + adapter->priv_flags &= ~IBMVNIC_USE_SERVER_MAXES; + + return 0; +} static const struct ethtool_ops ibmvnic_ethtool_ops = { .get_drvinfo = ibmvnic_get_drvinfo, .get_msglevel = ibmvnic_get_msglevel, @@ -2527,6 +2568,8 @@ static const struct ethtool_ops ibmvnic_ethtool_ops = { .get_sset_count = ibmvnic_get_sset_count, .get_ethtool_stats = ibmvnic_get_ethtool_stats, .get_link_ksettings = ibmvnic_get_link_ksettings, + .get_priv_flags = ibmvnic_get_priv_flags, + .set_priv_flags = ibmvnic_set_priv_flags, }; /* Routines for managing CRQs/sCRQs */ |