Path: blob/master/drivers/infiniband/hw/nes/nes_nic.c
15112 views
/*1* Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.2*3* This software is available to you under a choice of one of two4* licenses. You may choose to be licensed under the terms of the GNU5* General Public License (GPL) Version 2, available from the file6* COPYING in the main directory of this source tree, or the7* OpenIB.org BSD license below:8*9* Redistribution and use in source and binary forms, with or10* without modification, are permitted provided that the following11* conditions are met:12*13* - Redistributions of source code must retain the above14* copyright notice, this list of conditions and the following15* disclaimer.16*17* - Redistributions in binary form must reproduce the above18* copyright notice, this list of conditions and the following19* disclaimer in the documentation and/or other materials20* provided with the distribution.21*22* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,23* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF24* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND25* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS26* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN27* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN28* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE29* SOFTWARE.30*31*/3233#include <linux/module.h>34#include <linux/moduleparam.h>35#include <linux/netdevice.h>36#include <linux/etherdevice.h>37#include <linux/ip.h>38#include <linux/tcp.h>39#include <linux/if_arp.h>40#include <linux/if_vlan.h>41#include <linux/ethtool.h>42#include <linux/slab.h>43#include <net/tcp.h>4445#include <net/inet_common.h>46#include <linux/inet.h>4748#include "nes.h"4950static struct nic_qp_map nic_qp_mapping_0[] = {51{16,0,0,1},{24,4,0,0},{28,8,0,0},{32,12,0,0},52{20,2,2,1},{26,6,2,0},{30,10,2,0},{34,14,2,0},53{18,1,1,1},{25,5,1,0},{29,9,1,0},{33,13,1,0},54{22,3,3,1},{27,7,3,0},{31,11,3,0},{35,15,3,0}55};5657static struct nic_qp_map nic_qp_mapping_1[] = {58{18,1,1,1},{25,5,1,0},{29,9,1,0},{33,13,1,0},59{22,3,3,1},{27,7,3,0},{31,11,3,0},{35,15,3,0}60};6162static struct nic_qp_map nic_qp_mapping_2[] = {63{20,2,2,1},{26,6,2,0},{30,10,2,0},{34,14,2,0}64};6566static struct nic_qp_map nic_qp_mapping_3[] = {67{22,3,3,1},{27,7,3,0},{31,11,3,0},{35,15,3,0}68};6970static struct nic_qp_map nic_qp_mapping_4[] = {71{28,8,0,0},{32,12,0,0}72};7374static struct nic_qp_map nic_qp_mapping_5[] = {75{29,9,1,0},{33,13,1,0}76};7778static struct nic_qp_map nic_qp_mapping_6[] = {79{30,10,2,0},{34,14,2,0}80};8182static struct nic_qp_map nic_qp_mapping_7[] = {83{31,11,3,0},{35,15,3,0}84};8586static struct nic_qp_map *nic_qp_mapping_per_function[] = {87nic_qp_mapping_0, nic_qp_mapping_1, nic_qp_mapping_2, nic_qp_mapping_3,88nic_qp_mapping_4, nic_qp_mapping_5, nic_qp_mapping_6, nic_qp_mapping_789};9091static const u32 default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK92| NETIF_MSG_IFUP | NETIF_MSG_IFDOWN;93static int debug = -1;94static int nics_per_function = 1;9596/**97* nes_netdev_poll98*/99static int nes_netdev_poll(struct napi_struct *napi, int budget)100{101struct nes_vnic *nesvnic = container_of(napi, struct nes_vnic, napi);102struct nes_device *nesdev = nesvnic->nesdev;103struct nes_hw_nic_cq *nescq = &nesvnic->nic_cq;104105nesvnic->budget = budget;106nescq->cqes_pending = 0;107nescq->rx_cqes_completed = 0;108nescq->cqe_allocs_pending = 0;109nescq->rx_pkts_indicated = 0;110111nes_nic_ce_handler(nesdev, nescq);112113if (nescq->cqes_pending == 0) {114napi_complete(napi);115/* clear out completed cqes and arm */116nes_write32(nesdev->regs+NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT |117nescq->cq_number | (nescq->cqe_allocs_pending << 16));118nes_read32(nesdev->regs+NES_CQE_ALLOC);119} else {120/* clear out completed cqes but don't arm */121nes_write32(nesdev->regs+NES_CQE_ALLOC,122nescq->cq_number | (nescq->cqe_allocs_pending << 16));123nes_debug(NES_DBG_NETDEV, "%s: exiting with work pending\n",124nesvnic->netdev->name);125}126return nescq->rx_pkts_indicated;127}128129130/**131* nes_netdev_open - Activate the network interface; ifconfig132* ethx up.133*/134static int nes_netdev_open(struct net_device *netdev)135{136u32 macaddr_low;137u16 macaddr_high;138struct nes_vnic *nesvnic = netdev_priv(netdev);139struct nes_device *nesdev = nesvnic->nesdev;140int ret;141int i;142struct nes_vnic *first_nesvnic = NULL;143u32 nic_active_bit;144u32 nic_active;145struct list_head *list_pos, *list_temp;146unsigned long flags;147148assert(nesdev != NULL);149150if (nesvnic->netdev_open == 1)151return 0;152153if (netif_msg_ifup(nesvnic))154printk(KERN_INFO PFX "%s: enabling interface\n", netdev->name);155156ret = nes_init_nic_qp(nesdev, netdev);157if (ret) {158return ret;159}160161netif_carrier_off(netdev);162netif_stop_queue(netdev);163164if ((!nesvnic->of_device_registered) && (nesvnic->rdma_enabled)) {165nesvnic->nesibdev = nes_init_ofa_device(netdev);166if (nesvnic->nesibdev == NULL) {167printk(KERN_ERR PFX "%s: nesvnic->nesibdev alloc failed", netdev->name);168} else {169nesvnic->nesibdev->nesvnic = nesvnic;170ret = nes_register_ofa_device(nesvnic->nesibdev);171if (ret) {172printk(KERN_ERR PFX "%s: Unable to register RDMA device, ret = %d\n",173netdev->name, ret);174}175}176}177/* Set packet filters */178nic_active_bit = 1 << nesvnic->nic_index;179nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_ACTIVE);180nic_active |= nic_active_bit;181nes_write_indexed(nesdev, NES_IDX_NIC_ACTIVE, nic_active);182nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ENABLE);183nic_active |= nic_active_bit;184nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ENABLE, nic_active);185nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_BROADCAST_ON);186nic_active |= nic_active_bit;187nes_write_indexed(nesdev, NES_IDX_NIC_BROADCAST_ON, nic_active);188189macaddr_high = ((u16)netdev->dev_addr[0]) << 8;190macaddr_high += (u16)netdev->dev_addr[1];191192macaddr_low = ((u32)netdev->dev_addr[2]) << 24;193macaddr_low += ((u32)netdev->dev_addr[3]) << 16;194macaddr_low += ((u32)netdev->dev_addr[4]) << 8;195macaddr_low += (u32)netdev->dev_addr[5];196197/* Program the various MAC regs */198for (i = 0; i < NES_MAX_PORT_COUNT; i++) {199if (nesvnic->qp_nic_index[i] == 0xf) {200break;201}202nes_debug(NES_DBG_NETDEV, "i=%d, perfect filter table index= %d, PERF FILTER LOW"203" (Addr:%08X) = %08X, HIGH = %08X.\n",204i, nesvnic->qp_nic_index[i],205NES_IDX_PERFECT_FILTER_LOW+206(nesvnic->qp_nic_index[i] * 8),207macaddr_low,208(u32)macaddr_high | NES_MAC_ADDR_VALID |209((((u32)nesvnic->nic_index) << 16)));210nes_write_indexed(nesdev,211NES_IDX_PERFECT_FILTER_LOW + (nesvnic->qp_nic_index[i] * 8),212macaddr_low);213nes_write_indexed(nesdev,214NES_IDX_PERFECT_FILTER_HIGH + (nesvnic->qp_nic_index[i] * 8),215(u32)macaddr_high | NES_MAC_ADDR_VALID |216((((u32)nesvnic->nic_index) << 16)));217}218219220nes_write32(nesdev->regs+NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT |221nesvnic->nic_cq.cq_number);222nes_read32(nesdev->regs+NES_CQE_ALLOC);223list_for_each_safe(list_pos, list_temp, &nesdev->nesadapter->nesvnic_list[nesdev->mac_index]) {224first_nesvnic = container_of(list_pos, struct nes_vnic, list);225if (first_nesvnic->netdev_open == 1)226break;227}228if (first_nesvnic->netdev_open == 0) {229nes_debug(NES_DBG_INIT, "Setting up MAC interrupt mask.\n");230nes_write_indexed(nesdev, NES_IDX_MAC_INT_MASK + (0x200 * nesdev->mac_index),231~(NES_MAC_INT_LINK_STAT_CHG | NES_MAC_INT_XGMII_EXT |232NES_MAC_INT_TX_UNDERFLOW | NES_MAC_INT_TX_ERROR));233first_nesvnic = nesvnic;234}235236if (first_nesvnic->linkup) {237/* Enable network packets */238nesvnic->linkup = 1;239netif_start_queue(netdev);240netif_carrier_on(netdev);241}242243spin_lock_irqsave(&nesdev->nesadapter->phy_lock, flags);244if (nesdev->nesadapter->phy_type[nesdev->mac_index] == NES_PHY_TYPE_SFP_D) {245if (nesdev->link_recheck)246cancel_delayed_work(&nesdev->work);247nesdev->link_recheck = 1;248schedule_delayed_work(&nesdev->work, NES_LINK_RECHECK_DELAY);249}250spin_unlock_irqrestore(&nesdev->nesadapter->phy_lock, flags);251252spin_lock_irqsave(&nesvnic->port_ibevent_lock, flags);253if (nesvnic->of_device_registered) {254nesdev->nesadapter->send_term_ok = 1;255if (nesvnic->linkup == 1) {256if (nesdev->iw_status == 0) {257nesdev->iw_status = 1;258nes_port_ibevent(nesvnic);259}260} else {261nesdev->iw_status = 0;262}263}264spin_unlock_irqrestore(&nesvnic->port_ibevent_lock, flags);265266napi_enable(&nesvnic->napi);267nesvnic->netdev_open = 1;268269return 0;270}271272273/**274* nes_netdev_stop275*/276static int nes_netdev_stop(struct net_device *netdev)277{278struct nes_vnic *nesvnic = netdev_priv(netdev);279struct nes_device *nesdev = nesvnic->nesdev;280u32 nic_active_mask;281u32 nic_active;282struct nes_vnic *first_nesvnic = NULL;283struct list_head *list_pos, *list_temp;284unsigned long flags;285286nes_debug(NES_DBG_SHUTDOWN, "nesvnic=%p, nesdev=%p, netdev=%p %s\n",287nesvnic, nesdev, netdev, netdev->name);288if (nesvnic->netdev_open == 0)289return 0;290291if (netif_msg_ifdown(nesvnic))292printk(KERN_INFO PFX "%s: disabling interface\n", netdev->name);293netif_carrier_off(netdev);294295/* Disable network packets */296napi_disable(&nesvnic->napi);297netif_stop_queue(netdev);298list_for_each_safe(list_pos, list_temp, &nesdev->nesadapter->nesvnic_list[nesdev->mac_index]) {299first_nesvnic = container_of(list_pos, struct nes_vnic, list);300if ((first_nesvnic->netdev_open == 1) && (first_nesvnic != nesvnic))301break;302}303304if ((first_nesvnic->netdev_open == 1) && (first_nesvnic != nesvnic) &&305(PCI_FUNC(first_nesvnic->nesdev->pcidev->devfn) !=306PCI_FUNC(nesvnic->nesdev->pcidev->devfn))) {307nes_write_indexed(nesdev, NES_IDX_MAC_INT_MASK+308(0x200*nesdev->mac_index), 0xffffffff);309nes_write_indexed(first_nesvnic->nesdev,310NES_IDX_MAC_INT_MASK+311(0x200*first_nesvnic->nesdev->mac_index),312~(NES_MAC_INT_LINK_STAT_CHG | NES_MAC_INT_XGMII_EXT |313NES_MAC_INT_TX_UNDERFLOW | NES_MAC_INT_TX_ERROR));314} else {315nes_write_indexed(nesdev, NES_IDX_MAC_INT_MASK+(0x200*nesdev->mac_index), 0xffffffff);316}317318nic_active_mask = ~((u32)(1 << nesvnic->nic_index));319nes_write_indexed(nesdev, NES_IDX_PERFECT_FILTER_HIGH+320(nesvnic->perfect_filter_index*8), 0);321nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_ACTIVE);322nic_active &= nic_active_mask;323nes_write_indexed(nesdev, NES_IDX_NIC_ACTIVE, nic_active);324nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL);325nic_active &= nic_active_mask;326nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL, nic_active);327nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ENABLE);328nic_active &= nic_active_mask;329nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ENABLE, nic_active);330nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL);331nic_active &= nic_active_mask;332nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active);333nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_BROADCAST_ON);334nic_active &= nic_active_mask;335nes_write_indexed(nesdev, NES_IDX_NIC_BROADCAST_ON, nic_active);336337spin_lock_irqsave(&nesvnic->port_ibevent_lock, flags);338if (nesvnic->of_device_registered) {339nesdev->nesadapter->send_term_ok = 0;340nesdev->iw_status = 0;341if (nesvnic->linkup == 1)342nes_port_ibevent(nesvnic);343}344del_timer_sync(&nesvnic->event_timer);345nesvnic->event_timer.function = NULL;346spin_unlock_irqrestore(&nesvnic->port_ibevent_lock, flags);347348nes_destroy_nic_qp(nesvnic);349350nesvnic->netdev_open = 0;351352return 0;353}354355356/**357* nes_nic_send358*/359static int nes_nic_send(struct sk_buff *skb, struct net_device *netdev)360{361struct nes_vnic *nesvnic = netdev_priv(netdev);362struct nes_device *nesdev = nesvnic->nesdev;363struct nes_hw_nic *nesnic = &nesvnic->nic;364struct nes_hw_nic_sq_wqe *nic_sqe;365struct tcphdr *tcph;366__le16 *wqe_fragment_length;367u32 wqe_misc;368u16 wqe_fragment_index = 1; /* first fragment (0) is used by copy buffer */369u16 skb_fragment_index;370dma_addr_t bus_address;371372nic_sqe = &nesnic->sq_vbase[nesnic->sq_head];373wqe_fragment_length = (__le16 *)&nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_0_TAG_IDX];374375/* setup the VLAN tag if present */376if (vlan_tx_tag_present(skb)) {377nes_debug(NES_DBG_NIC_TX, "%s: VLAN packet to send... VLAN = %08X\n",378netdev->name, vlan_tx_tag_get(skb));379wqe_misc = NES_NIC_SQ_WQE_TAGVALUE_ENABLE;380wqe_fragment_length[0] = (__force __le16) vlan_tx_tag_get(skb);381} else382wqe_misc = 0;383384/* bump past the vlan tag */385wqe_fragment_length++;386/* wqe_fragment_address = (u64 *)&nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX]; */387388if (skb->ip_summed == CHECKSUM_PARTIAL) {389tcph = tcp_hdr(skb);390if (1) {391if (skb_is_gso(skb)) {392/* nes_debug(NES_DBG_NIC_TX, "%s: TSO request... seg size = %u\n",393netdev->name, skb_is_gso(skb)); */394wqe_misc |= NES_NIC_SQ_WQE_LSO_ENABLE |395NES_NIC_SQ_WQE_COMPLETION | (u16)skb_is_gso(skb);396set_wqe_32bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_LSO_INFO_IDX,397((u32)tcph->doff) |398(((u32)(((unsigned char *)tcph) - skb->data)) << 4));399} else {400wqe_misc |= NES_NIC_SQ_WQE_COMPLETION;401}402}403} else { /* CHECKSUM_HW */404wqe_misc |= NES_NIC_SQ_WQE_DISABLE_CHKSUM | NES_NIC_SQ_WQE_COMPLETION;405}406407set_wqe_32bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_TOTAL_LENGTH_IDX,408skb->len);409memcpy(&nesnic->first_frag_vbase[nesnic->sq_head].buffer,410skb->data, min(((unsigned int)NES_FIRST_FRAG_SIZE), skb_headlen(skb)));411wqe_fragment_length[0] = cpu_to_le16(min(((unsigned int)NES_FIRST_FRAG_SIZE),412skb_headlen(skb)));413wqe_fragment_length[1] = 0;414if (skb_headlen(skb) > NES_FIRST_FRAG_SIZE) {415if ((skb_shinfo(skb)->nr_frags + 1) > 4) {416nes_debug(NES_DBG_NIC_TX, "%s: Packet with %u fragments not sent, skb_headlen=%u\n",417netdev->name, skb_shinfo(skb)->nr_frags + 2, skb_headlen(skb));418kfree_skb(skb);419nesvnic->tx_sw_dropped++;420return NETDEV_TX_LOCKED;421}422set_bit(nesnic->sq_head, nesnic->first_frag_overflow);423bus_address = pci_map_single(nesdev->pcidev, skb->data + NES_FIRST_FRAG_SIZE,424skb_headlen(skb) - NES_FIRST_FRAG_SIZE, PCI_DMA_TODEVICE);425wqe_fragment_length[wqe_fragment_index++] =426cpu_to_le16(skb_headlen(skb) - NES_FIRST_FRAG_SIZE);427wqe_fragment_length[wqe_fragment_index] = 0;428set_wqe_64bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_FRAG1_LOW_IDX,429((u64)(bus_address)));430nesnic->tx_skb[nesnic->sq_head] = skb;431}432433if (skb_headlen(skb) == skb->len) {434if (skb_headlen(skb) <= NES_FIRST_FRAG_SIZE) {435nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_2_1_IDX] = 0;436nesnic->tx_skb[nesnic->sq_head] = skb;437}438} else {439/* Deal with Fragments */440nesnic->tx_skb[nesnic->sq_head] = skb;441for (skb_fragment_index = 0; skb_fragment_index < skb_shinfo(skb)->nr_frags;442skb_fragment_index++) {443bus_address = pci_map_page( nesdev->pcidev,444skb_shinfo(skb)->frags[skb_fragment_index].page,445skb_shinfo(skb)->frags[skb_fragment_index].page_offset,446skb_shinfo(skb)->frags[skb_fragment_index].size,447PCI_DMA_TODEVICE);448wqe_fragment_length[wqe_fragment_index] =449cpu_to_le16(skb_shinfo(skb)->frags[skb_fragment_index].size);450set_wqe_64bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_LOW_IDX+(2*wqe_fragment_index),451bus_address);452wqe_fragment_index++;453if (wqe_fragment_index < 5)454wqe_fragment_length[wqe_fragment_index] = 0;455}456}457458set_wqe_32bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_MISC_IDX, wqe_misc);459nesnic->sq_head++;460nesnic->sq_head &= nesnic->sq_size - 1;461462return NETDEV_TX_OK;463}464465466/**467* nes_netdev_start_xmit468*/469static int nes_netdev_start_xmit(struct sk_buff *skb, struct net_device *netdev)470{471struct nes_vnic *nesvnic = netdev_priv(netdev);472struct nes_device *nesdev = nesvnic->nesdev;473struct nes_hw_nic *nesnic = &nesvnic->nic;474struct nes_hw_nic_sq_wqe *nic_sqe;475struct tcphdr *tcph;476/* struct udphdr *udph; */477#define NES_MAX_TSO_FRAGS MAX_SKB_FRAGS478/* 64K segment plus overflow on each side */479dma_addr_t tso_bus_address[NES_MAX_TSO_FRAGS];480dma_addr_t bus_address;481u32 tso_frag_index;482u32 tso_frag_count;483u32 tso_wqe_length;484u32 curr_tcp_seq;485u32 wqe_count=1;486u32 send_rc;487struct iphdr *iph;488__le16 *wqe_fragment_length;489u32 nr_frags;490u32 original_first_length;491/* u64 *wqe_fragment_address; */492/* first fragment (0) is used by copy buffer */493u16 wqe_fragment_index=1;494u16 hoffset;495u16 nhoffset;496u16 wqes_needed;497u16 wqes_available;498u32 wqe_misc;499500/*501* nes_debug(NES_DBG_NIC_TX, "%s Request to tx NIC packet length %u, headlen %u,"502* " (%u frags), tso_size=%u\n",503* netdev->name, skb->len, skb_headlen(skb),504* skb_shinfo(skb)->nr_frags, skb_is_gso(skb));505*/506507if (!netif_carrier_ok(netdev))508return NETDEV_TX_OK;509510if (netif_queue_stopped(netdev))511return NETDEV_TX_BUSY;512513/* Check if SQ is full */514if ((((nesnic->sq_tail+(nesnic->sq_size*2))-nesnic->sq_head) & (nesnic->sq_size - 1)) == 1) {515if (!netif_queue_stopped(netdev)) {516netif_stop_queue(netdev);517barrier();518if ((((((volatile u16)nesnic->sq_tail)+(nesnic->sq_size*2))-nesnic->sq_head) & (nesnic->sq_size - 1)) != 1) {519netif_start_queue(netdev);520goto sq_no_longer_full;521}522}523nesvnic->sq_full++;524return NETDEV_TX_BUSY;525}526527sq_no_longer_full:528nr_frags = skb_shinfo(skb)->nr_frags;529if (skb_headlen(skb) > NES_FIRST_FRAG_SIZE) {530nr_frags++;531}532/* Check if too many fragments */533if (unlikely((nr_frags > 4))) {534if (skb_is_gso(skb)) {535nesvnic->segmented_tso_requests++;536nesvnic->tso_requests++;537/* Basically 4 fragments available per WQE with extended fragments */538wqes_needed = nr_frags >> 2;539wqes_needed += (nr_frags&3)?1:0;540wqes_available = (((nesnic->sq_tail+nesnic->sq_size)-nesnic->sq_head) - 1) &541(nesnic->sq_size - 1);542543if (unlikely(wqes_needed > wqes_available)) {544if (!netif_queue_stopped(netdev)) {545netif_stop_queue(netdev);546barrier();547wqes_available = (((((volatile u16)nesnic->sq_tail)+nesnic->sq_size)-nesnic->sq_head) - 1) &548(nesnic->sq_size - 1);549if (wqes_needed <= wqes_available) {550netif_start_queue(netdev);551goto tso_sq_no_longer_full;552}553}554nesvnic->sq_full++;555nes_debug(NES_DBG_NIC_TX, "%s: HNIC SQ full- TSO request has too many frags!\n",556netdev->name);557return NETDEV_TX_BUSY;558}559tso_sq_no_longer_full:560/* Map all the buffers */561for (tso_frag_count=0; tso_frag_count < skb_shinfo(skb)->nr_frags;562tso_frag_count++) {563tso_bus_address[tso_frag_count] = pci_map_page( nesdev->pcidev,564skb_shinfo(skb)->frags[tso_frag_count].page,565skb_shinfo(skb)->frags[tso_frag_count].page_offset,566skb_shinfo(skb)->frags[tso_frag_count].size,567PCI_DMA_TODEVICE);568}569570tso_frag_index = 0;571curr_tcp_seq = ntohl(tcp_hdr(skb)->seq);572hoffset = skb_transport_header(skb) - skb->data;573nhoffset = skb_network_header(skb) - skb->data;574original_first_length = hoffset + ((((struct tcphdr *)skb_transport_header(skb))->doff)<<2);575576for (wqe_count=0; wqe_count<((u32)wqes_needed); wqe_count++) {577tso_wqe_length = 0;578nic_sqe = &nesnic->sq_vbase[nesnic->sq_head];579wqe_fragment_length =580(__le16 *)&nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_0_TAG_IDX];581/* setup the VLAN tag if present */582if (vlan_tx_tag_present(skb)) {583nes_debug(NES_DBG_NIC_TX, "%s: VLAN packet to send... VLAN = %08X\n",584netdev->name, vlan_tx_tag_get(skb) );585wqe_misc = NES_NIC_SQ_WQE_TAGVALUE_ENABLE;586wqe_fragment_length[0] = (__force __le16) vlan_tx_tag_get(skb);587} else588wqe_misc = 0;589590/* bump past the vlan tag */591wqe_fragment_length++;592593/* Assumes header totally fits in allocated buffer and is in first fragment */594if (original_first_length > NES_FIRST_FRAG_SIZE) {595nes_debug(NES_DBG_NIC_TX, "ERROR: SKB header too big, headlen=%u, FIRST_FRAG_SIZE=%u\n",596original_first_length, NES_FIRST_FRAG_SIZE);597nes_debug(NES_DBG_NIC_TX, "%s Request to tx NIC packet length %u, headlen %u,"598" (%u frags), tso_size=%u\n",599netdev->name,600skb->len, skb_headlen(skb),601skb_shinfo(skb)->nr_frags, skb_is_gso(skb));602}603memcpy(&nesnic->first_frag_vbase[nesnic->sq_head].buffer,604skb->data, min(((unsigned int)NES_FIRST_FRAG_SIZE),605original_first_length));606iph = (struct iphdr *)607(&nesnic->first_frag_vbase[nesnic->sq_head].buffer[nhoffset]);608tcph = (struct tcphdr *)609(&nesnic->first_frag_vbase[nesnic->sq_head].buffer[hoffset]);610if ((wqe_count+1)!=(u32)wqes_needed) {611tcph->fin = 0;612tcph->psh = 0;613tcph->rst = 0;614tcph->urg = 0;615}616if (wqe_count) {617tcph->syn = 0;618}619tcph->seq = htonl(curr_tcp_seq);620wqe_fragment_length[0] = cpu_to_le16(min(((unsigned int)NES_FIRST_FRAG_SIZE),621original_first_length));622623wqe_fragment_index = 1;624if ((wqe_count==0) && (skb_headlen(skb) > original_first_length)) {625set_bit(nesnic->sq_head, nesnic->first_frag_overflow);626bus_address = pci_map_single(nesdev->pcidev, skb->data + original_first_length,627skb_headlen(skb) - original_first_length, PCI_DMA_TODEVICE);628wqe_fragment_length[wqe_fragment_index++] =629cpu_to_le16(skb_headlen(skb) - original_first_length);630wqe_fragment_length[wqe_fragment_index] = 0;631set_wqe_64bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_FRAG1_LOW_IDX,632bus_address);633tso_wqe_length += skb_headlen(skb) -634original_first_length;635}636while (wqe_fragment_index < 5) {637wqe_fragment_length[wqe_fragment_index] =638cpu_to_le16(skb_shinfo(skb)->frags[tso_frag_index].size);639set_wqe_64bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_LOW_IDX+(2*wqe_fragment_index),640(u64)tso_bus_address[tso_frag_index]);641wqe_fragment_index++;642tso_wqe_length += skb_shinfo(skb)->frags[tso_frag_index++].size;643if (wqe_fragment_index < 5)644wqe_fragment_length[wqe_fragment_index] = 0;645if (tso_frag_index == tso_frag_count)646break;647}648if ((wqe_count+1) == (u32)wqes_needed) {649nesnic->tx_skb[nesnic->sq_head] = skb;650} else {651nesnic->tx_skb[nesnic->sq_head] = NULL;652}653wqe_misc |= NES_NIC_SQ_WQE_COMPLETION | (u16)skb_is_gso(skb);654if ((tso_wqe_length + original_first_length) > skb_is_gso(skb)) {655wqe_misc |= NES_NIC_SQ_WQE_LSO_ENABLE;656} else {657iph->tot_len = htons(tso_wqe_length + original_first_length - nhoffset);658}659660set_wqe_32bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_MISC_IDX,661wqe_misc);662set_wqe_32bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_LSO_INFO_IDX,663((u32)tcph->doff) | (((u32)hoffset) << 4));664665set_wqe_32bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_TOTAL_LENGTH_IDX,666tso_wqe_length + original_first_length);667curr_tcp_seq += tso_wqe_length;668nesnic->sq_head++;669nesnic->sq_head &= nesnic->sq_size-1;670}671} else {672nesvnic->linearized_skbs++;673hoffset = skb_transport_header(skb) - skb->data;674nhoffset = skb_network_header(skb) - skb->data;675skb_linearize(skb);676skb_set_transport_header(skb, hoffset);677skb_set_network_header(skb, nhoffset);678send_rc = nes_nic_send(skb, netdev);679if (send_rc != NETDEV_TX_OK)680return NETDEV_TX_OK;681}682} else {683send_rc = nes_nic_send(skb, netdev);684if (send_rc != NETDEV_TX_OK)685return NETDEV_TX_OK;686}687688barrier();689690if (wqe_count)691nes_write32(nesdev->regs+NES_WQE_ALLOC,692(wqe_count << 24) | (1 << 23) | nesvnic->nic.qp_id);693694netdev->trans_start = jiffies;695696return NETDEV_TX_OK;697}698699700/**701* nes_netdev_get_stats702*/703static struct net_device_stats *nes_netdev_get_stats(struct net_device *netdev)704{705struct nes_vnic *nesvnic = netdev_priv(netdev);706struct nes_device *nesdev = nesvnic->nesdev;707u64 u64temp;708u32 u32temp;709710u32temp = nes_read_indexed(nesdev,711NES_IDX_ENDNODE0_NSTAT_RX_DISCARD + (nesvnic->nic_index*0x200));712nesvnic->netstats.rx_dropped += u32temp;713nesvnic->endnode_nstat_rx_discard += u32temp;714715u64temp = (u64)nes_read_indexed(nesdev,716NES_IDX_ENDNODE0_NSTAT_RX_OCTETS_LO + (nesvnic->nic_index*0x200));717u64temp += ((u64)nes_read_indexed(nesdev,718NES_IDX_ENDNODE0_NSTAT_RX_OCTETS_HI + (nesvnic->nic_index*0x200))) << 32;719720nesvnic->endnode_nstat_rx_octets += u64temp;721nesvnic->netstats.rx_bytes += u64temp;722723u64temp = (u64)nes_read_indexed(nesdev,724NES_IDX_ENDNODE0_NSTAT_RX_FRAMES_LO + (nesvnic->nic_index*0x200));725u64temp += ((u64)nes_read_indexed(nesdev,726NES_IDX_ENDNODE0_NSTAT_RX_FRAMES_HI + (nesvnic->nic_index*0x200))) << 32;727728nesvnic->endnode_nstat_rx_frames += u64temp;729nesvnic->netstats.rx_packets += u64temp;730731u64temp = (u64)nes_read_indexed(nesdev,732NES_IDX_ENDNODE0_NSTAT_TX_OCTETS_LO + (nesvnic->nic_index*0x200));733u64temp += ((u64)nes_read_indexed(nesdev,734NES_IDX_ENDNODE0_NSTAT_TX_OCTETS_HI + (nesvnic->nic_index*0x200))) << 32;735736nesvnic->endnode_nstat_tx_octets += u64temp;737nesvnic->netstats.tx_bytes += u64temp;738739u64temp = (u64)nes_read_indexed(nesdev,740NES_IDX_ENDNODE0_NSTAT_TX_FRAMES_LO + (nesvnic->nic_index*0x200));741u64temp += ((u64)nes_read_indexed(nesdev,742NES_IDX_ENDNODE0_NSTAT_TX_FRAMES_HI + (nesvnic->nic_index*0x200))) << 32;743744nesvnic->endnode_nstat_tx_frames += u64temp;745nesvnic->netstats.tx_packets += u64temp;746747u32temp = nes_read_indexed(nesdev,748NES_IDX_MAC_RX_SHORT_FRAMES + (nesvnic->nesdev->mac_index*0x200));749nesvnic->netstats.rx_dropped += u32temp;750nesvnic->nesdev->mac_rx_errors += u32temp;751nesvnic->nesdev->mac_rx_short_frames += u32temp;752753u32temp = nes_read_indexed(nesdev,754NES_IDX_MAC_RX_OVERSIZED_FRAMES + (nesvnic->nesdev->mac_index*0x200));755nesvnic->netstats.rx_dropped += u32temp;756nesvnic->nesdev->mac_rx_errors += u32temp;757nesvnic->nesdev->mac_rx_oversized_frames += u32temp;758759u32temp = nes_read_indexed(nesdev,760NES_IDX_MAC_RX_JABBER_FRAMES + (nesvnic->nesdev->mac_index*0x200));761nesvnic->netstats.rx_dropped += u32temp;762nesvnic->nesdev->mac_rx_errors += u32temp;763nesvnic->nesdev->mac_rx_jabber_frames += u32temp;764765u32temp = nes_read_indexed(nesdev,766NES_IDX_MAC_RX_SYMBOL_ERR_FRAMES + (nesvnic->nesdev->mac_index*0x200));767nesvnic->netstats.rx_dropped += u32temp;768nesvnic->nesdev->mac_rx_errors += u32temp;769nesvnic->nesdev->mac_rx_symbol_err_frames += u32temp;770771u32temp = nes_read_indexed(nesdev,772NES_IDX_MAC_RX_LENGTH_ERR_FRAMES + (nesvnic->nesdev->mac_index*0x200));773nesvnic->netstats.rx_length_errors += u32temp;774nesvnic->nesdev->mac_rx_errors += u32temp;775776u32temp = nes_read_indexed(nesdev,777NES_IDX_MAC_RX_CRC_ERR_FRAMES + (nesvnic->nesdev->mac_index*0x200));778nesvnic->nesdev->mac_rx_errors += u32temp;779nesvnic->nesdev->mac_rx_crc_errors += u32temp;780nesvnic->netstats.rx_crc_errors += u32temp;781782u32temp = nes_read_indexed(nesdev,783NES_IDX_MAC_TX_ERRORS + (nesvnic->nesdev->mac_index*0x200));784nesvnic->nesdev->mac_tx_errors += u32temp;785nesvnic->netstats.tx_errors += u32temp;786787return &nesvnic->netstats;788}789790791/**792* nes_netdev_tx_timeout793*/794static void nes_netdev_tx_timeout(struct net_device *netdev)795{796struct nes_vnic *nesvnic = netdev_priv(netdev);797798if (netif_msg_timer(nesvnic))799nes_debug(NES_DBG_NIC_TX, "%s: tx timeout\n", netdev->name);800}801802803/**804* nes_netdev_set_mac_address805*/806static int nes_netdev_set_mac_address(struct net_device *netdev, void *p)807{808struct nes_vnic *nesvnic = netdev_priv(netdev);809struct nes_device *nesdev = nesvnic->nesdev;810struct sockaddr *mac_addr = p;811int i;812u32 macaddr_low;813u16 macaddr_high;814815if (!is_valid_ether_addr(mac_addr->sa_data))816return -EADDRNOTAVAIL;817818memcpy(netdev->dev_addr, mac_addr->sa_data, netdev->addr_len);819printk(PFX "%s: Address length = %d, Address = %pM\n",820__func__, netdev->addr_len, mac_addr->sa_data);821macaddr_high = ((u16)netdev->dev_addr[0]) << 8;822macaddr_high += (u16)netdev->dev_addr[1];823macaddr_low = ((u32)netdev->dev_addr[2]) << 24;824macaddr_low += ((u32)netdev->dev_addr[3]) << 16;825macaddr_low += ((u32)netdev->dev_addr[4]) << 8;826macaddr_low += (u32)netdev->dev_addr[5];827828for (i = 0; i < NES_MAX_PORT_COUNT; i++) {829if (nesvnic->qp_nic_index[i] == 0xf) {830break;831}832nes_write_indexed(nesdev,833NES_IDX_PERFECT_FILTER_LOW + (nesvnic->qp_nic_index[i] * 8),834macaddr_low);835nes_write_indexed(nesdev,836NES_IDX_PERFECT_FILTER_HIGH + (nesvnic->qp_nic_index[i] * 8),837(u32)macaddr_high | NES_MAC_ADDR_VALID |838((((u32)nesvnic->nic_index) << 16)));839}840return 0;841}842843844static void set_allmulti(struct nes_device *nesdev, u32 nic_active_bit)845{846u32 nic_active;847848nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL);849nic_active |= nic_active_bit;850nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL, nic_active);851nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL);852nic_active &= ~nic_active_bit;853nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active);854}855856#define get_addr(addrs, index) ((addrs) + (index) * ETH_ALEN)857858/**859* nes_netdev_set_multicast_list860*/861static void nes_netdev_set_multicast_list(struct net_device *netdev)862{863struct nes_vnic *nesvnic = netdev_priv(netdev);864struct nes_device *nesdev = nesvnic->nesdev;865struct nes_adapter *nesadapter = nesvnic->nesdev->nesadapter;866u32 nic_active_bit;867u32 nic_active;868u32 perfect_filter_register_address;869u32 macaddr_low;870u16 macaddr_high;871u8 mc_all_on = 0;872u8 mc_index;873int mc_nic_index = -1;874u8 pft_entries_preallocated = max(nesadapter->adapter_fcn_count *875nics_per_function, 4);876u8 max_pft_entries_avaiable = NES_PFT_SIZE - pft_entries_preallocated;877unsigned long flags;878int mc_count = netdev_mc_count(netdev);879880spin_lock_irqsave(&nesadapter->resource_lock, flags);881nic_active_bit = 1 << nesvnic->nic_index;882883if (netdev->flags & IFF_PROMISC) {884nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL);885nic_active |= nic_active_bit;886nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL, nic_active);887nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL);888nic_active |= nic_active_bit;889nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active);890mc_all_on = 1;891} else if ((netdev->flags & IFF_ALLMULTI) ||892(nesvnic->nic_index > 3)) {893set_allmulti(nesdev, nic_active_bit);894mc_all_on = 1;895} else {896nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL);897nic_active &= ~nic_active_bit;898nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL, nic_active);899nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL);900nic_active &= ~nic_active_bit;901nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active);902}903904nes_debug(NES_DBG_NIC_RX, "Number of MC entries = %d, Promiscuous = %d, All Multicast = %d.\n",905mc_count, !!(netdev->flags & IFF_PROMISC),906!!(netdev->flags & IFF_ALLMULTI));907if (!mc_all_on) {908char *addrs;909int i;910struct netdev_hw_addr *ha;911912addrs = kmalloc(ETH_ALEN * mc_count, GFP_ATOMIC);913if (!addrs) {914set_allmulti(nesdev, nic_active_bit);915goto unlock;916}917i = 0;918netdev_for_each_mc_addr(ha, netdev)919memcpy(get_addr(addrs, i++), ha->addr, ETH_ALEN);920921perfect_filter_register_address = NES_IDX_PERFECT_FILTER_LOW +922pft_entries_preallocated * 0x8;923for (i = 0, mc_index = 0; mc_index < max_pft_entries_avaiable;924mc_index++) {925while (i < mc_count && nesvnic->mcrq_mcast_filter &&926((mc_nic_index = nesvnic->mcrq_mcast_filter(nesvnic,927get_addr(addrs, i++))) == 0));928if (mc_nic_index < 0)929mc_nic_index = nesvnic->nic_index;930while (nesadapter->pft_mcast_map[mc_index] < 16 &&931nesadapter->pft_mcast_map[mc_index] !=932nesvnic->nic_index &&933mc_index < max_pft_entries_avaiable) {934nes_debug(NES_DBG_NIC_RX,935"mc_index=%d skipping nic_index=%d, "936"used for=%d \n", mc_index,937nesvnic->nic_index,938nesadapter->pft_mcast_map[mc_index]);939mc_index++;940}941if (mc_index >= max_pft_entries_avaiable)942break;943if (i < mc_count) {944char *addr = get_addr(addrs, i++);945946nes_debug(NES_DBG_NIC_RX, "Assigning MC Address %pM to register 0x%04X nic_idx=%d\n",947addr,948perfect_filter_register_address+(mc_index * 8),949mc_nic_index);950macaddr_high = ((u16) addr[0]) << 8;951macaddr_high += (u16) addr[1];952macaddr_low = ((u32) addr[2]) << 24;953macaddr_low += ((u32) addr[3]) << 16;954macaddr_low += ((u32) addr[4]) << 8;955macaddr_low += (u32) addr[5];956nes_write_indexed(nesdev,957perfect_filter_register_address+(mc_index * 8),958macaddr_low);959nes_write_indexed(nesdev,960perfect_filter_register_address+4+(mc_index * 8),961(u32)macaddr_high | NES_MAC_ADDR_VALID |962((((u32)(1<<mc_nic_index)) << 16)));963nesadapter->pft_mcast_map[mc_index] =964nesvnic->nic_index;965} else {966nes_debug(NES_DBG_NIC_RX, "Clearing MC Address at register 0x%04X\n",967perfect_filter_register_address+(mc_index * 8));968nes_write_indexed(nesdev,969perfect_filter_register_address+4+(mc_index * 8),9700);971nesadapter->pft_mcast_map[mc_index] = 255;972}973}974kfree(addrs);975/* PFT is not large enough */976if (i < mc_count)977set_allmulti(nesdev, nic_active_bit);978}979980unlock:981spin_unlock_irqrestore(&nesadapter->resource_lock, flags);982}983984985/**986* nes_netdev_change_mtu987*/988static int nes_netdev_change_mtu(struct net_device *netdev, int new_mtu)989{990struct nes_vnic *nesvnic = netdev_priv(netdev);991struct nes_device *nesdev = nesvnic->nesdev;992int ret = 0;993u8 jumbomode = 0;994u32 nic_active;995u32 nic_active_bit;996u32 uc_all_active;997u32 mc_all_active;998999if ((new_mtu < ETH_ZLEN) || (new_mtu > max_mtu))1000return -EINVAL;10011002netdev->mtu = new_mtu;1003nesvnic->max_frame_size = new_mtu + VLAN_ETH_HLEN;10041005if (netdev->mtu > 1500) {1006jumbomode=1;1007}1008nes_nic_init_timer_defaults(nesdev, jumbomode);10091010if (netif_running(netdev)) {1011nic_active_bit = 1 << nesvnic->nic_index;1012mc_all_active = nes_read_indexed(nesdev,1013NES_IDX_NIC_MULTICAST_ALL) & nic_active_bit;1014uc_all_active = nes_read_indexed(nesdev,1015NES_IDX_NIC_UNICAST_ALL) & nic_active_bit;10161017nes_netdev_stop(netdev);1018nes_netdev_open(netdev);10191020nic_active = nes_read_indexed(nesdev,1021NES_IDX_NIC_MULTICAST_ALL);1022nic_active |= mc_all_active;1023nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL,1024nic_active);10251026nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL);1027nic_active |= uc_all_active;1028nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active);1029}10301031return ret;1032}103310341035static const char nes_ethtool_stringset[][ETH_GSTRING_LEN] = {1036"Link Change Interrupts",1037"Linearized SKBs",1038"T/GSO Requests",1039"Pause Frames Sent",1040"Pause Frames Received",1041"Internal Routing Errors",1042"SQ SW Dropped SKBs",1043"SQ Full",1044"Segmented TSO Requests",1045"Rx Symbol Errors",1046"Rx Jabber Errors",1047"Rx Oversized Frames",1048"Rx Short Frames",1049"Rx Length Errors",1050"Rx CRC Errors",1051"Rx Port Discard",1052"Endnode Rx Discards",1053"Endnode Rx Octets",1054"Endnode Rx Frames",1055"Endnode Tx Octets",1056"Endnode Tx Frames",1057"Tx Errors",1058"mh detected",1059"mh pauses",1060"Retransmission Count",1061"CM Connects",1062"CM Accepts",1063"Disconnects",1064"Connected Events",1065"Connect Requests",1066"CM Rejects",1067"ModifyQP Timeouts",1068"CreateQPs",1069"SW DestroyQPs",1070"DestroyQPs",1071"CM Closes",1072"CM Packets Sent",1073"CM Packets Bounced",1074"CM Packets Created",1075"CM Packets Rcvd",1076"CM Packets Dropped",1077"CM Packets Retrans",1078"CM Listens Created",1079"CM Listens Destroyed",1080"CM Backlog Drops",1081"CM Loopbacks",1082"CM Nodes Created",1083"CM Nodes Destroyed",1084"CM Accel Drops",1085"CM Resets Received",1086"Free 4Kpbls",1087"Free 256pbls",1088"Timer Inits",1089"LRO aggregated",1090"LRO flushed",1091"LRO no_desc",1092};1093#define NES_ETHTOOL_STAT_COUNT ARRAY_SIZE(nes_ethtool_stringset)109410951096/**1097* nes_netdev_get_sset_count1098*/1099static int nes_netdev_get_sset_count(struct net_device *netdev, int stringset)1100{1101if (stringset == ETH_SS_STATS)1102return NES_ETHTOOL_STAT_COUNT;1103else1104return -EINVAL;1105}110611071108/**1109* nes_netdev_get_strings1110*/1111static void nes_netdev_get_strings(struct net_device *netdev, u32 stringset,1112u8 *ethtool_strings)1113{1114if (stringset == ETH_SS_STATS)1115memcpy(ethtool_strings,1116&nes_ethtool_stringset,1117sizeof(nes_ethtool_stringset));1118}111911201121/**1122* nes_netdev_get_ethtool_stats1123*/11241125static void nes_netdev_get_ethtool_stats(struct net_device *netdev,1126struct ethtool_stats *target_ethtool_stats, u64 *target_stat_values)1127{1128u64 u64temp;1129struct nes_vnic *nesvnic = netdev_priv(netdev);1130struct nes_device *nesdev = nesvnic->nesdev;1131struct nes_adapter *nesadapter = nesdev->nesadapter;1132u32 nic_count;1133u32 u32temp;1134u32 index = 0;11351136target_ethtool_stats->n_stats = NES_ETHTOOL_STAT_COUNT;1137target_stat_values[index] = nesvnic->nesdev->link_status_interrupts;1138target_stat_values[++index] = nesvnic->linearized_skbs;1139target_stat_values[++index] = nesvnic->tso_requests;11401141u32temp = nes_read_indexed(nesdev,1142NES_IDX_MAC_TX_PAUSE_FRAMES + (nesvnic->nesdev->mac_index*0x200));1143nesvnic->nesdev->mac_pause_frames_sent += u32temp;1144target_stat_values[++index] = nesvnic->nesdev->mac_pause_frames_sent;11451146u32temp = nes_read_indexed(nesdev,1147NES_IDX_MAC_RX_PAUSE_FRAMES + (nesvnic->nesdev->mac_index*0x200));1148nesvnic->nesdev->mac_pause_frames_received += u32temp;11491150u32temp = nes_read_indexed(nesdev,1151NES_IDX_PORT_RX_DISCARDS + (nesvnic->nesdev->mac_index*0x40));1152nesvnic->nesdev->port_rx_discards += u32temp;1153nesvnic->netstats.rx_dropped += u32temp;11541155u32temp = nes_read_indexed(nesdev,1156NES_IDX_PORT_TX_DISCARDS + (nesvnic->nesdev->mac_index*0x40));1157nesvnic->nesdev->port_tx_discards += u32temp;1158nesvnic->netstats.tx_dropped += u32temp;11591160u32temp = nes_read_indexed(nesdev,1161NES_IDX_MAC_RX_SHORT_FRAMES + (nesvnic->nesdev->mac_index*0x200));1162nesvnic->netstats.rx_dropped += u32temp;1163nesvnic->nesdev->mac_rx_errors += u32temp;1164nesvnic->nesdev->mac_rx_short_frames += u32temp;11651166u32temp = nes_read_indexed(nesdev,1167NES_IDX_MAC_RX_OVERSIZED_FRAMES + (nesvnic->nesdev->mac_index*0x200));1168nesvnic->netstats.rx_dropped += u32temp;1169nesvnic->nesdev->mac_rx_errors += u32temp;1170nesvnic->nesdev->mac_rx_oversized_frames += u32temp;11711172u32temp = nes_read_indexed(nesdev,1173NES_IDX_MAC_RX_JABBER_FRAMES + (nesvnic->nesdev->mac_index*0x200));1174nesvnic->netstats.rx_dropped += u32temp;1175nesvnic->nesdev->mac_rx_errors += u32temp;1176nesvnic->nesdev->mac_rx_jabber_frames += u32temp;11771178u32temp = nes_read_indexed(nesdev,1179NES_IDX_MAC_RX_SYMBOL_ERR_FRAMES + (nesvnic->nesdev->mac_index*0x200));1180nesvnic->netstats.rx_dropped += u32temp;1181nesvnic->nesdev->mac_rx_errors += u32temp;1182nesvnic->nesdev->mac_rx_symbol_err_frames += u32temp;11831184u32temp = nes_read_indexed(nesdev,1185NES_IDX_MAC_RX_LENGTH_ERR_FRAMES + (nesvnic->nesdev->mac_index*0x200));1186nesvnic->netstats.rx_length_errors += u32temp;1187nesvnic->nesdev->mac_rx_errors += u32temp;11881189u32temp = nes_read_indexed(nesdev,1190NES_IDX_MAC_RX_CRC_ERR_FRAMES + (nesvnic->nesdev->mac_index*0x200));1191nesvnic->nesdev->mac_rx_errors += u32temp;1192nesvnic->nesdev->mac_rx_crc_errors += u32temp;1193nesvnic->netstats.rx_crc_errors += u32temp;11941195u32temp = nes_read_indexed(nesdev,1196NES_IDX_MAC_TX_ERRORS + (nesvnic->nesdev->mac_index*0x200));1197nesvnic->nesdev->mac_tx_errors += u32temp;1198nesvnic->netstats.tx_errors += u32temp;11991200for (nic_count = 0; nic_count < NES_MAX_PORT_COUNT; nic_count++) {1201if (nesvnic->qp_nic_index[nic_count] == 0xf)1202break;12031204u32temp = nes_read_indexed(nesdev,1205NES_IDX_ENDNODE0_NSTAT_RX_DISCARD +1206(nesvnic->qp_nic_index[nic_count]*0x200));1207nesvnic->netstats.rx_dropped += u32temp;1208nesvnic->endnode_nstat_rx_discard += u32temp;12091210u64temp = (u64)nes_read_indexed(nesdev,1211NES_IDX_ENDNODE0_NSTAT_RX_OCTETS_LO +1212(nesvnic->qp_nic_index[nic_count]*0x200));1213u64temp += ((u64)nes_read_indexed(nesdev,1214NES_IDX_ENDNODE0_NSTAT_RX_OCTETS_HI +1215(nesvnic->qp_nic_index[nic_count]*0x200))) << 32;12161217nesvnic->endnode_nstat_rx_octets += u64temp;1218nesvnic->netstats.rx_bytes += u64temp;12191220u64temp = (u64)nes_read_indexed(nesdev,1221NES_IDX_ENDNODE0_NSTAT_RX_FRAMES_LO +1222(nesvnic->qp_nic_index[nic_count]*0x200));1223u64temp += ((u64)nes_read_indexed(nesdev,1224NES_IDX_ENDNODE0_NSTAT_RX_FRAMES_HI +1225(nesvnic->qp_nic_index[nic_count]*0x200))) << 32;12261227nesvnic->endnode_nstat_rx_frames += u64temp;1228nesvnic->netstats.rx_packets += u64temp;12291230u64temp = (u64)nes_read_indexed(nesdev,1231NES_IDX_ENDNODE0_NSTAT_TX_OCTETS_LO +1232(nesvnic->qp_nic_index[nic_count]*0x200));1233u64temp += ((u64)nes_read_indexed(nesdev,1234NES_IDX_ENDNODE0_NSTAT_TX_OCTETS_HI +1235(nesvnic->qp_nic_index[nic_count]*0x200))) << 32;12361237nesvnic->endnode_nstat_tx_octets += u64temp;1238nesvnic->netstats.tx_bytes += u64temp;12391240u64temp = (u64)nes_read_indexed(nesdev,1241NES_IDX_ENDNODE0_NSTAT_TX_FRAMES_LO +1242(nesvnic->qp_nic_index[nic_count]*0x200));1243u64temp += ((u64)nes_read_indexed(nesdev,1244NES_IDX_ENDNODE0_NSTAT_TX_FRAMES_HI +1245(nesvnic->qp_nic_index[nic_count]*0x200))) << 32;12461247nesvnic->endnode_nstat_tx_frames += u64temp;1248nesvnic->netstats.tx_packets += u64temp;12491250u32temp = nes_read_indexed(nesdev,1251NES_IDX_IPV4_TCP_REXMITS + (nesvnic->qp_nic_index[nic_count]*0x200));1252nesvnic->endnode_ipv4_tcp_retransmits += u32temp;1253}12541255target_stat_values[++index] = nesvnic->nesdev->mac_pause_frames_received;1256target_stat_values[++index] = nesdev->nesadapter->nic_rx_eth_route_err;1257target_stat_values[++index] = nesvnic->tx_sw_dropped;1258target_stat_values[++index] = nesvnic->sq_full;1259target_stat_values[++index] = nesvnic->segmented_tso_requests;1260target_stat_values[++index] = nesvnic->nesdev->mac_rx_symbol_err_frames;1261target_stat_values[++index] = nesvnic->nesdev->mac_rx_jabber_frames;1262target_stat_values[++index] = nesvnic->nesdev->mac_rx_oversized_frames;1263target_stat_values[++index] = nesvnic->nesdev->mac_rx_short_frames;1264target_stat_values[++index] = nesvnic->netstats.rx_length_errors;1265target_stat_values[++index] = nesvnic->nesdev->mac_rx_crc_errors;1266target_stat_values[++index] = nesvnic->nesdev->port_rx_discards;1267target_stat_values[++index] = nesvnic->endnode_nstat_rx_discard;1268target_stat_values[++index] = nesvnic->endnode_nstat_rx_octets;1269target_stat_values[++index] = nesvnic->endnode_nstat_rx_frames;1270target_stat_values[++index] = nesvnic->endnode_nstat_tx_octets;1271target_stat_values[++index] = nesvnic->endnode_nstat_tx_frames;1272target_stat_values[++index] = nesvnic->nesdev->mac_tx_errors;1273target_stat_values[++index] = mh_detected;1274target_stat_values[++index] = mh_pauses_sent;1275target_stat_values[++index] = nesvnic->endnode_ipv4_tcp_retransmits;1276target_stat_values[++index] = atomic_read(&cm_connects);1277target_stat_values[++index] = atomic_read(&cm_accepts);1278target_stat_values[++index] = atomic_read(&cm_disconnects);1279target_stat_values[++index] = atomic_read(&cm_connecteds);1280target_stat_values[++index] = atomic_read(&cm_connect_reqs);1281target_stat_values[++index] = atomic_read(&cm_rejects);1282target_stat_values[++index] = atomic_read(&mod_qp_timouts);1283target_stat_values[++index] = atomic_read(&qps_created);1284target_stat_values[++index] = atomic_read(&sw_qps_destroyed);1285target_stat_values[++index] = atomic_read(&qps_destroyed);1286target_stat_values[++index] = atomic_read(&cm_closes);1287target_stat_values[++index] = cm_packets_sent;1288target_stat_values[++index] = cm_packets_bounced;1289target_stat_values[++index] = cm_packets_created;1290target_stat_values[++index] = cm_packets_received;1291target_stat_values[++index] = cm_packets_dropped;1292target_stat_values[++index] = cm_packets_retrans;1293target_stat_values[++index] = atomic_read(&cm_listens_created);1294target_stat_values[++index] = atomic_read(&cm_listens_destroyed);1295target_stat_values[++index] = cm_backlog_drops;1296target_stat_values[++index] = atomic_read(&cm_loopbacks);1297target_stat_values[++index] = atomic_read(&cm_nodes_created);1298target_stat_values[++index] = atomic_read(&cm_nodes_destroyed);1299target_stat_values[++index] = atomic_read(&cm_accel_dropped_pkts);1300target_stat_values[++index] = atomic_read(&cm_resets_recvd);1301target_stat_values[++index] = nesadapter->free_4kpbl;1302target_stat_values[++index] = nesadapter->free_256pbl;1303target_stat_values[++index] = int_mod_timer_init;1304target_stat_values[++index] = nesvnic->lro_mgr.stats.aggregated;1305target_stat_values[++index] = nesvnic->lro_mgr.stats.flushed;1306target_stat_values[++index] = nesvnic->lro_mgr.stats.no_desc;1307}13081309/**1310* nes_netdev_get_drvinfo1311*/1312static void nes_netdev_get_drvinfo(struct net_device *netdev,1313struct ethtool_drvinfo *drvinfo)1314{1315struct nes_vnic *nesvnic = netdev_priv(netdev);1316struct nes_adapter *nesadapter = nesvnic->nesdev->nesadapter;13171318strcpy(drvinfo->driver, DRV_NAME);1319strcpy(drvinfo->bus_info, pci_name(nesvnic->nesdev->pcidev));1320sprintf(drvinfo->fw_version, "%u.%u", nesadapter->firmware_version>>16,1321nesadapter->firmware_version & 0x000000ff);1322strcpy(drvinfo->version, DRV_VERSION);1323drvinfo->testinfo_len = 0;1324drvinfo->eedump_len = 0;1325drvinfo->regdump_len = 0;1326}132713281329/**1330* nes_netdev_set_coalesce1331*/1332static int nes_netdev_set_coalesce(struct net_device *netdev,1333struct ethtool_coalesce *et_coalesce)1334{1335struct nes_vnic *nesvnic = netdev_priv(netdev);1336struct nes_device *nesdev = nesvnic->nesdev;1337struct nes_adapter *nesadapter = nesdev->nesadapter;1338struct nes_hw_tune_timer *shared_timer = &nesadapter->tune_timer;1339unsigned long flags;13401341spin_lock_irqsave(&nesadapter->periodic_timer_lock, flags);1342if (et_coalesce->rx_max_coalesced_frames_low) {1343shared_timer->threshold_low = et_coalesce->rx_max_coalesced_frames_low;1344}1345if (et_coalesce->rx_max_coalesced_frames_irq) {1346shared_timer->threshold_target = et_coalesce->rx_max_coalesced_frames_irq;1347}1348if (et_coalesce->rx_max_coalesced_frames_high) {1349shared_timer->threshold_high = et_coalesce->rx_max_coalesced_frames_high;1350}1351if (et_coalesce->rx_coalesce_usecs_low) {1352shared_timer->timer_in_use_min = et_coalesce->rx_coalesce_usecs_low;1353}1354if (et_coalesce->rx_coalesce_usecs_high) {1355shared_timer->timer_in_use_max = et_coalesce->rx_coalesce_usecs_high;1356}1357spin_unlock_irqrestore(&nesadapter->periodic_timer_lock, flags);13581359/* using this to drive total interrupt moderation */1360nesadapter->et_rx_coalesce_usecs_irq = et_coalesce->rx_coalesce_usecs_irq;1361if (et_coalesce->use_adaptive_rx_coalesce) {1362nesadapter->et_use_adaptive_rx_coalesce = 1;1363nesadapter->timer_int_limit = NES_TIMER_INT_LIMIT_DYNAMIC;1364nesadapter->et_rx_coalesce_usecs_irq = 0;1365if (et_coalesce->pkt_rate_low) {1366nesadapter->et_pkt_rate_low = et_coalesce->pkt_rate_low;1367}1368} else {1369nesadapter->et_use_adaptive_rx_coalesce = 0;1370nesadapter->timer_int_limit = NES_TIMER_INT_LIMIT;1371if (nesadapter->et_rx_coalesce_usecs_irq) {1372nes_write32(nesdev->regs+NES_PERIODIC_CONTROL,13730x80000000 | ((u32)(nesadapter->et_rx_coalesce_usecs_irq*8)));1374}1375}1376return 0;1377}137813791380/**1381* nes_netdev_get_coalesce1382*/1383static int nes_netdev_get_coalesce(struct net_device *netdev,1384struct ethtool_coalesce *et_coalesce)1385{1386struct nes_vnic *nesvnic = netdev_priv(netdev);1387struct nes_device *nesdev = nesvnic->nesdev;1388struct nes_adapter *nesadapter = nesdev->nesadapter;1389struct ethtool_coalesce temp_et_coalesce;1390struct nes_hw_tune_timer *shared_timer = &nesadapter->tune_timer;1391unsigned long flags;13921393memset(&temp_et_coalesce, 0, sizeof(temp_et_coalesce));1394temp_et_coalesce.rx_coalesce_usecs_irq = nesadapter->et_rx_coalesce_usecs_irq;1395temp_et_coalesce.use_adaptive_rx_coalesce = nesadapter->et_use_adaptive_rx_coalesce;1396temp_et_coalesce.rate_sample_interval = nesadapter->et_rate_sample_interval;1397temp_et_coalesce.pkt_rate_low = nesadapter->et_pkt_rate_low;1398spin_lock_irqsave(&nesadapter->periodic_timer_lock, flags);1399temp_et_coalesce.rx_max_coalesced_frames_low = shared_timer->threshold_low;1400temp_et_coalesce.rx_max_coalesced_frames_irq = shared_timer->threshold_target;1401temp_et_coalesce.rx_max_coalesced_frames_high = shared_timer->threshold_high;1402temp_et_coalesce.rx_coalesce_usecs_low = shared_timer->timer_in_use_min;1403temp_et_coalesce.rx_coalesce_usecs_high = shared_timer->timer_in_use_max;1404if (nesadapter->et_use_adaptive_rx_coalesce) {1405temp_et_coalesce.rx_coalesce_usecs_irq = shared_timer->timer_in_use;1406}1407spin_unlock_irqrestore(&nesadapter->periodic_timer_lock, flags);1408memcpy(et_coalesce, &temp_et_coalesce, sizeof(*et_coalesce));1409return 0;1410}141114121413/**1414* nes_netdev_get_pauseparam1415*/1416static void nes_netdev_get_pauseparam(struct net_device *netdev,1417struct ethtool_pauseparam *et_pauseparam)1418{1419struct nes_vnic *nesvnic = netdev_priv(netdev);14201421et_pauseparam->autoneg = 0;1422et_pauseparam->rx_pause = (nesvnic->nesdev->disable_rx_flow_control == 0) ? 1:0;1423et_pauseparam->tx_pause = (nesvnic->nesdev->disable_tx_flow_control == 0) ? 1:0;1424}142514261427/**1428* nes_netdev_set_pauseparam1429*/1430static int nes_netdev_set_pauseparam(struct net_device *netdev,1431struct ethtool_pauseparam *et_pauseparam)1432{1433struct nes_vnic *nesvnic = netdev_priv(netdev);1434struct nes_device *nesdev = nesvnic->nesdev;1435u32 u32temp;14361437if (et_pauseparam->autoneg) {1438/* TODO: should return unsupported */1439return 0;1440}1441if ((et_pauseparam->tx_pause == 1) && (nesdev->disable_tx_flow_control == 1)) {1442u32temp = nes_read_indexed(nesdev,1443NES_IDX_MAC_TX_CONFIG + (nesdev->mac_index*0x200));1444u32temp |= NES_IDX_MAC_TX_CONFIG_ENABLE_PAUSE;1445nes_write_indexed(nesdev,1446NES_IDX_MAC_TX_CONFIG + (nesdev->mac_index*0x200), u32temp);1447nesdev->disable_tx_flow_control = 0;1448} else if ((et_pauseparam->tx_pause == 0) && (nesdev->disable_tx_flow_control == 0)) {1449u32temp = nes_read_indexed(nesdev,1450NES_IDX_MAC_TX_CONFIG + (nesdev->mac_index*0x200));1451u32temp &= ~NES_IDX_MAC_TX_CONFIG_ENABLE_PAUSE;1452nes_write_indexed(nesdev,1453NES_IDX_MAC_TX_CONFIG + (nesdev->mac_index*0x200), u32temp);1454nesdev->disable_tx_flow_control = 1;1455}1456if ((et_pauseparam->rx_pause == 1) && (nesdev->disable_rx_flow_control == 1)) {1457u32temp = nes_read_indexed(nesdev,1458NES_IDX_MPP_DEBUG + (nesdev->mac_index*0x40));1459u32temp &= ~NES_IDX_MPP_DEBUG_PORT_DISABLE_PAUSE;1460nes_write_indexed(nesdev,1461NES_IDX_MPP_DEBUG + (nesdev->mac_index*0x40), u32temp);1462nesdev->disable_rx_flow_control = 0;1463} else if ((et_pauseparam->rx_pause == 0) && (nesdev->disable_rx_flow_control == 0)) {1464u32temp = nes_read_indexed(nesdev,1465NES_IDX_MPP_DEBUG + (nesdev->mac_index*0x40));1466u32temp |= NES_IDX_MPP_DEBUG_PORT_DISABLE_PAUSE;1467nes_write_indexed(nesdev,1468NES_IDX_MPP_DEBUG + (nesdev->mac_index*0x40), u32temp);1469nesdev->disable_rx_flow_control = 1;1470}14711472return 0;1473}147414751476/**1477* nes_netdev_get_settings1478*/1479static int nes_netdev_get_settings(struct net_device *netdev, struct ethtool_cmd *et_cmd)1480{1481struct nes_vnic *nesvnic = netdev_priv(netdev);1482struct nes_device *nesdev = nesvnic->nesdev;1483struct nes_adapter *nesadapter = nesdev->nesadapter;1484u32 mac_index = nesdev->mac_index;1485u8 phy_type = nesadapter->phy_type[mac_index];1486u8 phy_index = nesadapter->phy_index[mac_index];1487u16 phy_data;14881489et_cmd->duplex = DUPLEX_FULL;1490et_cmd->port = PORT_MII;1491et_cmd->maxtxpkt = 511;1492et_cmd->maxrxpkt = 511;14931494if (nesadapter->OneG_Mode) {1495ethtool_cmd_speed_set(et_cmd, SPEED_1000);1496if (phy_type == NES_PHY_TYPE_PUMA_1G) {1497et_cmd->supported = SUPPORTED_1000baseT_Full;1498et_cmd->advertising = ADVERTISED_1000baseT_Full;1499et_cmd->autoneg = AUTONEG_DISABLE;1500et_cmd->transceiver = XCVR_INTERNAL;1501et_cmd->phy_address = mac_index;1502} else {1503unsigned long flags;1504et_cmd->supported = SUPPORTED_1000baseT_Full1505| SUPPORTED_Autoneg;1506et_cmd->advertising = ADVERTISED_1000baseT_Full1507| ADVERTISED_Autoneg;1508spin_lock_irqsave(&nesadapter->phy_lock, flags);1509nes_read_1G_phy_reg(nesdev, 0, phy_index, &phy_data);1510spin_unlock_irqrestore(&nesadapter->phy_lock, flags);1511if (phy_data & 0x1000)1512et_cmd->autoneg = AUTONEG_ENABLE;1513else1514et_cmd->autoneg = AUTONEG_DISABLE;1515et_cmd->transceiver = XCVR_EXTERNAL;1516et_cmd->phy_address = phy_index;1517}1518return 0;1519}1520if ((phy_type == NES_PHY_TYPE_ARGUS) ||1521(phy_type == NES_PHY_TYPE_SFP_D) ||1522(phy_type == NES_PHY_TYPE_KR)) {1523et_cmd->transceiver = XCVR_EXTERNAL;1524et_cmd->port = PORT_FIBRE;1525et_cmd->supported = SUPPORTED_FIBRE;1526et_cmd->advertising = ADVERTISED_FIBRE;1527et_cmd->phy_address = phy_index;1528} else {1529et_cmd->transceiver = XCVR_INTERNAL;1530et_cmd->supported = SUPPORTED_10000baseT_Full;1531et_cmd->advertising = ADVERTISED_10000baseT_Full;1532et_cmd->phy_address = mac_index;1533}1534ethtool_cmd_speed_set(et_cmd, SPEED_10000);1535et_cmd->autoneg = AUTONEG_DISABLE;1536return 0;1537}153815391540/**1541* nes_netdev_set_settings1542*/1543static int nes_netdev_set_settings(struct net_device *netdev, struct ethtool_cmd *et_cmd)1544{1545struct nes_vnic *nesvnic = netdev_priv(netdev);1546struct nes_device *nesdev = nesvnic->nesdev;1547struct nes_adapter *nesadapter = nesdev->nesadapter;15481549if ((nesadapter->OneG_Mode) &&1550(nesadapter->phy_type[nesdev->mac_index] != NES_PHY_TYPE_PUMA_1G)) {1551unsigned long flags;1552u16 phy_data;1553u8 phy_index = nesadapter->phy_index[nesdev->mac_index];15541555spin_lock_irqsave(&nesadapter->phy_lock, flags);1556nes_read_1G_phy_reg(nesdev, 0, phy_index, &phy_data);1557if (et_cmd->autoneg) {1558/* Turn on Full duplex, Autoneg, and restart autonegotiation */1559phy_data |= 0x1300;1560} else {1561/* Turn off autoneg */1562phy_data &= ~0x1000;1563}1564nes_write_1G_phy_reg(nesdev, 0, phy_index, phy_data);1565spin_unlock_irqrestore(&nesadapter->phy_lock, flags);1566}15671568return 0;1569}157015711572static const struct ethtool_ops nes_ethtool_ops = {1573.get_link = ethtool_op_get_link,1574.get_settings = nes_netdev_get_settings,1575.set_settings = nes_netdev_set_settings,1576.get_strings = nes_netdev_get_strings,1577.get_sset_count = nes_netdev_get_sset_count,1578.get_ethtool_stats = nes_netdev_get_ethtool_stats,1579.get_drvinfo = nes_netdev_get_drvinfo,1580.get_coalesce = nes_netdev_get_coalesce,1581.set_coalesce = nes_netdev_set_coalesce,1582.get_pauseparam = nes_netdev_get_pauseparam,1583.set_pauseparam = nes_netdev_set_pauseparam,1584};158515861587static void nes_netdev_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)1588{1589struct nes_vnic *nesvnic = netdev_priv(netdev);1590struct nes_device *nesdev = nesvnic->nesdev;1591struct nes_adapter *nesadapter = nesdev->nesadapter;1592u32 u32temp;1593unsigned long flags;15941595spin_lock_irqsave(&nesadapter->phy_lock, flags);1596nesvnic->vlan_grp = grp;15971598nes_debug(NES_DBG_NETDEV, "%s: %s\n", __func__, netdev->name);15991600/* Enable/Disable VLAN Stripping */1601u32temp = nes_read_indexed(nesdev, NES_IDX_PCIX_DIAG);1602if (grp)1603u32temp &= 0xfdffffff;1604else1605u32temp |= 0x02000000;16061607nes_write_indexed(nesdev, NES_IDX_PCIX_DIAG, u32temp);1608spin_unlock_irqrestore(&nesadapter->phy_lock, flags);1609}16101611static const struct net_device_ops nes_netdev_ops = {1612.ndo_open = nes_netdev_open,1613.ndo_stop = nes_netdev_stop,1614.ndo_start_xmit = nes_netdev_start_xmit,1615.ndo_get_stats = nes_netdev_get_stats,1616.ndo_tx_timeout = nes_netdev_tx_timeout,1617.ndo_set_mac_address = nes_netdev_set_mac_address,1618.ndo_set_multicast_list = nes_netdev_set_multicast_list,1619.ndo_change_mtu = nes_netdev_change_mtu,1620.ndo_validate_addr = eth_validate_addr,1621.ndo_vlan_rx_register = nes_netdev_vlan_rx_register,1622};16231624/**1625* nes_netdev_init - initialize network device1626*/1627struct net_device *nes_netdev_init(struct nes_device *nesdev,1628void __iomem *mmio_addr)1629{1630u64 u64temp;1631struct nes_vnic *nesvnic;1632struct net_device *netdev;1633struct nic_qp_map *curr_qp_map;1634u8 phy_type = nesdev->nesadapter->phy_type[nesdev->mac_index];16351636netdev = alloc_etherdev(sizeof(struct nes_vnic));1637if (!netdev) {1638printk(KERN_ERR PFX "nesvnic etherdev alloc failed");1639return NULL;1640}1641nesvnic = netdev_priv(netdev);16421643nes_debug(NES_DBG_INIT, "netdev = %p, %s\n", netdev, netdev->name);16441645SET_NETDEV_DEV(netdev, &nesdev->pcidev->dev);16461647netdev->watchdog_timeo = NES_TX_TIMEOUT;1648netdev->irq = nesdev->pcidev->irq;1649netdev->mtu = ETH_DATA_LEN;1650netdev->hard_header_len = ETH_HLEN;1651netdev->addr_len = ETH_ALEN;1652netdev->type = ARPHRD_ETHER;1653netdev->features = NETIF_F_HIGHDMA;1654netdev->netdev_ops = &nes_netdev_ops;1655netdev->ethtool_ops = &nes_ethtool_ops;1656netif_napi_add(netdev, &nesvnic->napi, nes_netdev_poll, 128);1657nes_debug(NES_DBG_INIT, "Enabling VLAN Insert/Delete.\n");1658netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;16591660/* Fill in the port structure */1661nesvnic->netdev = netdev;1662nesvnic->nesdev = nesdev;1663nesvnic->msg_enable = netif_msg_init(debug, default_msg);1664nesvnic->netdev_index = nesdev->netdev_count;1665nesvnic->perfect_filter_index = nesdev->nesadapter->netdev_count;1666nesvnic->max_frame_size = netdev->mtu + netdev->hard_header_len + VLAN_HLEN;16671668curr_qp_map = nic_qp_mapping_per_function[PCI_FUNC(nesdev->pcidev->devfn)];1669nesvnic->nic.qp_id = curr_qp_map[nesdev->netdev_count].qpid;1670nesvnic->nic_index = curr_qp_map[nesdev->netdev_count].nic_index;1671nesvnic->logical_port = curr_qp_map[nesdev->netdev_count].logical_port;16721673/* Setup the burned in MAC address */1674u64temp = (u64)nesdev->nesadapter->mac_addr_low;1675u64temp += ((u64)nesdev->nesadapter->mac_addr_high) << 32;1676u64temp += nesvnic->nic_index;1677netdev->dev_addr[0] = (u8)(u64temp>>40);1678netdev->dev_addr[1] = (u8)(u64temp>>32);1679netdev->dev_addr[2] = (u8)(u64temp>>24);1680netdev->dev_addr[3] = (u8)(u64temp>>16);1681netdev->dev_addr[4] = (u8)(u64temp>>8);1682netdev->dev_addr[5] = (u8)u64temp;1683memcpy(netdev->perm_addr, netdev->dev_addr, 6);16841685netdev->hw_features = NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_IP_CSUM;1686if ((nesvnic->logical_port < 2) || (nesdev->nesadapter->hw_rev != NE020_REV))1687netdev->hw_features |= NETIF_F_TSO;1688netdev->features |= netdev->hw_features;1689netdev->hw_features |= NETIF_F_LRO;16901691nes_debug(NES_DBG_INIT, "nesvnic = %p, reported features = 0x%lX, QPid = %d,"1692" nic_index = %d, logical_port = %d, mac_index = %d.\n",1693nesvnic, (unsigned long)netdev->features, nesvnic->nic.qp_id,1694nesvnic->nic_index, nesvnic->logical_port, nesdev->mac_index);16951696if (nesvnic->nesdev->nesadapter->port_count == 1 &&1697nesvnic->nesdev->nesadapter->adapter_fcn_count == 1) {16981699nesvnic->qp_nic_index[0] = nesvnic->nic_index;1700nesvnic->qp_nic_index[1] = nesvnic->nic_index + 1;1701if (nes_drv_opt & NES_DRV_OPT_DUAL_LOGICAL_PORT) {1702nesvnic->qp_nic_index[2] = 0xf;1703nesvnic->qp_nic_index[3] = 0xf;1704} else {1705nesvnic->qp_nic_index[2] = nesvnic->nic_index + 2;1706nesvnic->qp_nic_index[3] = nesvnic->nic_index + 3;1707}1708} else {1709if (nesvnic->nesdev->nesadapter->port_count == 2 ||1710(nesvnic->nesdev->nesadapter->port_count == 1 &&1711nesvnic->nesdev->nesadapter->adapter_fcn_count == 2)) {1712nesvnic->qp_nic_index[0] = nesvnic->nic_index;1713nesvnic->qp_nic_index[1] = nesvnic->nic_index1714+ 2;1715nesvnic->qp_nic_index[2] = 0xf;1716nesvnic->qp_nic_index[3] = 0xf;1717} else {1718nesvnic->qp_nic_index[0] = nesvnic->nic_index;1719nesvnic->qp_nic_index[1] = 0xf;1720nesvnic->qp_nic_index[2] = 0xf;1721nesvnic->qp_nic_index[3] = 0xf;1722}1723}1724nesvnic->next_qp_nic_index = 0;17251726if (nesdev->netdev_count == 0) {1727nesvnic->rdma_enabled = 1;1728} else {1729nesvnic->rdma_enabled = 0;1730}1731nesvnic->nic_cq.cq_number = nesvnic->nic.qp_id;1732init_timer(&nesvnic->event_timer);1733nesvnic->event_timer.function = NULL;1734spin_lock_init(&nesvnic->tx_lock);1735spin_lock_init(&nesvnic->port_ibevent_lock);1736nesdev->netdev[nesdev->netdev_count] = netdev;17371738nes_debug(NES_DBG_INIT, "Adding nesvnic (%p) to the adapters nesvnic_list for MAC%d.\n",1739nesvnic, nesdev->mac_index);1740list_add_tail(&nesvnic->list, &nesdev->nesadapter->nesvnic_list[nesdev->mac_index]);17411742if ((nesdev->netdev_count == 0) &&1743((PCI_FUNC(nesdev->pcidev->devfn) == nesdev->mac_index) ||1744((phy_type == NES_PHY_TYPE_PUMA_1G) &&1745(((PCI_FUNC(nesdev->pcidev->devfn) == 1) && (nesdev->mac_index == 2)) ||1746((PCI_FUNC(nesdev->pcidev->devfn) == 2) && (nesdev->mac_index == 1)))))) {1747u32 u32temp;1748u32 link_mask = 0;1749u32 link_val = 0;1750u16 temp_phy_data;1751u16 phy_data = 0;1752unsigned long flags;17531754u32temp = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 +1755(0x200 * (nesdev->mac_index & 1)));1756if (phy_type != NES_PHY_TYPE_PUMA_1G) {1757u32temp |= 0x00200000;1758nes_write_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 +1759(0x200 * (nesdev->mac_index & 1)), u32temp);1760}17611762/* Check and set linkup here. This is for back to back */1763/* configuration where second port won't get link interrupt */1764switch (phy_type) {1765case NES_PHY_TYPE_PUMA_1G:1766if (nesdev->mac_index < 2) {1767link_mask = 0x01010000;1768link_val = 0x01010000;1769} else {1770link_mask = 0x02020000;1771link_val = 0x02020000;1772}1773break;1774case NES_PHY_TYPE_SFP_D:1775spin_lock_irqsave(&nesdev->nesadapter->phy_lock, flags);1776nes_read_10G_phy_reg(nesdev,1777nesdev->nesadapter->phy_index[nesdev->mac_index],17781, 0x9003);1779temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);1780nes_read_10G_phy_reg(nesdev,1781nesdev->nesadapter->phy_index[nesdev->mac_index],17823, 0x0021);1783nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);1784nes_read_10G_phy_reg(nesdev,1785nesdev->nesadapter->phy_index[nesdev->mac_index],17863, 0x0021);1787phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);1788spin_unlock_irqrestore(&nesdev->nesadapter->phy_lock, flags);1789phy_data = (!temp_phy_data && (phy_data == 0x8000)) ? 0x4 : 0x0;1790break;1791default:1792link_mask = 0x0f1f0000;1793link_val = 0x0f0f0000;1794break;1795}17961797u32temp = nes_read_indexed(nesdev,1798NES_IDX_PHY_PCS_CONTROL_STATUS0 +1799(0x200 * (nesdev->mac_index & 1)));18001801if (phy_type == NES_PHY_TYPE_SFP_D) {1802if (phy_data & 0x0004)1803nesvnic->linkup = 1;1804} else {1805if ((u32temp & link_mask) == link_val)1806nesvnic->linkup = 1;1807}18081809/* clear the MAC interrupt status, assumes direct logical to physical mapping */1810u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (0x200 * nesdev->mac_index));1811nes_debug(NES_DBG_INIT, "Phy interrupt status = 0x%X.\n", u32temp);1812nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (0x200 * nesdev->mac_index), u32temp);18131814nes_init_phy(nesdev);1815}18161817return netdev;1818}181918201821/**1822* nes_netdev_destroy - destroy network device structure1823*/1824void nes_netdev_destroy(struct net_device *netdev)1825{1826struct nes_vnic *nesvnic = netdev_priv(netdev);18271828/* make sure 'stop' method is called by Linux stack */1829/* nes_netdev_stop(netdev); */18301831list_del(&nesvnic->list);18321833if (nesvnic->of_device_registered) {1834nes_destroy_ofa_device(nesvnic->nesibdev);1835}18361837free_netdev(netdev);1838}183918401841/**1842* nes_nic_cm_xmit -- CM calls this to send out pkts1843*/1844int nes_nic_cm_xmit(struct sk_buff *skb, struct net_device *netdev)1845{1846int ret;18471848skb->dev = netdev;1849ret = dev_queue_xmit(skb);1850if (ret) {1851nes_debug(NES_DBG_CM, "Bad return code from dev_queue_xmit %d\n", ret);1852}18531854return ret;1855}185618571858