Path: blob/master/drivers/infiniband/hw/nes/nes_hw.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_vlan.h>40#include <linux/inet_lro.h>41#include <linux/slab.h>4243#include "nes.h"4445static unsigned int nes_lro_max_aggr = NES_LRO_MAX_AGGR;46module_param(nes_lro_max_aggr, uint, 0444);47MODULE_PARM_DESC(nes_lro_max_aggr, "NIC LRO max packet aggregation");4849static int wide_ppm_offset;50module_param(wide_ppm_offset, int, 0644);51MODULE_PARM_DESC(wide_ppm_offset, "Increase CX4 interface clock ppm offset, 0=100ppm (default), 1=300ppm");5253static u32 crit_err_count;54u32 int_mod_timer_init;55u32 int_mod_cq_depth_256;56u32 int_mod_cq_depth_128;57u32 int_mod_cq_depth_32;58u32 int_mod_cq_depth_24;59u32 int_mod_cq_depth_16;60u32 int_mod_cq_depth_4;61u32 int_mod_cq_depth_1;62static const u8 nes_max_critical_error_count = 100;63#include "nes_cm.h"6465static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq);66static void nes_init_csr_ne020(struct nes_device *nesdev, u8 hw_rev, u8 port_count);67static int nes_init_serdes(struct nes_device *nesdev, u8 hw_rev, u8 port_count,68struct nes_adapter *nesadapter, u8 OneG_Mode);69static void nes_nic_napi_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq);70static void nes_process_aeq(struct nes_device *nesdev, struct nes_hw_aeq *aeq);71static void nes_process_ceq(struct nes_device *nesdev, struct nes_hw_ceq *ceq);72static void nes_process_iwarp_aeqe(struct nes_device *nesdev,73struct nes_hw_aeqe *aeqe);74static void process_critical_error(struct nes_device *nesdev);75static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number);76static unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode);77static void nes_terminate_timeout(unsigned long context);78static void nes_terminate_start_timer(struct nes_qp *nesqp);7980#ifdef CONFIG_INFINIBAND_NES_DEBUG81static unsigned char *nes_iwarp_state_str[] = {82"Non-Existent",83"Idle",84"RTS",85"Closing",86"RSVD1",87"Terminate",88"Error",89"RSVD2",90};9192static unsigned char *nes_tcp_state_str[] = {93"Non-Existent",94"Closed",95"Listen",96"SYN Sent",97"SYN Rcvd",98"Established",99"Close Wait",100"FIN Wait 1",101"Closing",102"Last Ack",103"FIN Wait 2",104"Time Wait",105"RSVD1",106"RSVD2",107"RSVD3",108"RSVD4",109};110#endif111112113/**114* nes_nic_init_timer_defaults115*/116void nes_nic_init_timer_defaults(struct nes_device *nesdev, u8 jumbomode)117{118unsigned long flags;119struct nes_adapter *nesadapter = nesdev->nesadapter;120struct nes_hw_tune_timer *shared_timer = &nesadapter->tune_timer;121122spin_lock_irqsave(&nesadapter->periodic_timer_lock, flags);123124shared_timer->timer_in_use_min = NES_NIC_FAST_TIMER_LOW;125shared_timer->timer_in_use_max = NES_NIC_FAST_TIMER_HIGH;126if (jumbomode) {127shared_timer->threshold_low = DEFAULT_JUMBO_NES_QL_LOW;128shared_timer->threshold_target = DEFAULT_JUMBO_NES_QL_TARGET;129shared_timer->threshold_high = DEFAULT_JUMBO_NES_QL_HIGH;130} else {131shared_timer->threshold_low = DEFAULT_NES_QL_LOW;132shared_timer->threshold_target = DEFAULT_NES_QL_TARGET;133shared_timer->threshold_high = DEFAULT_NES_QL_HIGH;134}135136/* todo use netdev->mtu to set thresholds */137spin_unlock_irqrestore(&nesadapter->periodic_timer_lock, flags);138}139140141/**142* nes_nic_init_timer143*/144static void nes_nic_init_timer(struct nes_device *nesdev)145{146unsigned long flags;147struct nes_adapter *nesadapter = nesdev->nesadapter;148struct nes_hw_tune_timer *shared_timer = &nesadapter->tune_timer;149150spin_lock_irqsave(&nesadapter->periodic_timer_lock, flags);151152if (shared_timer->timer_in_use_old == 0) {153nesdev->deepcq_count = 0;154shared_timer->timer_direction_upward = 0;155shared_timer->timer_direction_downward = 0;156shared_timer->timer_in_use = NES_NIC_FAST_TIMER;157shared_timer->timer_in_use_old = 0;158159}160if (shared_timer->timer_in_use != shared_timer->timer_in_use_old) {161shared_timer->timer_in_use_old = shared_timer->timer_in_use;162nes_write32(nesdev->regs+NES_PERIODIC_CONTROL,1630x80000000 | ((u32)(shared_timer->timer_in_use*8)));164}165/* todo use netdev->mtu to set thresholds */166spin_unlock_irqrestore(&nesadapter->periodic_timer_lock, flags);167}168169170/**171* nes_nic_tune_timer172*/173static void nes_nic_tune_timer(struct nes_device *nesdev)174{175unsigned long flags;176struct nes_adapter *nesadapter = nesdev->nesadapter;177struct nes_hw_tune_timer *shared_timer = &nesadapter->tune_timer;178u16 cq_count = nesdev->currcq_count;179180spin_lock_irqsave(&nesadapter->periodic_timer_lock, flags);181182if (shared_timer->cq_count_old <= cq_count)183shared_timer->cq_direction_downward = 0;184else185shared_timer->cq_direction_downward++;186shared_timer->cq_count_old = cq_count;187if (shared_timer->cq_direction_downward > NES_NIC_CQ_DOWNWARD_TREND) {188if (cq_count <= shared_timer->threshold_low &&189shared_timer->threshold_low > 4) {190shared_timer->threshold_low = shared_timer->threshold_low/2;191shared_timer->cq_direction_downward=0;192nesdev->currcq_count = 0;193spin_unlock_irqrestore(&nesadapter->periodic_timer_lock, flags);194return;195}196}197198if (cq_count > 1) {199nesdev->deepcq_count += cq_count;200if (cq_count <= shared_timer->threshold_low) { /* increase timer gently */201shared_timer->timer_direction_upward++;202shared_timer->timer_direction_downward = 0;203} else if (cq_count <= shared_timer->threshold_target) { /* balanced */204shared_timer->timer_direction_upward = 0;205shared_timer->timer_direction_downward = 0;206} else if (cq_count <= shared_timer->threshold_high) { /* decrease timer gently */207shared_timer->timer_direction_downward++;208shared_timer->timer_direction_upward = 0;209} else if (cq_count <= (shared_timer->threshold_high) * 2) {210shared_timer->timer_in_use -= 2;211shared_timer->timer_direction_upward = 0;212shared_timer->timer_direction_downward++;213} else {214shared_timer->timer_in_use -= 4;215shared_timer->timer_direction_upward = 0;216shared_timer->timer_direction_downward++;217}218219if (shared_timer->timer_direction_upward > 3 ) { /* using history */220shared_timer->timer_in_use += 3;221shared_timer->timer_direction_upward = 0;222shared_timer->timer_direction_downward = 0;223}224if (shared_timer->timer_direction_downward > 5) { /* using history */225shared_timer->timer_in_use -= 4 ;226shared_timer->timer_direction_downward = 0;227shared_timer->timer_direction_upward = 0;228}229}230231/* boundary checking */232if (shared_timer->timer_in_use > shared_timer->threshold_high)233shared_timer->timer_in_use = shared_timer->threshold_high;234else if (shared_timer->timer_in_use < shared_timer->threshold_low)235shared_timer->timer_in_use = shared_timer->threshold_low;236237nesdev->currcq_count = 0;238239spin_unlock_irqrestore(&nesadapter->periodic_timer_lock, flags);240}241242243/**244* nes_init_adapter - initialize adapter245*/246struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) {247struct nes_adapter *nesadapter = NULL;248unsigned long num_pds;249u32 u32temp;250u32 port_count;251u16 max_rq_wrs;252u16 max_sq_wrs;253u32 max_mr;254u32 max_256pbl;255u32 max_4kpbl;256u32 max_qp;257u32 max_irrq;258u32 max_cq;259u32 hte_index_mask;260u32 adapter_size;261u32 arp_table_size;262u16 vendor_id;263u16 device_id;264u8 OneG_Mode;265u8 func_index;266267/* search the list of existing adapters */268list_for_each_entry(nesadapter, &nes_adapter_list, list) {269nes_debug(NES_DBG_INIT, "Searching Adapter list for PCI devfn = 0x%X,"270" adapter PCI slot/bus = %u/%u, pci devices PCI slot/bus = %u/%u, .\n",271nesdev->pcidev->devfn,272PCI_SLOT(nesadapter->devfn),273nesadapter->bus_number,274PCI_SLOT(nesdev->pcidev->devfn),275nesdev->pcidev->bus->number );276if ((PCI_SLOT(nesadapter->devfn) == PCI_SLOT(nesdev->pcidev->devfn)) &&277(nesadapter->bus_number == nesdev->pcidev->bus->number)) {278nesadapter->ref_count++;279return nesadapter;280}281}282283/* no adapter found */284num_pds = pci_resource_len(nesdev->pcidev, BAR_1) >> PAGE_SHIFT;285if ((hw_rev != NE020_REV) && (hw_rev != NE020_REV1)) {286nes_debug(NES_DBG_INIT, "NE020 driver detected unknown hardware revision 0x%x\n",287hw_rev);288return NULL;289}290291nes_debug(NES_DBG_INIT, "Determine Soft Reset, QP_control=0x%x, CPU0=0x%x, CPU1=0x%x, CPU2=0x%x\n",292nes_read_indexed(nesdev, NES_IDX_QP_CONTROL + PCI_FUNC(nesdev->pcidev->devfn) * 8),293nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS),294nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS + 4),295nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS + 8));296297nes_debug(NES_DBG_INIT, "Reset and init NE020\n");298299300if ((port_count = nes_reset_adapter_ne020(nesdev, &OneG_Mode)) == 0)301return NULL;302303max_qp = nes_read_indexed(nesdev, NES_IDX_QP_CTX_SIZE);304nes_debug(NES_DBG_INIT, "QP_CTX_SIZE=%u\n", max_qp);305306u32temp = nes_read_indexed(nesdev, NES_IDX_QUAD_HASH_TABLE_SIZE);307if (max_qp > ((u32)1 << (u32temp & 0x001f))) {308nes_debug(NES_DBG_INIT, "Reducing Max QPs to %u due to hash table size = 0x%08X\n",309max_qp, u32temp);310max_qp = (u32)1 << (u32temp & 0x001f);311}312313hte_index_mask = ((u32)1 << ((u32temp & 0x001f)+1))-1;314nes_debug(NES_DBG_INIT, "Max QP = %u, hte_index_mask = 0x%08X.\n",315max_qp, hte_index_mask);316317u32temp = nes_read_indexed(nesdev, NES_IDX_IRRQ_COUNT);318319max_irrq = 1 << (u32temp & 0x001f);320321if (max_qp > max_irrq) {322max_qp = max_irrq;323nes_debug(NES_DBG_INIT, "Reducing Max QPs to %u due to Available Q1s.\n",324max_qp);325}326327/* there should be no reason to allocate more pds than qps */328if (num_pds > max_qp)329num_pds = max_qp;330331u32temp = nes_read_indexed(nesdev, NES_IDX_MRT_SIZE);332max_mr = (u32)8192 << (u32temp & 0x7);333334u32temp = nes_read_indexed(nesdev, NES_IDX_PBL_REGION_SIZE);335max_256pbl = (u32)1 << (u32temp & 0x0000001f);336max_4kpbl = (u32)1 << ((u32temp >> 16) & 0x0000001f);337max_cq = nes_read_indexed(nesdev, NES_IDX_CQ_CTX_SIZE);338339u32temp = nes_read_indexed(nesdev, NES_IDX_ARP_CACHE_SIZE);340arp_table_size = 1 << u32temp;341342adapter_size = (sizeof(struct nes_adapter) +343(sizeof(unsigned long)-1)) & (~(sizeof(unsigned long)-1));344adapter_size += sizeof(unsigned long) * BITS_TO_LONGS(max_qp);345adapter_size += sizeof(unsigned long) * BITS_TO_LONGS(max_mr);346adapter_size += sizeof(unsigned long) * BITS_TO_LONGS(max_cq);347adapter_size += sizeof(unsigned long) * BITS_TO_LONGS(num_pds);348adapter_size += sizeof(unsigned long) * BITS_TO_LONGS(arp_table_size);349adapter_size += sizeof(struct nes_qp **) * max_qp;350351/* allocate a new adapter struct */352nesadapter = kzalloc(adapter_size, GFP_KERNEL);353if (nesadapter == NULL) {354return NULL;355}356357nes_debug(NES_DBG_INIT, "Allocating new nesadapter @ %p, size = %u (actual size = %u).\n",358nesadapter, (u32)sizeof(struct nes_adapter), adapter_size);359360if (nes_read_eeprom_values(nesdev, nesadapter)) {361printk(KERN_ERR PFX "Unable to read EEPROM data.\n");362kfree(nesadapter);363return NULL;364}365366nesadapter->vendor_id = (((u32) nesadapter->mac_addr_high) << 8) |367(nesadapter->mac_addr_low >> 24);368369pci_bus_read_config_word(nesdev->pcidev->bus, nesdev->pcidev->devfn,370PCI_DEVICE_ID, &device_id);371nesadapter->vendor_part_id = device_id;372373if (nes_init_serdes(nesdev, hw_rev, port_count, nesadapter,374OneG_Mode)) {375kfree(nesadapter);376return NULL;377}378nes_init_csr_ne020(nesdev, hw_rev, port_count);379380memset(nesadapter->pft_mcast_map, 255,381sizeof nesadapter->pft_mcast_map);382383/* populate the new nesadapter */384nesadapter->devfn = nesdev->pcidev->devfn;385nesadapter->bus_number = nesdev->pcidev->bus->number;386nesadapter->ref_count = 1;387nesadapter->timer_int_req = 0xffff0000;388nesadapter->OneG_Mode = OneG_Mode;389nesadapter->doorbell_start = nesdev->doorbell_region;390391/* nesadapter->tick_delta = clk_divisor; */392nesadapter->hw_rev = hw_rev;393nesadapter->port_count = port_count;394395nesadapter->max_qp = max_qp;396nesadapter->hte_index_mask = hte_index_mask;397nesadapter->max_irrq = max_irrq;398nesadapter->max_mr = max_mr;399nesadapter->max_256pbl = max_256pbl - 1;400nesadapter->max_4kpbl = max_4kpbl - 1;401nesadapter->max_cq = max_cq;402nesadapter->free_256pbl = max_256pbl - 1;403nesadapter->free_4kpbl = max_4kpbl - 1;404nesadapter->max_pd = num_pds;405nesadapter->arp_table_size = arp_table_size;406407nesadapter->et_pkt_rate_low = NES_TIMER_ENABLE_LIMIT;408if (nes_drv_opt & NES_DRV_OPT_DISABLE_INT_MOD) {409nesadapter->et_use_adaptive_rx_coalesce = 0;410nesadapter->timer_int_limit = NES_TIMER_INT_LIMIT;411nesadapter->et_rx_coalesce_usecs_irq = interrupt_mod_interval;412} else {413nesadapter->et_use_adaptive_rx_coalesce = 1;414nesadapter->timer_int_limit = NES_TIMER_INT_LIMIT_DYNAMIC;415nesadapter->et_rx_coalesce_usecs_irq = 0;416printk(PFX "%s: Using Adaptive Interrupt Moderation\n", __func__);417}418/* Setup and enable the periodic timer */419if (nesadapter->et_rx_coalesce_usecs_irq)420nes_write32(nesdev->regs+NES_PERIODIC_CONTROL, 0x80000000 |421((u32)(nesadapter->et_rx_coalesce_usecs_irq * 8)));422else423nes_write32(nesdev->regs+NES_PERIODIC_CONTROL, 0x00000000);424425nesadapter->base_pd = 1;426427nesadapter->device_cap_flags = IB_DEVICE_LOCAL_DMA_LKEY |428IB_DEVICE_MEM_WINDOW |429IB_DEVICE_MEM_MGT_EXTENSIONS;430431nesadapter->allocated_qps = (unsigned long *)&(((unsigned char *)nesadapter)432[(sizeof(struct nes_adapter)+(sizeof(unsigned long)-1))&(~(sizeof(unsigned long)-1))]);433nesadapter->allocated_cqs = &nesadapter->allocated_qps[BITS_TO_LONGS(max_qp)];434nesadapter->allocated_mrs = &nesadapter->allocated_cqs[BITS_TO_LONGS(max_cq)];435nesadapter->allocated_pds = &nesadapter->allocated_mrs[BITS_TO_LONGS(max_mr)];436nesadapter->allocated_arps = &nesadapter->allocated_pds[BITS_TO_LONGS(num_pds)];437nesadapter->qp_table = (struct nes_qp **)(&nesadapter->allocated_arps[BITS_TO_LONGS(arp_table_size)]);438439440/* mark the usual suspect QPs, MR and CQs as in use */441for (u32temp = 0; u32temp < NES_FIRST_QPN; u32temp++) {442set_bit(u32temp, nesadapter->allocated_qps);443set_bit(u32temp, nesadapter->allocated_cqs);444}445set_bit(0, nesadapter->allocated_mrs);446447for (u32temp = 0; u32temp < 20; u32temp++)448set_bit(u32temp, nesadapter->allocated_pds);449u32temp = nes_read_indexed(nesdev, NES_IDX_QP_MAX_CFG_SIZES);450451max_rq_wrs = ((u32temp >> 8) & 3);452switch (max_rq_wrs) {453case 0:454max_rq_wrs = 4;455break;456case 1:457max_rq_wrs = 16;458break;459case 2:460max_rq_wrs = 32;461break;462case 3:463max_rq_wrs = 512;464break;465}466467max_sq_wrs = (u32temp & 3);468switch (max_sq_wrs) {469case 0:470max_sq_wrs = 4;471break;472case 1:473max_sq_wrs = 16;474break;475case 2:476max_sq_wrs = 32;477break;478case 3:479max_sq_wrs = 512;480break;481}482nesadapter->max_qp_wr = min(max_rq_wrs, max_sq_wrs);483nesadapter->max_irrq_wr = (u32temp >> 16) & 3;484485nesadapter->max_sge = 4;486nesadapter->max_cqe = 32766;487488if (nes_read_eeprom_values(nesdev, nesadapter)) {489printk(KERN_ERR PFX "Unable to read EEPROM data.\n");490kfree(nesadapter);491return NULL;492}493494u32temp = nes_read_indexed(nesdev, NES_IDX_TCP_TIMER_CONFIG);495nes_write_indexed(nesdev, NES_IDX_TCP_TIMER_CONFIG,496(u32temp & 0xff000000) | (nesadapter->tcp_timer_core_clk_divisor & 0x00ffffff));497498/* setup port configuration */499if (nesadapter->port_count == 1) {500nesadapter->log_port = 0x00000000;501if (nes_drv_opt & NES_DRV_OPT_DUAL_LOGICAL_PORT)502nes_write_indexed(nesdev, NES_IDX_TX_POOL_SIZE, 0x00000002);503else504nes_write_indexed(nesdev, NES_IDX_TX_POOL_SIZE, 0x00000003);505} else {506if (nesadapter->phy_type[0] == NES_PHY_TYPE_PUMA_1G) {507nesadapter->log_port = 0x000000D8;508} else {509if (nesadapter->port_count == 2)510nesadapter->log_port = 0x00000044;511else512nesadapter->log_port = 0x000000e4;513}514nes_write_indexed(nesdev, NES_IDX_TX_POOL_SIZE, 0x00000003);515}516517nes_write_indexed(nesdev, NES_IDX_NIC_LOGPORT_TO_PHYPORT,518nesadapter->log_port);519nes_debug(NES_DBG_INIT, "Probe time, LOG2PHY=%u\n",520nes_read_indexed(nesdev, NES_IDX_NIC_LOGPORT_TO_PHYPORT));521522spin_lock_init(&nesadapter->resource_lock);523spin_lock_init(&nesadapter->phy_lock);524spin_lock_init(&nesadapter->pbl_lock);525spin_lock_init(&nesadapter->periodic_timer_lock);526527INIT_LIST_HEAD(&nesadapter->nesvnic_list[0]);528INIT_LIST_HEAD(&nesadapter->nesvnic_list[1]);529INIT_LIST_HEAD(&nesadapter->nesvnic_list[2]);530INIT_LIST_HEAD(&nesadapter->nesvnic_list[3]);531532if ((!nesadapter->OneG_Mode) && (nesadapter->port_count == 2)) {533u32 pcs_control_status0, pcs_control_status1;534u32 reset_value;535u32 i = 0;536u32 int_cnt = 0;537u32 ext_cnt = 0;538unsigned long flags;539u32 j = 0;540541pcs_control_status0 = nes_read_indexed(nesdev,542NES_IDX_PHY_PCS_CONTROL_STATUS0);543pcs_control_status1 = nes_read_indexed(nesdev,544NES_IDX_PHY_PCS_CONTROL_STATUS0 + 0x200);545546for (i = 0; i < NES_MAX_LINK_CHECK; i++) {547pcs_control_status0 = nes_read_indexed(nesdev,548NES_IDX_PHY_PCS_CONTROL_STATUS0);549pcs_control_status1 = nes_read_indexed(nesdev,550NES_IDX_PHY_PCS_CONTROL_STATUS0 + 0x200);551if ((0x0F000100 == (pcs_control_status0 & 0x0F000100))552|| (0x0F000100 == (pcs_control_status1 & 0x0F000100)))553int_cnt++;554msleep(1);555}556if (int_cnt > 1) {557spin_lock_irqsave(&nesadapter->phy_lock, flags);558nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x0000F0C8);559mh_detected++;560reset_value = nes_read32(nesdev->regs+NES_SOFTWARE_RESET);561reset_value |= 0x0000003d;562nes_write32(nesdev->regs+NES_SOFTWARE_RESET, reset_value);563564while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET)565& 0x00000040) != 0x00000040) && (j++ < 5000));566spin_unlock_irqrestore(&nesadapter->phy_lock, flags);567568pcs_control_status0 = nes_read_indexed(nesdev,569NES_IDX_PHY_PCS_CONTROL_STATUS0);570pcs_control_status1 = nes_read_indexed(nesdev,571NES_IDX_PHY_PCS_CONTROL_STATUS0 + 0x200);572573for (i = 0; i < NES_MAX_LINK_CHECK; i++) {574pcs_control_status0 = nes_read_indexed(nesdev,575NES_IDX_PHY_PCS_CONTROL_STATUS0);576pcs_control_status1 = nes_read_indexed(nesdev,577NES_IDX_PHY_PCS_CONTROL_STATUS0 + 0x200);578if ((0x0F000100 == (pcs_control_status0 & 0x0F000100))579|| (0x0F000100 == (pcs_control_status1 & 0x0F000100))) {580if (++ext_cnt > int_cnt) {581spin_lock_irqsave(&nesadapter->phy_lock, flags);582nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1,5830x0000F088);584mh_detected++;585reset_value = nes_read32(nesdev->regs+NES_SOFTWARE_RESET);586reset_value |= 0x0000003d;587nes_write32(nesdev->regs+NES_SOFTWARE_RESET, reset_value);588589while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET)590& 0x00000040) != 0x00000040) && (j++ < 5000));591spin_unlock_irqrestore(&nesadapter->phy_lock, flags);592break;593}594}595msleep(1);596}597}598}599600if (nesadapter->hw_rev == NE020_REV) {601init_timer(&nesadapter->mh_timer);602nesadapter->mh_timer.function = nes_mh_fix;603nesadapter->mh_timer.expires = jiffies + (HZ/5); /* 1 second */604nesadapter->mh_timer.data = (unsigned long)nesdev;605add_timer(&nesadapter->mh_timer);606} else {607nes_write32(nesdev->regs+NES_INTF_INT_STAT, 0x0f000000);608}609610init_timer(&nesadapter->lc_timer);611nesadapter->lc_timer.function = nes_clc;612nesadapter->lc_timer.expires = jiffies + 3600 * HZ; /* 1 hour */613nesadapter->lc_timer.data = (unsigned long)nesdev;614add_timer(&nesadapter->lc_timer);615616list_add_tail(&nesadapter->list, &nes_adapter_list);617618for (func_index = 0; func_index < 8; func_index++) {619pci_bus_read_config_word(nesdev->pcidev->bus,620PCI_DEVFN(PCI_SLOT(nesdev->pcidev->devfn),621func_index), 0, &vendor_id);622if (vendor_id == 0xffff)623break;624}625nes_debug(NES_DBG_INIT, "%s %d functions found for %s.\n", __func__,626func_index, pci_name(nesdev->pcidev));627nesadapter->adapter_fcn_count = func_index;628629return nesadapter;630}631632633/**634* nes_reset_adapter_ne020635*/636static unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode)637{638u32 port_count;639u32 u32temp;640u32 i;641642u32temp = nes_read32(nesdev->regs+NES_SOFTWARE_RESET);643port_count = ((u32temp & 0x00000300) >> 8) + 1;644/* TODO: assuming that both SERDES are set the same for now */645*OneG_Mode = (u32temp & 0x00003c00) ? 0 : 1;646nes_debug(NES_DBG_INIT, "Initial Software Reset = 0x%08X, port_count=%u\n",647u32temp, port_count);648if (*OneG_Mode)649nes_debug(NES_DBG_INIT, "Running in 1G mode.\n");650u32temp &= 0xff00ffc0;651switch (port_count) {652case 1:653u32temp |= 0x00ee0000;654break;655case 2:656u32temp |= 0x00cc0000;657break;658case 4:659u32temp |= 0x00000000;660break;661default:662return 0;663break;664}665666/* check and do full reset if needed */667if (nes_read_indexed(nesdev, NES_IDX_QP_CONTROL+(PCI_FUNC(nesdev->pcidev->devfn)*8))) {668nes_debug(NES_DBG_INIT, "Issuing Full Soft reset = 0x%08X\n", u32temp | 0xd);669nes_write32(nesdev->regs+NES_SOFTWARE_RESET, u32temp | 0xd);670671i = 0;672while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET) & 0x00000040) == 0) && i++ < 10000)673mdelay(1);674if (i > 10000) {675nes_debug(NES_DBG_INIT, "Did not see full soft reset done.\n");676return 0;677}678679i = 0;680while ((nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS) != 0x80) && i++ < 10000)681mdelay(1);682if (i > 10000) {683printk(KERN_ERR PFX "Internal CPU not ready, status = %02X\n",684nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS));685return 0;686}687}688689/* port reset */690switch (port_count) {691case 1:692u32temp |= 0x00ee0010;693break;694case 2:695u32temp |= 0x00cc0030;696break;697case 4:698u32temp |= 0x00000030;699break;700}701702nes_debug(NES_DBG_INIT, "Issuing Port Soft reset = 0x%08X\n", u32temp | 0xd);703nes_write32(nesdev->regs+NES_SOFTWARE_RESET, u32temp | 0xd);704705i = 0;706while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET) & 0x00000040) == 0) && i++ < 10000)707mdelay(1);708if (i > 10000) {709nes_debug(NES_DBG_INIT, "Did not see port soft reset done.\n");710return 0;711}712713/* serdes 0 */714i = 0;715while (((u32temp = (nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS0)716& 0x0000000f)) != 0x0000000f) && i++ < 5000)717mdelay(1);718if (i > 5000) {719nes_debug(NES_DBG_INIT, "Serdes 0 not ready, status=%x\n", u32temp);720return 0;721}722723/* serdes 1 */724if (port_count > 1) {725i = 0;726while (((u32temp = (nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS1)727& 0x0000000f)) != 0x0000000f) && i++ < 5000)728mdelay(1);729if (i > 5000) {730nes_debug(NES_DBG_INIT, "Serdes 1 not ready, status=%x\n", u32temp);731return 0;732}733}734735return port_count;736}737738739/**740* nes_init_serdes741*/742static int nes_init_serdes(struct nes_device *nesdev, u8 hw_rev, u8 port_count,743struct nes_adapter *nesadapter, u8 OneG_Mode)744{745int i;746u32 u32temp;747u32 sds;748749if (hw_rev != NE020_REV) {750/* init serdes 0 */751switch (nesadapter->phy_type[0]) {752case NES_PHY_TYPE_CX4:753if (wide_ppm_offset)754nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000FFFAA);755else756nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000000FF);757break;758case NES_PHY_TYPE_KR:759nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000000FF);760nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP0, 0x00000000);761break;762case NES_PHY_TYPE_PUMA_1G:763nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000000FF);764sds = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0);765sds |= 0x00000100;766nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0, sds);767break;768default:769nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000000FF);770break;771}772773if (!OneG_Mode)774nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_HIGHZ_LANE_MODE0, 0x11110000);775776if (port_count < 2)777return 0;778779/* init serdes 1 */780if (!(OneG_Mode && (nesadapter->phy_type[1] != NES_PHY_TYPE_PUMA_1G)))781nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL1, 0x000000FF);782783switch (nesadapter->phy_type[1]) {784case NES_PHY_TYPE_ARGUS:785case NES_PHY_TYPE_SFP_D:786nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP0, 0x00000000);787nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP1, 0x00000000);788break;789case NES_PHY_TYPE_CX4:790if (wide_ppm_offset)791nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL1, 0x000FFFAA);792break;793case NES_PHY_TYPE_KR:794nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP1, 0x00000000);795break;796case NES_PHY_TYPE_PUMA_1G:797sds = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1);798sds |= 0x000000100;799nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, sds);800}801if (!OneG_Mode) {802nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_HIGHZ_LANE_MODE1, 0x11110000);803sds = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1);804sds &= 0xFFFFFFBF;805nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, sds);806}807} else {808/* init serdes 0 */809nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0, 0x00000008);810i = 0;811while (((u32temp = (nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS0)812& 0x0000000f)) != 0x0000000f) && i++ < 5000)813mdelay(1);814if (i > 5000) {815nes_debug(NES_DBG_PHY, "Init: serdes 0 not ready, status=%x\n", u32temp);816return 1;817}818nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP0, 0x000bdef7);819nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_DRIVE0, 0x9ce73000);820nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_MODE0, 0x0ff00000);821nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_SIGDET0, 0x00000000);822nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_BYPASS0, 0x00000000);823nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_LOOPBACK_CONTROL0, 0x00000000);824if (OneG_Mode)825nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_EQ_CONTROL0, 0xf0182222);826else827nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_EQ_CONTROL0, 0xf0042222);828829nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000000ff);830if (port_count > 1) {831/* init serdes 1 */832nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x00000048);833i = 0;834while (((u32temp = (nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS1)835& 0x0000000f)) != 0x0000000f) && (i++ < 5000))836mdelay(1);837if (i > 5000) {838printk("%s: Init: serdes 1 not ready, status=%x\n", __func__, u32temp);839/* return 1; */840}841nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP1, 0x000bdef7);842nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_DRIVE1, 0x9ce73000);843nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_MODE1, 0x0ff00000);844nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_SIGDET1, 0x00000000);845nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_BYPASS1, 0x00000000);846nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_LOOPBACK_CONTROL1, 0x00000000);847nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_EQ_CONTROL1, 0xf0002222);848nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL1, 0x000000ff);849}850}851return 0;852}853854855/**856* nes_init_csr_ne020857* Initialize registers for ne020 hardware858*/859static void nes_init_csr_ne020(struct nes_device *nesdev, u8 hw_rev, u8 port_count)860{861u32 u32temp;862863nes_debug(NES_DBG_INIT, "port_count=%d\n", port_count);864865nes_write_indexed(nesdev, 0x000001E4, 0x00000007);866/* nes_write_indexed(nesdev, 0x000001E8, 0x000208C4); */867nes_write_indexed(nesdev, 0x000001E8, 0x00020874);868nes_write_indexed(nesdev, 0x000001D8, 0x00048002);869/* nes_write_indexed(nesdev, 0x000001D8, 0x0004B002); */870nes_write_indexed(nesdev, 0x000001FC, 0x00050005);871nes_write_indexed(nesdev, 0x00000600, 0x55555555);872nes_write_indexed(nesdev, 0x00000604, 0x55555555);873874/* TODO: move these MAC register settings to NIC bringup */875nes_write_indexed(nesdev, 0x00002000, 0x00000001);876nes_write_indexed(nesdev, 0x00002004, 0x00000001);877nes_write_indexed(nesdev, 0x00002008, 0x0000FFFF);878nes_write_indexed(nesdev, 0x0000200C, 0x00000001);879nes_write_indexed(nesdev, 0x00002010, 0x000003c1);880nes_write_indexed(nesdev, 0x0000201C, 0x75345678);881if (port_count > 1) {882nes_write_indexed(nesdev, 0x00002200, 0x00000001);883nes_write_indexed(nesdev, 0x00002204, 0x00000001);884nes_write_indexed(nesdev, 0x00002208, 0x0000FFFF);885nes_write_indexed(nesdev, 0x0000220C, 0x00000001);886nes_write_indexed(nesdev, 0x00002210, 0x000003c1);887nes_write_indexed(nesdev, 0x0000221C, 0x75345678);888nes_write_indexed(nesdev, 0x00000908, 0x20000001);889}890if (port_count > 2) {891nes_write_indexed(nesdev, 0x00002400, 0x00000001);892nes_write_indexed(nesdev, 0x00002404, 0x00000001);893nes_write_indexed(nesdev, 0x00002408, 0x0000FFFF);894nes_write_indexed(nesdev, 0x0000240C, 0x00000001);895nes_write_indexed(nesdev, 0x00002410, 0x000003c1);896nes_write_indexed(nesdev, 0x0000241C, 0x75345678);897nes_write_indexed(nesdev, 0x00000910, 0x20000001);898899nes_write_indexed(nesdev, 0x00002600, 0x00000001);900nes_write_indexed(nesdev, 0x00002604, 0x00000001);901nes_write_indexed(nesdev, 0x00002608, 0x0000FFFF);902nes_write_indexed(nesdev, 0x0000260C, 0x00000001);903nes_write_indexed(nesdev, 0x00002610, 0x000003c1);904nes_write_indexed(nesdev, 0x0000261C, 0x75345678);905nes_write_indexed(nesdev, 0x00000918, 0x20000001);906}907908nes_write_indexed(nesdev, 0x00005000, 0x00018000);909/* nes_write_indexed(nesdev, 0x00005000, 0x00010000); */910nes_write_indexed(nesdev, NES_IDX_WQM_CONFIG1, (wqm_quanta << 1) |9110x00000001);912nes_write_indexed(nesdev, 0x00005008, 0x1F1F1F1F);913nes_write_indexed(nesdev, 0x00005010, 0x1F1F1F1F);914nes_write_indexed(nesdev, 0x00005018, 0x1F1F1F1F);915nes_write_indexed(nesdev, 0x00005020, 0x1F1F1F1F);916nes_write_indexed(nesdev, 0x00006090, 0xFFFFFFFF);917918/* TODO: move this to code, get from EEPROM */919nes_write_indexed(nesdev, 0x00000900, 0x20000001);920nes_write_indexed(nesdev, 0x000060C0, 0x0000028e);921nes_write_indexed(nesdev, 0x000060C8, 0x00000020);922923nes_write_indexed(nesdev, 0x000001EC, 0x7b2625a0);924/* nes_write_indexed(nesdev, 0x000001EC, 0x5f2625a0); */925926if (hw_rev != NE020_REV) {927u32temp = nes_read_indexed(nesdev, 0x000008e8);928u32temp |= 0x80000000;929nes_write_indexed(nesdev, 0x000008e8, u32temp);930u32temp = nes_read_indexed(nesdev, 0x000021f8);931u32temp &= 0x7fffffff;932u32temp |= 0x7fff0010;933nes_write_indexed(nesdev, 0x000021f8, u32temp);934if (port_count > 1) {935u32temp = nes_read_indexed(nesdev, 0x000023f8);936u32temp &= 0x7fffffff;937u32temp |= 0x7fff0010;938nes_write_indexed(nesdev, 0x000023f8, u32temp);939}940}941}942943944/**945* nes_destroy_adapter - destroy the adapter structure946*/947void nes_destroy_adapter(struct nes_adapter *nesadapter)948{949struct nes_adapter *tmp_adapter;950951list_for_each_entry(tmp_adapter, &nes_adapter_list, list) {952nes_debug(NES_DBG_SHUTDOWN, "Nes Adapter list entry = 0x%p.\n",953tmp_adapter);954}955956nesadapter->ref_count--;957if (!nesadapter->ref_count) {958if (nesadapter->hw_rev == NE020_REV) {959del_timer(&nesadapter->mh_timer);960}961del_timer(&nesadapter->lc_timer);962963list_del(&nesadapter->list);964kfree(nesadapter);965}966}967968969/**970* nes_init_cqp971*/972int nes_init_cqp(struct nes_device *nesdev)973{974struct nes_adapter *nesadapter = nesdev->nesadapter;975struct nes_hw_cqp_qp_context *cqp_qp_context;976struct nes_hw_cqp_wqe *cqp_wqe;977struct nes_hw_ceq *ceq;978struct nes_hw_ceq *nic_ceq;979struct nes_hw_aeq *aeq;980void *vmem;981dma_addr_t pmem;982u32 count=0;983u32 cqp_head;984u64 u64temp;985u32 u32temp;986987/* allocate CQP memory */988/* Need to add max_cq to the aeq size once cq overflow checking is added back */989/* SQ is 512 byte aligned, others are 256 byte aligned */990nesdev->cqp_mem_size = 512 +991(sizeof(struct nes_hw_cqp_wqe) * NES_CQP_SQ_SIZE) +992(sizeof(struct nes_hw_cqe) * NES_CCQ_SIZE) +993max(((u32)sizeof(struct nes_hw_ceqe) * NES_CCEQ_SIZE), (u32)256) +994max(((u32)sizeof(struct nes_hw_ceqe) * NES_NIC_CEQ_SIZE), (u32)256) +995(sizeof(struct nes_hw_aeqe) * nesadapter->max_qp) +996sizeof(struct nes_hw_cqp_qp_context);997998nesdev->cqp_vbase = pci_alloc_consistent(nesdev->pcidev, nesdev->cqp_mem_size,999&nesdev->cqp_pbase);1000if (!nesdev->cqp_vbase) {1001nes_debug(NES_DBG_INIT, "Unable to allocate memory for host descriptor rings\n");1002return -ENOMEM;1003}1004memset(nesdev->cqp_vbase, 0, nesdev->cqp_mem_size);10051006/* Allocate a twice the number of CQP requests as the SQ size */1007nesdev->nes_cqp_requests = kzalloc(sizeof(struct nes_cqp_request) *10082 * NES_CQP_SQ_SIZE, GFP_KERNEL);1009if (nesdev->nes_cqp_requests == NULL) {1010nes_debug(NES_DBG_INIT, "Unable to allocate memory CQP request entries.\n");1011pci_free_consistent(nesdev->pcidev, nesdev->cqp_mem_size, nesdev->cqp.sq_vbase,1012nesdev->cqp.sq_pbase);1013return -ENOMEM;1014}10151016nes_debug(NES_DBG_INIT, "Allocated CQP structures at %p (phys = %016lX), size = %u.\n",1017nesdev->cqp_vbase, (unsigned long)nesdev->cqp_pbase, nesdev->cqp_mem_size);10181019spin_lock_init(&nesdev->cqp.lock);1020init_waitqueue_head(&nesdev->cqp.waitq);10211022/* Setup Various Structures */1023vmem = (void *)(((unsigned long)nesdev->cqp_vbase + (512 - 1)) &1024~(unsigned long)(512 - 1));1025pmem = (dma_addr_t)(((unsigned long long)nesdev->cqp_pbase + (512 - 1)) &1026~(unsigned long long)(512 - 1));10271028nesdev->cqp.sq_vbase = vmem;1029nesdev->cqp.sq_pbase = pmem;1030nesdev->cqp.sq_size = NES_CQP_SQ_SIZE;1031nesdev->cqp.sq_head = 0;1032nesdev->cqp.sq_tail = 0;1033nesdev->cqp.qp_id = PCI_FUNC(nesdev->pcidev->devfn);10341035vmem += (sizeof(struct nes_hw_cqp_wqe) * nesdev->cqp.sq_size);1036pmem += (sizeof(struct nes_hw_cqp_wqe) * nesdev->cqp.sq_size);10371038nesdev->ccq.cq_vbase = vmem;1039nesdev->ccq.cq_pbase = pmem;1040nesdev->ccq.cq_size = NES_CCQ_SIZE;1041nesdev->ccq.cq_head = 0;1042nesdev->ccq.ce_handler = nes_cqp_ce_handler;1043nesdev->ccq.cq_number = PCI_FUNC(nesdev->pcidev->devfn);10441045vmem += (sizeof(struct nes_hw_cqe) * nesdev->ccq.cq_size);1046pmem += (sizeof(struct nes_hw_cqe) * nesdev->ccq.cq_size);10471048nesdev->ceq_index = PCI_FUNC(nesdev->pcidev->devfn);1049ceq = &nesadapter->ceq[nesdev->ceq_index];1050ceq->ceq_vbase = vmem;1051ceq->ceq_pbase = pmem;1052ceq->ceq_size = NES_CCEQ_SIZE;1053ceq->ceq_head = 0;10541055vmem += max(((u32)sizeof(struct nes_hw_ceqe) * ceq->ceq_size), (u32)256);1056pmem += max(((u32)sizeof(struct nes_hw_ceqe) * ceq->ceq_size), (u32)256);10571058nesdev->nic_ceq_index = PCI_FUNC(nesdev->pcidev->devfn) + 8;1059nic_ceq = &nesadapter->ceq[nesdev->nic_ceq_index];1060nic_ceq->ceq_vbase = vmem;1061nic_ceq->ceq_pbase = pmem;1062nic_ceq->ceq_size = NES_NIC_CEQ_SIZE;1063nic_ceq->ceq_head = 0;10641065vmem += max(((u32)sizeof(struct nes_hw_ceqe) * nic_ceq->ceq_size), (u32)256);1066pmem += max(((u32)sizeof(struct nes_hw_ceqe) * nic_ceq->ceq_size), (u32)256);10671068aeq = &nesadapter->aeq[PCI_FUNC(nesdev->pcidev->devfn)];1069aeq->aeq_vbase = vmem;1070aeq->aeq_pbase = pmem;1071aeq->aeq_size = nesadapter->max_qp;1072aeq->aeq_head = 0;10731074/* Setup QP Context */1075vmem += (sizeof(struct nes_hw_aeqe) * aeq->aeq_size);1076pmem += (sizeof(struct nes_hw_aeqe) * aeq->aeq_size);10771078cqp_qp_context = vmem;1079cqp_qp_context->context_words[0] =1080cpu_to_le32((PCI_FUNC(nesdev->pcidev->devfn) << 12) + (2 << 10));1081cqp_qp_context->context_words[1] = 0;1082cqp_qp_context->context_words[2] = cpu_to_le32((u32)nesdev->cqp.sq_pbase);1083cqp_qp_context->context_words[3] = cpu_to_le32(((u64)nesdev->cqp.sq_pbase) >> 32);108410851086/* Write the address to Create CQP */1087if ((sizeof(dma_addr_t) > 4)) {1088nes_write_indexed(nesdev,1089NES_IDX_CREATE_CQP_HIGH + (PCI_FUNC(nesdev->pcidev->devfn) * 8),1090((u64)pmem) >> 32);1091} else {1092nes_write_indexed(nesdev,1093NES_IDX_CREATE_CQP_HIGH + (PCI_FUNC(nesdev->pcidev->devfn) * 8), 0);1094}1095nes_write_indexed(nesdev,1096NES_IDX_CREATE_CQP_LOW + (PCI_FUNC(nesdev->pcidev->devfn) * 8),1097(u32)pmem);10981099INIT_LIST_HEAD(&nesdev->cqp_avail_reqs);1100INIT_LIST_HEAD(&nesdev->cqp_pending_reqs);11011102for (count = 0; count < 2*NES_CQP_SQ_SIZE; count++) {1103init_waitqueue_head(&nesdev->nes_cqp_requests[count].waitq);1104list_add_tail(&nesdev->nes_cqp_requests[count].list, &nesdev->cqp_avail_reqs);1105}11061107/* Write Create CCQ WQE */1108cqp_head = nesdev->cqp.sq_head++;1109cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];1110nes_fill_init_cqp_wqe(cqp_wqe, nesdev);1111set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,1112(NES_CQP_CREATE_CQ | NES_CQP_CQ_CEQ_VALID |1113NES_CQP_CQ_CHK_OVERFLOW | ((u32)nesdev->ccq.cq_size << 16)));1114set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,1115(nesdev->ccq.cq_number |1116((u32)nesdev->ceq_index << 16)));1117u64temp = (u64)nesdev->ccq.cq_pbase;1118set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp);1119cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] = 0;1120u64temp = (unsigned long)&nesdev->ccq;1121cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_LOW_IDX] =1122cpu_to_le32((u32)(u64temp >> 1));1123cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] =1124cpu_to_le32(((u32)((u64temp) >> 33)) & 0x7FFFFFFF);1125cqp_wqe->wqe_words[NES_CQP_CQ_WQE_DOORBELL_INDEX_HIGH_IDX] = 0;11261127/* Write Create CEQ WQE */1128cqp_head = nesdev->cqp.sq_head++;1129cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];1130nes_fill_init_cqp_wqe(cqp_wqe, nesdev);1131set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,1132(NES_CQP_CREATE_CEQ + ((u32)nesdev->ceq_index << 8)));1133set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_CEQ_WQE_ELEMENT_COUNT_IDX, ceq->ceq_size);1134u64temp = (u64)ceq->ceq_pbase;1135set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp);11361137/* Write Create AEQ WQE */1138cqp_head = nesdev->cqp.sq_head++;1139cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];1140nes_fill_init_cqp_wqe(cqp_wqe, nesdev);1141set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,1142(NES_CQP_CREATE_AEQ + ((u32)PCI_FUNC(nesdev->pcidev->devfn) << 8)));1143set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_AEQ_WQE_ELEMENT_COUNT_IDX, aeq->aeq_size);1144u64temp = (u64)aeq->aeq_pbase;1145set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp);11461147/* Write Create NIC CEQ WQE */1148cqp_head = nesdev->cqp.sq_head++;1149cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];1150nes_fill_init_cqp_wqe(cqp_wqe, nesdev);1151set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,1152(NES_CQP_CREATE_CEQ + ((u32)nesdev->nic_ceq_index << 8)));1153set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_CEQ_WQE_ELEMENT_COUNT_IDX, nic_ceq->ceq_size);1154u64temp = (u64)nic_ceq->ceq_pbase;1155set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp);11561157/* Poll until CCQP done */1158count = 0;1159do {1160if (count++ > 1000) {1161printk(KERN_ERR PFX "Error creating CQP\n");1162pci_free_consistent(nesdev->pcidev, nesdev->cqp_mem_size,1163nesdev->cqp_vbase, nesdev->cqp_pbase);1164return -1;1165}1166udelay(10);1167} while (!(nes_read_indexed(nesdev,1168NES_IDX_QP_CONTROL + (PCI_FUNC(nesdev->pcidev->devfn) * 8)) & (1 << 8)));11691170nes_debug(NES_DBG_INIT, "CQP Status = 0x%08X\n", nes_read_indexed(nesdev,1171NES_IDX_QP_CONTROL+(PCI_FUNC(nesdev->pcidev->devfn)*8)));11721173u32temp = 0x04800000;1174nes_write32(nesdev->regs+NES_WQE_ALLOC, u32temp | nesdev->cqp.qp_id);11751176/* wait for the CCQ, CEQ, and AEQ to get created */1177count = 0;1178do {1179if (count++ > 1000) {1180printk(KERN_ERR PFX "Error creating CCQ, CEQ, and AEQ\n");1181pci_free_consistent(nesdev->pcidev, nesdev->cqp_mem_size,1182nesdev->cqp_vbase, nesdev->cqp_pbase);1183return -1;1184}1185udelay(10);1186} while (((nes_read_indexed(nesdev,1187NES_IDX_QP_CONTROL+(PCI_FUNC(nesdev->pcidev->devfn)*8)) & (15<<8)) != (15<<8)));11881189/* dump the QP status value */1190nes_debug(NES_DBG_INIT, "QP Status = 0x%08X\n", nes_read_indexed(nesdev,1191NES_IDX_QP_CONTROL+(PCI_FUNC(nesdev->pcidev->devfn)*8)));11921193nesdev->cqp.sq_tail++;11941195return 0;1196}119711981199/**1200* nes_destroy_cqp1201*/1202int nes_destroy_cqp(struct nes_device *nesdev)1203{1204struct nes_hw_cqp_wqe *cqp_wqe;1205u32 count = 0;1206u32 cqp_head;1207unsigned long flags;12081209do {1210if (count++ > 1000)1211break;1212udelay(10);1213} while (!(nesdev->cqp.sq_head == nesdev->cqp.sq_tail));12141215/* Reset CCQ */1216nes_write32(nesdev->regs+NES_CQE_ALLOC, NES_CQE_ALLOC_RESET |1217nesdev->ccq.cq_number);12181219/* Disable device interrupts */1220nes_write32(nesdev->regs+NES_INT_MASK, 0x7fffffff);12211222spin_lock_irqsave(&nesdev->cqp.lock, flags);12231224/* Destroy the AEQ */1225cqp_head = nesdev->cqp.sq_head++;1226nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;1227cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];1228cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_DESTROY_AEQ |1229((u32)PCI_FUNC(nesdev->pcidev->devfn) << 8));1230cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX] = 0;12311232/* Destroy the NIC CEQ */1233cqp_head = nesdev->cqp.sq_head++;1234nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;1235cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];1236cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_DESTROY_CEQ |1237((u32)nesdev->nic_ceq_index << 8));12381239/* Destroy the CEQ */1240cqp_head = nesdev->cqp.sq_head++;1241nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;1242cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];1243cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_DESTROY_CEQ |1244(nesdev->ceq_index << 8));12451246/* Destroy the CCQ */1247cqp_head = nesdev->cqp.sq_head++;1248nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;1249cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];1250cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_DESTROY_CQ);1251cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(nesdev->ccq.cq_number |1252((u32)nesdev->ceq_index << 16));12531254/* Destroy CQP */1255cqp_head = nesdev->cqp.sq_head++;1256nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;1257cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];1258cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_DESTROY_QP |1259NES_CQP_QP_TYPE_CQP);1260cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(nesdev->cqp.qp_id);12611262barrier();1263/* Ring doorbell (5 WQEs) */1264nes_write32(nesdev->regs+NES_WQE_ALLOC, 0x05800000 | nesdev->cqp.qp_id);12651266spin_unlock_irqrestore(&nesdev->cqp.lock, flags);12671268/* wait for the CCQ, CEQ, and AEQ to get destroyed */1269count = 0;1270do {1271if (count++ > 1000) {1272printk(KERN_ERR PFX "Function%d: Error destroying CCQ, CEQ, and AEQ\n",1273PCI_FUNC(nesdev->pcidev->devfn));1274break;1275}1276udelay(10);1277} while (((nes_read_indexed(nesdev,1278NES_IDX_QP_CONTROL + (PCI_FUNC(nesdev->pcidev->devfn)*8)) & (15 << 8)) != 0));12791280/* dump the QP status value */1281nes_debug(NES_DBG_SHUTDOWN, "Function%d: QP Status = 0x%08X\n",1282PCI_FUNC(nesdev->pcidev->devfn),1283nes_read_indexed(nesdev,1284NES_IDX_QP_CONTROL+(PCI_FUNC(nesdev->pcidev->devfn)*8)));12851286kfree(nesdev->nes_cqp_requests);12871288/* Free the control structures */1289pci_free_consistent(nesdev->pcidev, nesdev->cqp_mem_size, nesdev->cqp.sq_vbase,1290nesdev->cqp.sq_pbase);12911292return 0;1293}129412951296/**1297* nes_init_1g_phy1298*/1299static int nes_init_1g_phy(struct nes_device *nesdev, u8 phy_type, u8 phy_index)1300{1301u32 counter = 0;1302u16 phy_data;1303int ret = 0;13041305nes_read_1G_phy_reg(nesdev, 1, phy_index, &phy_data);1306nes_write_1G_phy_reg(nesdev, 23, phy_index, 0xb000);13071308/* Reset the PHY */1309nes_write_1G_phy_reg(nesdev, 0, phy_index, 0x8000);1310udelay(100);1311counter = 0;1312do {1313nes_read_1G_phy_reg(nesdev, 0, phy_index, &phy_data);1314if (counter++ > 100) {1315ret = -1;1316break;1317}1318} while (phy_data & 0x8000);13191320/* Setting no phy loopback */1321phy_data &= 0xbfff;1322phy_data |= 0x1140;1323nes_write_1G_phy_reg(nesdev, 0, phy_index, phy_data);1324nes_read_1G_phy_reg(nesdev, 0, phy_index, &phy_data);1325nes_read_1G_phy_reg(nesdev, 0x17, phy_index, &phy_data);1326nes_read_1G_phy_reg(nesdev, 0x1e, phy_index, &phy_data);13271328/* Setting the interrupt mask */1329nes_read_1G_phy_reg(nesdev, 0x19, phy_index, &phy_data);1330nes_write_1G_phy_reg(nesdev, 0x19, phy_index, 0xffee);1331nes_read_1G_phy_reg(nesdev, 0x19, phy_index, &phy_data);13321333/* turning on flow control */1334nes_read_1G_phy_reg(nesdev, 4, phy_index, &phy_data);1335nes_write_1G_phy_reg(nesdev, 4, phy_index, (phy_data & ~(0x03E0)) | 0xc00);1336nes_read_1G_phy_reg(nesdev, 4, phy_index, &phy_data);13371338/* Clear Half duplex */1339nes_read_1G_phy_reg(nesdev, 9, phy_index, &phy_data);1340nes_write_1G_phy_reg(nesdev, 9, phy_index, phy_data & ~(0x0100));1341nes_read_1G_phy_reg(nesdev, 9, phy_index, &phy_data);13421343nes_read_1G_phy_reg(nesdev, 0, phy_index, &phy_data);1344nes_write_1G_phy_reg(nesdev, 0, phy_index, phy_data | 0x0300);13451346return ret;1347}134813491350/**1351* nes_init_2025_phy1352*/1353static int nes_init_2025_phy(struct nes_device *nesdev, u8 phy_type, u8 phy_index)1354{1355u32 temp_phy_data = 0;1356u32 temp_phy_data2 = 0;1357u32 counter = 0;1358u32 sds;1359u32 mac_index = nesdev->mac_index;1360int ret = 0;1361unsigned int first_attempt = 1;13621363/* Check firmware heartbeat */1364nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee);1365temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);1366udelay(1500);1367nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee);1368temp_phy_data2 = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);13691370if (temp_phy_data != temp_phy_data2) {1371nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7fd);1372temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);1373if ((temp_phy_data & 0xff) > 0x20)1374return 0;1375printk(PFX "Reinitialize external PHY\n");1376}13771378/* no heartbeat, configure the PHY */1379nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0x0000, 0x8000);1380nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc300, 0x0000);1381nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc316, 0x000A);1382nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc318, 0x0052);13831384switch (phy_type) {1385case NES_PHY_TYPE_ARGUS:1386nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc316, 0x000A);1387nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc318, 0x0052);1388nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc302, 0x000C);1389nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc319, 0x0008);1390nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0027, 0x0001);1391nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc31a, 0x0098);1392nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0026, 0x0E00);13931394/* setup LEDs */1395nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd006, 0x0007);1396nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd007, 0x000A);1397nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd008, 0x0009);1398break;13991400case NES_PHY_TYPE_SFP_D:1401nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc316, 0x000A);1402nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc318, 0x0052);1403nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc302, 0x0004);1404nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc319, 0x0038);1405nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0027, 0x0013);1406nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc31a, 0x0098);1407nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0026, 0x0E00);14081409/* setup LEDs */1410nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd006, 0x0007);1411nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd007, 0x000A);1412nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd008, 0x0009);1413break;14141415case NES_PHY_TYPE_KR:1416nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc316, 0x000A);1417nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc318, 0x0052);1418nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc302, 0x000C);1419nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc319, 0x0010);1420nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0027, 0x0013);1421nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc31a, 0x0080);1422nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0026, 0x0E00);14231424/* setup LEDs */1425nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd006, 0x000B);1426nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd007, 0x0003);1427nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd008, 0x0004);14281429nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0022, 0x406D);1430nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0023, 0x0020);1431break;1432}14331434nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0028, 0xA528);14351436/* Bring PHY out of reset */1437nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc300, 0x0002);14381439/* Check for heartbeat */1440counter = 0;1441mdelay(690);1442nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee);1443temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);1444do {1445if (counter++ > 150) {1446printk(PFX "No PHY heartbeat\n");1447break;1448}1449mdelay(1);1450nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee);1451temp_phy_data2 = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);1452} while ((temp_phy_data2 == temp_phy_data));14531454/* wait for tracking */1455counter = 0;1456do {1457nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7fd);1458temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);1459if (counter++ > 300) {1460if (((temp_phy_data & 0xff) == 0x0) && first_attempt) {1461first_attempt = 0;1462counter = 0;1463/* reset AMCC PHY and try again */1464nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0xe854, 0x00c0);1465nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0xe854, 0x0040);1466continue;1467} else {1468ret = 1;1469break;1470}1471}1472mdelay(10);1473} while ((temp_phy_data & 0xff) < 0x30);14741475/* setup signal integrity */1476nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd003, 0x0000);1477nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xF00D, 0x00FE);1478nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xF00E, 0x0032);1479if (phy_type == NES_PHY_TYPE_KR) {1480nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xF00F, 0x000C);1481} else {1482nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xF00F, 0x0002);1483nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc314, 0x0063);1484}14851486/* reset serdes */1487sds = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0 + mac_index * 0x200);1488sds |= 0x1;1489nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0 + mac_index * 0x200, sds);1490sds &= 0xfffffffe;1491nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0 + mac_index * 0x200, sds);14921493counter = 0;1494while (((nes_read32(nesdev->regs + NES_SOFTWARE_RESET) & 0x00000040) != 0x00000040)1495&& (counter++ < 5000))1496;14971498return ret;1499}150015011502/**1503* nes_init_phy1504*/1505int nes_init_phy(struct nes_device *nesdev)1506{1507struct nes_adapter *nesadapter = nesdev->nesadapter;1508u32 mac_index = nesdev->mac_index;1509u32 tx_config = 0;1510unsigned long flags;1511u8 phy_type = nesadapter->phy_type[mac_index];1512u8 phy_index = nesadapter->phy_index[mac_index];1513int ret = 0;15141515tx_config = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONFIG);1516if (phy_type == NES_PHY_TYPE_1G) {1517/* setup 1G MDIO operation */1518tx_config &= 0xFFFFFFE3;1519tx_config |= 0x04;1520} else {1521/* setup 10G MDIO operation */1522tx_config &= 0xFFFFFFE3;1523tx_config |= 0x15;1524}1525nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG, tx_config);15261527spin_lock_irqsave(&nesdev->nesadapter->phy_lock, flags);15281529switch (phy_type) {1530case NES_PHY_TYPE_1G:1531ret = nes_init_1g_phy(nesdev, phy_type, phy_index);1532break;1533case NES_PHY_TYPE_ARGUS:1534case NES_PHY_TYPE_SFP_D:1535case NES_PHY_TYPE_KR:1536ret = nes_init_2025_phy(nesdev, phy_type, phy_index);1537break;1538}15391540spin_unlock_irqrestore(&nesdev->nesadapter->phy_lock, flags);15411542return ret;1543}154415451546/**1547* nes_replenish_nic_rq1548*/1549static void nes_replenish_nic_rq(struct nes_vnic *nesvnic)1550{1551unsigned long flags;1552dma_addr_t bus_address;1553struct sk_buff *skb;1554struct nes_hw_nic_rq_wqe *nic_rqe;1555struct nes_hw_nic *nesnic;1556struct nes_device *nesdev;1557u32 rx_wqes_posted = 0;15581559nesnic = &nesvnic->nic;1560nesdev = nesvnic->nesdev;1561spin_lock_irqsave(&nesnic->rq_lock, flags);1562if (nesnic->replenishing_rq !=0) {1563if (((nesnic->rq_size-1) == atomic_read(&nesvnic->rx_skbs_needed)) &&1564(atomic_read(&nesvnic->rx_skb_timer_running) == 0)) {1565atomic_set(&nesvnic->rx_skb_timer_running, 1);1566spin_unlock_irqrestore(&nesnic->rq_lock, flags);1567nesvnic->rq_wqes_timer.expires = jiffies + (HZ/2); /* 1/2 second */1568add_timer(&nesvnic->rq_wqes_timer);1569} else1570spin_unlock_irqrestore(&nesnic->rq_lock, flags);1571return;1572}1573nesnic->replenishing_rq = 1;1574spin_unlock_irqrestore(&nesnic->rq_lock, flags);1575do {1576skb = dev_alloc_skb(nesvnic->max_frame_size);1577if (skb) {1578skb->dev = nesvnic->netdev;15791580bus_address = pci_map_single(nesdev->pcidev,1581skb->data, nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);15821583nic_rqe = &nesnic->rq_vbase[nesvnic->nic.rq_head];1584nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] =1585cpu_to_le32(nesvnic->max_frame_size);1586nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_3_2_IDX] = 0;1587nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX] =1588cpu_to_le32((u32)bus_address);1589nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX] =1590cpu_to_le32((u32)((u64)bus_address >> 32));1591nesnic->rx_skb[nesnic->rq_head] = skb;1592nesnic->rq_head++;1593nesnic->rq_head &= nesnic->rq_size - 1;1594atomic_dec(&nesvnic->rx_skbs_needed);1595barrier();1596if (++rx_wqes_posted == 255) {1597nes_write32(nesdev->regs+NES_WQE_ALLOC, (rx_wqes_posted << 24) | nesnic->qp_id);1598rx_wqes_posted = 0;1599}1600} else {1601spin_lock_irqsave(&nesnic->rq_lock, flags);1602if (((nesnic->rq_size-1) == atomic_read(&nesvnic->rx_skbs_needed)) &&1603(atomic_read(&nesvnic->rx_skb_timer_running) == 0)) {1604atomic_set(&nesvnic->rx_skb_timer_running, 1);1605spin_unlock_irqrestore(&nesnic->rq_lock, flags);1606nesvnic->rq_wqes_timer.expires = jiffies + (HZ/2); /* 1/2 second */1607add_timer(&nesvnic->rq_wqes_timer);1608} else1609spin_unlock_irqrestore(&nesnic->rq_lock, flags);1610break;1611}1612} while (atomic_read(&nesvnic->rx_skbs_needed));1613barrier();1614if (rx_wqes_posted)1615nes_write32(nesdev->regs+NES_WQE_ALLOC, (rx_wqes_posted << 24) | nesnic->qp_id);1616nesnic->replenishing_rq = 0;1617}161816191620/**1621* nes_rq_wqes_timeout1622*/1623static void nes_rq_wqes_timeout(unsigned long parm)1624{1625struct nes_vnic *nesvnic = (struct nes_vnic *)parm;1626printk("%s: Timer fired.\n", __func__);1627atomic_set(&nesvnic->rx_skb_timer_running, 0);1628if (atomic_read(&nesvnic->rx_skbs_needed))1629nes_replenish_nic_rq(nesvnic);1630}163116321633static int nes_lro_get_skb_hdr(struct sk_buff *skb, void **iphdr,1634void **tcph, u64 *hdr_flags, void *priv)1635{1636unsigned int ip_len;1637struct iphdr *iph;1638skb_reset_network_header(skb);1639iph = ip_hdr(skb);1640if (iph->protocol != IPPROTO_TCP)1641return -1;1642ip_len = ip_hdrlen(skb);1643skb_set_transport_header(skb, ip_len);1644*tcph = tcp_hdr(skb);16451646*hdr_flags = LRO_IPV4 | LRO_TCP;1647*iphdr = iph;1648return 0;1649}165016511652/**1653* nes_init_nic_qp1654*/1655int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)1656{1657struct nes_hw_cqp_wqe *cqp_wqe;1658struct nes_hw_nic_sq_wqe *nic_sqe;1659struct nes_hw_nic_qp_context *nic_context;1660struct sk_buff *skb;1661struct nes_hw_nic_rq_wqe *nic_rqe;1662struct nes_vnic *nesvnic = netdev_priv(netdev);1663unsigned long flags;1664void *vmem;1665dma_addr_t pmem;1666u64 u64temp;1667int ret;1668u32 cqp_head;1669u32 counter;1670u32 wqe_count;1671u8 jumbomode=0;16721673/* Allocate fragment, SQ, RQ, and CQ; Reuse CEQ based on the PCI function */1674nesvnic->nic_mem_size = 256 +1675(NES_NIC_WQ_SIZE * sizeof(struct nes_first_frag)) +1676(NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_sq_wqe)) +1677(NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_rq_wqe)) +1678(NES_NIC_WQ_SIZE * 2 * sizeof(struct nes_hw_nic_cqe)) +1679sizeof(struct nes_hw_nic_qp_context);16801681nesvnic->nic_vbase = pci_alloc_consistent(nesdev->pcidev, nesvnic->nic_mem_size,1682&nesvnic->nic_pbase);1683if (!nesvnic->nic_vbase) {1684nes_debug(NES_DBG_INIT, "Unable to allocate memory for NIC host descriptor rings\n");1685return -ENOMEM;1686}1687memset(nesvnic->nic_vbase, 0, nesvnic->nic_mem_size);1688nes_debug(NES_DBG_INIT, "Allocated NIC QP structures at %p (phys = %016lX), size = %u.\n",1689nesvnic->nic_vbase, (unsigned long)nesvnic->nic_pbase, nesvnic->nic_mem_size);16901691vmem = (void *)(((unsigned long)nesvnic->nic_vbase + (256 - 1)) &1692~(unsigned long)(256 - 1));1693pmem = (dma_addr_t)(((unsigned long long)nesvnic->nic_pbase + (256 - 1)) &1694~(unsigned long long)(256 - 1));16951696/* Setup the first Fragment buffers */1697nesvnic->nic.first_frag_vbase = vmem;16981699for (counter = 0; counter < NES_NIC_WQ_SIZE; counter++) {1700nesvnic->nic.frag_paddr[counter] = pmem;1701pmem += sizeof(struct nes_first_frag);1702}17031704/* setup the SQ */1705vmem += (NES_NIC_WQ_SIZE * sizeof(struct nes_first_frag));17061707nesvnic->nic.sq_vbase = (void *)vmem;1708nesvnic->nic.sq_pbase = pmem;1709nesvnic->nic.sq_head = 0;1710nesvnic->nic.sq_tail = 0;1711nesvnic->nic.sq_size = NES_NIC_WQ_SIZE;1712for (counter = 0; counter < NES_NIC_WQ_SIZE; counter++) {1713nic_sqe = &nesvnic->nic.sq_vbase[counter];1714nic_sqe->wqe_words[NES_NIC_SQ_WQE_MISC_IDX] =1715cpu_to_le32(NES_NIC_SQ_WQE_DISABLE_CHKSUM |1716NES_NIC_SQ_WQE_COMPLETION);1717nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_0_TAG_IDX] =1718cpu_to_le32((u32)NES_FIRST_FRAG_SIZE << 16);1719nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX] =1720cpu_to_le32((u32)nesvnic->nic.frag_paddr[counter]);1721nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX] =1722cpu_to_le32((u32)((u64)nesvnic->nic.frag_paddr[counter] >> 32));1723}17241725nesvnic->get_cqp_request = nes_get_cqp_request;1726nesvnic->post_cqp_request = nes_post_cqp_request;1727nesvnic->mcrq_mcast_filter = NULL;17281729spin_lock_init(&nesvnic->nic.rq_lock);17301731/* setup the RQ */1732vmem += (NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_sq_wqe));1733pmem += (NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_sq_wqe));173417351736nesvnic->nic.rq_vbase = vmem;1737nesvnic->nic.rq_pbase = pmem;1738nesvnic->nic.rq_head = 0;1739nesvnic->nic.rq_tail = 0;1740nesvnic->nic.rq_size = NES_NIC_WQ_SIZE;17411742/* setup the CQ */1743vmem += (NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_rq_wqe));1744pmem += (NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_rq_wqe));17451746if (nesdev->nesadapter->netdev_count > 2)1747nesvnic->mcrq_qp_id = nesvnic->nic_index + 32;1748else1749nesvnic->mcrq_qp_id = nesvnic->nic.qp_id + 4;17501751nesvnic->nic_cq.cq_vbase = vmem;1752nesvnic->nic_cq.cq_pbase = pmem;1753nesvnic->nic_cq.cq_head = 0;1754nesvnic->nic_cq.cq_size = NES_NIC_WQ_SIZE * 2;17551756nesvnic->nic_cq.ce_handler = nes_nic_napi_ce_handler;17571758/* Send CreateCQ request to CQP */1759spin_lock_irqsave(&nesdev->cqp.lock, flags);1760cqp_head = nesdev->cqp.sq_head;17611762cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];1763nes_fill_init_cqp_wqe(cqp_wqe, nesdev);17641765cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(1766NES_CQP_CREATE_CQ | NES_CQP_CQ_CEQ_VALID |1767((u32)nesvnic->nic_cq.cq_size << 16));1768cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(1769nesvnic->nic_cq.cq_number | ((u32)nesdev->nic_ceq_index << 16));1770u64temp = (u64)nesvnic->nic_cq.cq_pbase;1771set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp);1772cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] = 0;1773u64temp = (unsigned long)&nesvnic->nic_cq;1774cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_LOW_IDX] = cpu_to_le32((u32)(u64temp >> 1));1775cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] =1776cpu_to_le32(((u32)((u64temp) >> 33)) & 0x7FFFFFFF);1777cqp_wqe->wqe_words[NES_CQP_CQ_WQE_DOORBELL_INDEX_HIGH_IDX] = 0;1778if (++cqp_head >= nesdev->cqp.sq_size)1779cqp_head = 0;1780cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];1781nes_fill_init_cqp_wqe(cqp_wqe, nesdev);17821783/* Send CreateQP request to CQP */1784nic_context = (void *)(&nesvnic->nic_cq.cq_vbase[nesvnic->nic_cq.cq_size]);1785nic_context->context_words[NES_NIC_CTX_MISC_IDX] =1786cpu_to_le32((u32)NES_NIC_CTX_SIZE |1787((u32)PCI_FUNC(nesdev->pcidev->devfn) << 12));1788nes_debug(NES_DBG_INIT, "RX_WINDOW_BUFFER_PAGE_TABLE_SIZE = 0x%08X, RX_WINDOW_BUFFER_SIZE = 0x%08X\n",1789nes_read_indexed(nesdev, NES_IDX_RX_WINDOW_BUFFER_PAGE_TABLE_SIZE),1790nes_read_indexed(nesdev, NES_IDX_RX_WINDOW_BUFFER_SIZE));1791if (nes_read_indexed(nesdev, NES_IDX_RX_WINDOW_BUFFER_SIZE) != 0) {1792nic_context->context_words[NES_NIC_CTX_MISC_IDX] |= cpu_to_le32(NES_NIC_BACK_STORE);1793}17941795u64temp = (u64)nesvnic->nic.sq_pbase;1796nic_context->context_words[NES_NIC_CTX_SQ_LOW_IDX] = cpu_to_le32((u32)u64temp);1797nic_context->context_words[NES_NIC_CTX_SQ_HIGH_IDX] = cpu_to_le32((u32)(u64temp >> 32));1798u64temp = (u64)nesvnic->nic.rq_pbase;1799nic_context->context_words[NES_NIC_CTX_RQ_LOW_IDX] = cpu_to_le32((u32)u64temp);1800nic_context->context_words[NES_NIC_CTX_RQ_HIGH_IDX] = cpu_to_le32((u32)(u64temp >> 32));18011802cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_CREATE_QP |1803NES_CQP_QP_TYPE_NIC);1804cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(nesvnic->nic.qp_id);1805u64temp = (u64)nesvnic->nic_cq.cq_pbase +1806(nesvnic->nic_cq.cq_size * sizeof(struct nes_hw_nic_cqe));1807set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, u64temp);18081809if (++cqp_head >= nesdev->cqp.sq_size)1810cqp_head = 0;1811nesdev->cqp.sq_head = cqp_head;18121813barrier();18141815/* Ring doorbell (2 WQEs) */1816nes_write32(nesdev->regs+NES_WQE_ALLOC, 0x02800000 | nesdev->cqp.qp_id);18171818spin_unlock_irqrestore(&nesdev->cqp.lock, flags);1819nes_debug(NES_DBG_INIT, "Waiting for create NIC QP%u to complete.\n",1820nesvnic->nic.qp_id);18211822ret = wait_event_timeout(nesdev->cqp.waitq, (nesdev->cqp.sq_tail == cqp_head),1823NES_EVENT_TIMEOUT);1824nes_debug(NES_DBG_INIT, "Create NIC QP%u completed, wait_event_timeout ret = %u.\n",1825nesvnic->nic.qp_id, ret);1826if (!ret) {1827nes_debug(NES_DBG_INIT, "NIC QP%u create timeout expired\n", nesvnic->nic.qp_id);1828pci_free_consistent(nesdev->pcidev, nesvnic->nic_mem_size, nesvnic->nic_vbase,1829nesvnic->nic_pbase);1830return -EIO;1831}18321833/* Populate the RQ */1834for (counter = 0; counter < (NES_NIC_WQ_SIZE - 1); counter++) {1835skb = dev_alloc_skb(nesvnic->max_frame_size);1836if (!skb) {1837nes_debug(NES_DBG_INIT, "%s: out of memory for receive skb\n", netdev->name);18381839nes_destroy_nic_qp(nesvnic);1840return -ENOMEM;1841}18421843skb->dev = netdev;18441845pmem = pci_map_single(nesdev->pcidev, skb->data,1846nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);18471848nic_rqe = &nesvnic->nic.rq_vbase[counter];1849nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] = cpu_to_le32(nesvnic->max_frame_size);1850nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_3_2_IDX] = 0;1851nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX] = cpu_to_le32((u32)pmem);1852nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX] = cpu_to_le32((u32)((u64)pmem >> 32));1853nesvnic->nic.rx_skb[counter] = skb;1854}18551856wqe_count = NES_NIC_WQ_SIZE - 1;1857nesvnic->nic.rq_head = wqe_count;1858barrier();1859do {1860counter = min(wqe_count, ((u32)255));1861wqe_count -= counter;1862nes_write32(nesdev->regs+NES_WQE_ALLOC, (counter << 24) | nesvnic->nic.qp_id);1863} while (wqe_count);1864init_timer(&nesvnic->rq_wqes_timer);1865nesvnic->rq_wqes_timer.function = nes_rq_wqes_timeout;1866nesvnic->rq_wqes_timer.data = (unsigned long)nesvnic;1867nes_debug(NES_DBG_INIT, "NAPI support Enabled\n");1868if (nesdev->nesadapter->et_use_adaptive_rx_coalesce)1869{1870nes_nic_init_timer(nesdev);1871if (netdev->mtu > 1500)1872jumbomode = 1;1873nes_nic_init_timer_defaults(nesdev, jumbomode);1874}1875nesvnic->lro_mgr.max_aggr = nes_lro_max_aggr;1876nesvnic->lro_mgr.max_desc = NES_MAX_LRO_DESCRIPTORS;1877nesvnic->lro_mgr.lro_arr = nesvnic->lro_desc;1878nesvnic->lro_mgr.get_skb_header = nes_lro_get_skb_hdr;1879nesvnic->lro_mgr.features = LRO_F_NAPI | LRO_F_EXTRACT_VLAN_ID;1880nesvnic->lro_mgr.dev = netdev;1881nesvnic->lro_mgr.ip_summed = CHECKSUM_UNNECESSARY;1882nesvnic->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;1883return 0;1884}188518861887/**1888* nes_destroy_nic_qp1889*/1890void nes_destroy_nic_qp(struct nes_vnic *nesvnic)1891{1892u64 u64temp;1893dma_addr_t bus_address;1894struct nes_device *nesdev = nesvnic->nesdev;1895struct nes_hw_cqp_wqe *cqp_wqe;1896struct nes_hw_nic_sq_wqe *nic_sqe;1897struct nes_hw_nic_rq_wqe *nic_rqe;1898__le16 *wqe_fragment_length;1899u16 wqe_fragment_index;1900u64 wqe_frag;1901u32 cqp_head;1902u32 wqm_cfg0;1903unsigned long flags;1904int ret;19051906/* clear wqe stall before destroying NIC QP */1907wqm_cfg0 = nes_read_indexed(nesdev, NES_IDX_WQM_CONFIG0);1908nes_write_indexed(nesdev, NES_IDX_WQM_CONFIG0, wqm_cfg0 & 0xFFFF7FFF);19091910/* Free remaining NIC receive buffers */1911while (nesvnic->nic.rq_head != nesvnic->nic.rq_tail) {1912nic_rqe = &nesvnic->nic.rq_vbase[nesvnic->nic.rq_tail];1913wqe_frag = (u64)le32_to_cpu(1914nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]);1915wqe_frag |= ((u64)le32_to_cpu(1916nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX]))<<32;1917pci_unmap_single(nesdev->pcidev, (dma_addr_t)wqe_frag,1918nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);1919dev_kfree_skb(nesvnic->nic.rx_skb[nesvnic->nic.rq_tail++]);1920nesvnic->nic.rq_tail &= (nesvnic->nic.rq_size - 1);1921}19221923/* Free remaining NIC transmit buffers */1924while (nesvnic->nic.sq_head != nesvnic->nic.sq_tail) {1925nic_sqe = &nesvnic->nic.sq_vbase[nesvnic->nic.sq_tail];1926wqe_fragment_index = 1;1927wqe_fragment_length = (__le16 *)1928&nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_0_TAG_IDX];1929/* bump past the vlan tag */1930wqe_fragment_length++;1931if (le16_to_cpu(wqe_fragment_length[wqe_fragment_index]) != 0) {1932u64temp = (u64)le32_to_cpu(1933nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX+1934wqe_fragment_index*2]);1935u64temp += ((u64)le32_to_cpu(1936nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX1937+ wqe_fragment_index*2]))<<32;1938bus_address = (dma_addr_t)u64temp;1939if (test_and_clear_bit(nesvnic->nic.sq_tail,1940nesvnic->nic.first_frag_overflow)) {1941pci_unmap_single(nesdev->pcidev,1942bus_address,1943le16_to_cpu(wqe_fragment_length[1944wqe_fragment_index++]),1945PCI_DMA_TODEVICE);1946}1947for (; wqe_fragment_index < 5; wqe_fragment_index++) {1948if (wqe_fragment_length[wqe_fragment_index]) {1949u64temp = le32_to_cpu(1950nic_sqe->wqe_words[1951NES_NIC_SQ_WQE_FRAG0_LOW_IDX+1952wqe_fragment_index*2]);1953u64temp += ((u64)le32_to_cpu(1954nic_sqe->wqe_words[1955NES_NIC_SQ_WQE_FRAG0_HIGH_IDX+1956wqe_fragment_index*2]))<<32;1957bus_address = (dma_addr_t)u64temp;1958pci_unmap_page(nesdev->pcidev,1959bus_address,1960le16_to_cpu(1961wqe_fragment_length[1962wqe_fragment_index]),1963PCI_DMA_TODEVICE);1964} else1965break;1966}1967}1968if (nesvnic->nic.tx_skb[nesvnic->nic.sq_tail])1969dev_kfree_skb(1970nesvnic->nic.tx_skb[nesvnic->nic.sq_tail]);19711972nesvnic->nic.sq_tail = (nesvnic->nic.sq_tail + 1)1973& (nesvnic->nic.sq_size - 1);1974}19751976spin_lock_irqsave(&nesdev->cqp.lock, flags);19771978/* Destroy NIC QP */1979cqp_head = nesdev->cqp.sq_head;1980cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];1981nes_fill_init_cqp_wqe(cqp_wqe, nesdev);19821983set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,1984(NES_CQP_DESTROY_QP | NES_CQP_QP_TYPE_NIC));1985set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,1986nesvnic->nic.qp_id);19871988if (++cqp_head >= nesdev->cqp.sq_size)1989cqp_head = 0;19901991cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];19921993/* Destroy NIC CQ */1994nes_fill_init_cqp_wqe(cqp_wqe, nesdev);1995set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,1996(NES_CQP_DESTROY_CQ | ((u32)nesvnic->nic_cq.cq_size << 16)));1997set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,1998(nesvnic->nic_cq.cq_number | ((u32)nesdev->nic_ceq_index << 16)));19992000if (++cqp_head >= nesdev->cqp.sq_size)2001cqp_head = 0;20022003nesdev->cqp.sq_head = cqp_head;2004barrier();20052006/* Ring doorbell (2 WQEs) */2007nes_write32(nesdev->regs+NES_WQE_ALLOC, 0x02800000 | nesdev->cqp.qp_id);20082009spin_unlock_irqrestore(&nesdev->cqp.lock, flags);2010nes_debug(NES_DBG_SHUTDOWN, "Waiting for CQP, cqp_head=%u, cqp.sq_head=%u,"2011" cqp.sq_tail=%u, cqp.sq_size=%u\n",2012cqp_head, nesdev->cqp.sq_head,2013nesdev->cqp.sq_tail, nesdev->cqp.sq_size);20142015ret = wait_event_timeout(nesdev->cqp.waitq, (nesdev->cqp.sq_tail == cqp_head),2016NES_EVENT_TIMEOUT);20172018nes_debug(NES_DBG_SHUTDOWN, "Destroy NIC QP returned, wait_event_timeout ret = %u, cqp_head=%u,"2019" cqp.sq_head=%u, cqp.sq_tail=%u\n",2020ret, cqp_head, nesdev->cqp.sq_head, nesdev->cqp.sq_tail);2021if (!ret) {2022nes_debug(NES_DBG_SHUTDOWN, "NIC QP%u destroy timeout expired\n",2023nesvnic->nic.qp_id);2024}20252026pci_free_consistent(nesdev->pcidev, nesvnic->nic_mem_size, nesvnic->nic_vbase,2027nesvnic->nic_pbase);20282029/* restore old wqm_cfg0 value */2030nes_write_indexed(nesdev, NES_IDX_WQM_CONFIG0, wqm_cfg0);2031}20322033/**2034* nes_napi_isr2035*/2036int nes_napi_isr(struct nes_device *nesdev)2037{2038struct nes_adapter *nesadapter = nesdev->nesadapter;2039u32 int_stat;20402041if (nesdev->napi_isr_ran) {2042/* interrupt status has already been read in ISR */2043int_stat = nesdev->int_stat;2044} else {2045int_stat = nes_read32(nesdev->regs + NES_INT_STAT);2046nesdev->int_stat = int_stat;2047nesdev->napi_isr_ran = 1;2048}20492050int_stat &= nesdev->int_req;2051/* iff NIC, process here, else wait for DPC */2052if ((int_stat) && ((int_stat & 0x0000ff00) == int_stat)) {2053nesdev->napi_isr_ran = 0;2054nes_write32(nesdev->regs + NES_INT_STAT,2055(int_stat &2056~(NES_INT_INTF | NES_INT_TIMER | NES_INT_MAC0 | NES_INT_MAC1 | NES_INT_MAC2 | NES_INT_MAC3)));20572058/* Process the CEQs */2059nes_process_ceq(nesdev, &nesdev->nesadapter->ceq[nesdev->nic_ceq_index]);20602061if (unlikely((((nesadapter->et_rx_coalesce_usecs_irq) &&2062(!nesadapter->et_use_adaptive_rx_coalesce)) ||2063((nesadapter->et_use_adaptive_rx_coalesce) &&2064(nesdev->deepcq_count > nesadapter->et_pkt_rate_low))))) {2065if ((nesdev->int_req & NES_INT_TIMER) == 0) {2066/* Enable Periodic timer interrupts */2067nesdev->int_req |= NES_INT_TIMER;2068/* ack any pending periodic timer interrupts so we don't get an immediate interrupt */2069/* TODO: need to also ack other unused periodic timer values, get from nesadapter */2070nes_write32(nesdev->regs+NES_TIMER_STAT,2071nesdev->timer_int_req | ~(nesdev->nesadapter->timer_int_req));2072nes_write32(nesdev->regs+NES_INTF_INT_MASK,2073~(nesdev->intf_int_req | NES_INTF_PERIODIC_TIMER));2074}20752076if (unlikely(nesadapter->et_use_adaptive_rx_coalesce))2077{2078nes_nic_init_timer(nesdev);2079}2080/* Enable interrupts, except CEQs */2081nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff | (~nesdev->int_req));2082} else {2083/* Enable interrupts, make sure timer is off */2084nesdev->int_req &= ~NES_INT_TIMER;2085nes_write32(nesdev->regs+NES_INTF_INT_MASK, ~(nesdev->intf_int_req));2086nes_write32(nesdev->regs+NES_INT_MASK, ~nesdev->int_req);2087}2088nesdev->deepcq_count = 0;2089return 1;2090} else {2091return 0;2092}2093}20942095static void process_critical_error(struct nes_device *nesdev)2096{2097u32 debug_error;2098u32 nes_idx_debug_error_masks0 = 0;2099u16 error_module = 0;21002101debug_error = nes_read_indexed(nesdev, NES_IDX_DEBUG_ERROR_CONTROL_STATUS);2102printk(KERN_ERR PFX "Critical Error reported by device!!! 0x%02X\n",2103(u16)debug_error);2104nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_CONTROL_STATUS,21050x01010000 | (debug_error & 0x0000ffff));2106if (crit_err_count++ > 10)2107nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS1, 1 << 0x17);2108error_module = (u16) (debug_error & 0x1F00) >> 8;2109if (++nesdev->nesadapter->crit_error_count[error_module-1] >=2110nes_max_critical_error_count) {2111printk(KERN_ERR PFX "Masking off critical error for module "2112"0x%02X\n", (u16)error_module);2113nes_idx_debug_error_masks0 = nes_read_indexed(nesdev,2114NES_IDX_DEBUG_ERROR_MASKS0);2115nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS0,2116nes_idx_debug_error_masks0 | (1 << error_module));2117}2118}2119/**2120* nes_dpc2121*/2122void nes_dpc(unsigned long param)2123{2124struct nes_device *nesdev = (struct nes_device *)param;2125struct nes_adapter *nesadapter = nesdev->nesadapter;2126u32 counter;2127u32 loop_counter = 0;2128u32 int_status_bit;2129u32 int_stat;2130u32 timer_stat;2131u32 temp_int_stat;2132u32 intf_int_stat;2133u32 processed_intf_int = 0;2134u16 processed_timer_int = 0;2135u16 completion_ints = 0;2136u16 timer_ints = 0;21372138/* nes_debug(NES_DBG_ISR, "\n"); */21392140do {2141timer_stat = 0;2142if (nesdev->napi_isr_ran) {2143nesdev->napi_isr_ran = 0;2144int_stat = nesdev->int_stat;2145} else2146int_stat = nes_read32(nesdev->regs+NES_INT_STAT);2147if (processed_intf_int != 0)2148int_stat &= nesdev->int_req & ~NES_INT_INTF;2149else2150int_stat &= nesdev->int_req;2151if (processed_timer_int == 0) {2152processed_timer_int = 1;2153if (int_stat & NES_INT_TIMER) {2154timer_stat = nes_read32(nesdev->regs + NES_TIMER_STAT);2155if ((timer_stat & nesdev->timer_int_req) == 0) {2156int_stat &= ~NES_INT_TIMER;2157}2158}2159} else {2160int_stat &= ~NES_INT_TIMER;2161}21622163if (int_stat) {2164if (int_stat & ~(NES_INT_INTF | NES_INT_TIMER | NES_INT_MAC0|2165NES_INT_MAC1|NES_INT_MAC2 | NES_INT_MAC3)) {2166/* Ack the interrupts */2167nes_write32(nesdev->regs+NES_INT_STAT,2168(int_stat & ~(NES_INT_INTF | NES_INT_TIMER | NES_INT_MAC0|2169NES_INT_MAC1 | NES_INT_MAC2 | NES_INT_MAC3)));2170}21712172temp_int_stat = int_stat;2173for (counter = 0, int_status_bit = 1; counter < 16; counter++) {2174if (int_stat & int_status_bit) {2175nes_process_ceq(nesdev, &nesadapter->ceq[counter]);2176temp_int_stat &= ~int_status_bit;2177completion_ints = 1;2178}2179if (!(temp_int_stat & 0x0000ffff))2180break;2181int_status_bit <<= 1;2182}21832184/* Process the AEQ for this pci function */2185int_status_bit = 1 << (16 + PCI_FUNC(nesdev->pcidev->devfn));2186if (int_stat & int_status_bit) {2187nes_process_aeq(nesdev, &nesadapter->aeq[PCI_FUNC(nesdev->pcidev->devfn)]);2188}21892190/* Process the MAC interrupt for this pci function */2191int_status_bit = 1 << (24 + nesdev->mac_index);2192if (int_stat & int_status_bit) {2193nes_process_mac_intr(nesdev, nesdev->mac_index);2194}21952196if (int_stat & NES_INT_TIMER) {2197if (timer_stat & nesdev->timer_int_req) {2198nes_write32(nesdev->regs + NES_TIMER_STAT,2199(timer_stat & nesdev->timer_int_req) |2200~(nesdev->nesadapter->timer_int_req));2201timer_ints = 1;2202}2203}22042205if (int_stat & NES_INT_INTF) {2206processed_intf_int = 1;2207intf_int_stat = nes_read32(nesdev->regs+NES_INTF_INT_STAT);2208intf_int_stat &= nesdev->intf_int_req;2209if (NES_INTF_INT_CRITERR & intf_int_stat) {2210process_critical_error(nesdev);2211}2212if (NES_INTF_INT_PCIERR & intf_int_stat) {2213printk(KERN_ERR PFX "PCI Error reported by device!!!\n");2214BUG();2215}2216if (NES_INTF_INT_AEQ_OFLOW & intf_int_stat) {2217printk(KERN_ERR PFX "AEQ Overflow reported by device!!!\n");2218BUG();2219}2220nes_write32(nesdev->regs+NES_INTF_INT_STAT, intf_int_stat);2221}22222223if (int_stat & NES_INT_TSW) {2224}2225}2226/* Don't use the interface interrupt bit stay in loop */2227int_stat &= ~NES_INT_INTF | NES_INT_TIMER | NES_INT_MAC0 |2228NES_INT_MAC1 | NES_INT_MAC2 | NES_INT_MAC3;2229} while ((int_stat != 0) && (loop_counter++ < MAX_DPC_ITERATIONS));22302231if (timer_ints == 1) {2232if ((nesadapter->et_rx_coalesce_usecs_irq) || (nesadapter->et_use_adaptive_rx_coalesce)) {2233if (completion_ints == 0) {2234nesdev->timer_only_int_count++;2235if (nesdev->timer_only_int_count>=nesadapter->timer_int_limit) {2236nesdev->timer_only_int_count = 0;2237nesdev->int_req &= ~NES_INT_TIMER;2238nes_write32(nesdev->regs + NES_INTF_INT_MASK, ~(nesdev->intf_int_req));2239nes_write32(nesdev->regs + NES_INT_MASK, ~nesdev->int_req);2240} else {2241nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff | (~nesdev->int_req));2242}2243} else {2244if (unlikely(nesadapter->et_use_adaptive_rx_coalesce))2245{2246nes_nic_init_timer(nesdev);2247}2248nesdev->timer_only_int_count = 0;2249nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff | (~nesdev->int_req));2250}2251} else {2252nesdev->timer_only_int_count = 0;2253nesdev->int_req &= ~NES_INT_TIMER;2254nes_write32(nesdev->regs+NES_INTF_INT_MASK, ~(nesdev->intf_int_req));2255nes_write32(nesdev->regs+NES_TIMER_STAT,2256nesdev->timer_int_req | ~(nesdev->nesadapter->timer_int_req));2257nes_write32(nesdev->regs+NES_INT_MASK, ~nesdev->int_req);2258}2259} else {2260if ( (completion_ints == 1) &&2261(((nesadapter->et_rx_coalesce_usecs_irq) &&2262(!nesadapter->et_use_adaptive_rx_coalesce)) ||2263((nesdev->deepcq_count > nesadapter->et_pkt_rate_low) &&2264(nesadapter->et_use_adaptive_rx_coalesce) )) ) {2265/* nes_debug(NES_DBG_ISR, "Enabling periodic timer interrupt.\n" ); */2266nesdev->timer_only_int_count = 0;2267nesdev->int_req |= NES_INT_TIMER;2268nes_write32(nesdev->regs+NES_TIMER_STAT,2269nesdev->timer_int_req | ~(nesdev->nesadapter->timer_int_req));2270nes_write32(nesdev->regs+NES_INTF_INT_MASK,2271~(nesdev->intf_int_req | NES_INTF_PERIODIC_TIMER));2272nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff | (~nesdev->int_req));2273} else {2274nes_write32(nesdev->regs+NES_INT_MASK, ~nesdev->int_req);2275}2276}2277nesdev->deepcq_count = 0;2278}227922802281/**2282* nes_process_ceq2283*/2284static void nes_process_ceq(struct nes_device *nesdev, struct nes_hw_ceq *ceq)2285{2286u64 u64temp;2287struct nes_hw_cq *cq;2288u32 head;2289u32 ceq_size;22902291/* nes_debug(NES_DBG_CQ, "\n"); */2292head = ceq->ceq_head;2293ceq_size = ceq->ceq_size;22942295do {2296if (le32_to_cpu(ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_HIGH_IDX]) &2297NES_CEQE_VALID) {2298u64temp = (((u64)(le32_to_cpu(ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_HIGH_IDX]))) << 32) |2299((u64)(le32_to_cpu(ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_LOW_IDX])));2300u64temp <<= 1;2301cq = *((struct nes_hw_cq **)&u64temp);2302/* nes_debug(NES_DBG_CQ, "pCQ = %p\n", cq); */2303barrier();2304ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_HIGH_IDX] = 0;23052306/* call the event handler */2307cq->ce_handler(nesdev, cq);23082309if (++head >= ceq_size)2310head = 0;2311} else {2312break;2313}23142315} while (1);23162317ceq->ceq_head = head;2318}231923202321/**2322* nes_process_aeq2323*/2324static void nes_process_aeq(struct nes_device *nesdev, struct nes_hw_aeq *aeq)2325{2326/* u64 u64temp; */2327u32 head;2328u32 aeq_size;2329u32 aeqe_misc;2330u32 aeqe_cq_id;2331struct nes_hw_aeqe volatile *aeqe;23322333head = aeq->aeq_head;2334aeq_size = aeq->aeq_size;23352336do {2337aeqe = &aeq->aeq_vbase[head];2338if ((le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]) & NES_AEQE_VALID) == 0)2339break;2340aeqe_misc = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]);2341aeqe_cq_id = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]);2342if (aeqe_misc & (NES_AEQE_QP|NES_AEQE_CQ)) {2343if (aeqe_cq_id >= NES_FIRST_QPN) {2344/* dealing with an accelerated QP related AE */2345/*2346* u64temp = (((u64)(le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX]))) << 32) |2347* ((u64)(le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX])));2348*/2349nes_process_iwarp_aeqe(nesdev, (struct nes_hw_aeqe *)aeqe);2350} else {2351/* TODO: dealing with a CQP related AE */2352nes_debug(NES_DBG_AEQ, "Processing CQP related AE, misc = 0x%04X\n",2353(u16)(aeqe_misc >> 16));2354}2355}23562357aeqe->aeqe_words[NES_AEQE_MISC_IDX] = 0;23582359if (++head >= aeq_size)2360head = 0;23612362nes_write32(nesdev->regs + NES_AEQ_ALLOC, 1 << 16);2363}2364while (1);2365aeq->aeq_head = head;2366}23672368static void nes_reset_link(struct nes_device *nesdev, u32 mac_index)2369{2370struct nes_adapter *nesadapter = nesdev->nesadapter;2371u32 reset_value;2372u32 i=0;2373u32 u32temp;23742375if (nesadapter->hw_rev == NE020_REV) {2376return;2377}2378mh_detected++;23792380reset_value = nes_read32(nesdev->regs+NES_SOFTWARE_RESET);23812382if ((mac_index == 0) || ((mac_index == 1) && (nesadapter->OneG_Mode)))2383reset_value |= 0x0000001d;2384else2385reset_value |= 0x0000002d;23862387if (4 <= (nesadapter->link_interrupt_count[mac_index] / ((u16)NES_MAX_LINK_INTERRUPTS))) {2388if ((!nesadapter->OneG_Mode) && (nesadapter->port_count == 2)) {2389nesadapter->link_interrupt_count[0] = 0;2390nesadapter->link_interrupt_count[1] = 0;2391u32temp = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1);2392if (0x00000040 & u32temp)2393nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x0000F088);2394else2395nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x0000F0C8);23962397reset_value |= 0x0000003d;2398}2399nesadapter->link_interrupt_count[mac_index] = 0;2400}24012402nes_write32(nesdev->regs+NES_SOFTWARE_RESET, reset_value);24032404while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET)2405& 0x00000040) != 0x00000040) && (i++ < 5000));24062407if (0x0000003d == (reset_value & 0x0000003d)) {2408u32 pcs_control_status0, pcs_control_status1;24092410for (i = 0; i < 10; i++) {2411pcs_control_status0 = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0);2412pcs_control_status1 = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 + 0x200);2413if (((0x0F000000 == (pcs_control_status0 & 0x0F000000))2414&& (pcs_control_status0 & 0x00100000))2415|| ((0x0F000000 == (pcs_control_status1 & 0x0F000000))2416&& (pcs_control_status1 & 0x00100000)))2417continue;2418else2419break;2420}2421if (10 == i) {2422u32temp = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1);2423if (0x00000040 & u32temp)2424nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x0000F088);2425else2426nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x0000F0C8);24272428nes_write32(nesdev->regs+NES_SOFTWARE_RESET, reset_value);24292430while (((nes_read32(nesdev->regs + NES_SOFTWARE_RESET)2431& 0x00000040) != 0x00000040) && (i++ < 5000));2432}2433}2434}24352436/**2437* nes_process_mac_intr2438*/2439static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number)2440{2441unsigned long flags;2442u32 pcs_control_status;2443struct nes_adapter *nesadapter = nesdev->nesadapter;2444struct nes_vnic *nesvnic;2445u32 mac_status;2446u32 mac_index = nesdev->mac_index;2447u32 u32temp;2448u16 phy_data;2449u16 temp_phy_data;2450u32 pcs_val = 0x0f0f0000;2451u32 pcs_mask = 0x0f1f0000;2452u32 cdr_ctrl;24532454spin_lock_irqsave(&nesadapter->phy_lock, flags);2455if (nesadapter->mac_sw_state[mac_number] != NES_MAC_SW_IDLE) {2456spin_unlock_irqrestore(&nesadapter->phy_lock, flags);2457return;2458}2459nesadapter->mac_sw_state[mac_number] = NES_MAC_SW_INTERRUPT;24602461/* ack the MAC interrupt */2462mac_status = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (mac_index * 0x200));2463/* Clear the interrupt */2464nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (mac_index * 0x200), mac_status);24652466nes_debug(NES_DBG_PHY, "MAC%u interrupt status = 0x%X.\n", mac_number, mac_status);24672468if (mac_status & (NES_MAC_INT_LINK_STAT_CHG | NES_MAC_INT_XGMII_EXT)) {2469nesdev->link_status_interrupts++;2470if (0 == (++nesadapter->link_interrupt_count[mac_index] % ((u16)NES_MAX_LINK_INTERRUPTS)))2471nes_reset_link(nesdev, mac_index);24722473/* read the PHY interrupt status register */2474if ((nesadapter->OneG_Mode) &&2475(nesadapter->phy_type[mac_index] != NES_PHY_TYPE_PUMA_1G)) {2476do {2477nes_read_1G_phy_reg(nesdev, 0x1a,2478nesadapter->phy_index[mac_index], &phy_data);2479nes_debug(NES_DBG_PHY, "Phy%d data from register 0x1a = 0x%X.\n",2480nesadapter->phy_index[mac_index], phy_data);2481} while (phy_data&0x8000);24822483temp_phy_data = 0;2484do {2485nes_read_1G_phy_reg(nesdev, 0x11,2486nesadapter->phy_index[mac_index], &phy_data);2487nes_debug(NES_DBG_PHY, "Phy%d data from register 0x11 = 0x%X.\n",2488nesadapter->phy_index[mac_index], phy_data);2489if (temp_phy_data == phy_data)2490break;2491temp_phy_data = phy_data;2492} while (1);24932494nes_read_1G_phy_reg(nesdev, 0x1e,2495nesadapter->phy_index[mac_index], &phy_data);2496nes_debug(NES_DBG_PHY, "Phy%d data from register 0x1e = 0x%X.\n",2497nesadapter->phy_index[mac_index], phy_data);24982499nes_read_1G_phy_reg(nesdev, 1,2500nesadapter->phy_index[mac_index], &phy_data);2501nes_debug(NES_DBG_PHY, "1G phy%u data from register 1 = 0x%X\n",2502nesadapter->phy_index[mac_index], phy_data);25032504if (temp_phy_data & 0x1000) {2505nes_debug(NES_DBG_PHY, "The Link is up according to the PHY\n");2506phy_data = 4;2507} else {2508nes_debug(NES_DBG_PHY, "The Link is down according to the PHY\n");2509}2510}2511nes_debug(NES_DBG_PHY, "Eth SERDES Common Status: 0=0x%08X, 1=0x%08X\n",2512nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS0),2513nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS0+0x200));25142515if (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_PUMA_1G) {2516switch (mac_index) {2517case 1:2518case 3:2519pcs_control_status = nes_read_indexed(nesdev,2520NES_IDX_PHY_PCS_CONTROL_STATUS0 + 0x200);2521break;2522default:2523pcs_control_status = nes_read_indexed(nesdev,2524NES_IDX_PHY_PCS_CONTROL_STATUS0);2525break;2526}2527} else {2528pcs_control_status = nes_read_indexed(nesdev,2529NES_IDX_PHY_PCS_CONTROL_STATUS0 + ((mac_index & 1) * 0x200));2530pcs_control_status = nes_read_indexed(nesdev,2531NES_IDX_PHY_PCS_CONTROL_STATUS0 + ((mac_index & 1) * 0x200));2532}25332534nes_debug(NES_DBG_PHY, "PCS PHY Control/Status%u: 0x%08X\n",2535mac_index, pcs_control_status);2536if ((nesadapter->OneG_Mode) &&2537(nesadapter->phy_type[mac_index] != NES_PHY_TYPE_PUMA_1G)) {2538u32temp = 0x01010000;2539if (nesadapter->port_count > 2) {2540u32temp |= 0x02020000;2541}2542if ((pcs_control_status & u32temp)!= u32temp) {2543phy_data = 0;2544nes_debug(NES_DBG_PHY, "PCS says the link is down\n");2545}2546} else {2547switch (nesadapter->phy_type[mac_index]) {2548case NES_PHY_TYPE_ARGUS:2549case NES_PHY_TYPE_SFP_D:2550case NES_PHY_TYPE_KR:2551/* clear the alarms */2552nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0x0008);2553nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0xc001);2554nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0xc002);2555nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0xc005);2556nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0xc006);2557nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 0x9003);2558nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 0x9004);2559nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 0x9005);2560/* check link status */2561nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 0x9003);2562temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);25632564nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 3, 0x0021);2565nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);2566nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 3, 0x0021);2567phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);25682569phy_data = (!temp_phy_data && (phy_data == 0x8000)) ? 0x4 : 0x0;25702571nes_debug(NES_DBG_PHY, "%s: Phy data = 0x%04X, link was %s.\n",2572__func__, phy_data, nesadapter->mac_link_down[mac_index] ? "DOWN" : "UP");2573break;25742575case NES_PHY_TYPE_PUMA_1G:2576if (mac_index < 2)2577pcs_val = pcs_mask = 0x01010000;2578else2579pcs_val = pcs_mask = 0x02020000;2580/* fall through */2581default:2582phy_data = (pcs_val == (pcs_control_status & pcs_mask)) ? 0x4 : 0x0;2583break;2584}2585}25862587if (phy_data & 0x0004) {2588if (wide_ppm_offset &&2589(nesadapter->phy_type[mac_index] == NES_PHY_TYPE_CX4) &&2590(nesadapter->hw_rev != NE020_REV)) {2591cdr_ctrl = nes_read_indexed(nesdev,2592NES_IDX_ETH_SERDES_CDR_CONTROL0 +2593mac_index * 0x200);2594nes_write_indexed(nesdev,2595NES_IDX_ETH_SERDES_CDR_CONTROL0 +2596mac_index * 0x200,2597cdr_ctrl | 0x000F0000);2598}2599nesadapter->mac_link_down[mac_index] = 0;2600list_for_each_entry(nesvnic, &nesadapter->nesvnic_list[mac_index], list) {2601nes_debug(NES_DBG_PHY, "The Link is UP!!. linkup was %d\n",2602nesvnic->linkup);2603if (nesvnic->linkup == 0) {2604printk(PFX "The Link is now up for port %s, netdev %p.\n",2605nesvnic->netdev->name, nesvnic->netdev);2606if (netif_queue_stopped(nesvnic->netdev))2607netif_start_queue(nesvnic->netdev);2608nesvnic->linkup = 1;2609netif_carrier_on(nesvnic->netdev);26102611spin_lock(&nesvnic->port_ibevent_lock);2612if (nesvnic->of_device_registered) {2613if (nesdev->iw_status == 0) {2614nesdev->iw_status = 1;2615nes_port_ibevent(nesvnic);2616}2617}2618spin_unlock(&nesvnic->port_ibevent_lock);2619}2620}2621} else {2622if (wide_ppm_offset &&2623(nesadapter->phy_type[mac_index] == NES_PHY_TYPE_CX4) &&2624(nesadapter->hw_rev != NE020_REV)) {2625cdr_ctrl = nes_read_indexed(nesdev,2626NES_IDX_ETH_SERDES_CDR_CONTROL0 +2627mac_index * 0x200);2628nes_write_indexed(nesdev,2629NES_IDX_ETH_SERDES_CDR_CONTROL0 +2630mac_index * 0x200,2631cdr_ctrl & 0xFFF0FFFF);2632}2633nesadapter->mac_link_down[mac_index] = 1;2634list_for_each_entry(nesvnic, &nesadapter->nesvnic_list[mac_index], list) {2635nes_debug(NES_DBG_PHY, "The Link is Down!!. linkup was %d\n",2636nesvnic->linkup);2637if (nesvnic->linkup == 1) {2638printk(PFX "The Link is now down for port %s, netdev %p.\n",2639nesvnic->netdev->name, nesvnic->netdev);2640if (!(netif_queue_stopped(nesvnic->netdev)))2641netif_stop_queue(nesvnic->netdev);2642nesvnic->linkup = 0;2643netif_carrier_off(nesvnic->netdev);26442645spin_lock(&nesvnic->port_ibevent_lock);2646if (nesvnic->of_device_registered) {2647if (nesdev->iw_status == 1) {2648nesdev->iw_status = 0;2649nes_port_ibevent(nesvnic);2650}2651}2652spin_unlock(&nesvnic->port_ibevent_lock);2653}2654}2655}2656if (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_SFP_D) {2657if (nesdev->link_recheck)2658cancel_delayed_work(&nesdev->work);2659nesdev->link_recheck = 1;2660schedule_delayed_work(&nesdev->work,2661NES_LINK_RECHECK_DELAY);2662}2663}26642665spin_unlock_irqrestore(&nesadapter->phy_lock, flags);26662667nesadapter->mac_sw_state[mac_number] = NES_MAC_SW_IDLE;2668}26692670void nes_recheck_link_status(struct work_struct *work)2671{2672unsigned long flags;2673struct nes_device *nesdev = container_of(work, struct nes_device, work.work);2674struct nes_adapter *nesadapter = nesdev->nesadapter;2675struct nes_vnic *nesvnic;2676u32 mac_index = nesdev->mac_index;2677u16 phy_data;2678u16 temp_phy_data;26792680spin_lock_irqsave(&nesadapter->phy_lock, flags);26812682/* check link status */2683nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 0x9003);2684temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);26852686nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 3, 0x0021);2687nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);2688nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 3, 0x0021);2689phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);26902691phy_data = (!temp_phy_data && (phy_data == 0x8000)) ? 0x4 : 0x0;26922693nes_debug(NES_DBG_PHY, "%s: Phy data = 0x%04X, link was %s.\n",2694__func__, phy_data,2695nesadapter->mac_link_down[mac_index] ? "DOWN" : "UP");26962697if (phy_data & 0x0004) {2698nesadapter->mac_link_down[mac_index] = 0;2699list_for_each_entry(nesvnic, &nesadapter->nesvnic_list[mac_index], list) {2700if (nesvnic->linkup == 0) {2701printk(PFX "The Link is now up for port %s, netdev %p.\n",2702nesvnic->netdev->name, nesvnic->netdev);2703if (netif_queue_stopped(nesvnic->netdev))2704netif_start_queue(nesvnic->netdev);2705nesvnic->linkup = 1;2706netif_carrier_on(nesvnic->netdev);27072708spin_lock(&nesvnic->port_ibevent_lock);2709if (nesvnic->of_device_registered) {2710if (nesdev->iw_status == 0) {2711nesdev->iw_status = 1;2712nes_port_ibevent(nesvnic);2713}2714}2715spin_unlock(&nesvnic->port_ibevent_lock);2716}2717}27182719} else {2720nesadapter->mac_link_down[mac_index] = 1;2721list_for_each_entry(nesvnic, &nesadapter->nesvnic_list[mac_index], list) {2722if (nesvnic->linkup == 1) {2723printk(PFX "The Link is now down for port %s, netdev %p.\n",2724nesvnic->netdev->name, nesvnic->netdev);2725if (!(netif_queue_stopped(nesvnic->netdev)))2726netif_stop_queue(nesvnic->netdev);2727nesvnic->linkup = 0;2728netif_carrier_off(nesvnic->netdev);27292730spin_lock(&nesvnic->port_ibevent_lock);2731if (nesvnic->of_device_registered) {2732if (nesdev->iw_status == 1) {2733nesdev->iw_status = 0;2734nes_port_ibevent(nesvnic);2735}2736}2737spin_unlock(&nesvnic->port_ibevent_lock);2738}2739}2740}2741if (nesdev->link_recheck++ < NES_LINK_RECHECK_MAX)2742schedule_delayed_work(&nesdev->work, NES_LINK_RECHECK_DELAY);2743else2744nesdev->link_recheck = 0;27452746spin_unlock_irqrestore(&nesadapter->phy_lock, flags);2747}274827492750static void nes_nic_napi_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)2751{2752struct nes_vnic *nesvnic = container_of(cq, struct nes_vnic, nic_cq);27532754napi_schedule(&nesvnic->napi);2755}275627572758/* The MAX_RQES_TO_PROCESS defines how many max read requests to complete before2759* getting out of nic_ce_handler2760*/2761#define MAX_RQES_TO_PROCESS 38427622763/**2764* nes_nic_ce_handler2765*/2766void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)2767{2768u64 u64temp;2769dma_addr_t bus_address;2770struct nes_hw_nic *nesnic;2771struct nes_vnic *nesvnic = container_of(cq, struct nes_vnic, nic_cq);2772struct nes_adapter *nesadapter = nesdev->nesadapter;2773struct nes_hw_nic_rq_wqe *nic_rqe;2774struct nes_hw_nic_sq_wqe *nic_sqe;2775struct sk_buff *skb;2776struct sk_buff *rx_skb;2777__le16 *wqe_fragment_length;2778u32 head;2779u32 cq_size;2780u32 rx_pkt_size;2781u32 cqe_count=0;2782u32 cqe_errv;2783u32 cqe_misc;2784u16 wqe_fragment_index = 1; /* first fragment (0) is used by copy buffer */2785u16 vlan_tag;2786u16 pkt_type;2787u16 rqes_processed = 0;2788u8 sq_cqes = 0;2789u8 nes_use_lro = 0;27902791head = cq->cq_head;2792cq_size = cq->cq_size;2793cq->cqes_pending = 1;2794if (nesvnic->netdev->features & NETIF_F_LRO)2795nes_use_lro = 1;2796do {2797if (le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_NIC_CQE_MISC_IDX]) &2798NES_NIC_CQE_VALID) {2799nesnic = &nesvnic->nic;2800cqe_misc = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_NIC_CQE_MISC_IDX]);2801if (cqe_misc & NES_NIC_CQE_SQ) {2802sq_cqes++;2803wqe_fragment_index = 1;2804nic_sqe = &nesnic->sq_vbase[nesnic->sq_tail];2805skb = nesnic->tx_skb[nesnic->sq_tail];2806wqe_fragment_length = (__le16 *)&nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_0_TAG_IDX];2807/* bump past the vlan tag */2808wqe_fragment_length++;2809if (le16_to_cpu(wqe_fragment_length[wqe_fragment_index]) != 0) {2810u64temp = (u64) le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX +2811wqe_fragment_index * 2]);2812u64temp += ((u64)le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX +2813wqe_fragment_index * 2])) << 32;2814bus_address = (dma_addr_t)u64temp;2815if (test_and_clear_bit(nesnic->sq_tail, nesnic->first_frag_overflow)) {2816pci_unmap_single(nesdev->pcidev,2817bus_address,2818le16_to_cpu(wqe_fragment_length[wqe_fragment_index++]),2819PCI_DMA_TODEVICE);2820}2821for (; wqe_fragment_index < 5; wqe_fragment_index++) {2822if (wqe_fragment_length[wqe_fragment_index]) {2823u64temp = le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX +2824wqe_fragment_index * 2]);2825u64temp += ((u64)le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX2826+ wqe_fragment_index * 2])) <<32;2827bus_address = (dma_addr_t)u64temp;2828pci_unmap_page(nesdev->pcidev,2829bus_address,2830le16_to_cpu(wqe_fragment_length[wqe_fragment_index]),2831PCI_DMA_TODEVICE);2832} else2833break;2834}2835}2836if (skb)2837dev_kfree_skb_any(skb);2838nesnic->sq_tail++;2839nesnic->sq_tail &= nesnic->sq_size-1;2840if (sq_cqes > 128) {2841barrier();2842/* restart the queue if it had been stopped */2843if (netif_queue_stopped(nesvnic->netdev))2844netif_wake_queue(nesvnic->netdev);2845sq_cqes = 0;2846}2847} else {2848rqes_processed ++;28492850cq->rx_cqes_completed++;2851cq->rx_pkts_indicated++;2852rx_pkt_size = cqe_misc & 0x0000ffff;2853nic_rqe = &nesnic->rq_vbase[nesnic->rq_tail];2854/* Get the skb */2855rx_skb = nesnic->rx_skb[nesnic->rq_tail];2856nic_rqe = &nesnic->rq_vbase[nesvnic->nic.rq_tail];2857bus_address = (dma_addr_t)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]);2858bus_address += ((u64)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX])) << 32;2859pci_unmap_single(nesdev->pcidev, bus_address,2860nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);2861/* rx_skb->tail = rx_skb->data + rx_pkt_size; */2862/* rx_skb->len = rx_pkt_size; */2863rx_skb->len = 0; /* TODO: see if this is necessary */2864skb_put(rx_skb, rx_pkt_size);2865rx_skb->protocol = eth_type_trans(rx_skb, nesvnic->netdev);2866nesnic->rq_tail++;2867nesnic->rq_tail &= nesnic->rq_size - 1;28682869atomic_inc(&nesvnic->rx_skbs_needed);2870if (atomic_read(&nesvnic->rx_skbs_needed) > (nesvnic->nic.rq_size>>1)) {2871nes_write32(nesdev->regs+NES_CQE_ALLOC,2872cq->cq_number | (cqe_count << 16));2873/* nesadapter->tune_timer.cq_count += cqe_count; */2874nesdev->currcq_count += cqe_count;2875cqe_count = 0;2876nes_replenish_nic_rq(nesvnic);2877}2878pkt_type = (u16)(le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_NIC_CQE_TAG_PKT_TYPE_IDX]));2879cqe_errv = (cqe_misc & NES_NIC_CQE_ERRV_MASK) >> NES_NIC_CQE_ERRV_SHIFT;2880rx_skb->ip_summed = CHECKSUM_NONE;28812882if ((NES_PKT_TYPE_TCPV4_BITS == (pkt_type & NES_PKT_TYPE_TCPV4_MASK)) ||2883(NES_PKT_TYPE_UDPV4_BITS == (pkt_type & NES_PKT_TYPE_UDPV4_MASK))) {2884if ((cqe_errv &2885(NES_NIC_ERRV_BITS_IPV4_CSUM_ERR | NES_NIC_ERRV_BITS_TCPUDP_CSUM_ERR |2886NES_NIC_ERRV_BITS_IPH_ERR | NES_NIC_ERRV_BITS_WQE_OVERRUN)) == 0) {2887if (nesvnic->netdev->features & NETIF_F_RXCSUM)2888rx_skb->ip_summed = CHECKSUM_UNNECESSARY;2889} else2890nes_debug(NES_DBG_CQ, "%s: unsuccessfully checksummed TCP or UDP packet."2891" errv = 0x%X, pkt_type = 0x%X.\n",2892nesvnic->netdev->name, cqe_errv, pkt_type);28932894} else if ((pkt_type & NES_PKT_TYPE_IPV4_MASK) == NES_PKT_TYPE_IPV4_BITS) {2895if ((cqe_errv &2896(NES_NIC_ERRV_BITS_IPV4_CSUM_ERR | NES_NIC_ERRV_BITS_IPH_ERR |2897NES_NIC_ERRV_BITS_WQE_OVERRUN)) == 0) {2898if (nesvnic->netdev->features & NETIF_F_RXCSUM) {2899rx_skb->ip_summed = CHECKSUM_UNNECESSARY;2900/* nes_debug(NES_DBG_CQ, "%s: Reporting successfully checksummed IPv4 packet.\n",2901nesvnic->netdev->name); */2902}2903} else2904nes_debug(NES_DBG_CQ, "%s: unsuccessfully checksummed TCP or UDP packet."2905" errv = 0x%X, pkt_type = 0x%X.\n",2906nesvnic->netdev->name, cqe_errv, pkt_type);2907}2908/* nes_debug(NES_DBG_CQ, "pkt_type=%x, APBVT_MASK=%x\n",2909pkt_type, (pkt_type & NES_PKT_TYPE_APBVT_MASK)); */29102911if ((pkt_type & NES_PKT_TYPE_APBVT_MASK) == NES_PKT_TYPE_APBVT_BITS) {2912if (nes_cm_recv(rx_skb, nesvnic->netdev))2913rx_skb = NULL;2914}2915if (rx_skb == NULL)2916goto skip_rx_indicate0;291729182919if ((cqe_misc & NES_NIC_CQE_TAG_VALID) &&2920(nesvnic->vlan_grp != NULL)) {2921vlan_tag = (u16)(le32_to_cpu(2922cq->cq_vbase[head].cqe_words[NES_NIC_CQE_TAG_PKT_TYPE_IDX])2923>> 16);2924nes_debug(NES_DBG_CQ, "%s: Reporting stripped VLAN packet. Tag = 0x%04X\n",2925nesvnic->netdev->name, vlan_tag);2926if (nes_use_lro)2927lro_vlan_hwaccel_receive_skb(&nesvnic->lro_mgr, rx_skb,2928nesvnic->vlan_grp, vlan_tag, NULL);2929else2930nes_vlan_rx(rx_skb, nesvnic->vlan_grp, vlan_tag);2931} else {2932if (nes_use_lro)2933lro_receive_skb(&nesvnic->lro_mgr, rx_skb, NULL);2934else2935nes_netif_rx(rx_skb);2936}29372938skip_rx_indicate0:2939;2940/* nesvnic->netstats.rx_packets++; */2941/* nesvnic->netstats.rx_bytes += rx_pkt_size; */2942}29432944cq->cq_vbase[head].cqe_words[NES_NIC_CQE_MISC_IDX] = 0;2945/* Accounting... */2946cqe_count++;2947if (++head >= cq_size)2948head = 0;2949if (cqe_count == 255) {2950/* Replenish Nic CQ */2951nes_write32(nesdev->regs+NES_CQE_ALLOC,2952cq->cq_number | (cqe_count << 16));2953/* nesdev->nesadapter->tune_timer.cq_count += cqe_count; */2954nesdev->currcq_count += cqe_count;2955cqe_count = 0;2956}29572958if (cq->rx_cqes_completed >= nesvnic->budget)2959break;2960} else {2961cq->cqes_pending = 0;2962break;2963}29642965} while (1);29662967if (nes_use_lro)2968lro_flush_all(&nesvnic->lro_mgr);2969if (sq_cqes) {2970barrier();2971/* restart the queue if it had been stopped */2972if (netif_queue_stopped(nesvnic->netdev))2973netif_wake_queue(nesvnic->netdev);2974}2975cq->cq_head = head;2976/* nes_debug(NES_DBG_CQ, "CQ%u Processed = %u cqes, new head = %u.\n",2977cq->cq_number, cqe_count, cq->cq_head); */2978cq->cqe_allocs_pending = cqe_count;2979if (unlikely(nesadapter->et_use_adaptive_rx_coalesce))2980{2981/* nesdev->nesadapter->tune_timer.cq_count += cqe_count; */2982nesdev->currcq_count += cqe_count;2983nes_nic_tune_timer(nesdev);2984}2985if (atomic_read(&nesvnic->rx_skbs_needed))2986nes_replenish_nic_rq(nesvnic);2987}298829892990/**2991* nes_cqp_ce_handler2992*/2993static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)2994{2995u64 u64temp;2996unsigned long flags;2997struct nes_hw_cqp *cqp = NULL;2998struct nes_cqp_request *cqp_request;2999struct nes_hw_cqp_wqe *cqp_wqe;3000u32 head;3001u32 cq_size;3002u32 cqe_count=0;3003u32 error_code;3004/* u32 counter; */30053006head = cq->cq_head;3007cq_size = cq->cq_size;30083009do {3010/* process the CQE */3011/* nes_debug(NES_DBG_CQP, "head=%u cqe_words=%08X\n", head,3012le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX])); */30133014if (le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]) & NES_CQE_VALID) {3015u64temp = (((u64)(le32_to_cpu(cq->cq_vbase[head].3016cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX]))) << 32) |3017((u64)(le32_to_cpu(cq->cq_vbase[head].3018cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX])));3019cqp = *((struct nes_hw_cqp **)&u64temp);30203021error_code = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_ERROR_CODE_IDX]);3022if (error_code) {3023nes_debug(NES_DBG_CQP, "Bad Completion code for opcode 0x%02X from CQP,"3024" Major/Minor codes = 0x%04X:%04X.\n",3025le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX])&0x3f,3026(u16)(error_code >> 16),3027(u16)error_code);3028nes_debug(NES_DBG_CQP, "cqp: qp_id=%u, sq_head=%u, sq_tail=%u\n",3029cqp->qp_id, cqp->sq_head, cqp->sq_tail);3030}30313032u64temp = (((u64)(le32_to_cpu(nesdev->cqp.sq_vbase[cqp->sq_tail].3033wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX]))) << 32) |3034((u64)(le32_to_cpu(nesdev->cqp.sq_vbase[cqp->sq_tail].3035wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX])));3036cqp_request = *((struct nes_cqp_request **)&u64temp);3037if (cqp_request) {3038if (cqp_request->waiting) {3039/* nes_debug(NES_DBG_CQP, "%s: Waking up requestor\n"); */3040cqp_request->major_code = (u16)(error_code >> 16);3041cqp_request->minor_code = (u16)error_code;3042barrier();3043cqp_request->request_done = 1;3044wake_up(&cqp_request->waitq);3045nes_put_cqp_request(nesdev, cqp_request);3046} else {3047if (cqp_request->callback)3048cqp_request->cqp_callback(nesdev, cqp_request);3049nes_free_cqp_request(nesdev, cqp_request);3050}3051} else {3052wake_up(&nesdev->cqp.waitq);3053}30543055cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX] = 0;3056nes_write32(nesdev->regs + NES_CQE_ALLOC, cq->cq_number | (1 << 16));3057if (++cqp->sq_tail >= cqp->sq_size)3058cqp->sq_tail = 0;30593060/* Accounting... */3061cqe_count++;3062if (++head >= cq_size)3063head = 0;3064} else {3065break;3066}3067} while (1);3068cq->cq_head = head;30693070spin_lock_irqsave(&nesdev->cqp.lock, flags);3071while ((!list_empty(&nesdev->cqp_pending_reqs)) &&3072((((nesdev->cqp.sq_tail+nesdev->cqp.sq_size)-nesdev->cqp.sq_head) &3073(nesdev->cqp.sq_size - 1)) != 1)) {3074cqp_request = list_entry(nesdev->cqp_pending_reqs.next,3075struct nes_cqp_request, list);3076list_del_init(&cqp_request->list);3077head = nesdev->cqp.sq_head++;3078nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;3079cqp_wqe = &nesdev->cqp.sq_vbase[head];3080memcpy(cqp_wqe, &cqp_request->cqp_wqe, sizeof(*cqp_wqe));3081barrier();3082cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] =3083cpu_to_le32((u32)((unsigned long)cqp_request));3084cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] =3085cpu_to_le32((u32)(upper_32_bits((unsigned long)cqp_request)));3086nes_debug(NES_DBG_CQP, "CQP request %p (opcode 0x%02X) put on CQPs SQ wqe%u.\n",3087cqp_request, le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f, head);3088/* Ring doorbell (1 WQEs) */3089barrier();3090nes_write32(nesdev->regs+NES_WQE_ALLOC, 0x01800000 | nesdev->cqp.qp_id);3091}3092spin_unlock_irqrestore(&nesdev->cqp.lock, flags);30933094/* Arm the CCQ */3095nes_write32(nesdev->regs+NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT |3096cq->cq_number);3097nes_read32(nesdev->regs+NES_CQE_ALLOC);3098}309931003101static u8 *locate_mpa(u8 *pkt, u32 aeq_info)3102{3103if (aeq_info & NES_AEQE_Q2_DATA_ETHERNET) {3104/* skip over ethernet header */3105pkt += ETH_HLEN;31063107/* Skip over IP and TCP headers */3108pkt += 4 * (pkt[0] & 0x0f);3109pkt += 4 * ((pkt[12] >> 4) & 0x0f);3110}3111return pkt;3112}31133114/* Determine if incoming error pkt is rdma layer */3115static u32 iwarp_opcode(struct nes_qp *nesqp, u32 aeq_info)3116{3117u8 *pkt;3118u16 *mpa;3119u32 opcode = 0xffffffff;31203121if (aeq_info & NES_AEQE_Q2_DATA_WRITTEN) {3122pkt = nesqp->hwqp.q2_vbase + BAD_FRAME_OFFSET;3123mpa = (u16 *)locate_mpa(pkt, aeq_info);3124opcode = be16_to_cpu(mpa[1]) & 0xf;3125}31263127return opcode;3128}31293130/* Build iWARP terminate header */3131static int nes_bld_terminate_hdr(struct nes_qp *nesqp, u16 async_event_id, u32 aeq_info)3132{3133u8 *pkt = nesqp->hwqp.q2_vbase + BAD_FRAME_OFFSET;3134u16 ddp_seg_len;3135int copy_len = 0;3136u8 is_tagged = 0;3137u8 flush_code = 0;3138struct nes_terminate_hdr *termhdr;31393140termhdr = (struct nes_terminate_hdr *)nesqp->hwqp.q2_vbase;3141memset(termhdr, 0, 64);31423143if (aeq_info & NES_AEQE_Q2_DATA_WRITTEN) {31443145/* Use data from offending packet to fill in ddp & rdma hdrs */3146pkt = locate_mpa(pkt, aeq_info);3147ddp_seg_len = be16_to_cpu(*(u16 *)pkt);3148if (ddp_seg_len) {3149copy_len = 2;3150termhdr->hdrct = DDP_LEN_FLAG;3151if (pkt[2] & 0x80) {3152is_tagged = 1;3153if (ddp_seg_len >= TERM_DDP_LEN_TAGGED) {3154copy_len += TERM_DDP_LEN_TAGGED;3155termhdr->hdrct |= DDP_HDR_FLAG;3156}3157} else {3158if (ddp_seg_len >= TERM_DDP_LEN_UNTAGGED) {3159copy_len += TERM_DDP_LEN_UNTAGGED;3160termhdr->hdrct |= DDP_HDR_FLAG;3161}31623163if (ddp_seg_len >= (TERM_DDP_LEN_UNTAGGED + TERM_RDMA_LEN)) {3164if ((pkt[3] & RDMA_OPCODE_MASK) == RDMA_READ_REQ_OPCODE) {3165copy_len += TERM_RDMA_LEN;3166termhdr->hdrct |= RDMA_HDR_FLAG;3167}3168}3169}3170}3171}31723173switch (async_event_id) {3174case NES_AEQE_AEID_AMP_UNALLOCATED_STAG:3175switch (iwarp_opcode(nesqp, aeq_info)) {3176case IWARP_OPCODE_WRITE:3177flush_code = IB_WC_LOC_PROT_ERR;3178termhdr->layer_etype = (LAYER_DDP << 4) | DDP_TAGGED_BUFFER;3179termhdr->error_code = DDP_TAGGED_INV_STAG;3180break;3181default:3182flush_code = IB_WC_REM_ACCESS_ERR;3183termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT;3184termhdr->error_code = RDMAP_INV_STAG;3185}3186break;3187case NES_AEQE_AEID_AMP_INVALID_STAG:3188flush_code = IB_WC_REM_ACCESS_ERR;3189termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT;3190termhdr->error_code = RDMAP_INV_STAG;3191break;3192case NES_AEQE_AEID_AMP_BAD_QP:3193flush_code = IB_WC_LOC_QP_OP_ERR;3194termhdr->layer_etype = (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER;3195termhdr->error_code = DDP_UNTAGGED_INV_QN;3196break;3197case NES_AEQE_AEID_AMP_BAD_STAG_KEY:3198case NES_AEQE_AEID_AMP_BAD_STAG_INDEX:3199switch (iwarp_opcode(nesqp, aeq_info)) {3200case IWARP_OPCODE_SEND_INV:3201case IWARP_OPCODE_SEND_SE_INV:3202flush_code = IB_WC_REM_OP_ERR;3203termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_OP;3204termhdr->error_code = RDMAP_CANT_INV_STAG;3205break;3206default:3207flush_code = IB_WC_REM_ACCESS_ERR;3208termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT;3209termhdr->error_code = RDMAP_INV_STAG;3210}3211break;3212case NES_AEQE_AEID_AMP_BOUNDS_VIOLATION:3213if (aeq_info & (NES_AEQE_Q2_DATA_ETHERNET | NES_AEQE_Q2_DATA_MPA)) {3214flush_code = IB_WC_LOC_PROT_ERR;3215termhdr->layer_etype = (LAYER_DDP << 4) | DDP_TAGGED_BUFFER;3216termhdr->error_code = DDP_TAGGED_BOUNDS;3217} else {3218flush_code = IB_WC_REM_ACCESS_ERR;3219termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT;3220termhdr->error_code = RDMAP_INV_BOUNDS;3221}3222break;3223case NES_AEQE_AEID_AMP_RIGHTS_VIOLATION:3224case NES_AEQE_AEID_AMP_INVALIDATE_NO_REMOTE_ACCESS_RIGHTS:3225case NES_AEQE_AEID_PRIV_OPERATION_DENIED:3226flush_code = IB_WC_REM_ACCESS_ERR;3227termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT;3228termhdr->error_code = RDMAP_ACCESS;3229break;3230case NES_AEQE_AEID_AMP_TO_WRAP:3231flush_code = IB_WC_REM_ACCESS_ERR;3232termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT;3233termhdr->error_code = RDMAP_TO_WRAP;3234break;3235case NES_AEQE_AEID_AMP_BAD_PD:3236switch (iwarp_opcode(nesqp, aeq_info)) {3237case IWARP_OPCODE_WRITE:3238flush_code = IB_WC_LOC_PROT_ERR;3239termhdr->layer_etype = (LAYER_DDP << 4) | DDP_TAGGED_BUFFER;3240termhdr->error_code = DDP_TAGGED_UNASSOC_STAG;3241break;3242case IWARP_OPCODE_SEND_INV:3243case IWARP_OPCODE_SEND_SE_INV:3244flush_code = IB_WC_REM_ACCESS_ERR;3245termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT;3246termhdr->error_code = RDMAP_CANT_INV_STAG;3247break;3248default:3249flush_code = IB_WC_REM_ACCESS_ERR;3250termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT;3251termhdr->error_code = RDMAP_UNASSOC_STAG;3252}3253break;3254case NES_AEQE_AEID_LLP_RECEIVED_MARKER_AND_LENGTH_FIELDS_DONT_MATCH:3255flush_code = IB_WC_LOC_LEN_ERR;3256termhdr->layer_etype = (LAYER_MPA << 4) | DDP_LLP;3257termhdr->error_code = MPA_MARKER;3258break;3259case NES_AEQE_AEID_LLP_RECEIVED_MPA_CRC_ERROR:3260flush_code = IB_WC_GENERAL_ERR;3261termhdr->layer_etype = (LAYER_MPA << 4) | DDP_LLP;3262termhdr->error_code = MPA_CRC;3263break;3264case NES_AEQE_AEID_LLP_SEGMENT_TOO_LARGE:3265case NES_AEQE_AEID_LLP_SEGMENT_TOO_SMALL:3266flush_code = IB_WC_LOC_LEN_ERR;3267termhdr->layer_etype = (LAYER_DDP << 4) | DDP_CATASTROPHIC;3268termhdr->error_code = DDP_CATASTROPHIC_LOCAL;3269break;3270case NES_AEQE_AEID_DDP_LCE_LOCAL_CATASTROPHIC:3271case NES_AEQE_AEID_DDP_NO_L_BIT:3272flush_code = IB_WC_FATAL_ERR;3273termhdr->layer_etype = (LAYER_DDP << 4) | DDP_CATASTROPHIC;3274termhdr->error_code = DDP_CATASTROPHIC_LOCAL;3275break;3276case NES_AEQE_AEID_DDP_INVALID_MSN_GAP_IN_MSN:3277case NES_AEQE_AEID_DDP_INVALID_MSN_RANGE_IS_NOT_VALID:3278flush_code = IB_WC_GENERAL_ERR;3279termhdr->layer_etype = (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER;3280termhdr->error_code = DDP_UNTAGGED_INV_MSN_RANGE;3281break;3282case NES_AEQE_AEID_DDP_UBE_DDP_MESSAGE_TOO_LONG_FOR_AVAILABLE_BUFFER:3283flush_code = IB_WC_LOC_LEN_ERR;3284termhdr->layer_etype = (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER;3285termhdr->error_code = DDP_UNTAGGED_INV_TOO_LONG;3286break;3287case NES_AEQE_AEID_DDP_UBE_INVALID_DDP_VERSION:3288flush_code = IB_WC_GENERAL_ERR;3289if (is_tagged) {3290termhdr->layer_etype = (LAYER_DDP << 4) | DDP_TAGGED_BUFFER;3291termhdr->error_code = DDP_TAGGED_INV_DDP_VER;3292} else {3293termhdr->layer_etype = (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER;3294termhdr->error_code = DDP_UNTAGGED_INV_DDP_VER;3295}3296break;3297case NES_AEQE_AEID_DDP_UBE_INVALID_MO:3298flush_code = IB_WC_GENERAL_ERR;3299termhdr->layer_etype = (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER;3300termhdr->error_code = DDP_UNTAGGED_INV_MO;3301break;3302case NES_AEQE_AEID_DDP_UBE_INVALID_MSN_NO_BUFFER_AVAILABLE:3303flush_code = IB_WC_REM_OP_ERR;3304termhdr->layer_etype = (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER;3305termhdr->error_code = DDP_UNTAGGED_INV_MSN_NO_BUF;3306break;3307case NES_AEQE_AEID_DDP_UBE_INVALID_QN:3308flush_code = IB_WC_GENERAL_ERR;3309termhdr->layer_etype = (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER;3310termhdr->error_code = DDP_UNTAGGED_INV_QN;3311break;3312case NES_AEQE_AEID_RDMAP_ROE_INVALID_RDMAP_VERSION:3313flush_code = IB_WC_GENERAL_ERR;3314termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_OP;3315termhdr->error_code = RDMAP_INV_RDMAP_VER;3316break;3317case NES_AEQE_AEID_RDMAP_ROE_UNEXPECTED_OPCODE:3318flush_code = IB_WC_LOC_QP_OP_ERR;3319termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_OP;3320termhdr->error_code = RDMAP_UNEXPECTED_OP;3321break;3322default:3323flush_code = IB_WC_FATAL_ERR;3324termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_OP;3325termhdr->error_code = RDMAP_UNSPECIFIED;3326break;3327}33283329if (copy_len)3330memcpy(termhdr + 1, pkt, copy_len);33313332if ((flush_code) && ((NES_AEQE_INBOUND_RDMA & aeq_info) == 0)) {3333if (aeq_info & NES_AEQE_SQ)3334nesqp->term_sq_flush_code = flush_code;3335else3336nesqp->term_rq_flush_code = flush_code;3337}33383339return sizeof(struct nes_terminate_hdr) + copy_len;3340}33413342static void nes_terminate_connection(struct nes_device *nesdev, struct nes_qp *nesqp,3343struct nes_hw_aeqe *aeqe, enum ib_event_type eventtype)3344{3345u64 context;3346unsigned long flags;3347u32 aeq_info;3348u16 async_event_id;3349u8 tcp_state;3350u8 iwarp_state;3351u32 termlen = 0;3352u32 mod_qp_flags = NES_CQP_QP_IWARP_STATE_TERMINATE |3353NES_CQP_QP_TERM_DONT_SEND_FIN;3354struct nes_adapter *nesadapter = nesdev->nesadapter;33553356if (nesqp->term_flags & NES_TERM_SENT)3357return; /* Sanity check */33583359aeq_info = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]);3360tcp_state = (aeq_info & NES_AEQE_TCP_STATE_MASK) >> NES_AEQE_TCP_STATE_SHIFT;3361iwarp_state = (aeq_info & NES_AEQE_IWARP_STATE_MASK) >> NES_AEQE_IWARP_STATE_SHIFT;3362async_event_id = (u16)aeq_info;33633364context = (unsigned long)nesadapter->qp_table[le32_to_cpu(3365aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]) - NES_FIRST_QPN];3366if (!context) {3367WARN_ON(!context);3368return;3369}33703371nesqp = (struct nes_qp *)(unsigned long)context;3372spin_lock_irqsave(&nesqp->lock, flags);3373nesqp->hw_iwarp_state = iwarp_state;3374nesqp->hw_tcp_state = tcp_state;3375nesqp->last_aeq = async_event_id;3376nesqp->terminate_eventtype = eventtype;3377spin_unlock_irqrestore(&nesqp->lock, flags);33783379if (nesadapter->send_term_ok)3380termlen = nes_bld_terminate_hdr(nesqp, async_event_id, aeq_info);3381else3382mod_qp_flags |= NES_CQP_QP_TERM_DONT_SEND_TERM_MSG;33833384if (!nesdev->iw_status) {3385nesqp->term_flags = NES_TERM_DONE;3386nes_hw_modify_qp(nesdev, nesqp, NES_CQP_QP_IWARP_STATE_ERROR, 0, 0);3387nes_cm_disconn(nesqp);3388} else {3389nes_terminate_start_timer(nesqp);3390nesqp->term_flags |= NES_TERM_SENT;3391nes_hw_modify_qp(nesdev, nesqp, mod_qp_flags, termlen, 0);3392}3393}33943395static void nes_terminate_send_fin(struct nes_device *nesdev,3396struct nes_qp *nesqp, struct nes_hw_aeqe *aeqe)3397{3398u32 aeq_info;3399u16 async_event_id;3400u8 tcp_state;3401u8 iwarp_state;3402unsigned long flags;34033404aeq_info = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]);3405tcp_state = (aeq_info & NES_AEQE_TCP_STATE_MASK) >> NES_AEQE_TCP_STATE_SHIFT;3406iwarp_state = (aeq_info & NES_AEQE_IWARP_STATE_MASK) >> NES_AEQE_IWARP_STATE_SHIFT;3407async_event_id = (u16)aeq_info;34083409spin_lock_irqsave(&nesqp->lock, flags);3410nesqp->hw_iwarp_state = iwarp_state;3411nesqp->hw_tcp_state = tcp_state;3412nesqp->last_aeq = async_event_id;3413spin_unlock_irqrestore(&nesqp->lock, flags);34143415/* Send the fin only */3416nes_hw_modify_qp(nesdev, nesqp, NES_CQP_QP_IWARP_STATE_TERMINATE |3417NES_CQP_QP_TERM_DONT_SEND_TERM_MSG, 0, 0);3418}34193420/* Cleanup after a terminate sent or received */3421static void nes_terminate_done(struct nes_qp *nesqp, int timeout_occurred)3422{3423u32 next_iwarp_state = NES_CQP_QP_IWARP_STATE_ERROR;3424unsigned long flags;3425struct nes_vnic *nesvnic = to_nesvnic(nesqp->ibqp.device);3426struct nes_device *nesdev = nesvnic->nesdev;3427u8 first_time = 0;34283429spin_lock_irqsave(&nesqp->lock, flags);3430if (nesqp->hte_added) {3431nesqp->hte_added = 0;3432next_iwarp_state |= NES_CQP_QP_DEL_HTE;3433}34343435first_time = (nesqp->term_flags & NES_TERM_DONE) == 0;3436nesqp->term_flags |= NES_TERM_DONE;3437spin_unlock_irqrestore(&nesqp->lock, flags);34383439/* Make sure we go through this only once */3440if (first_time) {3441if (timeout_occurred == 0)3442del_timer(&nesqp->terminate_timer);3443else3444next_iwarp_state |= NES_CQP_QP_RESET;34453446nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0, 0);3447nes_cm_disconn(nesqp);3448}3449}34503451static void nes_terminate_received(struct nes_device *nesdev,3452struct nes_qp *nesqp, struct nes_hw_aeqe *aeqe)3453{3454u32 aeq_info;3455u8 *pkt;3456u32 *mpa;3457u8 ddp_ctl;3458u8 rdma_ctl;3459u16 aeq_id = 0;34603461aeq_info = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]);3462if (aeq_info & NES_AEQE_Q2_DATA_WRITTEN) {3463/* Terminate is not a performance path so the silicon */3464/* did not validate the frame - do it now */3465pkt = nesqp->hwqp.q2_vbase + BAD_FRAME_OFFSET;3466mpa = (u32 *)locate_mpa(pkt, aeq_info);3467ddp_ctl = (be32_to_cpu(mpa[0]) >> 8) & 0xff;3468rdma_ctl = be32_to_cpu(mpa[0]) & 0xff;3469if ((ddp_ctl & 0xc0) != 0x40)3470aeq_id = NES_AEQE_AEID_DDP_LCE_LOCAL_CATASTROPHIC;3471else if ((ddp_ctl & 0x03) != 1)3472aeq_id = NES_AEQE_AEID_DDP_UBE_INVALID_DDP_VERSION;3473else if (be32_to_cpu(mpa[2]) != 2)3474aeq_id = NES_AEQE_AEID_DDP_UBE_INVALID_QN;3475else if (be32_to_cpu(mpa[3]) != 1)3476aeq_id = NES_AEQE_AEID_DDP_INVALID_MSN_GAP_IN_MSN;3477else if (be32_to_cpu(mpa[4]) != 0)3478aeq_id = NES_AEQE_AEID_DDP_UBE_INVALID_MO;3479else if ((rdma_ctl & 0xc0) != 0x40)3480aeq_id = NES_AEQE_AEID_RDMAP_ROE_INVALID_RDMAP_VERSION;34813482if (aeq_id) {3483/* Bad terminate recvd - send back a terminate */3484aeq_info = (aeq_info & 0xffff0000) | aeq_id;3485aeqe->aeqe_words[NES_AEQE_MISC_IDX] = cpu_to_le32(aeq_info);3486nes_terminate_connection(nesdev, nesqp, aeqe, IB_EVENT_QP_FATAL);3487return;3488}3489}34903491nesqp->term_flags |= NES_TERM_RCVD;3492nesqp->terminate_eventtype = IB_EVENT_QP_FATAL;3493nes_terminate_start_timer(nesqp);3494nes_terminate_send_fin(nesdev, nesqp, aeqe);3495}34963497/* Timeout routine in case terminate fails to complete */3498static void nes_terminate_timeout(unsigned long context)3499{3500struct nes_qp *nesqp = (struct nes_qp *)(unsigned long)context;35013502nes_terminate_done(nesqp, 1);3503}35043505/* Set a timer in case hw cannot complete the terminate sequence */3506static void nes_terminate_start_timer(struct nes_qp *nesqp)3507{3508init_timer(&nesqp->terminate_timer);3509nesqp->terminate_timer.function = nes_terminate_timeout;3510nesqp->terminate_timer.expires = jiffies + HZ;3511nesqp->terminate_timer.data = (unsigned long)nesqp;3512add_timer(&nesqp->terminate_timer);3513}35143515/**3516* nes_process_iwarp_aeqe3517*/3518static void nes_process_iwarp_aeqe(struct nes_device *nesdev,3519struct nes_hw_aeqe *aeqe)3520{3521u64 context;3522unsigned long flags;3523struct nes_qp *nesqp;3524struct nes_hw_cq *hw_cq;3525struct nes_cq *nescq;3526int resource_allocated;3527struct nes_adapter *nesadapter = nesdev->nesadapter;3528u32 aeq_info;3529u32 next_iwarp_state = 0;3530u32 aeqe_cq_id;3531u16 async_event_id;3532u8 tcp_state;3533u8 iwarp_state;3534struct ib_event ibevent;35353536nes_debug(NES_DBG_AEQ, "\n");3537aeq_info = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]);3538if ((NES_AEQE_INBOUND_RDMA & aeq_info) || (!(NES_AEQE_QP & aeq_info))) {3539context = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX]);3540context += ((u64)le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX])) << 32;3541} else {3542context = (unsigned long)nesadapter->qp_table[le32_to_cpu(3543aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]) - NES_FIRST_QPN];3544BUG_ON(!context);3545}35463547/* context is nesqp unless async_event_id == CQ ERROR */3548nesqp = (struct nes_qp *)(unsigned long)context;3549async_event_id = (u16)aeq_info;3550tcp_state = (aeq_info & NES_AEQE_TCP_STATE_MASK) >> NES_AEQE_TCP_STATE_SHIFT;3551iwarp_state = (aeq_info & NES_AEQE_IWARP_STATE_MASK) >> NES_AEQE_IWARP_STATE_SHIFT;3552nes_debug(NES_DBG_AEQ, "aeid = 0x%04X, qp-cq id = %d, aeqe = %p,"3553" Tcp state = %s, iWARP state = %s\n",3554async_event_id,3555le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]), aeqe,3556nes_tcp_state_str[tcp_state], nes_iwarp_state_str[iwarp_state]);35573558aeqe_cq_id = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]);3559if (aeq_info & NES_AEQE_QP) {3560if ((!nes_is_resource_allocated(nesadapter, nesadapter->allocated_qps,3561aeqe_cq_id)) ||3562(atomic_read(&nesqp->close_timer_started)))3563return;3564}35653566switch (async_event_id) {3567case NES_AEQE_AEID_LLP_FIN_RECEIVED:3568if (nesqp->term_flags)3569return; /* Ignore it, wait for close complete */35703571if (atomic_inc_return(&nesqp->close_timer_started) == 1) {3572if ((tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) &&3573(nesqp->ibqp_state == IB_QPS_RTS) &&3574((nesadapter->eeprom_version >> 16) != NES_A0)) {3575spin_lock_irqsave(&nesqp->lock, flags);3576nesqp->hw_iwarp_state = iwarp_state;3577nesqp->hw_tcp_state = tcp_state;3578nesqp->last_aeq = async_event_id;3579next_iwarp_state = NES_CQP_QP_IWARP_STATE_CLOSING;3580nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_CLOSING;3581spin_unlock_irqrestore(&nesqp->lock, flags);3582nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0, 0);3583nes_cm_disconn(nesqp);3584}3585nesqp->cm_id->add_ref(nesqp->cm_id);3586schedule_nes_timer(nesqp->cm_node, (struct sk_buff *)nesqp,3587NES_TIMER_TYPE_CLOSE, 1, 0);3588nes_debug(NES_DBG_AEQ, "QP%u Not decrementing QP refcount (%d),"3589" need ae to finish up, original_last_aeq = 0x%04X."3590" last_aeq = 0x%04X, scheduling timer. TCP state = %d\n",3591nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),3592async_event_id, nesqp->last_aeq, tcp_state);3593}3594break;3595case NES_AEQE_AEID_LLP_CLOSE_COMPLETE:3596if (nesqp->term_flags) {3597nes_terminate_done(nesqp, 0);3598return;3599}3600spin_lock_irqsave(&nesqp->lock, flags);3601nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_CLOSING;3602spin_unlock_irqrestore(&nesqp->lock, flags);3603nes_hw_modify_qp(nesdev, nesqp, NES_CQP_QP_IWARP_STATE_CLOSING, 0, 0);3604nes_cm_disconn(nesqp);3605break;36063607case NES_AEQE_AEID_RESET_SENT:3608tcp_state = NES_AEQE_TCP_STATE_CLOSED;3609spin_lock_irqsave(&nesqp->lock, flags);3610nesqp->hw_iwarp_state = iwarp_state;3611nesqp->hw_tcp_state = tcp_state;3612nesqp->last_aeq = async_event_id;3613nesqp->hte_added = 0;3614spin_unlock_irqrestore(&nesqp->lock, flags);3615next_iwarp_state = NES_CQP_QP_IWARP_STATE_ERROR | NES_CQP_QP_DEL_HTE;3616nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0, 0);3617nes_cm_disconn(nesqp);3618break;36193620case NES_AEQE_AEID_LLP_CONNECTION_RESET:3621if (atomic_read(&nesqp->close_timer_started))3622return;3623spin_lock_irqsave(&nesqp->lock, flags);3624nesqp->hw_iwarp_state = iwarp_state;3625nesqp->hw_tcp_state = tcp_state;3626nesqp->last_aeq = async_event_id;3627spin_unlock_irqrestore(&nesqp->lock, flags);3628nes_cm_disconn(nesqp);3629break;36303631case NES_AEQE_AEID_TERMINATE_SENT:3632nes_terminate_send_fin(nesdev, nesqp, aeqe);3633break;36343635case NES_AEQE_AEID_LLP_TERMINATE_RECEIVED:3636nes_terminate_received(nesdev, nesqp, aeqe);3637break;36383639case NES_AEQE_AEID_AMP_BAD_STAG_KEY:3640case NES_AEQE_AEID_AMP_BAD_STAG_INDEX:3641case NES_AEQE_AEID_AMP_UNALLOCATED_STAG:3642case NES_AEQE_AEID_AMP_INVALID_STAG:3643case NES_AEQE_AEID_AMP_RIGHTS_VIOLATION:3644case NES_AEQE_AEID_AMP_INVALIDATE_NO_REMOTE_ACCESS_RIGHTS:3645case NES_AEQE_AEID_PRIV_OPERATION_DENIED:3646case NES_AEQE_AEID_DDP_UBE_DDP_MESSAGE_TOO_LONG_FOR_AVAILABLE_BUFFER:3647case NES_AEQE_AEID_AMP_BOUNDS_VIOLATION:3648case NES_AEQE_AEID_AMP_TO_WRAP:3649printk(KERN_ERR PFX "QP[%u] async_event_id=0x%04X IB_EVENT_QP_ACCESS_ERR\n",3650nesqp->hwqp.qp_id, async_event_id);3651nes_terminate_connection(nesdev, nesqp, aeqe, IB_EVENT_QP_ACCESS_ERR);3652break;36533654case NES_AEQE_AEID_LLP_SEGMENT_TOO_LARGE:3655case NES_AEQE_AEID_LLP_SEGMENT_TOO_SMALL:3656case NES_AEQE_AEID_DDP_UBE_INVALID_MO:3657case NES_AEQE_AEID_DDP_UBE_INVALID_QN:3658if (iwarp_opcode(nesqp, aeq_info) > IWARP_OPCODE_TERM) {3659aeq_info &= 0xffff0000;3660aeq_info |= NES_AEQE_AEID_RDMAP_ROE_UNEXPECTED_OPCODE;3661aeqe->aeqe_words[NES_AEQE_MISC_IDX] = cpu_to_le32(aeq_info);3662}36633664case NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE:3665case NES_AEQE_AEID_LLP_TOO_MANY_RETRIES:3666case NES_AEQE_AEID_DDP_UBE_INVALID_MSN_NO_BUFFER_AVAILABLE:3667case NES_AEQE_AEID_LLP_RECEIVED_MPA_CRC_ERROR:3668case NES_AEQE_AEID_AMP_BAD_QP:3669case NES_AEQE_AEID_LLP_RECEIVED_MARKER_AND_LENGTH_FIELDS_DONT_MATCH:3670case NES_AEQE_AEID_DDP_LCE_LOCAL_CATASTROPHIC:3671case NES_AEQE_AEID_DDP_NO_L_BIT:3672case NES_AEQE_AEID_DDP_INVALID_MSN_GAP_IN_MSN:3673case NES_AEQE_AEID_DDP_INVALID_MSN_RANGE_IS_NOT_VALID:3674case NES_AEQE_AEID_DDP_UBE_INVALID_DDP_VERSION:3675case NES_AEQE_AEID_RDMAP_ROE_INVALID_RDMAP_VERSION:3676case NES_AEQE_AEID_RDMAP_ROE_UNEXPECTED_OPCODE:3677case NES_AEQE_AEID_AMP_BAD_PD:3678case NES_AEQE_AEID_AMP_FASTREG_SHARED:3679case NES_AEQE_AEID_AMP_FASTREG_VALID_STAG:3680case NES_AEQE_AEID_AMP_FASTREG_MW_STAG:3681case NES_AEQE_AEID_AMP_FASTREG_INVALID_RIGHTS:3682case NES_AEQE_AEID_AMP_FASTREG_PBL_TABLE_OVERFLOW:3683case NES_AEQE_AEID_AMP_FASTREG_INVALID_LENGTH:3684case NES_AEQE_AEID_AMP_INVALIDATE_SHARED:3685case NES_AEQE_AEID_AMP_INVALIDATE_MR_WITH_BOUND_WINDOWS:3686case NES_AEQE_AEID_AMP_MWBIND_VALID_STAG:3687case NES_AEQE_AEID_AMP_MWBIND_OF_MR_STAG:3688case NES_AEQE_AEID_AMP_MWBIND_TO_ZERO_BASED_STAG:3689case NES_AEQE_AEID_AMP_MWBIND_TO_MW_STAG:3690case NES_AEQE_AEID_AMP_MWBIND_INVALID_RIGHTS:3691case NES_AEQE_AEID_AMP_MWBIND_INVALID_BOUNDS:3692case NES_AEQE_AEID_AMP_MWBIND_TO_INVALID_PARENT:3693case NES_AEQE_AEID_AMP_MWBIND_BIND_DISABLED:3694case NES_AEQE_AEID_BAD_CLOSE:3695case NES_AEQE_AEID_RDMA_READ_WHILE_ORD_ZERO:3696case NES_AEQE_AEID_STAG_ZERO_INVALID:3697case NES_AEQE_AEID_ROE_INVALID_RDMA_READ_REQUEST:3698case NES_AEQE_AEID_ROE_INVALID_RDMA_WRITE_OR_READ_RESP:3699printk(KERN_ERR PFX "QP[%u] async_event_id=0x%04X IB_EVENT_QP_FATAL\n",3700nesqp->hwqp.qp_id, async_event_id);3701nes_terminate_connection(nesdev, nesqp, aeqe, IB_EVENT_QP_FATAL);3702break;37033704case NES_AEQE_AEID_CQ_OPERATION_ERROR:3705context <<= 1;3706nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_CQ_OPERATION_ERROR event on CQ%u, %p\n",3707le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]), (void *)(unsigned long)context);3708resource_allocated = nes_is_resource_allocated(nesadapter, nesadapter->allocated_cqs,3709le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]));3710if (resource_allocated) {3711printk(KERN_ERR PFX "%s: Processing an NES_AEQE_AEID_CQ_OPERATION_ERROR event on CQ%u\n",3712__func__, le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]));3713hw_cq = (struct nes_hw_cq *)(unsigned long)context;3714if (hw_cq) {3715nescq = container_of(hw_cq, struct nes_cq, hw_cq);3716if (nescq->ibcq.event_handler) {3717ibevent.device = nescq->ibcq.device;3718ibevent.event = IB_EVENT_CQ_ERR;3719ibevent.element.cq = &nescq->ibcq;3720nescq->ibcq.event_handler(&ibevent, nescq->ibcq.cq_context);3721}3722}3723}3724break;37253726default:3727nes_debug(NES_DBG_AEQ, "Processing an iWARP related AE for QP, misc = 0x%04X\n",3728async_event_id);3729break;3730}37313732}37333734/**3735* nes_iwarp_ce_handler3736*/3737void nes_iwarp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *hw_cq)3738{3739struct nes_cq *nescq = container_of(hw_cq, struct nes_cq, hw_cq);37403741/* nes_debug(NES_DBG_CQ, "Processing completion event for iWARP CQ%u.\n",3742nescq->hw_cq.cq_number); */3743nes_write32(nesdev->regs+NES_CQ_ACK, nescq->hw_cq.cq_number);37443745if (nescq->ibcq.comp_handler)3746nescq->ibcq.comp_handler(&nescq->ibcq, nescq->ibcq.cq_context);37473748return;3749}375037513752/**3753* nes_manage_apbvt()3754*/3755int nes_manage_apbvt(struct nes_vnic *nesvnic, u32 accel_local_port,3756u32 nic_index, u32 add_port)3757{3758struct nes_device *nesdev = nesvnic->nesdev;3759struct nes_hw_cqp_wqe *cqp_wqe;3760struct nes_cqp_request *cqp_request;3761int ret = 0;3762u16 major_code;37633764/* Send manage APBVT request to CQP */3765cqp_request = nes_get_cqp_request(nesdev);3766if (cqp_request == NULL) {3767nes_debug(NES_DBG_QP, "Failed to get a cqp_request.\n");3768return -ENOMEM;3769}3770cqp_request->waiting = 1;3771cqp_wqe = &cqp_request->cqp_wqe;37723773nes_debug(NES_DBG_QP, "%s APBV for local port=%u(0x%04x), nic_index=%u\n",3774(add_port == NES_MANAGE_APBVT_ADD) ? "ADD" : "DEL",3775accel_local_port, accel_local_port, nic_index);37763777nes_fill_init_cqp_wqe(cqp_wqe, nesdev);3778set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, (NES_CQP_MANAGE_APBVT |3779((add_port == NES_MANAGE_APBVT_ADD) ? NES_CQP_APBVT_ADD : 0)));3780set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,3781((nic_index << NES_CQP_APBVT_NIC_SHIFT) | accel_local_port));37823783nes_debug(NES_DBG_QP, "Waiting for CQP completion for APBVT.\n");37843785atomic_set(&cqp_request->refcount, 2);3786nes_post_cqp_request(nesdev, cqp_request);37873788if (add_port == NES_MANAGE_APBVT_ADD)3789ret = wait_event_timeout(cqp_request->waitq, (cqp_request->request_done != 0),3790NES_EVENT_TIMEOUT);3791nes_debug(NES_DBG_QP, "Completed, ret=%u, CQP Major:Minor codes = 0x%04X:0x%04X\n",3792ret, cqp_request->major_code, cqp_request->minor_code);3793major_code = cqp_request->major_code;37943795nes_put_cqp_request(nesdev, cqp_request);37963797if (!ret)3798return -ETIME;3799else if (major_code)3800return -EIO;3801else3802return 0;3803}380438053806/**3807* nes_manage_arp_cache3808*/3809void nes_manage_arp_cache(struct net_device *netdev, unsigned char *mac_addr,3810u32 ip_addr, u32 action)3811{3812struct nes_hw_cqp_wqe *cqp_wqe;3813struct nes_vnic *nesvnic = netdev_priv(netdev);3814struct nes_device *nesdev;3815struct nes_cqp_request *cqp_request;3816int arp_index;38173818nesdev = nesvnic->nesdev;3819arp_index = nes_arp_table(nesdev, ip_addr, mac_addr, action);3820if (arp_index == -1) {3821return;3822}38233824/* update the ARP entry */3825cqp_request = nes_get_cqp_request(nesdev);3826if (cqp_request == NULL) {3827nes_debug(NES_DBG_NETDEV, "Failed to get a cqp_request.\n");3828return;3829}3830cqp_request->waiting = 0;3831cqp_wqe = &cqp_request->cqp_wqe;3832nes_fill_init_cqp_wqe(cqp_wqe, nesdev);38333834cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(3835NES_CQP_MANAGE_ARP_CACHE | NES_CQP_ARP_PERM);3836cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= cpu_to_le32(3837(u32)PCI_FUNC(nesdev->pcidev->devfn) << NES_CQP_ARP_AEQ_INDEX_SHIFT);3838cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(arp_index);38393840if (action == NES_ARP_ADD) {3841cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= cpu_to_le32(NES_CQP_ARP_VALID);3842cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_ADDR_LOW_IDX] = cpu_to_le32(3843(((u32)mac_addr[2]) << 24) | (((u32)mac_addr[3]) << 16) |3844(((u32)mac_addr[4]) << 8) | (u32)mac_addr[5]);3845cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_HIGH_IDX] = cpu_to_le32(3846(((u32)mac_addr[0]) << 16) | (u32)mac_addr[1]);3847} else {3848cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_ADDR_LOW_IDX] = 0;3849cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_HIGH_IDX] = 0;3850}38513852nes_debug(NES_DBG_NETDEV, "Not waiting for CQP, cqp.sq_head=%u, cqp.sq_tail=%u\n",3853nesdev->cqp.sq_head, nesdev->cqp.sq_tail);38543855atomic_set(&cqp_request->refcount, 1);3856nes_post_cqp_request(nesdev, cqp_request);3857}385838593860/**3861* flush_wqes3862*/3863void flush_wqes(struct nes_device *nesdev, struct nes_qp *nesqp,3864u32 which_wq, u32 wait_completion)3865{3866struct nes_cqp_request *cqp_request;3867struct nes_hw_cqp_wqe *cqp_wqe;3868u32 sq_code = (NES_IWARP_CQE_MAJOR_FLUSH << 16) | NES_IWARP_CQE_MINOR_FLUSH;3869u32 rq_code = (NES_IWARP_CQE_MAJOR_FLUSH << 16) | NES_IWARP_CQE_MINOR_FLUSH;3870int ret;38713872cqp_request = nes_get_cqp_request(nesdev);3873if (cqp_request == NULL) {3874nes_debug(NES_DBG_QP, "Failed to get a cqp_request.\n");3875return;3876}3877if (wait_completion) {3878cqp_request->waiting = 1;3879atomic_set(&cqp_request->refcount, 2);3880} else {3881cqp_request->waiting = 0;3882}3883cqp_wqe = &cqp_request->cqp_wqe;3884nes_fill_init_cqp_wqe(cqp_wqe, nesdev);38853886/* If wqe in error was identified, set code to be put into cqe */3887if ((nesqp->term_sq_flush_code) && (which_wq & NES_CQP_FLUSH_SQ)) {3888which_wq |= NES_CQP_FLUSH_MAJ_MIN;3889sq_code = (CQE_MAJOR_DRV << 16) | nesqp->term_sq_flush_code;3890nesqp->term_sq_flush_code = 0;3891}38923893if ((nesqp->term_rq_flush_code) && (which_wq & NES_CQP_FLUSH_RQ)) {3894which_wq |= NES_CQP_FLUSH_MAJ_MIN;3895rq_code = (CQE_MAJOR_DRV << 16) | nesqp->term_rq_flush_code;3896nesqp->term_rq_flush_code = 0;3897}38983899if (which_wq & NES_CQP_FLUSH_MAJ_MIN) {3900cqp_wqe->wqe_words[NES_CQP_QP_WQE_FLUSH_SQ_CODE] = cpu_to_le32(sq_code);3901cqp_wqe->wqe_words[NES_CQP_QP_WQE_FLUSH_RQ_CODE] = cpu_to_le32(rq_code);3902}39033904cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] =3905cpu_to_le32(NES_CQP_FLUSH_WQES | which_wq);3906cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(nesqp->hwqp.qp_id);39073908nes_post_cqp_request(nesdev, cqp_request);39093910if (wait_completion) {3911/* Wait for CQP */3912ret = wait_event_timeout(cqp_request->waitq, (cqp_request->request_done != 0),3913NES_EVENT_TIMEOUT);3914nes_debug(NES_DBG_QP, "Flush SQ QP WQEs completed, ret=%u,"3915" CQP Major:Minor codes = 0x%04X:0x%04X\n",3916ret, cqp_request->major_code, cqp_request->minor_code);3917nes_put_cqp_request(nesdev, cqp_request);3918}3919}392039213922