From: Doug Ledford <dledford@redhat.com> Date: Mon, 24 Mar 2008 14:24:24 -0400 Subject: [openib] update the nes driver from 0.4 to 1.0 Message-id: 1206383072-7299-4-git-send-email-dledford@redhat.com O-Subject: [Patch RHEL5 03/10] Infiniband: Update the nes driver from 0.4 to 1.0 Bugzilla: 253023 The 1.0 nes driver was the final version that shipped in OFED 1.3. This updates to that revision, and also includes a single backport in include/linux/kernel.h that the driver needs. Signed-off-by: Doug Ledford <dledford@redhat.com> diff --git a/drivers/infiniband/hw/nes/Kconfig b/drivers/infiniband/hw/nes/Kconfig index d5f2a12..2aeb7ac 100644 --- a/drivers/infiniband/hw/nes/Kconfig +++ b/drivers/infiniband/hw/nes/Kconfig @@ -1,6 +1,7 @@ config INFINIBAND_NES tristate "NetEffect RNIC Driver" depends on PCI && INET && INFINIBAND + select LIBCRC32C ---help--- This is a low-level driver for NetEffect RDMA enabled Network Interface Cards (RNIC). diff --git a/drivers/infiniband/hw/nes/Makefile b/drivers/infiniband/hw/nes/Makefile index f68de45..3514851 100644 --- a/drivers/infiniband/hw/nes/Makefile +++ b/drivers/infiniband/hw/nes/Makefile @@ -1,10 +1,3 @@ -ifdef CONFIG_INFINIBAND_NES_DEBUG -EXTRA_CFLAGS += -DNES_DEBUG -endif - -EXTRA_CFLAGS += -DNES_MINICM - obj-$(CONFIG_INFINIBAND_NES) += iw_nes.o iw_nes-objs := nes.o nes_hw.o nes_nic.o nes_utils.o nes_verbs.o nes_cm.o - diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c index 88a71cf..cbd1347 100644 --- a/drivers/infiniband/hw/nes/nes.c +++ b/drivers/infiniband/hw/nes/nes.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2007 NetEffect, Inc. All rights reserved. + * Copyright (c) 2006 - 2008 NetEffect, Inc. All rights reserved. * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. * * This software is available to you under a choice of one of two @@ -43,6 +43,7 @@ #include <linux/fs.h> #include <linux/init.h> #include <linux/if_arp.h> +#include <linux/highmem.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/byteorder.h> @@ -58,26 +59,15 @@ #include <linux/route.h> #include <net/ip_fib.h> -#ifdef SPIN_BUG_ON -#undef SPIN_BUG_ON -#define SPIN_BUG_ON (...) -#endif - MODULE_AUTHOR("NetEffect"); MODULE_DESCRIPTION("NetEffect RNIC Low-level iWARP Driver"); MODULE_LICENSE("Dual BSD/GPL"); MODULE_VERSION(DRV_VERSION); -atomic_t qps_destroyed; - int max_mtu = 9000; int nics_per_function = 1; - -#ifdef NES_INT_MODERATE -int interrupt_mod_interval = 128; -#else int interrupt_mod_interval = 0; -#endif + /* Interoperability */ int mpa_version = 1; @@ -99,18 +89,29 @@ module_param(nes_drv_opt, int, 0); MODULE_PARM_DESC(nes_drv_opt, "Driver option parameters"); unsigned int nes_debug_level = 0; -module_param(nes_debug_level, uint, 0644); -MODULE_PARM_DESC(nes_debug_level, "Enable debug output level"); +module_param_named(debug_level, nes_debug_level, uint, 0644); +MODULE_PARM_DESC(debug_level, "Enable debug output level"); LIST_HEAD(nes_adapter_list); LIST_HEAD(nes_dev_list); +atomic_t qps_destroyed; +atomic_t cqp_reqs_allocated; +atomic_t cqp_reqs_freed; +atomic_t cqp_reqs_dynallocated; +atomic_t cqp_reqs_dynfreed; +atomic_t cqp_reqs_queued; +atomic_t cqp_reqs_redriven; + static void nes_print_macaddr(struct net_device *netdev); static irqreturn_t nes_interrupt(int, void *); static int __devinit nes_probe(struct pci_dev *, const struct pci_device_id *); static void __devexit nes_remove(struct pci_dev *); static int __init nes_init_module(void); static void __exit nes_exit_module(void); +static unsigned int ee_flsh_adapter; +static unsigned int sysfs_nonidx_addr; +static unsigned int sysfs_idx_addr; static struct pci_device_id nes_pci_table[] = { {PCI_VENDOR_ID_NETEFFECT, PCI_DEVICE_ID_NETEFFECT_NE020, PCI_ANY_ID, PCI_ANY_ID}, @@ -119,9 +120,9 @@ static struct pci_device_id nes_pci_table[] = { MODULE_DEVICE_TABLE(pci, nes_pci_table); -static int nes_inetaddr_event(struct notifier_block *notifier, unsigned long event, void *ptr); -static int nes_net_event(struct notifier_block *notifier, unsigned long event, void *ptr); -static int notifiers_registered = 0; +static int nes_inetaddr_event(struct notifier_block *, unsigned long, void *); +static int nes_net_event(struct notifier_block *, unsigned long, void *); +static int nes_notifiers_registered; static struct notifier_block nes_inetaddr_notifier = { @@ -149,41 +150,40 @@ static int nes_inetaddr_event(struct notifier_block *notifier, unsigned int addr; unsigned int mask; - dprintk("nes_inetaddr_event: notifier %p event=%ld netdev=%p," - " interface name = %s.\n", - notifier, event, event_netdev, event_netdev->name); - addr = ntohl(ifa->ifa_address); mask = ntohl(ifa->ifa_mask); - dprintk("nes_inetaddr_event: ip address %08X, netmask %08X.\n", addr, mask); + nes_debug(NES_DBG_NETDEV, "nes_inetaddr_event: ip address %08X, netmask %08X.\n", + addr, mask); list_for_each_entry(nesdev, &nes_dev_list, list) { - dprintk("Nesdev list entry = 0x%p. (%s) \n", nesdev, nesdev->netdev[0]->name); + nes_debug(NES_DBG_NETDEV, "Nesdev list entry = 0x%p. (%s)\n", + nesdev, nesdev->netdev[0]->name); netdev = nesdev->netdev[0]; nesvnic = netdev_priv(netdev); if (netdev == event_netdev) { - if (0 == nesvnic->rdma_enabled) { - dprintk("%s: Returning without processing event for %s since" - " RDMA is not enabled. \n", - __FUNCTION__, netdev->name); - return(NOTIFY_OK); + if (nesvnic->rdma_enabled == 0) { + nes_debug(NES_DBG_NETDEV, "Returning without processing event for %s since" + " RDMA is not enabled.\n", + netdev->name); + return NOTIFY_OK; } /* we have ifa->ifa_address/mask here if we need it */ switch (event) { case NETDEV_DOWN: - dprintk("event:DOWN \n"); + nes_debug(NES_DBG_NETDEV, "event:DOWN\n"); nes_write_indexed(nesdev, NES_IDX_DST_IP_ADDR+(0x10*PCI_FUNC(nesdev->pcidev->devfn)), 0); + nes_manage_arp_cache(netdev, netdev->dev_addr, + ntohl(nesvnic->local_ipaddr), NES_ARP_DELETE); nesvnic->local_ipaddr = 0; - return(NOTIFY_OK); + return NOTIFY_OK; break; case NETDEV_UP: - dprintk("event:UP \n"); + nes_debug(NES_DBG_NETDEV, "event:UP\n"); if (nesvnic->local_ipaddr != 0) { - dprintk("%s[%u] Interface already has local_ipaddr\n", - __FUNCTION__, __LINE__); - return(NOTIFY_OK); + nes_debug(NES_DBG_NETDEV, "Interface already has local_ipaddr\n"); + return NOTIFY_OK; } /* Add the address to the IP table */ nesvnic->local_ipaddr = ifa->ifa_address; @@ -191,7 +191,9 @@ static int nes_inetaddr_event(struct notifier_block *notifier, nes_write_indexed(nesdev, NES_IDX_DST_IP_ADDR+(0x10*PCI_FUNC(nesdev->pcidev->devfn)), ntohl(ifa->ifa_address)); - return(NOTIFY_OK); + nes_manage_arp_cache(netdev, netdev->dev_addr, + ntohl(nesvnic->local_ipaddr), NES_ARP_ADD); + return NOTIFY_OK; break; default: break; @@ -199,7 +201,7 @@ static int nes_inetaddr_event(struct notifier_block *notifier, } } - return(NOTIFY_DONE); + return NOTIFY_DONE; } @@ -216,44 +218,33 @@ static int nes_net_event(struct notifier_block *notifier, switch (event) { case NETEVENT_NEIGH_UPDATE: - /* dprintk("NETEVENT_NEIGH_UPDATE:\n"); */ list_for_each_entry(nesdev, &nes_dev_list, list) { - /* dprintk("Nesdev list entry = 0x%p.\n", nesdev); */ + /* nes_debug(NES_DBG_NETDEV, "Nesdev list entry = 0x%p.\n", nesdev); */ netdev = nesdev->netdev[0]; nesvnic = netdev_priv(netdev); if (netdev == neigh->dev) { - if (0 == nesvnic->rdma_enabled) { - dprintk("Skipping device %s since no RDMA\n", netdev->name); + if (nesvnic->rdma_enabled == 0) { + nes_debug(NES_DBG_NETDEV, "Skipping device %s since no RDMA\n", + netdev->name); } else { - /* dprintk("Neighbour is considered: "); */ if (neigh->nud_state & NUD_VALID) { - /* dprintk("VALID\n"); */ nes_manage_arp_cache(neigh->dev, neigh->ha, - ntohl(*(u32 *)neigh->primary_key), NES_ARP_ADD); + ntohl(*(__be32 *)neigh->primary_key), NES_ARP_ADD); } else { - /* dprintk("INVALID\n"); */ nes_manage_arp_cache(neigh->dev, neigh->ha, - ntohl(*(u32 *)neigh->primary_key), NES_ARP_DELETE); + ntohl(*(__be32 *)neigh->primary_key), NES_ARP_DELETE); } } - return(NOTIFY_OK); + return NOTIFY_OK; } } break; - - case NETEVENT_PMTU_UPDATE: - dprintk("NETEVENT_PMTU_UPDATE:\n"); - break; - case NETEVENT_REDIRECT: - dprintk("NETEVENT_REDIRECT:\n"); - break; - default: - dprintk("NETEVENT_ %lu undefined\n", event); + nes_debug(NES_DBG_NETDEV, "NETEVENT_ %lu undefined\n", event); break; } - return(NOTIFY_DONE); + return NOTIFY_DONE; } @@ -265,11 +256,41 @@ void nes_add_ref(struct ib_qp *ibqp) struct nes_qp *nesqp; nesqp = to_nesqp(ibqp); - dprintk("%s: Bumping refcount for QP%u. Pre-inc value = %u\n", - __FUNCTION__, ibqp->qp_num, atomic_read(&nesqp->refcount)); + nes_debug(NES_DBG_QP, "Bumping refcount for QP%u. Pre-inc value = %u\n", + ibqp->qp_num, atomic_read(&nesqp->refcount)); atomic_inc(&nesqp->refcount); } +static void nes_cqp_rem_ref_callback(struct nes_device *nesdev, struct nes_cqp_request *cqp_request) +{ + unsigned long flags; + struct nes_qp *nesqp = cqp_request->cqp_callback_pointer; + struct nes_adapter *nesadapter = nesdev->nesadapter; + u32 qp_id; + + atomic_inc(&qps_destroyed); + + /* Free the control structures */ + + qp_id = nesqp->hwqp.qp_id; + if (nesqp->pbl_vbase) { + pci_free_consistent(nesdev->pcidev, nesqp->qp_mem_size, + nesqp->hwqp.q2_vbase, nesqp->hwqp.q2_pbase); + spin_lock_irqsave(&nesadapter->pbl_lock, flags); + nesadapter->free_256pbl++; + spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); + pci_free_consistent(nesdev->pcidev, 256, nesqp->pbl_vbase, nesqp->pbl_pbase); + nesqp->pbl_vbase = NULL; + + } else { + pci_free_consistent(nesdev->pcidev, nesqp->qp_mem_size, + nesqp->hwqp.sq_vbase, nesqp->hwqp.sq_pbase); + } + nes_free_resource(nesadapter, nesadapter->allocated_qps, nesqp->hwqp.qp_id); + + kfree(nesqp->allocated_buffer); + +} /** * nes_rem_ref @@ -283,67 +304,43 @@ void nes_rem_ref(struct ib_qp *ibqp) struct nes_adapter *nesadapter = nesdev->nesadapter; struct nes_hw_cqp_wqe *cqp_wqe; struct nes_cqp_request *cqp_request; - unsigned long flags; + u32 opcode; nesqp = to_nesqp(ibqp); - dprintk("%s: Decing refcount for QP%u. Pre-dec value = %u\n", - __FUNCTION__, ibqp->qp_num, atomic_read(&nesqp->refcount) ); if (atomic_read(&nesqp->refcount) == 0) { printk(KERN_INFO PFX "%s: Reference count already 0 for QP%d, last aeq = 0x%04X.\n", - __FUNCTION__, ibqp->qp_num, nesqp->last_aeq ); + __FUNCTION__, ibqp->qp_num, nesqp->last_aeq); BUG(); } if (atomic_dec_and_test(&nesqp->refcount)) { - dprintk("%s: Refcount for QP%u is 0. Freeing QP structure, nesadapter = %p\n", - __FUNCTION__, ibqp->qp_num, nesadapter); - atomic_inc(&qps_destroyed); - - /* Free the control structures */ - pci_free_consistent(nesdev->pcidev, nesqp->qp_mem_size, nesqp->hwqp.sq_vbase, - nesqp->hwqp.sq_pbase); - nesadapter->qp_table[nesqp->hwqp.qp_id-NES_FIRST_QPN] = NULL; - nes_free_resource(nesadapter, nesadapter->allocated_qps, nesqp->hwqp.qp_id); /* Destroy the QP */ - spin_lock_irqsave(&nesdev->cqp.lock, flags); - cqp_request = nes_get_cqp_request(nesdev, NES_CQP_REQUEST_HOLDING_LOCK); - if (NULL == cqp_request) { - dprintk("%s: Failed to get a cqp_request.\n", __FUNCTION__); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + cqp_request = nes_get_cqp_request(nesdev); + if (cqp_request == NULL) { + nes_debug(NES_DBG_QP, "Failed to get a cqp_request.\n"); return; } cqp_request->waiting = 0; + cqp_request->callback = 1; + cqp_request->cqp_callback = nes_cqp_rem_ref_callback; + cqp_request->cqp_callback_pointer = nesqp; cqp_wqe = &cqp_request->cqp_wqe; - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = - cpu_to_le32(NES_CQP_DESTROY_QP | NES_CQP_QP_TYPE_IWARP); + nes_fill_init_cqp_wqe(cqp_wqe, nesdev); + opcode = NES_CQP_DESTROY_QP | NES_CQP_QP_TYPE_IWARP; if (nesqp->hte_added) { - dprintk("%s:%u: set CQP_QP_DEL_HTE\n", __FUNCTION__, __LINE__); - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= cpu_to_le32(NES_CQP_QP_DEL_HTE); + opcode |= NES_CQP_QP_DEL_HTE; nesqp->hte_added = 0; } - - cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(nesqp->hwqp.qp_id); - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX] = 0; - *((struct nes_hw_cqp **)&cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_LOW_IDX]) = - &nesdev->cqp; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] = 0; + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, opcode); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX, nesqp->hwqp.qp_id); u64temp = (u64)nesqp->nesqp_context_pbase; - cqp_wqe->wqe_words[NES_CQP_QP_WQE_CONTEXT_LOW_IDX] = cpu_to_le32((u32)u64temp); - cqp_wqe->wqe_words[NES_CQP_QP_WQE_CONTEXT_HIGH_IDX] = - cpu_to_le32((u32)(u64temp >> 32)); - - nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_HOLDING_LOCK, - NES_CQP_REQUEST_RING_DOORBELL); - - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); - - kfree(nesqp->allocated_buffer); + set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, u64temp); + nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_RING_DOORBELL); } } @@ -351,15 +348,16 @@ void nes_rem_ref(struct ib_qp *ibqp) /** * nes_get_qp */ -struct ib_qp *nes_get_qp(struct ib_device *device, int qpn) { +struct ib_qp *nes_get_qp(struct ib_device *device, int qpn) +{ struct nes_vnic *nesvnic = to_nesvnic(device); struct nes_device *nesdev = nesvnic->nesdev; struct nes_adapter *nesadapter = nesdev->nesadapter; - if ((qpn<NES_FIRST_QPN) || (qpn>=(NES_FIRST_QPN+nesadapter->max_qp))) - return (NULL); + if ((qpn < NES_FIRST_QPN) || (qpn >= (NES_FIRST_QPN + nesadapter->max_qp))) + return NULL; - return(&nesadapter->qp_table[qpn-NES_FIRST_QPN]->ibqp); + return &nesadapter->qp_table[qpn - NES_FIRST_QPN]->ibqp; } @@ -368,8 +366,8 @@ struct ib_qp *nes_get_qp(struct ib_device *device, int qpn) { */ static void nes_print_macaddr(struct net_device *netdev) { - dprintk("%s: MAC %02X:%02X:%02X:%02X:%02X:%02X, " - "IRQ %u\n", netdev->name, + nes_debug(NES_DBG_INIT, "%s: MAC %02X:%02X:%02X:%02X:%02X:%02X, IRQ %u\n", + netdev->name, netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2], netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5], netdev->irq); @@ -383,77 +381,67 @@ static irqreturn_t nes_interrupt(int irq, void *dev_id) { struct nes_device *nesdev = (struct nes_device *)dev_id; int handled = 0; -#ifdef NES_LEGACY_INT_DETECT u32 int_mask; u32 int_req; u32 int_stat; u32 intf_int_stat; u32 timer_stat; -#endif if (nesdev->msi_enabled) { /* No need to read the interrupt pending register if msi is enabled */ handled = 1; } else { -#ifdef NES_LEGACY_INT_DETECT - /* Master interrupt enable provides synchronization for kicking off bottom half - when interrupt sharing is going on */ - int_mask = nes_read32(nesdev->regs + NES_INT_MASK); - if (int_mask & 0x80000000) { - /* Check interrupt status to see if this might be ours */ - int_stat = nes_read32(nesdev->regs + NES_INT_STAT); - int_req = nesdev->int_req; - if (int_stat&int_req) { - /* if interesting CEQ or AEQ is pending, claim the interrupt */ - if ((int_stat&int_req) & (~(NES_INT_TIMER|NES_INT_INTF))) { - /* dprintk("%s: Handling CEQ/AEQ/MAC Interrupt, int_req = 0x%08X\n", - __FUNCTION__, int_req); */ - handled = 1; - } else { - if (((int_stat & int_req) & NES_INT_TIMER) == NES_INT_TIMER) { - /* Timer might be running but might be for another function */ - timer_stat = nes_read32(nesdev->regs + NES_TIMER_STAT); - if ((timer_stat & nesdev->timer_int_req) != 0) { - /* dprintk("%s: Handling Timer Interrupt\n", __FUNCTION__); */ - handled = 1; + if (unlikely(nesdev->nesadapter->hw_rev == NE020_REV)) { + /* Master interrupt enable provides synchronization for kicking off bottom half + when interrupt sharing is going on */ + int_mask = nes_read32(nesdev->regs + NES_INT_MASK); + if (int_mask & 0x80000000) { + /* Check interrupt status to see if this might be ours */ + int_stat = nes_read32(nesdev->regs + NES_INT_STAT); + int_req = nesdev->int_req; + if (int_stat&int_req) { + /* if interesting CEQ or AEQ is pending, claim the interrupt */ + if ((int_stat&int_req) & (~(NES_INT_TIMER|NES_INT_INTF))) { + handled = 1; + } else { + if (((int_stat & int_req) & NES_INT_TIMER) == NES_INT_TIMER) { + /* Timer might be running but might be for another function */ + timer_stat = nes_read32(nesdev->regs + NES_TIMER_STAT); + if ((timer_stat & nesdev->timer_int_req) != 0) { + handled = 1; + } } - } - if ((((int_stat & int_req) & NES_INT_INTF) == NES_INT_INTF) && - (0 == handled)) { - intf_int_stat = nes_read32(nesdev->regs+NES_INTF_INT_STAT); - if ((intf_int_stat & nesdev->intf_int_req) != 0) { - /* dprintk("%s: Handling an Interface Interrupt\n", __FUNCTION__); */ - handled = 1; + if ((((int_stat & int_req) & NES_INT_INTF) == NES_INT_INTF) && + (handled == 0)) { + intf_int_stat = nes_read32(nesdev->regs+NES_INTF_INT_STAT); + if ((intf_int_stat & nesdev->intf_int_req) != 0) { + handled = 1; + } } } - } - if (handled) { - nes_write32(nesdev->regs+NES_INT_MASK, int_mask & (~0x80000000)); - int_mask = nes_read32(nesdev->regs+NES_INT_MASK); - /* Save off the status to save an additional read */ - nesdev->int_stat = int_stat; - nesdev->napi_isr_ran = 1; + if (handled) { + nes_write32(nesdev->regs+NES_INT_MASK, int_mask & (~0x80000000)); + int_mask = nes_read32(nesdev->regs+NES_INT_MASK); + /* Save off the status to save an additional read */ + nesdev->int_stat = int_stat; + nesdev->napi_isr_ran = 1; + } } } + } else { + handled = nes_read32(nesdev->regs+NES_INT_PENDING); } -#else - handled = nes_read32(nesdev->regs+NES_INT_PENDING); - /* dprintk("Interrupt Pending value = 0x%08X\n", handled ); */ -#endif } if (handled) { -#ifdef NES_NAPI - if (0 == nes_napi_isr(nesdev)) { -#endif + + if (nes_napi_isr(nesdev) == 0) { tasklet_schedule(&nesdev->dpc_tasklet); -#ifdef NES_NAPI + } -#endif - return(IRQ_HANDLED); + return IRQ_HANDLED; } else { - /* dprintk("%s[%u] Returning IRQ_NONE\n", __FUNCTION__, __LINE__); */ - return(IRQ_NONE); + return IRQ_NONE; } } @@ -482,16 +470,16 @@ static int __devinit nes_probe(struct pci_dev *pcidev, const struct pci_device_i goto bail0; } - dprintk("BAR0 (@0x%08lX) size = 0x%lX bytes\n", + nes_debug(NES_DBG_INIT, "BAR0 (@0x%08lX) size = 0x%lX bytes\n", (long unsigned int)pci_resource_start(pcidev, BAR_0), (long unsigned int)pci_resource_len(pcidev, BAR_0)); - dprintk("BAR1 (@0x%08lX) size = 0x%lX bytes\n", + nes_debug(NES_DBG_INIT, "BAR1 (@0x%08lX) size = 0x%lX bytes\n", (long unsigned int)pci_resource_start(pcidev, BAR_1), (long unsigned int)pci_resource_len(pcidev, BAR_1)); /* Make sure PCI base addr are MMIO */ if (!(pci_resource_flags(pcidev, BAR_0) & IORESOURCE_MEM) || - !(pci_resource_flags(pcidev, BAR_1) & IORESOURCE_MEM)) { + !(pci_resource_flags(pcidev, BAR_1) & IORESOURCE_MEM)) { printk(KERN_ERR PFX "PCI regions not an MMIO resource\n"); ret = -ENODEV; goto bail1; @@ -531,26 +519,25 @@ static int __devinit nes_probe(struct pci_dev *pcidev, const struct pci_device_i pci_set_master(pcidev); /* Allocate hardware structure */ - nesdev = kmalloc(sizeof(struct nes_device), GFP_KERNEL); + nesdev = kzalloc(sizeof(struct nes_device), GFP_KERNEL); if (!nesdev) { printk(KERN_ERR PFX "%s: Unable to alloc hardware struct\n", pci_name(pcidev)); ret = -ENOMEM; goto bail2; } - memset(nesdev, 0, sizeof(struct nes_device)); - dprintk("%s: Allocated nes device at %p\n", __FUNCTION__, nesdev); + nes_debug(NES_DBG_INIT, "Allocated nes device at %p\n", nesdev); nesdev->pcidev = pcidev; pci_set_drvdata(pcidev, nesdev); pci_read_config_byte(pcidev, 0x0008, &hw_rev); - dprintk("hw_rev=%u\n", hw_rev); + nes_debug(NES_DBG_INIT, "hw_rev=%u\n", hw_rev); spin_lock_init(&nesdev->indexed_regs_lock); /* Remap the PCI registers in adapter BAR0 to kernel VA space */ mmio_regs = ioremap_nocache(pci_resource_start(pcidev, BAR_0), sizeof(mmio_regs)); - if (mmio_regs == 0UL) { + if (mmio_regs == NULL) { printk(KERN_ERR PFX "Unable to remap BAR0\n"); ret = -EIO; goto bail3; @@ -561,38 +548,38 @@ static int __devinit nes_probe(struct pci_dev *pcidev, const struct pci_device_i /* Ensure interrupts are disabled */ nes_write32(nesdev->regs+NES_INT_MASK, 0x7fffffff); -#ifdef CONFIG_PCI_MSI if (nes_drv_opt & NES_DRV_OPT_ENABLE_MSI) { if (!pci_enable_msi(nesdev->pcidev)) { nesdev->msi_enabled = 1; - dprintk("%s: MSI is enabled for device %s\n", - __FUNCTION__, pci_name(pcidev)); + nes_debug(NES_DBG_INIT, "MSI is enabled for device %s\n", + pci_name(pcidev)); } else { - dprintk("%s: MSI is disabled by linux for device %s\n", - __FUNCTION__, pci_name(pcidev)); + nes_debug(NES_DBG_INIT, "MSI is disabled by linux for device %s\n", + pci_name(pcidev)); } } else { - dprintk("%s: MSI not requested due to driver options for device %s\n", - __FUNCTION__, pci_name(pcidev)); + nes_debug(NES_DBG_INIT, "MSI not requested due to driver options for device %s\n", + pci_name(pcidev)); } -#else - dprintk("%s: MSI not supported by this kernel for device %s\n", - __FUNCTION__, pci_name(pcidev)); -#endif - nesdev->et_rx_coalesce_usecs_irq = interrupt_mod_interval; nesdev->csr_start = pci_resource_start(nesdev->pcidev, BAR_0); - nesdev->doorbell_start = pci_resource_start(nesdev->pcidev, BAR_1); + nesdev->doorbell_region = pci_resource_start(nesdev->pcidev, BAR_1); /* Init the adapter */ nesdev->nesadapter = nes_init_adapter(nesdev, hw_rev); if (!nesdev->nesadapter) { - printk(KERN_ERR PFX "Unable to initialize adapter.\n" ); + printk(KERN_ERR PFX "Unable to initialize adapter.\n"); ret = -ENOMEM; goto bail5; } + nesdev->nesadapter->et_rx_coalesce_usecs_irq = interrupt_mod_interval; + + /* nesdev->base_doorbell_index = + nesdev->nesadapter->pd_config_base[PCI_FUNC(nesdev->pcidev->devfn)]; */ + nesdev->base_doorbell_index = 1; + nesdev->doorbell_start = nesdev->nesadapter->doorbell_start; + nesdev->mac_index = PCI_FUNC(nesdev->pcidev->devfn) % nesdev->nesadapter->port_count; - nesdev->mac_index = PCI_FUNC(nesdev->pcidev->devfn)%nesdev->nesadapter->port_count; tasklet_init(&nesdev->dpc_tasklet, nes_dpc, (unsigned long)nesdev); /* bring up the Control QP */ @@ -614,7 +601,7 @@ static int __devinit nes_probe(struct pci_dev *pcidev, const struct pci_device_i } /* TODO: This really should be the first driver to load, not function 0 */ - if (0 == PCI_FUNC(nesdev->pcidev->devfn)) { + if (PCI_FUNC(nesdev->pcidev->devfn) == 0) { /* pick up PCI and critical errors if the first driver to load */ nesdev->intf_int_req = NES_INTF_INT_PCIERR | NES_INTF_INT_CRITERR; nesdev->int_req |= NES_INT_INTF; @@ -632,60 +619,54 @@ static int __devinit nes_probe(struct pci_dev *pcidev, const struct pci_device_i /* deal with both periodic and one_shot */ nesdev->timer_int_req = 0x101 << PCI_FUNC(nesdev->pcidev->devfn); nesdev->nesadapter->timer_int_req |= nesdev->timer_int_req; - dprintk("%s: setting int_req for function %u, nesdev = 0x%04X, adapter = 0x%04X\n", - __FUNCTION__, PCI_FUNC(nesdev->pcidev->devfn), + nes_debug(NES_DBG_INIT, "setting int_req for function %u, nesdev = 0x%04X, adapter = 0x%04X\n", + PCI_FUNC(nesdev->pcidev->devfn), nesdev->timer_int_req, nesdev->nesadapter->timer_int_req); nes_write32(nesdev->regs+NES_INTF_INT_MASK, ~(nesdev->intf_int_req)); list_add_tail(&nesdev->list, &nes_dev_list); - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); /* Request an interrupt line for the driver */ -#ifdef IRQF_SHARED ret = request_irq(pcidev->irq, nes_interrupt, IRQF_SHARED, DRV_NAME, nesdev); -#else - ret = request_irq(pcidev->irq, nes_interrupt, SA_SHIRQ, DRV_NAME, nesdev); -#endif if (ret) { - printk(KERN_ERR PFX "%s: requested IRQ %u is busy\n", pci_name(pcidev), pcidev->irq); + printk(KERN_ERR PFX "%s: requested IRQ %u is busy\n", + pci_name(pcidev), pcidev->irq); goto bail65; } nes_write32(nesdev->regs+NES_INT_MASK, ~nesdev->int_req); - if (!notifiers_registered) { + if (nes_notifiers_registered == 0) { register_inetaddr_notifier(&nes_inetaddr_notifier); register_netevent_notifier(&nes_net_notifier); - notifiers_registered = 1; } + nes_notifiers_registered++; /* Initialize network devices */ - if ((netdev = nes_netdev_init(nesdev, mmio_regs)) == NULL) { - goto bail7; - } + if ((netdev = nes_netdev_init(nesdev, mmio_regs)) == NULL) { + goto bail7; + } - /* Register network device */ - ret = register_netdev(netdev); - if (ret) { - printk(KERN_ERR PFX "Unable to register netdev, ret = %d\n", ret); - nes_netdev_destroy(netdev); - goto bail7; - } + /* Register network device */ + ret = register_netdev(netdev); + if (ret) { + printk(KERN_ERR PFX "Unable to register netdev, ret = %d\n", ret); + nes_netdev_destroy(netdev); + goto bail7; + } - nes_print_macaddr(netdev); + nes_print_macaddr(netdev); /* create a CM core for this netdev */ - nesvnic = netdev_priv(netdev); + nesvnic = netdev_priv(netdev); - nesdev->netdev_count++; - nesdev->nesadapter->netdev_count++; + nesdev->netdev_count++; + nesdev->nesadapter->netdev_count++; - printk(KERN_ERR PFX "%s: NetEffect RNIC driver successfully loaded" - " for port %d (%d ports available).\n", - pci_name(pcidev), PCI_FUNC(pcidev->devfn), - nesdev->nesadapter->port_count); - return (0); + printk(KERN_ERR PFX "%s: NetEffect RNIC driver successfully loaded.\n", + pci_name(pcidev)); + return 0; bail7: printk(KERN_ERR PFX "bail7\n"); @@ -697,13 +678,13 @@ static int __devinit nes_probe(struct pci_dev *pcidev, const struct pci_device_i nes_netdev_destroy(nesdev->netdev[nesdev->netdev_count]); } - dprintk("%s: netdev_count=%d, nesadapter->netdev_count=%d\n", - __FUNCTION__, nesdev->netdev_count, nesdev->nesadapter->netdev_count); + nes_debug(NES_DBG_INIT, "netdev_count=%d, nesadapter->netdev_count=%d\n", + nesdev->netdev_count, nesdev->nesadapter->netdev_count); - if (notifiers_registered) { + nes_notifiers_registered--; + if (nes_notifiers_registered == 0) { unregister_netevent_notifier(&nes_net_notifier); unregister_inetaddr_notifier(&nes_inetaddr_notifier); - notifiers_registered = 0; } list_del(&nesdev->list); @@ -712,11 +693,9 @@ static int __devinit nes_probe(struct pci_dev *pcidev, const struct pci_device_i bail65: printk(KERN_ERR PFX "bail65\n"); free_irq(pcidev->irq, nesdev); -#ifdef CONFIG_PCI_MSI if (nesdev->msi_enabled) { pci_disable_msi(pcidev); } -#endif bail6: printk(KERN_ERR PFX "bail6\n"); tasklet_kill(&nesdev->dpc_tasklet); @@ -738,7 +717,7 @@ static int __devinit nes_probe(struct pci_dev *pcidev, const struct pci_device_i pci_disable_device(pcidev); bail0: - return(ret); + return ret; } @@ -749,56 +728,46 @@ static void __devexit nes_remove(struct pci_dev *pcidev) { struct nes_device *nesdev = pci_get_drvdata(pcidev); struct net_device *netdev; - int netdev_index=0; - - /* dprintk("%s called.\n", __FUNCTION__); */ - if (nesdev->netdev_count) { - netdev = nesdev->netdev[netdev_index]; - if (netdev) { - netif_stop_queue(netdev); - unregister_netdev(netdev); - nes_netdev_destroy(netdev); - - nesdev->netdev[netdev_index] = NULL; - nesdev->netdev_count--; - nesdev->nesadapter->netdev_count--; + int netdev_index = 0; + + if (nesdev->netdev_count) { + netdev = nesdev->netdev[netdev_index]; + if (netdev) { + netif_stop_queue(netdev); + unregister_netdev(netdev); + nes_netdev_destroy(netdev); + + nesdev->netdev[netdev_index] = NULL; + nesdev->netdev_count--; + nesdev->nesadapter->netdev_count--; + } } - } - if (notifiers_registered) { + + nes_notifiers_registered--; + if (nes_notifiers_registered == 0) { unregister_netevent_notifier(&nes_net_notifier); unregister_inetaddr_notifier(&nes_inetaddr_notifier); - notifiers_registered = 0; } list_del(&nesdev->list); nes_destroy_cqp(nesdev); tasklet_kill(&nesdev->dpc_tasklet); - dprintk("nes_remove: calling nes_destroy_adapter(%p).\n", nesdev->nesadapter); /* Deallocate the Adapter Structure */ nes_destroy_adapter(nesdev->nesadapter); - dprintk("nes_remove: calling free_irq.\n"); free_irq(pcidev->irq, nesdev); -#ifdef CONFIG_PCI_MSI if (nesdev->msi_enabled) { pci_disable_msi(pcidev); } -#endif - dprintk("nes_remove: calling iounmap.\n"); iounmap(nesdev->regs); - kfree(nesdev); - /* dprintk("nes_remove: calling pci_release_regions.\n"); */ + /* nes_debug(NES_DBG_SHUTDOWN, "calling pci_release_regions.\n"); */ pci_release_regions(pcidev); - - /* dprintk("nes_remove: calling pci_disable_device.\n"); */ pci_disable_device(pcidev); - - dprintk("nes_remove: calling pci_set_drvdata.\n"); pci_set_drvdata(pcidev, NULL); } @@ -810,6 +779,339 @@ static struct pci_driver nes_pci_driver = { .remove = __devexit_p(nes_remove), }; +static ssize_t nes_show_adapter(struct device_driver *ddp, char *buf) +{ + unsigned int devfn = 0xffffffff; + unsigned char bus_number = 0xff; + unsigned int i = 0; + struct nes_device *nesdev; + + list_for_each_entry(nesdev, &nes_dev_list, list) { + if (i == ee_flsh_adapter) { + devfn = nesdev->nesadapter->devfn; + bus_number = nesdev->nesadapter->bus_number; + break; + } + i++; + } + + return snprintf(buf, PAGE_SIZE, "%x:%x", bus_number, devfn); +} + +static ssize_t nes_store_adapter(struct device_driver *ddp, + const char *buf, size_t count) +{ + char *p = (char *)buf; + + ee_flsh_adapter = simple_strtoul(p, &p, 10); + return strnlen(buf, count); +} + +static ssize_t nes_show_ee_cmd(struct device_driver *ddp, char *buf) +{ + u32 eeprom_cmd = 0xdead; + u32 i = 0; + struct nes_device *nesdev; + + list_for_each_entry(nesdev, &nes_dev_list, list) { + if (i == ee_flsh_adapter) { + eeprom_cmd = nes_read32(nesdev->regs + NES_EEPROM_COMMAND); + break; + } + i++; + } + return snprintf(buf, PAGE_SIZE, "0x%x\n", eeprom_cmd); +} + +static ssize_t nes_store_ee_cmd(struct device_driver *ddp, + const char *buf, size_t count) +{ + char *p = (char *)buf; + u32 val; + u32 i = 0; + struct nes_device *nesdev; + + if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { + val = simple_strtoul(p, &p, 16); + list_for_each_entry(nesdev, &nes_dev_list, list) { + if (i == ee_flsh_adapter) { + nes_write32(nesdev->regs + NES_EEPROM_COMMAND, val); + break; + } + i++; + } + } + return strnlen(buf, count); +} + +static ssize_t nes_show_ee_data(struct device_driver *ddp, char *buf) +{ + u32 eeprom_data = 0xdead; + u32 i = 0; + struct nes_device *nesdev; + + list_for_each_entry(nesdev, &nes_dev_list, list) { + if (i == ee_flsh_adapter) { + eeprom_data = nes_read32(nesdev->regs + NES_EEPROM_DATA); + break; + } + i++; + } + + return snprintf(buf, PAGE_SIZE, "0x%x\n", eeprom_data); +} + +static ssize_t nes_store_ee_data(struct device_driver *ddp, + const char *buf, size_t count) +{ + char *p = (char *)buf; + u32 val; + u32 i = 0; + struct nes_device *nesdev; + + if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { + val = simple_strtoul(p, &p, 16); + list_for_each_entry(nesdev, &nes_dev_list, list) { + if (i == ee_flsh_adapter) { + nes_write32(nesdev->regs + NES_EEPROM_DATA, val); + break; + } + i++; + } + } + return strnlen(buf, count); +} + +static ssize_t nes_show_flash_cmd(struct device_driver *ddp, char *buf) +{ + u32 flash_cmd = 0xdead; + u32 i = 0; + struct nes_device *nesdev; + + list_for_each_entry(nesdev, &nes_dev_list, list) { + if (i == ee_flsh_adapter) { + flash_cmd = nes_read32(nesdev->regs + NES_FLASH_COMMAND); + break; + } + i++; + } + + return snprintf(buf, PAGE_SIZE, "0x%x\n", flash_cmd); +} + +static ssize_t nes_store_flash_cmd(struct device_driver *ddp, + const char *buf, size_t count) +{ + char *p = (char *)buf; + u32 val; + u32 i = 0; + struct nes_device *nesdev; + + if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { + val = simple_strtoul(p, &p, 16); + list_for_each_entry(nesdev, &nes_dev_list, list) { + if (i == ee_flsh_adapter) { + nes_write32(nesdev->regs + NES_FLASH_COMMAND, val); + break; + } + i++; + } + } + return strnlen(buf, count); +} + +static ssize_t nes_show_flash_data(struct device_driver *ddp, char *buf) +{ + u32 flash_data = 0xdead; + u32 i = 0; + struct nes_device *nesdev; + + list_for_each_entry(nesdev, &nes_dev_list, list) { + if (i == ee_flsh_adapter) { + flash_data = nes_read32(nesdev->regs + NES_FLASH_DATA); + break; + } + i++; + } + + return snprintf(buf, PAGE_SIZE, "0x%x\n", flash_data); +} + +static ssize_t nes_store_flash_data(struct device_driver *ddp, + const char *buf, size_t count) +{ + char *p = (char *)buf; + u32 val; + u32 i = 0; + struct nes_device *nesdev; + + if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { + val = simple_strtoul(p, &p, 16); + list_for_each_entry(nesdev, &nes_dev_list, list) { + if (i == ee_flsh_adapter) { + nes_write32(nesdev->regs + NES_FLASH_DATA, val); + break; + } + i++; + } + } + return strnlen(buf, count); +} + +static ssize_t nes_show_nonidx_addr(struct device_driver *ddp, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "0x%x\n", sysfs_nonidx_addr); +} + +static ssize_t nes_store_nonidx_addr(struct device_driver *ddp, + const char *buf, size_t count) +{ + char *p = (char *)buf; + + if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') + sysfs_nonidx_addr = simple_strtoul(p, &p, 16); + + return strnlen(buf, count); +} + +static ssize_t nes_show_nonidx_data(struct device_driver *ddp, char *buf) +{ + u32 nonidx_data = 0xdead; + u32 i = 0; + struct nes_device *nesdev; + + list_for_each_entry(nesdev, &nes_dev_list, list) { + if (i == ee_flsh_adapter) { + nonidx_data = nes_read32(nesdev->regs + sysfs_nonidx_addr); + break; + } + i++; + } + + return snprintf(buf, PAGE_SIZE, "0x%x\n", nonidx_data); +} + +static ssize_t nes_store_nonidx_data(struct device_driver *ddp, + const char *buf, size_t count) +{ + char *p = (char *)buf; + u32 val; + u32 i = 0; + struct nes_device *nesdev; + + if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { + val = simple_strtoul(p, &p, 16); + list_for_each_entry(nesdev, &nes_dev_list, list) { + if (i == ee_flsh_adapter) { + nes_write32(nesdev->regs + sysfs_nonidx_addr, val); + break; + } + i++; + } + } + + return strnlen(buf, count); +} + +static ssize_t nes_show_idx_addr(struct device_driver *ddp, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "0x%x\n", sysfs_idx_addr); +} + +static ssize_t nes_store_idx_addr(struct device_driver *ddp, + const char *buf, size_t count) +{ + char *p = (char *)buf; + + if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') + sysfs_idx_addr = simple_strtoul(p, &p, 16); + return strnlen(buf, count); +} + +static ssize_t nes_show_idx_data(struct device_driver *ddp, char *buf) +{ + u32 idx_data = 0xdead; + u32 i = 0; + struct nes_device *nesdev; + + list_for_each_entry(nesdev, &nes_dev_list, list) { + if (i == ee_flsh_adapter) { + idx_data = nes_read_indexed(nesdev, sysfs_idx_addr); + break; + } + i++; + } + + return snprintf(buf, PAGE_SIZE, "0x%x\n", idx_data); +} + +static ssize_t nes_store_idx_data(struct device_driver *ddp, + const char *buf, size_t count) +{ + char *p = (char *)buf; + u32 val; + u32 i = 0; + struct nes_device *nesdev; + + if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { + val = simple_strtoul(p, &p, 16); + list_for_each_entry(nesdev, &nes_dev_list, list) { + if (i == ee_flsh_adapter) { + nes_write_indexed(nesdev, sysfs_idx_addr, val); + break; + } + i++; + } + } + return strnlen(buf, count); +} + +static DRIVER_ATTR(adapter, S_IRUSR | S_IWUSR, + nes_show_adapter, nes_store_adapter); +static DRIVER_ATTR(eeprom_cmd, S_IRUSR | S_IWUSR, + nes_show_ee_cmd, nes_store_ee_cmd); +static DRIVER_ATTR(eeprom_data, S_IRUSR | S_IWUSR, + nes_show_ee_data, nes_store_ee_data); +static DRIVER_ATTR(flash_cmd, S_IRUSR | S_IWUSR, + nes_show_flash_cmd, nes_store_flash_cmd); +static DRIVER_ATTR(flash_data, S_IRUSR | S_IWUSR, + nes_show_flash_data, nes_store_flash_data); +static DRIVER_ATTR(nonidx_addr, S_IRUSR | S_IWUSR, + nes_show_nonidx_addr, nes_store_nonidx_addr); +static DRIVER_ATTR(nonidx_data, S_IRUSR | S_IWUSR, + nes_show_nonidx_data, nes_store_nonidx_data); +static DRIVER_ATTR(idx_addr, S_IRUSR | S_IWUSR, + nes_show_idx_addr, nes_store_idx_addr); +static DRIVER_ATTR(idx_data, S_IRUSR | S_IWUSR, + nes_show_idx_data, nes_store_idx_data); + +static int nes_create_driver_sysfs(struct pci_driver *drv) +{ + int error; + error = driver_create_file(&drv->driver, &driver_attr_adapter); + error |= driver_create_file(&drv->driver, &driver_attr_eeprom_cmd); + error |= driver_create_file(&drv->driver, &driver_attr_eeprom_data); + error |= driver_create_file(&drv->driver, &driver_attr_flash_cmd); + error |= driver_create_file(&drv->driver, &driver_attr_flash_data); + error |= driver_create_file(&drv->driver, &driver_attr_nonidx_addr); + error |= driver_create_file(&drv->driver, &driver_attr_nonidx_data); + error |= driver_create_file(&drv->driver, &driver_attr_idx_addr); + error |= driver_create_file(&drv->driver, &driver_attr_idx_data); + return error; +} + +static void nes_remove_driver_sysfs(struct pci_driver *drv) +{ + driver_remove_file(&drv->driver, &driver_attr_adapter); + driver_remove_file(&drv->driver, &driver_attr_eeprom_cmd); + driver_remove_file(&drv->driver, &driver_attr_eeprom_data); + driver_remove_file(&drv->driver, &driver_attr_flash_cmd); + driver_remove_file(&drv->driver, &driver_attr_flash_data); + driver_remove_file(&drv->driver, &driver_attr_nonidx_addr); + driver_remove_file(&drv->driver, &driver_attr_nonidx_data); + driver_remove_file(&drv->driver, &driver_attr_idx_addr); + driver_remove_file(&drv->driver, &driver_attr_idx_data); +} /** * nes_init_module - module initialization entry point @@ -817,16 +1119,20 @@ static struct pci_driver nes_pci_driver = { static int __init nes_init_module(void) { int retval; + int retval1; + retval = nes_cm_start(); if (retval) { printk(KERN_ERR PFX "Unable to start NetEffect iWARP CM.\n"); - return(retval); + return retval; } -#ifdef OFED_1_2 - return(pci_module_init(&nes_pci_driver)); -#else - return(pci_register_driver(&nes_pci_driver)); -#endif + retval = pci_register_driver(&nes_pci_driver); + if (retval >= 0) { + retval1 = nes_create_driver_sysfs(&nes_pci_driver); + if (retval1 < 0) + printk(KERN_ERR PFX "Unable to create NetEffect sys files.\n"); + } + return retval; } @@ -836,10 +1142,11 @@ static int __init nes_init_module(void) static void __exit nes_exit_module(void) { nes_cm_stop(); + nes_remove_driver_sysfs(&nes_pci_driver); + pci_unregister_driver(&nes_pci_driver); } module_init(nes_init_module); module_exit(nes_exit_module); - diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h index 8f025bc..81d2eca 100644 --- a/drivers/infiniband/hw/nes/nes.h +++ b/drivers/infiniband/hw/nes/nes.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2007 NetEffect, Inc. All rights reserved. + * Copyright (c) 2006 - 2008 NetEffect, Inc. All rights reserved. * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. * * This software is available to you under a choice of one of two @@ -45,6 +45,8 @@ #include <linux/slab.h> #include <asm/semaphore.h> #include <linux/version.h> +#include <asm/io.h> +#include <linux/crc32c.h> #include <rdma/ib_smi.h> #include <rdma/ib_verbs.h> @@ -52,79 +54,109 @@ #include <rdma/rdma_cm.h> #include <rdma/iw_cm.h> -#define TBIRD -#define NES_TWO_PORT -#define NES_LEGACY_INT_DETECT -#define NES_ENABLE_CQE_READ #define NES_SEND_FIRST_WRITE #define QUEUE_DISCONNECTS -#define DRV_BUILD "1" +#define DRV_BUILD "1" #define DRV_NAME "iw_nes" -#define DRV_VERSION "0.4 Build " DRV_BUILD +#define DRV_VERSION "1.0 OFED Build " DRV_BUILD #define PFX DRV_NAME ": " /* * NetEffect PCI vendor id and NE010 PCI device id. */ #ifndef PCI_VENDOR_ID_NETEFFECT /* not in pci.ids yet */ -#define PCI_VENDOR_ID_NETEFFECT 0x1678 +#define PCI_VENDOR_ID_NETEFFECT 0x1678 #define PCI_DEVICE_ID_NETEFFECT_NE020 0x0100 #endif -#define NE020_REV 4 +#define NE020_REV 4 +#define NE020_REV1 5 -#define BAR_0 0 -#define BAR_1 2 +#define BAR_0 0 +#define BAR_1 2 -#define RX_BUF_SIZE (1536 + 8) +#define RX_BUF_SIZE (1536 + 8) +#define NES_REG0_SIZE (4 * 1024) +#define NES_TX_TIMEOUT (6*HZ) +#define NES_FIRST_QPN 64 +#define NES_SW_CONTEXT_ALIGN 1024 -#define NES_REG0_SIZE (4 * 1024) -#define NES_TX_TIMEOUT (6*HZ) -#define NES_FIRST_QPN 64 -#define NES_SW_CONTEXT_ALIGN 1024 +#define NES_NIC_MAX_NICS 16 +#define NES_MAX_ARP_TABLE_SIZE 4096 -#define NES_NIC_MAX_NICS 16 -#define NES_MAX_ARP_TABLE_SIZE 4096 +#define NES_NIC_CEQ_SIZE 8 +/* NICs will be on a separate CQ */ +#define NES_CCEQ_SIZE ((nesadapter->max_cq / nesadapter->port_count) - 32) -#define MAX_DPC_ITERATIONS 128 +#define NES_MAX_PORT_COUNT 4 + +#define MAX_DPC_ITERATIONS 128 + +#define NES_CQP_REQUEST_NO_DOORBELL_RING 0 +#define NES_CQP_REQUEST_RING_DOORBELL 1 + +#define NES_DRV_OPT_ENABLE_MPA_VER_0 0x00000001 +#define NES_DRV_OPT_DISABLE_MPA_CRC 0x00000002 +#define NES_DRV_OPT_DISABLE_FIRST_WRITE 0x00000004 +#define NES_DRV_OPT_DISABLE_INTF 0x00000008 +#define NES_DRV_OPT_ENABLE_MSI 0x00000010 +#define NES_DRV_OPT_DUAL_LOGICAL_PORT 0x00000020 +#define NES_DRV_OPT_SUPRESS_OPTION_BC 0x00000040 +#define NES_DRV_OPT_NO_INLINE_DATA 0x00000080 +#define NES_DRV_OPT_DISABLE_INT_MOD 0x00000100 +#define NES_DRV_OPT_DISABLE_VIRT_WQ 0x00000200 + +#define NES_AEQ_EVENT_TIMEOUT 2500 +#define NES_DISCONNECT_EVENT_TIMEOUT 2000 /* debug levels */ -#define NES_DBG_RX 0x00000001 -#define NES_DBG_RX_PKT_DUMP 0x00000002 -#define NES_DBG_TX 0x00000004 -#define NES_DBG_TX_PKT_DUMP 0x00000008 -#define NES_DBG_ALL 0xffffffff - -#define NES_DRV_OPT_ENABLE_MPA_VER_0 0x00000001 -#define NES_DRV_OPT_DISABLE_MPA_CRC 0x00000002 -#define NES_DRV_OPT_DISABLE_FIRST_WRITE 0x00000004 -#define NES_DRV_OPT_DISABLE_INTF 0x00000008 -#define NES_DRV_OPT_ENABLE_MSI 0x00000010 -#define NES_DRV_OPT_DUAL_LOGICAL_PORT 0x00000020 -#define NES_DRV_OPT_SUPRESS_OPTION_BC 0x00000040 - -#define NES_AEQ_EVENT_TIMEOUT 2500 -#define NES_DISCONNECT_EVENT_TIMEOUT 2000 - -#ifdef NES_DEBUG -#define assert(expr) \ -if(!(expr)) { \ - printk(KERN_ERR PFX "Assertion failed! %s, %s, %s, line %d\n", \ - #expr, __FILE__, __FUNCTION__, __LINE__); \ +/* must match userspace */ +#define NES_DBG_HW 0x00000001 +#define NES_DBG_INIT 0x00000002 +#define NES_DBG_ISR 0x00000004 +#define NES_DBG_PHY 0x00000008 +#define NES_DBG_NETDEV 0x00000010 +#define NES_DBG_CM 0x00000020 +#define NES_DBG_CM1 0x00000040 +#define NES_DBG_NIC_RX 0x00000080 +#define NES_DBG_NIC_TX 0x00000100 +#define NES_DBG_CQP 0x00000200 +#define NES_DBG_MMAP 0x00000400 +#define NES_DBG_MR 0x00000800 +#define NES_DBG_PD 0x00001000 +#define NES_DBG_CQ 0x00002000 +#define NES_DBG_QP 0x00004000 +#define NES_DBG_MOD_QP 0x00008000 +#define NES_DBG_AEQ 0x00010000 +#define NES_DBG_IW_RX 0x00020000 +#define NES_DBG_IW_TX 0x00040000 +#define NES_DBG_SHUTDOWN 0x00080000 +#define NES_DBG_RSVD1 0x10000000 +#define NES_DBG_RSVD2 0x20000000 +#define NES_DBG_RSVD3 0x40000000 +#define NES_DBG_RSVD4 0x80000000 +#define NES_DBG_ALL 0xffffffff + +#ifdef CONFIG_INFINIBAND_NES_DEBUG +#define nes_debug(level, fmt, args...) \ + if (level & nes_debug_level) \ + printk(KERN_ERR PFX "%s[%u]: " fmt, __FUNCTION__, __LINE__, ##args) + +#define assert(expr) \ +if (!(expr)) { \ + printk(KERN_ERR PFX "Assertion failed! %s, %s, %s, line %d\n", \ + #expr, __FILE__, __FUNCTION__, __LINE__); \ } -#ifndef dprintk -#define dprintk(fmt, args...) do { printk(KERN_ERR PFX fmt, ##args); } while (0) -#endif -#define NES_EVENT_TIMEOUT 1200000 -/* #define NES_EVENT_TIMEOUT 1200 */ + +#define NES_EVENT_TIMEOUT 1200000 #else +#define nes_debug(level, fmt, args...) #define assert(expr) do {} while (0) -#define dprintk(fmt, args...) do {} while (0) -#define NES_EVENT_TIMEOUT 100000 +#define NES_EVENT_TIMEOUT 100000 #endif #include "nes_hw.h" @@ -133,139 +165,234 @@ if(!(expr)) { \ #include "nes_user.h" #include "nes_cm.h" - +extern int max_mtu; +extern int nics_per_function; +#define max_frame_len (max_mtu+ETH_HLEN) +extern int interrupt_mod_interval; +extern int nes_if_count; +extern int mpa_version; +extern int disable_mpa_crc; +extern unsigned int send_first; extern unsigned int nes_drv_opt; extern unsigned int nes_debug_level; extern struct list_head nes_adapter_list; extern struct list_head nes_dev_list; -extern int max_mtu; -#define max_frame_len (max_mtu+ETH_HLEN) -extern int interrupt_mod_interval; +extern struct nes_cm_core *g_cm_core; + +extern atomic_t cm_connects; +extern atomic_t cm_accepts; +extern atomic_t cm_disconnects; +extern atomic_t cm_closes; +extern atomic_t cm_connecteds; +extern atomic_t cm_connect_reqs; +extern atomic_t cm_rejects; +extern atomic_t mod_qp_timouts; +extern atomic_t qps_created; +extern atomic_t qps_destroyed; +extern atomic_t sw_qps_destroyed; +extern u32 mh_detected; +extern u32 mh_pauses_sent; +extern u32 cm_packets_sent; +extern u32 cm_packets_bounced; +extern u32 cm_packets_created; +extern u32 cm_packets_received; +extern u32 cm_packets_dropped; +extern u32 cm_packets_retrans; +extern u32 cm_listens_created; +extern u32 cm_listens_destroyed; +extern u32 cm_backlog_drops; +extern atomic_t cm_loopbacks; +extern atomic_t cm_nodes_created; +extern atomic_t cm_nodes_destroyed; +extern atomic_t cm_accel_dropped_pkts; +extern atomic_t cm_resets_recvd; + +extern u32 crit_err_count; +extern u32 int_mod_timer_init; +extern u32 int_mod_cq_depth_256; +extern u32 int_mod_cq_depth_128; +extern u32 int_mod_cq_depth_32; +extern u32 int_mod_cq_depth_24; +extern u32 int_mod_cq_depth_16; +extern u32 int_mod_cq_depth_4; +extern u32 int_mod_cq_depth_1; + +extern atomic_t cqp_reqs_allocated; +extern atomic_t cqp_reqs_freed; +extern atomic_t cqp_reqs_dynallocated; +extern atomic_t cqp_reqs_dynfreed; +extern atomic_t cqp_reqs_queued; +extern atomic_t cqp_reqs_redriven; + struct nes_device { - struct nes_adapter *nesadapter; - void __iomem *regs; - void __iomem *index_reg; - struct pci_dev *pcidev; - struct net_device *netdev[NES_NIC_MAX_NICS]; - u64 link_status_interrupts; - struct tasklet_struct dpc_tasklet; - spinlock_t indexed_regs_lock; - unsigned long doorbell_start; - unsigned long csr_start; - unsigned long mac_tx_errors; - unsigned long mac_pause_frames_sent; - unsigned long mac_pause_frames_received; - unsigned long mac_rx_errors; - unsigned long mac_rx_crc_errors; - unsigned long mac_rx_symbol_err_frames; - unsigned long mac_rx_jabber_frames; - unsigned long mac_rx_oversized_frames; - unsigned long mac_rx_short_frames; - unsigned int mac_index; - unsigned int nes_stack_start; + struct nes_adapter *nesadapter; + void __iomem *regs; + void __iomem *index_reg; + struct pci_dev *pcidev; + struct net_device *netdev[NES_NIC_MAX_NICS]; + u64 link_status_interrupts; + struct tasklet_struct dpc_tasklet; + spinlock_t indexed_regs_lock; + unsigned long csr_start; + unsigned long doorbell_region; + unsigned long doorbell_start; + unsigned long mac_tx_errors; + unsigned long mac_pause_frames_sent; + unsigned long mac_pause_frames_received; + unsigned long mac_rx_errors; + unsigned long mac_rx_crc_errors; + unsigned long mac_rx_symbol_err_frames; + unsigned long mac_rx_jabber_frames; + unsigned long mac_rx_oversized_frames; + unsigned long mac_rx_short_frames; + unsigned long port_rx_discards; + unsigned long port_tx_discards; + unsigned int mac_index; + unsigned int nes_stack_start; /* Control Structures */ - void *cqp_vbase; - dma_addr_t cqp_pbase; - u32 cqp_mem_size; - u8 ceq_index; - u8 nic_ceq_index; - struct nes_hw_cqp cqp; - struct nes_hw_cq ccq; - struct list_head cqp_avail_reqs; - struct list_head cqp_pending_reqs; + void *cqp_vbase; + dma_addr_t cqp_pbase; + u32 cqp_mem_size; + u8 ceq_index; + u8 nic_ceq_index; + struct nes_hw_cqp cqp; + struct nes_hw_cq ccq; + struct list_head cqp_avail_reqs; + struct list_head cqp_pending_reqs; struct nes_cqp_request *nes_cqp_requests; - u32 int_req; - u32 int_stat; - u32 timer_int_req; - u32 timer_only_int_count; - u32 intf_int_req; - u32 et_rx_coalesce_usecs_irq; - u32 last_mac_tx_pauses; - u32 last_used_chunks_tx; - struct list_head list; - - u16 base_doorbell_index; - u8 msi_enabled; - u8 netdev_count; - u8 napi_isr_ran; - u8 disable_rx_flow_control; - u8 disable_tx_flow_control; + u32 int_req; + u32 int_stat; + u32 timer_int_req; + u32 timer_only_int_count; + u32 intf_int_req; + u32 last_mac_tx_pauses; + u32 last_used_chunks_tx; + struct list_head list; + + u16 base_doorbell_index; + u16 currcq_count; + u16 deepcq_count; + u8 msi_enabled; + u8 netdev_count; + u8 napi_isr_ran; + u8 disable_rx_flow_control; + u8 disable_tx_flow_control; }; -static inline unsigned short nes_skb_lso_size(const struct sk_buff *skb) +static inline u32 get_crc_value(struct nes_v4_quad* nes_quad) { - return(skb_shinfo(skb)->gso_size); + u32 crc_value; + crc_value = crc32c(~0, (void *)nes_quad, sizeof (struct nes_v4_quad)); + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)) + /* + * With commit ef19454bd437b2ba, behavior of crc32c changes on + * big-endian platforms. Our algorithm expects previous behavior + * otherwise we have rdma connection establishment issue on ppc64. + */ + crc_value = cpu_to_le32(crc_value); +#endif + return crc_value; +} + +static inline void +set_wqe_64bit_value(__le32 *wqe_words, u32 index, u64 value) +{ + wqe_words[index] = cpu_to_le32((u32) ((unsigned long)value)); + wqe_words[index + 1] = cpu_to_le32((u32)(upper_32_bits((unsigned long)value))); +} + +static inline void +set_wqe_32bit_value(__le32 *wqe_words, u32 index, u32 value) +{ + wqe_words[index] = cpu_to_le32(value); +} + +static inline void +nes_fill_init_cqp_wqe(struct nes_hw_cqp_wqe *cqp_wqe, struct nes_device *nesdev) +{ + set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_COMP_CTX_LOW_IDX, + (u64)((unsigned long) &nesdev->cqp)); + cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] = 0; + cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] = 0; + cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PBL_BLK_COUNT_IDX] = 0; + cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PBL_LEN_IDX] = 0; + cqp_wqe->wqe_words[NES_CQP_STAG_WQE_LEN_LOW_IDX] = 0; + cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PA_LOW_IDX] = 0; + cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PA_HIGH_IDX] = 0; +} + +static inline void +nes_fill_init_qp_wqe(struct nes_hw_qp_wqe *wqe, struct nes_qp *nesqp, u32 head) +{ + u32 value; + value = ((u32)((unsigned long) nesqp)) | head; + set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_CTX_HIGH_IDX, + (u32)(upper_32_bits((unsigned long)(nesqp)))); + set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX, value); } -#define nes_skb_linearize(_skb, _type) skb_linearize(_skb) -#define NES_INIT_WORK(_work, _func, _data) INIT_WORK(_work, _func) /* Read from memory-mapped device */ static inline u32 nes_read_indexed(struct nes_device *nesdev, u32 reg_index) { unsigned long flags; - void __iomem * addr = nesdev->index_reg; + void __iomem *addr = nesdev->index_reg; u32 value; spin_lock_irqsave(&nesdev->indexed_regs_lock, flags); - /* dprintk("Reading from indexed offset %08X using address %p and %p.\n", - reg_index, addr, addr+4); */ - writel(cpu_to_le32(reg_index), addr); - value = le32_to_cpu(readl((u8 *)addr + 4)); + writel(reg_index, addr); + value = readl((void __iomem *)addr + 4); - /* dprintk("Got %08X.\n", value); */ spin_unlock_irqrestore(&nesdev->indexed_regs_lock, flags); - return (value); + return value; } -static inline u32 nes_read32(const void __iomem * addr) +static inline u32 nes_read32(const void __iomem *addr) { - return(le32_to_cpu(readl(addr))); + return readl(addr); } -static inline u16 nes_read16(const void __iomem * addr) +static inline u16 nes_read16(const void __iomem *addr) { - return(le16_to_cpu(readw(addr))); + return readw(addr); } -static inline u8 nes_read8(const void __iomem * addr) +static inline u8 nes_read8(const void __iomem *addr) { - return(readb(addr)); + return readb(addr); } /* Write to memory-mapped device */ static inline void nes_write_indexed(struct nes_device *nesdev, u32 reg_index, u32 val) { unsigned long flags; - void __iomem * addr = nesdev->index_reg; + void __iomem *addr = nesdev->index_reg; spin_lock_irqsave(&nesdev->indexed_regs_lock, flags); - /* dprintk("Writing %08X, to indexed offset %08X using address %p and %p.\n", - val, reg_index, addr, addr+4); */ - writel(cpu_to_le32(reg_index), addr); - writel(cpu_to_le32(val),(u8 *)addr + 4); + writel(reg_index, addr); + writel(val, (void __iomem *)addr + 4); spin_unlock_irqrestore(&nesdev->indexed_regs_lock, flags); } -static inline void nes_write32(void __iomem * addr, u32 val) +static inline void nes_write32(void __iomem *addr, u32 val) { - /* dprintk("Writing %08X, to address %p.\n", val, addr); */ - writel(cpu_to_le32(val), addr); + writel(val, addr); } -static inline void nes_write16(void __iomem * addr, u16 val) +static inline void nes_write16(void __iomem *addr, u16 val) { - writew(cpu_to_le16(val), addr); + writew(val, addr); } -static inline void nes_write8(void __iomem * addr, u8 val) +static inline void nes_write8(void __iomem *addr, u8 val) { writeb(val, addr); } @@ -280,22 +407,16 @@ static inline int nes_alloc_resource(struct nes_adapter *nesadapter, u32 resource_num; spin_lock_irqsave(&nesadapter->resource_lock, flags); - dprintk("nes_alloc_resource: resource_array=%p, max_resources=%u," - " req_resource=%u, next=%u\n", - resource_array, max_resources, *req_resource_num, *next); resource_num = find_next_zero_bit(resource_array, max_resources, *next); - dprintk("nes_alloc_resource: resource_num=%u\n", resource_num); if (resource_num >= max_resources) { resource_num = find_first_zero_bit(resource_array, max_resources); if (resource_num >= max_resources) { printk(KERN_ERR PFX "%s: No available resourcess.\n", __FUNCTION__); spin_unlock_irqrestore(&nesadapter->resource_lock, flags); - return(-EMFILE); + return -EMFILE; } } - dprintk("%s: find_next_zero_bit returned = %u (max = %u).\n", - __FUNCTION__, resource_num, max_resources); set_bit(resource_num, resource_array); *next = resource_num+1; if (*next == max_resources) { @@ -303,7 +424,24 @@ static inline int nes_alloc_resource(struct nes_adapter *nesadapter, } spin_unlock_irqrestore(&nesadapter->resource_lock, flags); *req_resource_num = resource_num; - return (0); + + return 0; +} + +static inline int nes_is_resource_allocated(struct nes_adapter *nesadapter, + unsigned long *resource_array, u32 resource_num) +{ + unsigned long flags; + int bit_is_set; + + spin_lock_irqsave(&nesadapter->resource_lock, flags); + + bit_is_set = test_bit(resource_num, resource_array); + nes_debug(NES_DBG_HW, "resource_num %u is%s allocated.\n", + resource_num, (bit_is_set ? "": " not")); + spin_unlock_irqrestore(&nesadapter->resource_lock, flags); + + return bit_is_set; } static inline void nes_free_resource(struct nes_adapter *nesadapter, @@ -316,62 +454,66 @@ static inline void nes_free_resource(struct nes_adapter *nesadapter, spin_unlock_irqrestore(&nesadapter->resource_lock, flags); } -static inline struct nes_vnic *to_nesvnic(struct ib_device *ibdev) { - return (container_of(ibdev, struct nes_ib_device, ibdev)->nesvnic); +static inline struct nes_vnic *to_nesvnic(struct ib_device *ibdev) +{ + return container_of(ibdev, struct nes_ib_device, ibdev)->nesvnic; } -static inline struct nes_pd *to_nespd(struct ib_pd *ibpd) { - return (container_of(ibpd, struct nes_pd, ibpd)); +static inline struct nes_pd *to_nespd(struct ib_pd *ibpd) +{ + return container_of(ibpd, struct nes_pd, ibpd); } -static inline struct nes_ucontext *to_nesucontext(struct ib_ucontext *ibucontext) { - return (container_of(ibucontext, struct nes_ucontext, ibucontext)); +static inline struct nes_ucontext *to_nesucontext(struct ib_ucontext *ibucontext) +{ + return container_of(ibucontext, struct nes_ucontext, ibucontext); } -static inline struct nes_mr *to_nesmr(struct ib_mr *ibmr) { - return (container_of(ibmr, struct nes_mr, ibmr)); +static inline struct nes_mr *to_nesmr(struct ib_mr *ibmr) +{ + return container_of(ibmr, struct nes_mr, ibmr); } -static inline struct nes_mr *to_nesmr_from_ibfmr(struct ib_fmr *ibfmr) { - return (container_of(ibfmr, struct nes_mr, ibfmr)); +static inline struct nes_mr *to_nesmr_from_ibfmr(struct ib_fmr *ibfmr) +{ + return container_of(ibfmr, struct nes_mr, ibfmr); } -static inline struct nes_mr *to_nesmw(struct ib_mw *ibmw) { - return (container_of(ibmw, struct nes_mr, ibmw)); +static inline struct nes_mr *to_nesmw(struct ib_mw *ibmw) +{ + return container_of(ibmw, struct nes_mr, ibmw); } -static inline struct nes_fmr *to_nesfmr(struct nes_mr *nesmr) { - return (container_of(nesmr, struct nes_fmr, nesmr)); +static inline struct nes_fmr *to_nesfmr(struct nes_mr *nesmr) +{ + return container_of(nesmr, struct nes_fmr, nesmr); } -static inline struct nes_cq *to_nescq(struct ib_cq *ibcq) { - return (container_of(ibcq, struct nes_cq, ibcq)); +static inline struct nes_cq *to_nescq(struct ib_cq *ibcq) +{ + return container_of(ibcq, struct nes_cq, ibcq); } -static inline struct nes_qp *to_nesqp(struct ib_qp *ibqp) { - return (container_of(ibqp, struct nes_qp, ibqp)); +static inline struct nes_qp *to_nesqp(struct ib_qp *ibqp) +{ + return container_of(ibqp, struct nes_qp, ibqp); } -/* Utils */ -#define CRC32C_POLY 0x1EDC6F41 -#define ORDER 32 -#define REFIN 1 -#define REFOUT 1 -#define NES_HASH_CRC_INITAL_VALUE 0xFFFFFFFF -#define NES_HASH_CRC_FINAL_XOR 0xFFFFFFFF + /* nes.c */ void nes_add_ref(struct ib_qp *); void nes_rem_ref(struct ib_qp *); struct ib_qp *nes_get_qp(struct ib_device *, int); + /* nes_hw.c */ struct nes_adapter *nes_init_adapter(struct nes_device *, u8); -unsigned int nes_reset_adapter_ne010(struct nes_device *, u8 *); +void nes_nic_init_timer_defaults(struct nes_device *, u8); unsigned int nes_reset_adapter_ne020(struct nes_device *, u8 *); -int nes_init_serdes(struct nes_device *, u8 port_count); -void nes_init_csr_ne010(struct nes_device *, u8 hw_rev); -void nes_init_csr_ne020(struct nes_device *, u8 hw_rev, u8 port_count); +int nes_init_serdes(struct nes_device *, u8, u8, u8); +void nes_init_csr_ne020(struct nes_device *, u8, u8); +void nes_destroy_adapter(struct nes_adapter *); int nes_init_cqp(struct nes_device *); int nes_init_phy(struct nes_device *); int nes_init_nic_qp(struct nes_device *, struct net_device *); @@ -390,21 +532,21 @@ int nes_destroy_cqp(struct nes_device *); int nes_nic_cm_xmit(struct sk_buff *, struct net_device *); /* nes_nic.c */ +void nes_netdev_set_multicast_list(struct net_device *); +void nes_netdev_exit(struct nes_vnic *); struct net_device *nes_netdev_init(struct nes_device *, void __iomem *); void nes_netdev_destroy(struct net_device *); -void nes_destroy_adapter(struct nes_adapter *); +int nes_nic_cm_xmit(struct sk_buff *, struct net_device *); /* nes_cm.c */ -void *nes_cm_create(struct net_device *netdev); -int nes_cm_recv(struct sk_buff *skb_p, struct net_device *netdevice); +void *nes_cm_create(struct net_device *); +int nes_cm_recv(struct sk_buff *, struct net_device *); void nes_update_arp(unsigned char *, u32, u32, u16, u16); void nes_manage_arp_cache(struct net_device *, unsigned char *, u32, u32); void nes_sock_release(struct nes_qp *, unsigned long *); -void nes_disconnect_worker(void *); -void flush_wqes(struct nes_device *nesdev, struct nes_qp *nesqp, u32 which_wq, u32 wait_completion); -int nes_manage_apbvt(struct nes_vnic *nesvnic, u32 accel_local_port, - u32 nic_index, u32 add_port); - +struct nes_cm_core *nes_cm_alloc_core(void); +void flush_wqes(struct nes_device *nesdev, struct nes_qp *, u32, u32); +int nes_manage_apbvt(struct nes_vnic *, u32, u32, u32); int nes_cm_disconn(struct nes_qp *); void nes_cm_disconn_worker(void *); @@ -422,100 +564,12 @@ void nes_write_1G_phy_reg(struct nes_device *, u8, u8, u16); void nes_read_1G_phy_reg(struct nes_device *, u8, u8, u16 *); void nes_write_10G_phy_reg(struct nes_device *, u16, u8, u16); void nes_read_10G_phy_reg(struct nes_device *, u16, u8); +struct nes_cqp_request *nes_get_cqp_request(struct nes_device *); +void nes_post_cqp_request(struct nes_device *, struct nes_cqp_request *, int); int nes_arp_table(struct nes_device *, u32, u8 *, u32); void nes_mh_fix(unsigned long); -void nes_dump_mem(void *, int); +void nes_clc(unsigned long); +void nes_dump_mem(unsigned int, void *, int); u32 nes_crc32(u32, u32, u32, u32, u8 *, u32, u32, u32); -extern int nes_if_count; -extern int mpa_version; -extern unsigned int send_first; - - -#define NES_CQP_REQUEST_NOT_HOLDING_LOCK 0 -#define NES_CQP_REQUEST_HOLDING_LOCK 1 -#define NES_CQP_REQUEST_NO_DOORBELL_RING 0 -#define NES_CQP_REQUEST_RING_DOORBELL 1 - -static inline struct nes_cqp_request - *nes_get_cqp_request(struct nes_device *nesdev, int holding_lock) -{ - unsigned long flags; - struct nes_cqp_request *cqp_request = NULL; - - if (!holding_lock) { - spin_lock_irqsave(&nesdev->cqp.lock, flags); - } - if (!list_empty(&nesdev->cqp_avail_reqs)) { - cqp_request = list_entry(nesdev->cqp_avail_reqs.next, - struct nes_cqp_request, list); - list_del_init(&cqp_request->list); - } - if (!holding_lock) { - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); - } - - if (cqp_request) { - cqp_request->waiting = 0; - cqp_request->request_done = 0; - init_waitqueue_head(&cqp_request->waitq); - /* dprintk("%s: Got cqp request %p from the available list \n", - __FUNCTION__, cqp_request); */ - } else - dprintk("%s: CQP request queue is empty.\n", __FUNCTION__); - - return (cqp_request); -} - -static inline void nes_post_cqp_request(struct nes_device *nesdev, - struct nes_cqp_request *cqp_request, int holding_lock, int ring_doorbell) -{ - /* caller must be holding CQP lock */ - struct nes_hw_cqp_wqe *cqp_wqe; - unsigned long flags; - u32 cqp_head; - - if (!holding_lock) { - spin_lock_irqsave(&nesdev->cqp.lock, flags); - } - - if (((((nesdev->cqp.sq_tail+(nesdev->cqp.sq_size*2))-nesdev->cqp.sq_head) & - (nesdev->cqp.sq_size - 1)) != 1) - && (list_empty(&nesdev->cqp_pending_reqs))) { - cqp_head = nesdev->cqp.sq_head++; - nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1; - cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head]; - memcpy(cqp_wqe, &cqp_request->cqp_wqe, sizeof(*cqp_wqe)); - barrier(); - *((struct nes_cqp_request **)&cqp_wqe->wqe_words - [NES_CQP_WQE_COMP_SCRATCH_LOW_IDX]) = cqp_request; - dprintk("%s: CQP request (opcode 0x%02X), line 1 = 0x%08X put on CQPs SQ," - " request = %p, cqp_head = %u, cqp_tail = %u, cqp_size = %u," - " waiting = %d, refcount = %d.\n", - __FUNCTION__, cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX]&0x3f, - cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX], cqp_request, - nesdev->cqp.sq_head, nesdev->cqp.sq_tail, nesdev->cqp.sq_size, - cqp_request->waiting, atomic_read(&cqp_request->refcount)); - } else { - dprintk("%s: CQP request %p (opcode 0x%02X), line 1 = 0x%08X" - " put on the pending queue.\n", - __FUNCTION__, cqp_request, - cqp_request->cqp_wqe.wqe_words[NES_CQP_WQE_OPCODE_IDX]&0x3f, - cqp_request->cqp_wqe.wqe_words[NES_CQP_WQE_ID_IDX]); - list_add_tail(&cqp_request->list, &nesdev->cqp_pending_reqs); - } - - if (ring_doorbell) { - barrier(); - /* Ring doorbell (1 WQEs) */ - nes_write32(nesdev->regs+NES_WQE_ALLOC, 0x01800000 | nesdev->cqp.qp_id); - } - - if (!holding_lock) { - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); - } - - return; -} - #endif /* __NES_H */ diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index 3d3a0fc..4705dbc 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2007 NetEffect, Inc. All rights reserved. + * Copyright (c) 2006 - 2008 NetEffect, Inc. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -67,6 +67,11 @@ u32 cm_packets_received; u32 cm_listens_created; u32 cm_listens_destroyed; u32 cm_backlog_drops; +atomic_t cm_loopbacks; +atomic_t cm_nodes_created; +atomic_t cm_nodes_destroyed; +atomic_t cm_accel_dropped_pkts; +atomic_t cm_resets_recvd; static inline int mini_cm_accelerated(struct nes_cm_core *, struct nes_cm_node *); static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *, @@ -78,8 +83,8 @@ static int mini_cm_del_listen(struct nes_cm_core *, struct nes_cm_listener *); /* External CM API Interface */ /* instance of function pointers for client API */ -/* set address of this instance to cm_core->cm_ops_p at cm_core alloc */ -struct nes_cm_ops nes_cm_api = { +/* set address of this instance to cm_core->cm_ops at cm_core alloc */ +static struct nes_cm_ops nes_cm_api = { mini_cm_accelerated, mini_cm_listen, mini_cm_del_listen, @@ -93,7 +98,7 @@ struct nes_cm_ops nes_cm_api = { mini_cm_set }; -struct nes_cm_core *g_cm_core_p; +struct nes_cm_core *g_cm_core; atomic_t cm_connects; atomic_t cm_accepts; @@ -107,102 +112,95 @@ atomic_t cm_rejects; /** * create_event */ -static struct nes_cm_event *create_event(struct nes_cm_node *node_p, +static struct nes_cm_event *create_event(struct nes_cm_node *cm_node, enum nes_cm_event_type type) { - struct nes_cm_event *event_p; + struct nes_cm_event *event; - if(!node_p->cm_id) + if (!cm_node->cm_id) return NULL; /* allocate an empty event */ - event_p = (struct nes_cm_event *)kzalloc(sizeof(*event_p), GFP_ATOMIC); - - if (!event_p) - return(NULL); - - event_p->type = type; - event_p->node_p = node_p; - event_p->cm_info.rem_addr = node_p->rem_addr; - event_p->cm_info.loc_addr = node_p->loc_addr; - event_p->cm_info.rem_port = node_p->rem_port; - event_p->cm_info.loc_port = node_p->loc_port; - event_p->cm_info.cm_id = node_p->cm_id; - - dprintk("%s[%u] Created event_p=%p, type=%u, dst_addr=%08x[%x], src_addr=%08x[%x]\n", - __FUNCTION__, __LINE__, event_p, type, - event_p->cm_info.loc_addr, event_p->cm_info.loc_port, - event_p->cm_info.rem_addr, event_p->cm_info.rem_port); - - nes_cm_post_event(event_p); - return(event_p); + event = kzalloc(sizeof(*event), GFP_ATOMIC); + + if (!event) + return NULL; + + event->type = type; + event->cm_node = cm_node; + event->cm_info.rem_addr = cm_node->rem_addr; + event->cm_info.loc_addr = cm_node->loc_addr; + event->cm_info.rem_port = cm_node->rem_port; + event->cm_info.loc_port = cm_node->loc_port; + event->cm_info.cm_id = cm_node->cm_id; + + nes_debug(NES_DBG_CM, "Created event=%p, type=%u, dst_addr=%08x[%x]," + " src_addr=%08x[%x]\n", + event, type, + event->cm_info.loc_addr, event->cm_info.loc_port, + event->cm_info.rem_addr, event->cm_info.rem_port); + + nes_cm_post_event(event); + return event; } /** * send_mpa_request */ -int send_mpa_request(struct nes_cm_node *node_p) +int send_mpa_request(struct nes_cm_node *cm_node) { - struct sk_buff *skb_p; + struct sk_buff *skb; int ret; - skb_p = get_free_pkt(node_p); - if (!skb_p) { - dprintk("%s:%s[%u] -- Failed to get a Free pkt\n", - __FILE__, __FUNCTION__, __LINE__); - return (-1); + skb = get_free_pkt(cm_node); + if (!skb) { + nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n"); + return -1; } /* send an MPA Request frame */ - form_cm_frame(skb_p, node_p, NULL, 0, &node_p->mpa_frame_p, - node_p->mpa_frame_size, SET_ACK); + form_cm_frame(skb, cm_node, NULL, 0, &cm_node->mpa_frame, + cm_node->mpa_frame_size, SET_ACK); - ret = schedule_nes_timer(node_p, skb_p, NES_TIMER_TYPE_SEND, 1, 0); + ret = schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0); if (ret < 0) { - return (ret); + return ret; } - dprintk("%s[%u] -- \n", __FUNCTION__, __LINE__); - return (0); + return 0; } + /** * recv_mpa - process a received TCP pkt, we are expecting an * IETF MPA frame */ -static int parse_mpa(struct nes_cm_node *node_p, u8 *buffer, u32 len) +static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 len) { - struct ietf_mpa_frame *mpa_frame_p; - - dprintk("%s[%u] Enter, node_p=%p\n", __FUNCTION__, __LINE__, node_p); - nes_dump_mem(buffer, len); + struct ietf_mpa_frame *mpa_frame; /* assume req frame is in tcp data payload */ if (len < sizeof(struct ietf_mpa_frame)) { - dprintk("The received ietf buffer was too small (%x)\n", len); - return (-1); + nes_debug(NES_DBG_CM, "The received ietf buffer was too small (%x)\n", len); + return -1; } - mpa_frame_p = (struct ietf_mpa_frame *)buffer; - node_p->mpa_frame_size = (u32)ntohs(mpa_frame_p->priv_data_len); + mpa_frame = (struct ietf_mpa_frame *)buffer; + cm_node->mpa_frame_size = ntohs(mpa_frame->priv_data_len); - if (node_p->mpa_frame_size + sizeof(struct ietf_mpa_frame) != len) { - dprintk("The received ietf buffer was not right complete (%x + %x != %x)\n", - node_p->mpa_frame_size, (u32)sizeof(struct ietf_mpa_frame), len); - return (-1); + if (cm_node->mpa_frame_size + sizeof(struct ietf_mpa_frame) != len) { + nes_debug(NES_DBG_CM, "The received ietf buffer was not right" + " complete (%x + %x != %x)\n", + cm_node->mpa_frame_size, (u32)sizeof(struct ietf_mpa_frame), len); + return -1; } - dprintk("%s[%u] -- recvd MPA Frame - with private data len = %u\n", - __FILE__, __LINE__, node_p->mpa_frame_size); - - /* copy entire MPA frame to our node's frame */ - memcpy(node_p->mpa_frame_b, buffer + sizeof(struct ietf_mpa_frame), - node_p->mpa_frame_size); - nes_dump_mem(&node_p->mpa_frame_p, node_p->mpa_frame_size); - dprintk("%s:%s[%u] -- Exit\n", __FILE__, __FUNCTION__, __LINE__); + /* copy entire MPA frame to our cm_node's frame */ + memcpy(cm_node->mpa_frame_buf, buffer + sizeof(struct ietf_mpa_frame), + cm_node->mpa_frame_size); - return(0); + return 0; } @@ -211,37 +209,32 @@ static int parse_mpa(struct nes_cm_node *node_p, u8 *buffer, u32 len) * We have been in a TSA state, and we have now received SW * TCP/IP traffic should be a FIN request or IP pkt with options */ -static int handle_exception_pkt(struct nes_cm_node *node_p, - struct sk_buff *skb_p) +static int handle_exception_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb) { int ret = 0; -#ifdef OFED_1_2 - struct tcphdr *tcphdr_p = skb_p->h.th; -#else - struct tcphdr *tcphdr_p = tcp_hdr(skb_p); -#endif + struct tcphdr *tcph = tcp_hdr(skb); /* first check to see if this a FIN pkt */ - if (tcphdr_p->fin) { + if (tcph->fin) { /* we need to ACK the FIN request */ - send_ack(node_p); + send_ack(cm_node); /* check which side we are (client/server) and set next state accordingly */ - if (node_p->tcp_cntxt.client) - node_p->state = NES_CM_STATE_CLOSING; + if (cm_node->tcp_cntxt.client) + cm_node->state = NES_CM_STATE_CLOSING; else { /* we are the server side */ - node_p->state = NES_CM_STATE_CLOSE_WAIT; + cm_node->state = NES_CM_STATE_CLOSE_WAIT; /* since this is a self contained CM we don't wait for */ /* an APP to close us, just send final FIN immediately */ - ret = send_fin(node_p, NULL); - node_p->state = NES_CM_STATE_LAST_ACK; + ret = send_fin(cm_node, NULL); + cm_node->state = NES_CM_STATE_LAST_ACK; } } else { ret = -EINVAL; } - return(ret); + return ret; } @@ -249,231 +242,199 @@ static int handle_exception_pkt(struct nes_cm_node *node_p, * form_cm_frame - get a free packet and build empty frame Use * node info to build. */ -struct sk_buff *form_cm_frame(struct sk_buff *skb_p, struct nes_cm_node *node_p, +struct sk_buff *form_cm_frame(struct sk_buff *skb, struct nes_cm_node *cm_node, void *options, u32 optionsize, void *data, u32 datasize, u8 flags) { - struct tcphdr *tcphdr_p; - struct iphdr *iphdr_p; - struct ethhdr *ethhdr_p; - u8 *buf_p; - u16 packetsize = sizeof(*iphdr_p); + struct tcphdr *tcph; + struct iphdr *iph; + struct ethhdr *ethh; + u8 *buf; + u16 packetsize = sizeof(*iph); - packetsize += sizeof(*tcphdr_p); + packetsize += sizeof(*tcph); packetsize += optionsize + datasize; - memset(skb_p->data, 0x00, ETH_HLEN + sizeof(*iphdr_p) + sizeof(*tcphdr_p)); - - skb_p->len = 0; - buf_p = skb_put(skb_p, packetsize + ETH_HLEN); - - ethhdr_p = (struct ethhdr *) buf_p; - buf_p += ETH_HLEN; - -#ifdef OFED_1_2 - iphdr_p = skb_p->nh.iph = (struct iphdr *)buf_p; - buf_p += sizeof(*iphdr_p); - tcphdr_p = skb_p->h.th = (struct tcphdr *) buf_p; - skb_p->mac.raw = skb_p->data; -#else - iphdr_p = (struct iphdr *)buf_p; - buf_p += sizeof(*iphdr_p); - tcphdr_p = (struct tcphdr *) buf_p; - skb_reset_mac_header(skb_p); - skb_set_network_header(skb_p, ETH_HLEN); - skb_set_transport_header(skb_p, ETH_HLEN+sizeof(*iphdr_p)); -#endif - buf_p += sizeof(*tcphdr_p); - - skb_p->ip_summed = CHECKSUM_PARTIAL; - skb_p->protocol = ntohs(0x800); - skb_p->data_len = 0; - skb_p->mac_len = ETH_HLEN; - - memcpy(ethhdr_p->h_dest, node_p->rem_mac, ETH_ALEN); - memcpy(ethhdr_p->h_source, node_p->loc_mac, ETH_ALEN); - ethhdr_p->h_proto = htons(0x0800); - - iphdr_p->version = IPVERSION; - iphdr_p->ihl = 5; /* 5 * 4Byte words, IP headr len */ - iphdr_p->tos = 0; - iphdr_p->tot_len = htons(packetsize); - iphdr_p->id = htons(++node_p->tcp_cntxt.loc_id); - - iphdr_p->frag_off = ntohs(0x4000); - iphdr_p->ttl = 0x40; - iphdr_p->protocol= 0x06; /* IPPROTO_TCP */ - - iphdr_p->saddr = htonl(node_p->loc_addr); - iphdr_p->daddr = htonl(node_p->rem_addr); - - tcphdr_p->source = htons(node_p->loc_port); - tcphdr_p->dest = htons(node_p->rem_port); - tcphdr_p->seq = htonl(node_p->tcp_cntxt.loc_seq_num); + memset(skb->data, 0x00, ETH_HLEN + sizeof(*iph) + sizeof(*tcph)); + + skb->len = 0; + buf = skb_put(skb, packetsize + ETH_HLEN); + + ethh = (struct ethhdr *) buf; + buf += ETH_HLEN; + + iph = (struct iphdr *)buf; + buf += sizeof(*iph); + tcph = (struct tcphdr *)buf; + skb_reset_mac_header(skb); + skb_set_network_header(skb, ETH_HLEN); + skb_set_transport_header(skb, ETH_HLEN+sizeof(*iph)); + buf += sizeof(*tcph); + + skb->ip_summed = CHECKSUM_PARTIAL; + skb->protocol = htons(0x800); + skb->data_len = 0; + skb->mac_len = ETH_HLEN; + + memcpy(ethh->h_dest, cm_node->rem_mac, ETH_ALEN); + memcpy(ethh->h_source, cm_node->loc_mac, ETH_ALEN); + ethh->h_proto = htons(0x0800); + + iph->version = IPVERSION; + iph->ihl = 5; /* 5 * 4Byte words, IP headr len */ + iph->tos = 0; + iph->tot_len = htons(packetsize); + iph->id = htons(++cm_node->tcp_cntxt.loc_id); + + iph->frag_off = htons(0x4000); + iph->ttl = 0x40; + iph->protocol = 0x06; /* IPPROTO_TCP */ + + iph->saddr = htonl(cm_node->loc_addr); + iph->daddr = htonl(cm_node->rem_addr); + + tcph->source = htons(cm_node->loc_port); + tcph->dest = htons(cm_node->rem_port); + tcph->seq = htonl(cm_node->tcp_cntxt.loc_seq_num); if (flags & SET_ACK) { - node_p->tcp_cntxt.loc_ack_num = node_p->tcp_cntxt.rcv_nxt; - tcphdr_p->ack_seq = htonl(node_p->tcp_cntxt.loc_ack_num); - tcphdr_p->ack = 1; + cm_node->tcp_cntxt.loc_ack_num = cm_node->tcp_cntxt.rcv_nxt; + tcph->ack_seq = htonl(cm_node->tcp_cntxt.loc_ack_num); + tcph->ack = 1; } else - tcphdr_p->ack_seq = 0; + tcph->ack_seq = 0; if (flags & SET_SYN) { - node_p->tcp_cntxt.loc_seq_num ++; - tcphdr_p->syn = 1; + cm_node->tcp_cntxt.loc_seq_num++; + tcph->syn = 1; } else - node_p->tcp_cntxt.loc_seq_num += datasize; /* data (no headers) */ + cm_node->tcp_cntxt.loc_seq_num += datasize; /* data (no headers) */ - dprintk("%s[%u] Local seq # now %x\n", __FUNCTION__, __LINE__, - node_p->tcp_cntxt.loc_seq_num); if (flags & SET_FIN) - tcphdr_p->fin = 1; + tcph->fin = 1; if (flags & SET_RST) - tcphdr_p->rst = 1; + tcph->rst = 1; - tcphdr_p->doff = (u16) ((sizeof(*tcphdr_p) + optionsize + 3)>> 2); - tcphdr_p->window = htons(node_p->tcp_cntxt.rcv_wnd); - tcphdr_p->urg_ptr = 0; + tcph->doff = (u16)((sizeof(*tcph) + optionsize + 3) >> 2); + tcph->window = htons(cm_node->tcp_cntxt.rcv_wnd); + tcph->urg_ptr = 0; if (optionsize) - memcpy(buf_p, options, optionsize); - buf_p += optionsize; + memcpy(buf, options, optionsize); + buf += optionsize; if (datasize) - memcpy(buf_p, data, datasize); + memcpy(buf, data, datasize); - skb_shinfo(skb_p)->nr_frags = 0; + skb_shinfo(skb)->nr_frags = 0; cm_packets_created++; - return(skb_p); + return skb; } /** - * dump_pkt - */ -static void dump_pkt(struct sk_buff *skb_p) -{ - u8 *pkt_p; - - if (!skb_p) - return; - - pkt_p = (u8 *)skb_p->data; - /* dprintk("skb_p->head=%p, data=%p, tail=%p, end=%p," - "skb_p->len=%u, data_len=%u\n", - skb_p->head, skb_p->data, skb_p->tail, skb_p->end, - skb_p->len, skb_p->data_len); - */ - nes_dump_mem(pkt_p, skb_p->len); - - return; -} - -/** * print_core - dump a cm core */ -static void print_core(struct nes_cm_core *core_p) +static void print_core(struct nes_cm_core *core) { - dprintk("---------------------------------------------\n"); - dprintk("CM Core -- (core_p = %p )\n", core_p); - if (!core_p) + nes_debug(NES_DBG_CM, "---------------------------------------------\n"); + nes_debug(NES_DBG_CM, "CM Core -- (core = %p )\n", core); + if (!core) return; - dprintk("---------------------------------------------\n"); - dprintk("Session ID : %u \n", atomic_read(&core_p->session_id)); + nes_debug(NES_DBG_CM, "---------------------------------------------\n"); + nes_debug(NES_DBG_CM, "Session ID : %u \n", atomic_read(&core->session_id)); - dprintk("State : %u \n", core_p->state); + nes_debug(NES_DBG_CM, "State : %u \n", core->state); - dprintk("Tx Free cnt : %u \n", skb_queue_len(&core_p->tx_free_list)); - dprintk("Listen Nodes : %u \n", atomic_read(&core_p->listen_node_cnt)); - dprintk("Active Nodes : %u \n", atomic_read(&core_p->node_cnt)); + nes_debug(NES_DBG_CM, "Tx Free cnt : %u \n", skb_queue_len(&core->tx_free_list)); + nes_debug(NES_DBG_CM, "Listen Nodes : %u \n", atomic_read(&core->listen_node_cnt)); + nes_debug(NES_DBG_CM, "Active Nodes : %u \n", atomic_read(&core->node_cnt)); - dprintk("core_p : %p \n", core_p); + nes_debug(NES_DBG_CM, "core : %p \n", core); - dprintk("-------------- end core ---------------\n"); - return; + nes_debug(NES_DBG_CM, "-------------- end core ---------------\n"); } /** * schedule_nes_timer - * note - node_p needs to be protected before calling this. Encase in: - * rem_ref_cm_node(core_p, node_p);add_ref_cm_node(node_p); + * note - cm_node needs to be protected before calling this. Encase in: + * rem_ref_cm_node(cm_core, cm_node);add_ref_cm_node(cm_node); */ -int schedule_nes_timer(struct nes_cm_node *node_p, struct sk_buff *skb_p, - enum nes_timer_type type, int send_retrans, - int close_when_complete) +int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb, + enum nes_timer_type type, int send_retrans, + int close_when_complete) { unsigned long flags; - struct nes_cm_core *core_p; + struct nes_cm_core *cm_core; struct nes_timer_entry *new_send; int ret = 0; u32 was_timer_set; + if (!cm_node) + return -EINVAL; new_send = kzalloc(sizeof(*new_send), GFP_ATOMIC); - if(!new_send) + if (!new_send) return -1; - if(!node_p) - return -EINVAL; /* new_send->timetosend = currenttime */ new_send->retrycount = NES_DEFAULT_RETRYS; new_send->retranscount = NES_DEFAULT_RETRANS; - new_send->skb = skb_p; + new_send->skb = skb; new_send->timetosend = jiffies; new_send->type = type; - new_send->netdev = node_p->netdev_p; + new_send->netdev = cm_node->netdev; new_send->send_retrans = send_retrans; new_send->close_when_complete = close_when_complete; - if(type == NES_TIMER_TYPE_CLOSE) { - dprintk("Scheduling Close: node_p = %p, new_send = %p.\n", node_p, new_send); - new_send->timetosend += (HZ/2); /* TODO: decide on the correct value here */ - spin_lock_irqsave(&node_p->recv_list_lock, flags); - list_add_tail(&new_send->list, &node_p->recv_list); - spin_unlock_irqrestore(&node_p->recv_list_lock, flags); - } - - if(type == NES_TIMER_TYPE_SEND) { -#ifdef OFED_1_2 - dprintk("Sending Packet %p (timetosend = %lu, jiffies = %lu\n", - new_send, new_send->timetosend, jiffies); - new_send->seq_num = htonl(skb_p->h.th->seq); -#else - dprintk("Sending Packet %p (timetosend = %lu, jiffies = %lu, seq = 0x%08X, ack = 0x%08X):\n", - new_send, new_send->timetosend, jiffies, htonl(tcp_hdr(skb_p)->seq), htonl(tcp_hdr(skb_p)->ack)); - new_send->seq_num = htonl(tcp_hdr(skb_p)->seq); -#endif - dump_pkt(skb_p); - new_send->timetosend = jiffies; - spin_lock_irqsave(&node_p->retrans_list_lock, flags); - list_add_tail(&new_send->list, &node_p->retrans_list); - spin_unlock_irqrestore(&node_p->retrans_list_lock, flags); - } - if(type == NES_TIMER_TYPE_RECV) { -#ifdef OFED_1_2 - new_send->seq_num = htonl(skb_p->h.th->seq); -#else - new_send->seq_num = htonl(tcp_hdr(skb_p)->seq); -#endif - new_send->timetosend = jiffies; - spin_lock_irqsave(&node_p->recv_list_lock, flags); - list_add_tail(&new_send->list, &node_p->recv_list); - spin_unlock_irqrestore(&node_p->recv_list_lock, flags); + if (type == NES_TIMER_TYPE_CLOSE) { + new_send->timetosend += (HZ/2); /* TODO: decide on the correct value here */ + spin_lock_irqsave(&cm_node->recv_list_lock, flags); + list_add_tail(&new_send->list, &cm_node->recv_list); + spin_unlock_irqrestore(&cm_node->recv_list_lock, flags); } - core_p = node_p->core_p; - was_timer_set = timer_pending(&core_p->tcp_timer); + if (type == NES_TIMER_TYPE_SEND) { + new_send->seq_num = htonl(tcp_hdr(skb)->seq); + atomic_inc(&new_send->skb->users); - if(!was_timer_set || time_before(new_send->timetosend, - core_p->tcp_timer.expires)){ - if(was_timer_set) { - del_timer(&core_p->tcp_timer); + ret = nes_nic_cm_xmit(new_send->skb, cm_node->netdev); + if (ret != NETDEV_TX_OK) { + nes_debug(NES_DBG_CM, "Error sending packet %p (jiffies = %lu)\n", + new_send, jiffies); + atomic_dec(&new_send->skb->users); + new_send->timetosend = jiffies; + } else { + cm_packets_sent++; + if (!send_retrans) { + if (close_when_complete) + rem_ref_cm_node(cm_node->cm_core, cm_node); + dev_kfree_skb_any(new_send->skb); + kfree(new_send); + return ret; + } + new_send->timetosend = jiffies + NES_RETRY_TIMEOUT; } - core_p->tcp_timer.expires = new_send->timetosend; + spin_lock_irqsave(&cm_node->retrans_list_lock, flags); + list_add_tail(&new_send->list, &cm_node->retrans_list); + spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); + } + if (type == NES_TIMER_TYPE_RECV) { + new_send->seq_num = htonl(tcp_hdr(skb)->seq); + new_send->timetosend = jiffies; + spin_lock_irqsave(&cm_node->recv_list_lock, flags); + list_add_tail(&new_send->list, &cm_node->recv_list); + spin_unlock_irqrestore(&cm_node->recv_list_lock, flags); + } + cm_core = cm_node->cm_core; + + was_timer_set = timer_pending(&cm_core->tcp_timer); - add_timer(&core_p->tcp_timer); + if (!was_timer_set) { + cm_core->tcp_timer.expires = new_send->timetosend; + add_timer(&cm_core->tcp_timer); } - return(ret); + return ret; } @@ -485,48 +446,46 @@ void nes_cm_timer_tick(unsigned long pass) unsigned long flags, qplockflags; unsigned long nexttimeout = jiffies + NES_LONG_TIME; struct iw_cm_id *cm_id; - struct nes_cm_node *node_p, *node_p_next; + struct nes_cm_node *cm_node; struct nes_timer_entry *send_entry, *recv_entry; - struct list_head *list_p_core, *list_p_core_temp, *list_p_node_temp, *list_p_node; - struct nes_cm_core *core_p = g_cm_core_p; + struct list_head *list_core, *list_core_temp; + struct list_head *list_node, *list_node_temp; + struct nes_cm_core *cm_core = g_cm_core; struct nes_qp *nesqp; + struct sk_buff *skb; u32 settimer = 0; int ret = NETDEV_TX_OK; + int node_done; - spin_lock_irqsave(&core_p->ht_lock, flags); + spin_lock_irqsave(&cm_core->ht_lock, flags); - node_p_next = container_of(core_p->connected_nodes.next, struct nes_cm_node, list); - add_ref_cm_node(node_p_next); - - list_for_each_safe(list_p_node, list_p_core_temp, &core_p->connected_nodes) { - node_p = container_of(list_p_node, struct nes_cm_node, list); - if(list_p_core_temp != &core_p->connected_nodes) { - node_p_next = container_of(list_p_core_temp, struct nes_cm_node, list); - add_ref_cm_node(node_p_next); - } - spin_unlock_irqrestore(&core_p->ht_lock, flags); - spin_lock_irqsave(&node_p->recv_list_lock, flags); - list_for_each_safe(list_p_core, list_p_node_temp, &node_p->recv_list) { - recv_entry = container_of(list_p_core, struct nes_timer_entry, list); + list_for_each_safe(list_node, list_core_temp, &cm_core->connected_nodes) { + cm_node = container_of(list_node, struct nes_cm_node, list); + add_ref_cm_node(cm_node); + spin_unlock_irqrestore(&cm_core->ht_lock, flags); + spin_lock_irqsave(&cm_node->recv_list_lock, flags); + list_for_each_safe(list_core, list_node_temp, &cm_node->recv_list) { + recv_entry = container_of(list_core, struct nes_timer_entry, list); if ((time_after(recv_entry->timetosend, jiffies)) && (recv_entry->type == NES_TIMER_TYPE_CLOSE)) { - if(nexttimeout > recv_entry->timetosend || !settimer) { + if (nexttimeout > recv_entry->timetosend || !settimer) { nexttimeout = recv_entry->timetosend; settimer = 1; } continue; } list_del(&recv_entry->list); - cm_id = node_p->cm_id; - spin_unlock_irqrestore(&node_p->recv_list_lock, flags); - if(recv_entry->type == NES_TIMER_TYPE_CLOSE) { + cm_id = cm_node->cm_id; + spin_unlock_irqrestore(&cm_node->recv_list_lock, flags); + if (recv_entry->type == NES_TIMER_TYPE_CLOSE) { nesqp = (struct nes_qp *)recv_entry->skb; - cm_id->rem_ref(cm_id); spin_lock_irqsave(&nesqp->lock, qplockflags); if (nesqp->cm_id) { - dprintk("%s: QP%u: cm_id = %p: ****** HIT A NES_TIMER_TYPE_CLOSE" + nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, refcount = %d: " + "****** HIT A NES_TIMER_TYPE_CLOSE" " with something to do!!! ******\n", - __FUNCTION__, nesqp->hwqp.qp_id, cm_id); + nesqp->hwqp.qp_id, cm_id, + atomic_read(&nesqp->refcount)); nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED; nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT; nesqp->ibqp_state = IB_QPS_ERR; @@ -534,145 +493,149 @@ void nes_cm_timer_tick(unsigned long pass) nes_cm_disconn(nesqp); } else { spin_unlock_irqrestore(&nesqp->lock, qplockflags); - dprintk("%s: QP%u: cm_id = %p: ****** HIT A NES_TIMER_TYPE_CLOSE" + nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, refcount = %d:" + " ****** HIT A NES_TIMER_TYPE_CLOSE" " with nothing to do!!! ******\n", - __FUNCTION__, nesqp->hwqp.qp_id, cm_id); + nesqp->hwqp.qp_id, cm_id, + atomic_read(&nesqp->refcount)); nes_rem_ref(&nesqp->ibqp); } - } - else if(recv_entry->type == NES_TIMER_TYPE_RECV) { - dprintk("Processing Packet (%p):\n", recv_entry->skb->data); - dump_pkt(recv_entry->skb); - process_packet(node_p, recv_entry->skb, core_p); - dev_kfree_skb_any(recv_entry->skb); + if (cm_id) + cm_id->rem_ref(cm_id); } kfree(recv_entry); - spin_lock_irqsave(&node_p->recv_list_lock, flags); + spin_lock_irqsave(&cm_node->recv_list_lock, flags); } - spin_unlock_irqrestore(&node_p->recv_list_lock, flags); + spin_unlock_irqrestore(&cm_node->recv_list_lock, flags); - spin_lock_irqsave(&node_p->retrans_list_lock, flags); - list_for_each_safe(list_p_core, list_p_node_temp, &node_p->retrans_list) { - send_entry = container_of(list_p_core, struct nes_timer_entry, list); - if(time_after(send_entry->timetosend, jiffies)) { - if((nexttimeout > send_entry->timetosend) || !settimer) { - nexttimeout = send_entry->timetosend; - settimer = 1; + spin_lock_irqsave(&cm_node->retrans_list_lock, flags); + node_done = 0; + list_for_each_safe(list_core, list_node_temp, &cm_node->retrans_list) { + if (node_done) { + break; + } + send_entry = container_of(list_core, struct nes_timer_entry, list); + if (time_after(send_entry->timetosend, jiffies)) { + if (cm_node->state != NES_CM_STATE_TSA) { + if ((nexttimeout > send_entry->timetosend) || !settimer) { + nexttimeout = send_entry->timetosend; + settimer = 1; + } + node_done = 1; + continue; + } else { + list_del(&send_entry->list); + skb = send_entry->skb; + spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); + dev_kfree_skb_any(skb); + kfree(send_entry); + spin_lock_irqsave(&cm_node->retrans_list_lock, flags); + continue; } - continue; } - spin_unlock_irqrestore(&node_p->retrans_list_lock, flags); - if(send_entry->type == NES_TIMER_NODE_CLEANUP){ - dprintk("!send - %p-> next/prev=%p,%p, tts=%lx, skb=%p, type=%x," - " retry=%x, retrans=%x, context=%x, seq=%x\n", - send_entry, send_entry->list.next, send_entry->list.prev, - send_entry->timetosend, send_entry->skb, send_entry->type, - send_entry->retrycount, send_entry->retranscount, - send_entry->context, send_entry->seq_num); - spin_lock_irqsave(&node_p->retrans_list_lock, flags); + if (send_entry->type == NES_TIMER_NODE_CLEANUP) { list_del(&send_entry->list); + spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); + kfree(send_entry); + spin_lock_irqsave(&cm_node->retrans_list_lock, flags); continue; } - if(send_entry->seq_num < node_p->tcp_cntxt.rem_ack_num ) { - if (send_entry->retranscount == NES_DEFAULT_RETRANS) { - printk("%s: dumped packet due to seq check for local 0x%08X:%04X, remote 0x%08X:%04X," - " seq = 0x%08X, ack = 0x%08X, node state = %u\n", - __FUNCTION__, node_p->loc_addr, node_p->loc_port, - node_p->rem_addr, node_p->rem_port, - send_entry->seq_num, node_p->tcp_cntxt.rem_ack_num, node_p->state); - cm_packets_dropped++; - } - dev_kfree_skb_any(send_entry->skb); - spin_lock_irqsave(&node_p->retrans_list_lock, flags); + if ((send_entry->seq_num < cm_node->tcp_cntxt.rem_ack_num) || + (cm_node->state == NES_CM_STATE_TSA) || + (cm_node->state == NES_CM_STATE_CLOSED)) { + skb = send_entry->skb; list_del(&send_entry->list); + spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); kfree(send_entry); + dev_kfree_skb_any(skb); + spin_lock_irqsave(&cm_node->retrans_list_lock, flags); continue; } - if(!send_entry->retranscount || !send_entry->retrycount) { + if (!send_entry->retranscount || !send_entry->retrycount) { cm_packets_dropped++; - printk("%s: dumped packet due to retransmission count for local 0x%08X:%04X," - " remote 0x%08X:%04X, node state = %u, transcount = %u, retrycount = %u\n", - __FUNCTION__, node_p->loc_addr, node_p->loc_port, - node_p->rem_addr, node_p->rem_port, node_p->state, - send_entry->retranscount, send_entry->retrycount ); - dev_kfree_skb_any(send_entry->skb); - if (node_p->state == NES_CM_STATE_SYN_RCVD) { + skb = send_entry->skb; + list_del(&send_entry->list); + spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); + dev_kfree_skb_any(skb); + kfree(send_entry); + if (cm_node->state == NES_CM_STATE_SYN_RCVD) { /* this node never even generated an indication up to the cm */ - rem_ref_cm_node(core_p, node_p); + rem_ref_cm_node(cm_core, cm_node); } else { - create_event(node_p, NES_CM_EVENT_ABORTED); + cm_node->state = NES_CM_STATE_CLOSED; + create_event(cm_node, NES_CM_EVENT_ABORTED); } - spin_lock_irqsave(&node_p->retrans_list_lock, flags); - list_del(&send_entry->list); - kfree(send_entry); + spin_lock_irqsave(&cm_node->retrans_list_lock, flags); continue; } + /* this seems like the correct place, but leave send entry unprotected */ + // spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); atomic_inc(&send_entry->skb->users); - if (send_entry->retranscount != NES_DEFAULT_RETRANS) { - cm_packets_retrans++; - } - ret = nes_nic_cm_xmit(send_entry->skb, node_p->netdev_p); - if(ret != NETDEV_TX_OK) { + cm_packets_retrans++; + nes_debug(NES_DBG_CM, "Retransmitting send_entry %p for node %p," + " jiffies = %lu, time to send = %lu, retranscount = %u, " + "send_entry->seq_num = 0x%08X, cm_node->tcp_cntxt.rem_ack_num = 0x%08X\n", + send_entry, cm_node, jiffies, send_entry->timetosend, send_entry->retranscount, + send_entry->seq_num, cm_node->tcp_cntxt.rem_ack_num); + + spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); + ret = nes_nic_cm_xmit(send_entry->skb, cm_node->netdev); + if (ret != NETDEV_TX_OK) { cm_packets_bounced++; atomic_dec(&send_entry->skb->users); send_entry->retrycount--; nexttimeout = jiffies + NES_SHORT_TIME; settimer = 1; - spin_lock_irqsave(&node_p->retrans_list_lock, flags); + node_done = 1; + spin_lock_irqsave(&cm_node->retrans_list_lock, flags); continue; } else { cm_packets_sent++; } - spin_lock_irqsave(&node_p->retrans_list_lock, flags); + spin_lock_irqsave(&cm_node->retrans_list_lock, flags); list_del(&send_entry->list); - spin_unlock_irqrestore(&node_p->retrans_list_lock, flags); - dprintk("%s(%d) Packet Sent: retrans count = %u, retry count = %u.\n", - __FUNCTION__, __LINE__, send_entry->retranscount, send_entry->retrycount); - dump_pkt(send_entry->skb); - if(send_entry->send_retrans) { + nes_debug(NES_DBG_CM, "Packet Sent: retrans count = %u, retry count = %u.\n", + send_entry->retranscount, send_entry->retrycount); + if (send_entry->send_retrans) { send_entry->retranscount--; -#ifdef NES_DEBUG send_entry->timetosend = jiffies + NES_RETRY_TIMEOUT; -#else - send_entry->timetosend = jiffies + (NES_RETRY_TIMEOUT/10); -#endif - if(nexttimeout > send_entry->timetosend || !settimer) { + if (nexttimeout > send_entry->timetosend || !settimer) { nexttimeout = send_entry->timetosend; settimer = 1; } - spin_lock_irqsave(&node_p->retrans_list_lock, flags); - list_add(&send_entry->list, &node_p->retrans_list); + list_add(&send_entry->list, &cm_node->retrans_list); continue; } else { int close_when_complete; - dev_kfree_skb_any(send_entry->skb); + skb = send_entry->skb; close_when_complete = send_entry->close_when_complete; - kfree(send_entry); - if(close_when_complete) { - rem_ref_cm_node(core_p, node_p); + spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); + if (close_when_complete) { + BUG_ON(atomic_read(&cm_node->ref_count) == 1); + rem_ref_cm_node(cm_core, cm_node); } - spin_lock_irqsave(&node_p->retrans_list_lock, flags); + dev_kfree_skb_any(skb); + kfree(send_entry); + spin_lock_irqsave(&cm_node->retrans_list_lock, flags); continue; } } - spin_unlock_irqrestore(&node_p->retrans_list_lock, flags); + spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); - rem_ref_cm_node(core_p, node_p); + rem_ref_cm_node(cm_core, cm_node); - spin_lock_irqsave(&core_p->ht_lock, flags); - if(ret != NETDEV_TX_OK) + spin_lock_irqsave(&cm_core->ht_lock, flags); + if (ret != NETDEV_TX_OK) break; } - spin_unlock_irqrestore(&core_p->ht_lock, flags); + spin_unlock_irqrestore(&cm_core->ht_lock, flags); - if(settimer) - { - if(timer_pending(&core_p->tcp_timer)) { - del_timer(&core_p->tcp_timer); + if (settimer) { + if (!timer_pending(&cm_core->tcp_timer)) { + cm_core->tcp_timer.expires = nexttimeout; + add_timer(&cm_core->tcp_timer); } - core_p->tcp_timer.expires = nexttimeout; - add_timer(&core_p->tcp_timer); } } @@ -680,11 +643,11 @@ void nes_cm_timer_tick(unsigned long pass) /** * send_syn */ -int send_syn(struct nes_cm_node *node_p, u32 sendack) +int send_syn(struct nes_cm_node *cm_node, u32 sendack) { int ret; int flags = SET_SYN; - struct sk_buff *skb_p; + struct sk_buff *skb; char optionsbuffer[sizeof(struct option_mss) + sizeof(struct option_windowscale) + sizeof(struct option_base) + 1]; @@ -693,22 +656,23 @@ int send_syn(struct nes_cm_node *node_p, u32 sendack) /* Sending MSS option */ union all_known_options *options; - if (!node_p) - return(-EINVAL); + if (!cm_node) + return -EINVAL; options = (union all_known_options *)&optionsbuffer[optionssize]; options->as_mss.optionnum = OPTION_NUMBER_MSS; options->as_mss.length = sizeof(struct option_mss); - options->as_mss.mss = htons(node_p->tcp_cntxt.mss); + options->as_mss.mss = htons(cm_node->tcp_cntxt.mss); optionssize += sizeof(struct option_mss); options = (union all_known_options *)&optionsbuffer[optionssize]; options->as_windowscale.optionnum = OPTION_NUMBER_WINDOW_SCALE; options->as_windowscale.length = sizeof(struct option_windowscale); - options->as_windowscale.shiftcount = NES_CM_DEFAULT_RCV_WND_SCALE; + options->as_windowscale.shiftcount = cm_node->tcp_cntxt.rcv_wscale; optionssize += sizeof(struct option_windowscale); - if(sendack && !(NES_DRV_OPT_SUPRESS_OPTION_BC & nes_drv_opt) && (node_p->conn_type == NES_CM_IWARP_CONN_TYPE)) { + if (sendack && !(NES_DRV_OPT_SUPRESS_OPTION_BC & nes_drv_opt) + ) { options = (union all_known_options *)&optionsbuffer[optionssize]; options->as_base.optionnum = OPTION_NUMBER_WRITE0; options->as_base.length = sizeof(struct option_base); @@ -726,109 +690,109 @@ int send_syn(struct nes_cm_node *node_p, u32 sendack) options->as_end = OPTION_NUMBER_END; optionssize += 1; - dprintk("%s: Enter\n", __FUNCTION__); - - skb_p = get_free_pkt(node_p); - if (!skb_p) { - dprintk("%s:%s[%u] -- Failed to get a Free pkt\n",__FILE__, __FUNCTION__, __LINE__); - return (-1); + skb = get_free_pkt(cm_node); + if (!skb) { + nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n"); + return -1; } if (sendack) flags |= SET_ACK; - form_cm_frame(skb_p, node_p, optionsbuffer, optionssize, NULL, 0, flags); - ret = schedule_nes_timer(node_p, skb_p, NES_TIMER_TYPE_SEND, 1, 0); + form_cm_frame(skb, cm_node, optionsbuffer, optionssize, NULL, 0, flags); + ret = schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0); - return(ret); + return ret; } /** * send_reset */ -int send_reset(struct nes_cm_node *node_p) +int send_reset(struct nes_cm_node *cm_node) { int ret; - struct sk_buff *skb_p = get_free_pkt(node_p); - if (!skb_p) { - dprintk("%s:%s[%u] -- Failed to get a Free pkt\n", - __FILE__, __FUNCTION__, __LINE__); - return (-1); + struct sk_buff *skb = get_free_pkt(cm_node); + int flags = SET_RST | SET_ACK; + + if (!skb) { + nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n"); + return -1; } - add_ref_cm_node(node_p); - form_cm_frame(skb_p, node_p, NULL, 0, NULL, 0, SET_RST | SET_ACK); - ret = schedule_nes_timer(node_p, skb_p, NES_TIMER_TYPE_SEND, 0, 1); - return(ret); + add_ref_cm_node(cm_node); + form_cm_frame(skb, cm_node, NULL, 0, NULL, 0, flags); + ret = schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 0, 1); + + return ret; } /** * send_ack */ -int send_ack(struct nes_cm_node *node_p) +int send_ack(struct nes_cm_node *cm_node) { int ret; - struct sk_buff *skb_p = get_free_pkt(node_p); - if (!skb_p) { - dprintk("%s:%s[%u] -- Failed to get a Free pkt\n", - __FILE__, __FUNCTION__, __LINE__); - return (-1); + struct sk_buff *skb = get_free_pkt(cm_node); + + if (!skb) { + nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n"); + return -1; } - form_cm_frame(skb_p, node_p, NULL, 0, NULL, 0, SET_ACK); - ret = schedule_nes_timer(node_p, skb_p, NES_TIMER_TYPE_SEND, 0, 0); + form_cm_frame(skb, cm_node, NULL, 0, NULL, 0, SET_ACK); + ret = schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 0, 0); - return(ret); + return ret; } /** * send_fin */ -int send_fin(struct nes_cm_node *node_p, struct sk_buff *skb_p) +int send_fin(struct nes_cm_node *cm_node, struct sk_buff *skb) { int ret; /* if we didn't get a frame get one */ - if (!skb_p) - skb_p = get_free_pkt(node_p); + if (!skb) + skb = get_free_pkt(cm_node); - if (!skb_p) { - dprintk("%s:%s[%u] -- Failed to get a Free pkt\n", - __FILE__, __FUNCTION__, __LINE__); - return (-1); + if (!skb) { + nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n"); + return -1; } - form_cm_frame(skb_p, node_p, NULL, 0, NULL, 0, SET_ACK | SET_FIN); - ret = schedule_nes_timer(node_p, skb_p, NES_TIMER_TYPE_SEND, 1, 0); + form_cm_frame(skb, cm_node, NULL, 0, NULL, 0, SET_ACK | SET_FIN); + ret = schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0); - return(ret); + return ret; } /** * get_free_pkt */ -struct sk_buff *get_free_pkt(struct nes_cm_node *node_p) +struct sk_buff *get_free_pkt(struct nes_cm_node *cm_node) { - struct sk_buff *skb_p, *new_skb_p; + struct sk_buff *skb, *new_skb; /* check to see if we need to repopulate the free tx pkt queue */ - if (skb_queue_len(&node_p->core_p->tx_free_list) < NES_CM_FREE_PKT_LO_WATERMARK) { - while (skb_queue_len(&node_p->core_p->tx_free_list) < - node_p->core_p->free_tx_pkt_max) { + if (skb_queue_len(&cm_node->cm_core->tx_free_list) < NES_CM_FREE_PKT_LO_WATERMARK) { + while (skb_queue_len(&cm_node->cm_core->tx_free_list) < + cm_node->cm_core->free_tx_pkt_max) { /* replace the frame we took, we won't get it back */ - new_skb_p = dev_alloc_skb(node_p->core_p->mtu); - + new_skb = dev_alloc_skb(cm_node->cm_core->mtu); + BUG_ON(!new_skb); /* add a replacement frame to the free tx list head */ - skb_queue_head(&node_p->core_p->tx_free_list, new_skb_p); + skb_queue_head(&cm_node->cm_core->tx_free_list, new_skb); } } - skb_p = skb_dequeue(&node_p->core_p->tx_free_list); - return(skb_p); + skb = skb_dequeue(&cm_node->cm_core->tx_free_list); + + return skb; } @@ -843,349 +807,377 @@ static inline int make_hashkey(u16 loc_port, nes_addr_t loc_addr, u16 rem_port, hashkey = loc_addr + rem_addr + loc_port + rem_port; hashkey = (hashkey % NES_CM_HASHTABLE_SIZE); - return(hashkey); + return hashkey; } /** * find_node - find a cm node that matches the reference cm node */ -static struct nes_cm_node * find_node(struct nes_cm_core *core_p, +static struct nes_cm_node *find_node(struct nes_cm_core *cm_core, u16 rem_port, nes_addr_t rem_addr, u16 loc_port, nes_addr_t loc_addr) { unsigned long flags; u32 hashkey; - struct list_head *list_p; - struct list_head *hte_p; - struct nes_cm_node *node_p; + struct list_head *list_pos; + struct list_head *hte; + struct nes_cm_node *cm_node; /* make a hash index key for this packet */ hashkey = make_hashkey(loc_port, loc_addr, rem_port, rem_addr); /* get a handle on the hte */ - - hte_p = &core_p->connected_nodes; + hte = &cm_core->connected_nodes; - dprintk("%s[%u] -- Searching for an owner node:%x:%x from core %p->%p\n", - __FILE__, __LINE__, loc_addr, loc_port, core_p, hte_p); + nes_debug(NES_DBG_CM, "Searching for an owner node:%x:%x from core %p->%p\n", + loc_addr, loc_port, cm_core, hte); /* walk list and find cm_node associated with this session ID */ - spin_lock_irqsave(&core_p->ht_lock, flags); - list_for_each(list_p, hte_p) - { - node_p = container_of(list_p, struct nes_cm_node, list); + spin_lock_irqsave(&cm_core->ht_lock, flags); + list_for_each(list_pos, hte) { + cm_node = container_of(list_pos, struct nes_cm_node, list); /* compare quad, return node handle if a match */ - dprintk("finding node %x:%x =? %x:%x ^ %x:%x =? %x:%x\n", - node_p->loc_addr, node_p->loc_port, + nes_debug(NES_DBG_CM, "finding node %x:%x =? %x:%x ^ %x:%x =? %x:%x\n", + cm_node->loc_addr, cm_node->loc_port, loc_addr, loc_port, - node_p->rem_addr, node_p->rem_port, + cm_node->rem_addr, cm_node->rem_port, rem_addr, rem_port); - if ((node_p->loc_addr == loc_addr) && (node_p->loc_port == loc_port) && - (node_p->rem_addr == rem_addr) && (node_p->rem_port == rem_port)) { - add_ref_cm_node(node_p); - spin_unlock_irqrestore(&core_p->ht_lock, flags); - return(node_p); + if ((cm_node->loc_addr == loc_addr) && (cm_node->loc_port == loc_port) && + (cm_node->rem_addr == rem_addr) && (cm_node->rem_port == rem_port)) { + add_ref_cm_node(cm_node); + spin_unlock_irqrestore(&cm_core->ht_lock, flags); + return cm_node; } } - spin_unlock_irqrestore(&core_p->ht_lock, flags); + spin_unlock_irqrestore(&cm_core->ht_lock, flags); /* no owner node */ - return(NULL); + return NULL; } /** * find_listener - find a cm node listening on this addr-port pair */ -static struct nes_cm_listener * find_listener(struct nes_cm_core *core_p, - nes_addr_t dst_addr, u16 dst_port, enum nes_cm_listener_state listener_state ) +static struct nes_cm_listener *find_listener(struct nes_cm_core *cm_core, + nes_addr_t dst_addr, u16 dst_port, enum nes_cm_listener_state listener_state) { unsigned long flags; - struct list_head *list_p; - struct nes_cm_listener *listen_node_p; + struct list_head *listen_list; + struct nes_cm_listener *listen_node; /* walk list and find cm_node associated with this session ID */ - spin_lock_irqsave(&core_p->listen_list_lock, flags); - list_for_each(list_p, &core_p->listen_list.list) { - listen_node_p = container_of(list_p, struct nes_cm_listener, list);; + spin_lock_irqsave(&cm_core->listen_list_lock, flags); + list_for_each(listen_list, &cm_core->listen_list.list) { + listen_node = container_of(listen_list, struct nes_cm_listener, list); /* compare node pair, return node handle if a match */ - if (((listen_node_p->loc_addr == dst_addr) || - listen_node_p->loc_addr == 0x00000000) && - (listen_node_p->loc_port == dst_port) && - ( listener_state & listen_node_p->listener_state )) { - atomic_inc(&listen_node_p->ref_count); - spin_unlock_irqrestore(&core_p->listen_list_lock, flags); - return(listen_node_p); + if (((listen_node->loc_addr == dst_addr) || + listen_node->loc_addr == 0x00000000) && + (listen_node->loc_port == dst_port) && + (listener_state & listen_node->listener_state)) { + atomic_inc(&listen_node->ref_count); + spin_unlock_irqrestore(&cm_core->listen_list_lock, flags); + return listen_node; } } - spin_unlock_irqrestore(&core_p->listen_list_lock, flags); - dprintk("Unable to find listener- %x:%x\n", + spin_unlock_irqrestore(&cm_core->listen_list_lock, flags); + + nes_debug(NES_DBG_CM, "Unable to find listener- %x:%x\n", dst_addr, dst_port); /* no listener */ - return(NULL); + return NULL; } /** * add_hte_node - add a cm node to the hash table */ -static int add_hte_node(struct nes_cm_core *core_p, struct nes_cm_node *node_p) +static int add_hte_node(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node) { unsigned long flags; u32 hashkey; - struct list_head *hte_p; + struct list_head *hte; - if (!node_p || !core_p) - return(-EINVAL); + if (!cm_node || !cm_core) + return -EINVAL; - dprintk("%s:%s[%u] -- Adding Node to Active Connection HT\n", - __FILE__, __FUNCTION__, __LINE__); + nes_debug(NES_DBG_CM, "Adding Node to Active Connection HT\n"); /* first, make an index into our hash table */ - hashkey = make_hashkey(node_p->loc_port, node_p->loc_addr, - node_p->rem_port, node_p->rem_addr); - node_p->hashkey = hashkey; + hashkey = make_hashkey(cm_node->loc_port, cm_node->loc_addr, + cm_node->rem_port, cm_node->rem_addr); + cm_node->hashkey = hashkey; - spin_lock_irqsave(&core_p->ht_lock, flags); + spin_lock_irqsave(&cm_core->ht_lock, flags); /* get a handle on the hash table element (list head for this slot) */ - hte_p = &core_p->connected_nodes; - list_add_tail(&node_p->list, hte_p); - atomic_inc(&core_p->ht_node_cnt); + hte = &cm_core->connected_nodes; + list_add_tail(&cm_node->list, hte); + atomic_inc(&cm_core->ht_node_cnt); - spin_unlock_irqrestore(&core_p->ht_lock, flags); + spin_unlock_irqrestore(&cm_core->ht_lock, flags); - return(0); + return 0; } /** * mini_cm_dec_refcnt_listen */ -static int mini_cm_dec_refcnt_listen(struct nes_cm_core *core_p, - struct nes_cm_listener *listen_p) +static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core, + struct nes_cm_listener *listener, int free_hanging_nodes) { int ret = 1; unsigned long flags; - - spin_lock_irqsave(&core_p->listen_list_lock, flags); - if(!atomic_dec_return(&listen_p->ref_count)) { - list_del(&listen_p->list); + spin_lock_irqsave(&cm_core->listen_list_lock, flags); + if (!atomic_dec_return(&listener->ref_count)) { + list_del(&listener->list); /* decrement our listen node count */ - atomic_dec(&core_p->listen_node_cnt); + atomic_dec(&cm_core->listen_node_cnt); - spin_unlock_irqrestore(&core_p->listen_list_lock, flags); + spin_unlock_irqrestore(&cm_core->listen_list_lock, flags); - if (listen_p->nesvnic) { - nes_manage_apbvt(listen_p->nesvnic, listen_p->loc_port, - PCI_FUNC(listen_p->nesvnic->nesdev->pcidev->devfn), NES_MANAGE_APBVT_DEL); + if (listener->nesvnic) { + nes_manage_apbvt(listener->nesvnic, listener->loc_port, + PCI_FUNC(listener->nesvnic->nesdev->pcidev->devfn), NES_MANAGE_APBVT_DEL); } - dprintk("%s(%d) destroying listener (%p)\n", - __FUNCTION__, __LINE__, listen_p ); - kfree(listen_p); + + nes_debug(NES_DBG_CM, "destroying listener (%p)\n", listener); + + kfree(listener); + listener = NULL; ret = 0; cm_listens_destroyed++; } else { - spin_unlock_irqrestore(&core_p->listen_list_lock, flags); + spin_unlock_irqrestore(&cm_core->listen_list_lock, flags); } - if (listen_p) { - if ( atomic_read(&listen_p->pend_accepts_cnt) > 0 ) - dprintk( "%s(%d) destroying listener (%p) with non-zero pending accepts=%u \n", - __FUNCTION__, __LINE__, listen_p, atomic_read(&listen_p->pend_accepts_cnt) ); + if (listener) { + if (atomic_read(&listener->pend_accepts_cnt) > 0) + nes_debug(NES_DBG_CM, "destroying listener (%p)" + " with non-zero pending accepts=%u\n", + listener, atomic_read(&listener->pend_accepts_cnt)); } - return(ret); + return ret; } + /** * mini_cm_del_listen */ -static int mini_cm_del_listen(struct nes_cm_core *core_p, - struct nes_cm_listener *listen_p) +static int mini_cm_del_listen(struct nes_cm_core *cm_core, + struct nes_cm_listener *listener) { - listen_p->listener_state = NES_CM_LISTENER_PASSIVE_STATE; - if ((listen_p->conn_type == NES_CM_IWARP_CONN_TYPE) && listen_p->ksock) { - sock_release(listen_p->ksock); - listen_p->ksock = NULL; - } - return mini_cm_dec_refcnt_listen( core_p, listen_p ); + listener->listener_state = NES_CM_LISTENER_PASSIVE_STATE; + listener->cm_id = NULL; /* going to be destroyed pretty soon */ + return mini_cm_dec_refcnt_listen(cm_core, listener, 1); } + /** * mini_cm_accelerated */ -static inline int mini_cm_accelerated(struct nes_cm_core *core_p, - struct nes_cm_node *node_p) +static inline int mini_cm_accelerated(struct nes_cm_core *cm_core, + struct nes_cm_node *cm_node) { u32 was_timer_set; - node_p->accelerated = 1; + cm_node->accelerated = 1; - if( node_p->listen_p ) { - atomic_dec( &node_p->listen_p->pend_accepts_cnt ); - BUG_ON(atomic_read(&node_p->listen_p->pend_accepts_cnt) < 0 ); + if (cm_node->accept_pend) { + BUG_ON(!cm_node->listener); + atomic_dec(&cm_node->listener->pend_accepts_cnt); + BUG_ON(atomic_read(&cm_node->listener->pend_accepts_cnt) < 0); } - was_timer_set = timer_pending(&core_p->tcp_timer); - if(!was_timer_set){ - core_p->tcp_timer.expires = jiffies + NES_SHORT_TIME; - add_timer(&core_p->tcp_timer); + was_timer_set = timer_pending(&cm_core->tcp_timer); + if (!was_timer_set) { + cm_core->tcp_timer.expires = jiffies + NES_SHORT_TIME; + add_timer(&cm_core->tcp_timer); } - return(0); + + return 0; +} + + +/** + * nes_addr_send_arp + */ +static void nes_addr_send_arp(u32 dst_ip) +{ + struct rtable *rt; + struct flowi fl; + + memset(&fl, 0, sizeof fl); + fl.nl_u.ip4_u.daddr = htonl(dst_ip); + if (ip_route_output_key(&rt, &fl)) { + printk("%s: ip_route_output_key failed for 0x%08X\n", + __FUNCTION__, dst_ip); + return; + } + + neigh_event_send(rt->u.dst.neighbour, NULL); + ip_rt_put(rt); } /** * make_cm_node - create a new instance of a cm node */ -static struct nes_cm_node *make_cm_node(struct nes_cm_core *core_p, - struct nes_vnic *nesvnic, struct nes_cm_info *nfo_p, - struct nes_cm_listener *listen_p) +static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core, + struct nes_vnic *nesvnic, struct nes_cm_info *cm_info, + struct nes_cm_listener *listener) { - struct nes_cm_node *node_p; + struct nes_cm_node *cm_node; struct timespec ts; int arpindex = 0; struct nes_device *nesdev; struct nes_adapter *nesadapter; /* create an hte and cm_node for this instance */ - node_p = (struct nes_cm_node *)kzalloc(sizeof(*node_p), GFP_ATOMIC); - if (!node_p) + cm_node = kzalloc(sizeof(*cm_node), GFP_ATOMIC); + if (!cm_node) return NULL; - memset(node_p, 0, sizeof(struct nes_cm_node)); /* set our node specific transport info */ - node_p->loc_addr = nfo_p->loc_addr; - node_p->rem_addr = nfo_p->rem_addr; - node_p->loc_port = nfo_p->loc_port; - node_p->rem_port = nfo_p->rem_port; - node_p->send_write0 = send_first; - dprintk("Make node addresses : loc = %x:%x, rem = %x:%x\n", - node_p->loc_addr, node_p->loc_port, node_p->rem_addr, node_p->rem_port); - node_p->listen_p = listen_p; - node_p->netdev_p = nesvnic->netdev; - node_p->cm_id = nfo_p->cm_id; - memcpy(node_p->loc_mac, nesvnic->netdev->dev_addr, ETH_ALEN); - - INIT_LIST_HEAD(&node_p->retrans_list); - spin_lock_init(&node_p->retrans_list_lock); - INIT_LIST_HEAD(&node_p->recv_list); - spin_lock_init(&node_p->recv_list_lock); - - node_p->loopbackpartner = NULL; - atomic_set(&node_p->ref_count, 1); + cm_node->loc_addr = cm_info->loc_addr; + cm_node->rem_addr = cm_info->rem_addr; + cm_node->loc_port = cm_info->loc_port; + cm_node->rem_port = cm_info->rem_port; + cm_node->send_write0 = send_first; + nes_debug(NES_DBG_CM, "Make node addresses : loc = %x:%x, rem = %x:%x\n", + cm_node->loc_addr, cm_node->loc_port, cm_node->rem_addr, cm_node->rem_port); + cm_node->listener = listener; + cm_node->netdev = nesvnic->netdev; + cm_node->cm_id = cm_info->cm_id; + memcpy(cm_node->loc_mac, nesvnic->netdev->dev_addr, ETH_ALEN); + + nes_debug(NES_DBG_CM, "listener=%p, cm_id=%p\n", + cm_node->listener, cm_node->cm_id); + + INIT_LIST_HEAD(&cm_node->retrans_list); + spin_lock_init(&cm_node->retrans_list_lock); + INIT_LIST_HEAD(&cm_node->recv_list); + spin_lock_init(&cm_node->recv_list_lock); + + cm_node->loopbackpartner = NULL; + atomic_set(&cm_node->ref_count, 1); /* associate our parent CM core */ - node_p->core_p = core_p; - node_p->tcp_cntxt.loc_id = NES_CM_DEF_LOCAL_ID; - node_p->tcp_cntxt.rcv_wnd = NES_CM_DEFAULT_RCV_WND; + cm_node->cm_core = cm_core; + cm_node->tcp_cntxt.loc_id = NES_CM_DEF_LOCAL_ID; + cm_node->tcp_cntxt.rcv_wscale = NES_CM_DEFAULT_RCV_WND_SCALE; + cm_node->tcp_cntxt.rcv_wnd = NES_CM_DEFAULT_RCV_WND_SCALED >> + NES_CM_DEFAULT_RCV_WND_SCALE; ts = current_kernel_time(); - node_p->tcp_cntxt.loc_seq_num = cpu_to_le32(htonl(ts.tv_nsec)); - node_p->tcp_cntxt.mss = nesvnic->max_frame_size - sizeof(struct iphdr) - + cm_node->tcp_cntxt.loc_seq_num = htonl(ts.tv_nsec); + cm_node->tcp_cntxt.mss = nesvnic->max_frame_size - sizeof(struct iphdr) - sizeof(struct tcphdr) - ETH_HLEN; - dprintk("%s: Setting MSS to %u.\n",__FUNCTION__, node_p->tcp_cntxt.mss); - node_p->tcp_cntxt.rcv_nxt = 0; + cm_node->tcp_cntxt.rcv_nxt = 0; /* get a unique session ID , add thread_id to an upcounter to handle race */ - atomic_inc(&core_p->node_cnt); - atomic_inc(&core_p->session_id); - node_p->session_id = (u32)(atomic_read(&core_p->session_id) + current->tgid); - node_p->conn_type = nfo_p->conn_type; - - node_p->nesvnic = nesvnic; + atomic_inc(&cm_core->node_cnt); + atomic_inc(&cm_core->session_id); + cm_node->session_id = (u32)(atomic_read(&cm_core->session_id) + current->tgid); + cm_node->conn_type = cm_info->conn_type; + cm_node->apbvt_set = 0; + cm_node->accept_pend = 0; + + cm_node->nesvnic = nesvnic; /* get some device handles, for arp lookup */ nesdev = nesvnic->nesdev; nesadapter = nesdev->nesadapter; - node_p->loopbackpartner = NULL; + cm_node->loopbackpartner = NULL; /* get the mac addr for the remote node */ - arpindex = nes_arp_table(nesdev, node_p->rem_addr, NULL, NES_ARP_RESOLVE); + arpindex = nes_arp_table(nesdev, cm_node->rem_addr, NULL, NES_ARP_RESOLVE); if (arpindex < 0) { - dprintk("%s[%d] -- IP addr %x NOT found in ARP table\n", - __FILE__, __LINE__, node_p->rem_addr); - kfree(node_p); - return(NULL); + kfree(cm_node); + nes_addr_send_arp(cm_info->rem_addr); + return NULL; } /* copy the mac addr to node context */ - memcpy(node_p->rem_mac, nesadapter->arp_table[arpindex].mac_addr, ETH_ALEN); - dprintk("%s[%u] -- Remote mac addr from arp table:%02x, %02x, %02x, %02x, %02x, %02x\n", - __FILE__, __LINE__, - node_p->rem_mac[0], node_p->rem_mac[1], - node_p->rem_mac[2], node_p->rem_mac[3], - node_p->rem_mac[4], node_p->rem_mac[5]); + memcpy(cm_node->rem_mac, nesadapter->arp_table[arpindex].mac_addr, ETH_ALEN); + nes_debug(NES_DBG_CM, "Remote mac addr from arp table:%02x," + " %02x, %02x, %02x, %02x, %02x\n", + cm_node->rem_mac[0], cm_node->rem_mac[1], + cm_node->rem_mac[2], cm_node->rem_mac[3], + cm_node->rem_mac[4], cm_node->rem_mac[5]); - add_hte_node(core_p, node_p); + add_hte_node(cm_core, cm_node); + atomic_inc(&cm_nodes_created); - return(node_p); + return cm_node; } /** * add_ref_cm_node - destroy an instance of a cm node */ -static int add_ref_cm_node(struct nes_cm_node *node_p) +static int add_ref_cm_node(struct nes_cm_node *cm_node) { - atomic_inc(&node_p->ref_count); + atomic_inc(&cm_node->ref_count); return 0; } + /** * rem_ref_cm_node - destroy an instance of a cm node */ -static int rem_ref_cm_node(struct nes_cm_core *core_p, - struct nes_cm_node *node_p) +static int rem_ref_cm_node(struct nes_cm_core *cm_core, + struct nes_cm_node *cm_node) { unsigned long flags, qplockflags; struct nes_timer_entry *send_entry; struct nes_timer_entry *recv_entry; struct iw_cm_id *cm_id; - struct list_head *list_p_core, *list_p_node_temp; + struct list_head *list_core, *list_node_temp; struct nes_qp *nesqp; - if (!node_p) - return(-EINVAL); + if (!cm_node) + return -EINVAL; - spin_lock_irqsave(&node_p->core_p->ht_lock, flags); - if(atomic_dec_return(&node_p->ref_count)) { - spin_unlock_irqrestore(&node_p->core_p->ht_lock, flags); + spin_lock_irqsave(&cm_node->cm_core->ht_lock, flags); + if (atomic_dec_return(&cm_node->ref_count)) { + spin_unlock_irqrestore(&cm_node->cm_core->ht_lock, flags); return 0; } - list_del(&node_p->list); - atomic_dec(&core_p->ht_node_cnt); - spin_unlock_irqrestore(&node_p->core_p->ht_lock, flags); + list_del(&cm_node->list); + atomic_dec(&cm_core->ht_node_cnt); + spin_unlock_irqrestore(&cm_node->cm_core->ht_lock, flags); /* if the node is destroyed before connection was accelerated */ - if ( !node_p->accelerated ) { - atomic_dec( &node_p->listen_p->pend_accepts_cnt ); - BUG_ON(atomic_read(&node_p->listen_p->pend_accepts_cnt) < 0 ); + if (!cm_node->accelerated && cm_node->accept_pend) { + BUG_ON(!cm_node->listener); + atomic_dec(&cm_node->listener->pend_accepts_cnt); + BUG_ON(atomic_read(&cm_node->listener->pend_accepts_cnt) < 0); } - spin_lock_irqsave(&node_p->retrans_list_lock, flags); - list_for_each_safe(list_p_core, list_p_node_temp, &node_p->retrans_list) { - send_entry = container_of(list_p_core, struct nes_timer_entry, list); + spin_lock_irqsave(&cm_node->retrans_list_lock, flags); + list_for_each_safe(list_core, list_node_temp, &cm_node->retrans_list) { + send_entry = container_of(list_core, struct nes_timer_entry, list); list_del(&send_entry->list); - spin_unlock_irqrestore(&node_p->retrans_list_lock, flags); + spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); dev_kfree_skb_any(send_entry->skb); kfree(send_entry); - spin_lock_irqsave(&node_p->retrans_list_lock, flags); + spin_lock_irqsave(&cm_node->retrans_list_lock, flags); continue; } - spin_unlock_irqrestore(&node_p->retrans_list_lock, flags); + spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); - spin_lock_irqsave(&node_p->recv_list_lock, flags); - list_for_each_safe(list_p_core, list_p_node_temp, &node_p->recv_list) { - recv_entry = container_of(list_p_core, struct nes_timer_entry, list); + spin_lock_irqsave(&cm_node->recv_list_lock, flags); + list_for_each_safe(list_core, list_node_temp, &cm_node->recv_list) { + recv_entry = container_of(list_core, struct nes_timer_entry, list); list_del(&recv_entry->list); - cm_id = node_p->cm_id; - spin_unlock_irqrestore(&node_p->recv_list_lock, flags); - if(recv_entry->type == NES_TIMER_TYPE_CLOSE) { + cm_id = cm_node->cm_id; + spin_unlock_irqrestore(&cm_node->recv_list_lock, flags); + if (recv_entry->type == NES_TIMER_TYPE_CLOSE) { nesqp = (struct nes_qp *)recv_entry->skb; - cm_id->rem_ref(cm_id); spin_lock_irqsave(&nesqp->lock, qplockflags); if (nesqp->cm_id) { - dprintk("%s: QP%u: cm_id = %p: ****** HIT A NES_TIMER_TYPE_CLOSE" + nes_debug(NES_DBG_CM, "QP%u: cm_id = %p: ****** HIT A NES_TIMER_TYPE_CLOSE" " with something to do!!! ******\n", - __FUNCTION__, nesqp->hwqp.qp_id, cm_id); + nesqp->hwqp.qp_id, cm_id); nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED; nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT; nesqp->ibqp_state = IB_QPS_ERR; @@ -1193,215 +1185,224 @@ static int rem_ref_cm_node(struct nes_cm_core *core_p, nes_cm_disconn(nesqp); } else { spin_unlock_irqrestore(&nesqp->lock, qplockflags); - dprintk("%s: QP%u: cm_id = %p: ****** HIT A NES_TIMER_TYPE_CLOSE" + nes_debug(NES_DBG_CM, "QP%u: cm_id = %p: ****** HIT A NES_TIMER_TYPE_CLOSE" " with nothing to do!!! ******\n", - __FUNCTION__, nesqp->hwqp.qp_id, cm_id); + nesqp->hwqp.qp_id, cm_id); nes_rem_ref(&nesqp->ibqp); } - } - else if(recv_entry->type == NES_TIMER_TYPE_RECV) { + cm_id->rem_ref(cm_id); + } else if (recv_entry->type == NES_TIMER_TYPE_RECV) { dev_kfree_skb_any(recv_entry->skb); } kfree(recv_entry); - spin_lock_irqsave(&node_p->recv_list_lock, flags); + spin_lock_irqsave(&cm_node->recv_list_lock, flags); } - spin_unlock_irqrestore(&node_p->recv_list_lock, flags); + spin_unlock_irqrestore(&cm_node->recv_list_lock, flags); - if(node_p->listen_p) { - mini_cm_dec_refcnt_listen(core_p, node_p->listen_p); - } - else { - if (node_p->nesvnic) { - nes_manage_apbvt(node_p->nesvnic, node_p->loc_port, - PCI_FUNC(node_p->nesvnic->nesdev->pcidev->devfn), NES_MANAGE_APBVT_DEL); + if (cm_node->listener) { + mini_cm_dec_refcnt_listen(cm_core, cm_node->listener, 0); + } else { + if (cm_node->apbvt_set && cm_node->nesvnic) { + nes_manage_apbvt(cm_node->nesvnic, cm_node->loc_port, + PCI_FUNC(cm_node->nesvnic->nesdev->pcidev->devfn), + NES_MANAGE_APBVT_DEL); } } - if (node_p->conn_type == NES_CM_IWARP_CONN_TYPE && node_p->ksock) /* Close & release the socket we opened earlier */ { - sock_release(node_p->ksock); - node_p->ksock = NULL; - } - kfree(node_p); - atomic_dec(&core_p->node_cnt); + kfree(cm_node); + atomic_dec(&cm_core->node_cnt); + atomic_inc(&cm_nodes_destroyed); - return(0); + return 0; } /** * process_options */ -static void process_options(struct nes_cm_node *node_p, u8 *optionsloc, u32 optionsize) +static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc, u32 optionsize, u32 syn_packet) { u32 tmp; u32 offset = 0; union all_known_options *all_options; + char got_mss_option = 0; - while(offset < optionsize) - { + while (offset < optionsize) { all_options = (union all_known_options *)(optionsloc + offset); - switch(all_options->as_base.optionnum) - { - case OPTION_NUMBER_END: - offset = optionsize; - break; - case OPTION_NUMBER_NONE: - offset += 1; - continue; - case OPTION_NUMBER_MSS: - tmp = htons(all_options->as_mss.mss); - if(tmp < node_p->tcp_cntxt.mss) - node_p->tcp_cntxt.mss = tmp; - break; - case OPTION_NUMBER_WINDOW_SCALE: - node_p->tcp_cntxt.snd_wscale = all_options->as_windowscale.shiftcount; - node_p->tcp_cntxt.rcv_wscale = NES_CM_DEFAULT_RCV_WND_SCALE; - node_p->tcp_cntxt.rcv_wnd = NES_CM_DEFAULT_RCV_WND_SCALED >> - NES_CM_DEFAULT_RCV_WND_SCALE; - break; - case OPTION_NUMBER_WRITE0: - node_p->send_write0 = 1; - break; - default: - dprintk("TCP Option not understood: %x\n", all_options->as_base.optionnum); - break; + switch (all_options->as_base.optionnum) { + case OPTION_NUMBER_END: + offset = optionsize; + break; + case OPTION_NUMBER_NONE: + offset += 1; + continue; + case OPTION_NUMBER_MSS: + nes_debug(NES_DBG_CM, "%s: MSS Length: %d Offset: %d Size: %d\n", + __FUNCTION__, + all_options->as_mss.length, offset, optionsize); + got_mss_option = 1; + if (all_options->as_mss.length != 4) { + return 1; + } else { + tmp = ntohs(all_options->as_mss.mss); + if (tmp > 0 && tmp < cm_node->tcp_cntxt.mss) + cm_node->tcp_cntxt.mss = tmp; + } + break; + case OPTION_NUMBER_WINDOW_SCALE: + cm_node->tcp_cntxt.snd_wscale = all_options->as_windowscale.shiftcount; + break; + case OPTION_NUMBER_WRITE0: + cm_node->send_write0 = 1; + break; + default: + nes_debug(NES_DBG_CM, "TCP Option not understood: %x\n", + all_options->as_base.optionnum); + break; } offset += all_options->as_base.length; } + if ((!got_mss_option) && (syn_packet)) + cm_node->tcp_cntxt.mss = NES_CM_DEFAULT_MSS; + return 0; } /** * process_packet */ -int process_packet(struct nes_cm_node *node_p, struct sk_buff *skb_p, - struct nes_cm_core *core_p) +int process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb, + struct nes_cm_core *cm_core) { int optionsize; int datasize; int ret = 0; -#ifdef OFED_1_2 - struct tcphdr *tcphdr_p = skb_p->h.th; -#else - struct tcphdr *tcphdr_p = tcp_hdr(skb_p); -#endif + struct tcphdr *tcph = tcp_hdr(skb); u32 inc_sequence; + if (cm_node->state == NES_CM_STATE_SYN_SENT && tcph->syn) { + inc_sequence = ntohl(tcph->seq); + cm_node->tcp_cntxt.rcv_nxt = inc_sequence; + } - dprintk("%s[%u] node_p = %p, state = %u, tcphdr_p = %p.\n", - __FUNCTION__, __LINE__, node_p, node_p->state, tcphdr_p); - if(!tcphdr_p) + if ((!tcph) || (cm_node->state == NES_CM_STATE_TSA)) { + BUG_ON(!tcph); + atomic_inc(&cm_accel_dropped_pkts); return -1; + } - if (tcphdr_p->rst) { - dprintk("%s[%u] Received Reset, node_p = %p, state = %u.\n", - __FUNCTION__, __LINE__, node_p, node_p->state); - switch(node_p->state) { + if (tcph->rst) { + atomic_inc(&cm_resets_recvd); + nes_debug(NES_DBG_CM, "Received Reset, cm_node = %p, state = %u. refcnt=%d\n", + cm_node, cm_node->state, atomic_read(&cm_node->ref_count)); + switch (cm_node->state) { + case NES_CM_STATE_LISTENING: + rem_ref_cm_node(cm_core, cm_node); + break; case NES_CM_STATE_TSA: case NES_CM_STATE_CLOSED: - case NES_CM_STATE_LISTENING: break; case NES_CM_STATE_SYN_RCVD: - printk("%s: Received a reset for local 0x%08X:%04X, remote 0x%08X:%04X," - " node state = %u\n", - __FUNCTION__, node_p->loc_addr, node_p->loc_port, - node_p->rem_addr, node_p->rem_port, - node_p->state); - rem_ref_cm_node(core_p, node_p); + nes_debug(NES_DBG_CM, "Received a reset for local 0x%08X:%04X," + " remote 0x%08X:%04X, node state = %u\n", + cm_node->loc_addr, cm_node->loc_port, + cm_node->rem_addr, cm_node->rem_port, + cm_node->state); + rem_ref_cm_node(cm_core, cm_node); break; case NES_CM_STATE_ONE_SIDE_ESTABLISHED: case NES_CM_STATE_ESTABLISHED: case NES_CM_STATE_MPAREQ_SENT: default: - printk("%s: Received a reset for local 0x%08X:%04X, remote 0x%08X:%04X," - " node state = %u\n", - __FUNCTION__, node_p->loc_addr, node_p->loc_port, - node_p->rem_addr, node_p->rem_port, - node_p->state); + nes_debug(NES_DBG_CM, "Received a reset for local 0x%08X:%04X," + " remote 0x%08X:%04X, node state = %u refcnt=%d\n", + cm_node->loc_addr, cm_node->loc_port, + cm_node->rem_addr, cm_node->rem_port, + cm_node->state, atomic_read(&cm_node->ref_count)); // create event - node_p->state = NES_CM_STATE_CLOSED; - if ( NES_CM_IWARP_CONN_TYPE == node_p->conn_type ) - create_event(node_p, NES_CM_EVENT_ABORTED); + cm_node->state = NES_CM_STATE_CLOSED; + + create_event(cm_node, NES_CM_EVENT_ABORTED); break; } return -1; } - optionsize = (tcphdr_p->doff << 2) - sizeof(struct tcphdr); + optionsize = (tcph->doff << 2) - sizeof(struct tcphdr); -#ifdef OFED_1_2 - skb_pull(skb_p, skb_p->nh.iph->ihl << 2); -#else - skb_pull(skb_p, ip_hdr(skb_p)->ihl << 2); -#endif - skb_pull(skb_p, tcphdr_p->doff << 2); + skb_pull(skb, ip_hdr(skb)->ihl << 2); + skb_pull(skb, tcph->doff << 2); - datasize = skb_p->len; - inc_sequence = ntohl(tcphdr_p->seq); - dprintk("%s[%u] datasize = %u, sequence = 0x%08X, ack_seq = 0x%08X, rcv_nxt = 0x%08X Flags: %s %s.\n", - __FUNCTION__, __LINE__, datasize, inc_sequence,ntohl(tcphdr_p->ack_seq), - node_p->tcp_cntxt.rcv_nxt, (tcphdr_p->syn ? "SYN":""),(tcphdr_p->ack ? "ACK":"")); + datasize = skb->len; + inc_sequence = ntohl(tcph->seq); + nes_debug(NES_DBG_CM, "datasize = %u, sequence = 0x%08X, ack_seq = 0x%08X," + " rcv_nxt = 0x%08X Flags: %s %s.\n", + datasize, inc_sequence, ntohl(tcph->ack_seq), + cm_node->tcp_cntxt.rcv_nxt, (tcph->syn ? "SYN":""), + (tcph->ack ? "ACK":"")); - - if (!tcphdr_p->syn && (inc_sequence != node_p->tcp_cntxt.rcv_nxt)) { - return (-1); + if (!tcph->syn && (inc_sequence != cm_node->tcp_cntxt.rcv_nxt) + ) { + nes_debug(NES_DBG_CM, "dropping packet, datasize = %u, sequence = 0x%08X," + " ack_seq = 0x%08X, rcv_nxt = 0x%08X Flags: %s.\n", + datasize, inc_sequence, ntohl(tcph->ack_seq), + cm_node->tcp_cntxt.rcv_nxt, (tcph->ack ? "ACK":"")); + if (cm_node->state == NES_CM_STATE_LISTENING) { + rem_ref_cm_node(cm_core, cm_node); + } + return -1; } - if ( node_p->conn_type == NES_CM_IWARP_CONN_TYPE ) { - if (NES_CM_STATE_TSA == node_p->state) - printk("%s[%u] Bumping rcv_nxt for connection that is already in TSA mode, node_p = %p, state = %u.\n", - __FUNCTION__, __LINE__, node_p, node_p->state); - node_p->tcp_cntxt.rcv_nxt = inc_sequence + datasize; - } else { - if (NES_CM_STATE_TSA != node_p->state) - node_p->tcp_cntxt.rcv_nxt = inc_sequence; - } - node_p->tcp_cntxt.snd_wnd = htons(tcphdr_p->window) << - node_p->tcp_cntxt.snd_wscale; + cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize; - if (node_p->tcp_cntxt.snd_wnd > node_p->tcp_cntxt.max_snd_wnd) { - node_p->tcp_cntxt.max_snd_wnd = node_p->tcp_cntxt.snd_wnd; - } if (optionsize) { - u8 *optionsloc = (u8 *) &tcphdr_p[1]; - process_options(node_p, optionsloc, optionsize); + u8 *optionsloc = (u8 *)&tcph[1]; + if (process_options(cm_node, optionsloc, optionsize, (u32)tcph->syn)) { + nes_debug(NES_DBG_CM, "%s: Node %p, Sending RESET\n", __FUNCTION__, cm_node); + send_reset(cm_node); + if (cm_node->state != NES_CM_STATE_SYN_SENT) + rem_ref_cm_node(cm_core, cm_node); + return 0; + } + } else if (tcph->syn) + cm_node->tcp_cntxt.mss = NES_CM_DEFAULT_MSS; + + cm_node->tcp_cntxt.snd_wnd = ntohs(tcph->window) << + cm_node->tcp_cntxt.snd_wscale; + + if (cm_node->tcp_cntxt.snd_wnd > cm_node->tcp_cntxt.max_snd_wnd) { + cm_node->tcp_cntxt.max_snd_wnd = cm_node->tcp_cntxt.snd_wnd; } - if (tcphdr_p->ack) { - node_p->tcp_cntxt.rem_ack_num = ntohl(tcphdr_p->ack_seq); - switch (node_p->state) { + if (tcph->ack) { + cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq); + switch (cm_node->state) { case NES_CM_STATE_SYN_RCVD: case NES_CM_STATE_SYN_SENT: /* read and stash current sequence number */ - if (node_p->tcp_cntxt.rem_ack_num > node_p->tcp_cntxt.loc_seq_num) { - dprintk("ERROR - node_p->tcp_cntxt.rem_ack_num >" - " node_p->tcp_cntxt.loc_seq_num\n"); - send_reset(node_p); - return (0); + if (cm_node->tcp_cntxt.rem_ack_num != cm_node->tcp_cntxt.loc_seq_num) { + nes_debug(NES_DBG_CM, "ERROR - cm_node->tcp_cntxt.rem_ack_num !=" + " cm_node->tcp_cntxt.loc_seq_num\n"); + send_reset(cm_node); + return 0; } - if (node_p->state == NES_CM_STATE_SYN_SENT) - node_p->state = NES_CM_STATE_ONE_SIDE_ESTABLISHED; - else { - if (node_p->conn_type == NES_CM_IWARP_CONN_TYPE) { - node_p->state = NES_CM_STATE_ESTABLISHED; - } else { - create_event(node_p, NES_CM_EVENT_MPA_REQ); - /* we are done handling this state, set node to a TSA state */ - node_p->state = NES_CM_STATE_TSA; - } + if (cm_node->state == NES_CM_STATE_SYN_SENT) + cm_node->state = NES_CM_STATE_ONE_SIDE_ESTABLISHED; + else { + cm_node->state = NES_CM_STATE_ESTABLISHED; } break; case NES_CM_STATE_LAST_ACK: - node_p->state = NES_CM_STATE_CLOSED; + cm_node->state = NES_CM_STATE_CLOSED; break; case NES_CM_STATE_FIN_WAIT1: - node_p->state = NES_CM_STATE_FIN_WAIT2; + cm_node->state = NES_CM_STATE_FIN_WAIT2; break; case NES_CM_STATE_CLOSING: - node_p->state = NES_CM_STATE_TIME_WAIT; + cm_node->state = NES_CM_STATE_TIME_WAIT; /* need to schedule this to happen in 2MSL timeouts */ - node_p->state = NES_CM_STATE_CLOSED; + cm_node->state = NES_CM_STATE_CLOSED; break; case NES_CM_STATE_ONE_SIDE_ESTABLISHED: case NES_CM_STATE_ESTABLISHED: @@ -1411,110 +1412,104 @@ int process_packet(struct nes_cm_node *node_p, struct sk_buff *skb_p, case NES_CM_STATE_CLOSED: break; case NES_CM_STATE_LISTENING: - if (!(tcphdr_p->syn)) { - dprintk("Received an ack without a SYN on a listening port\n"); - send_reset(node_p); - //rem_ref_cm_node(core_p, node_p); - } else { - dprintk("Received an ack on a listening port (syn-ack maybe?)\n"); - } + nes_debug(NES_DBG_CM, "Received an ACK on a listening port (SYN %d)\n", tcph->syn); + cm_node->tcp_cntxt.loc_seq_num = ntohl(tcph->ack_seq); + send_reset(cm_node); + /* send_reset bumps refcount, this should have been a new node */ + rem_ref_cm_node(cm_core, cm_node); + return -1; break; case NES_CM_STATE_TSA: - dprintk("Received a packet with the ack bit set while in TSA state\n"); + nes_debug(NES_DBG_CM, "Received a packet with the ack bit set while in TSA state\n"); break; case NES_CM_STATE_UNKNOWN: case NES_CM_STATE_INITED: case NES_CM_STATE_ACCEPTING: case NES_CM_STATE_FIN_WAIT2: default: - dprintk("Received ack from unknown state: %x\n", node_p->state); - send_reset(node_p); + nes_debug(NES_DBG_CM, "Received ack from unknown state: %x\n", + cm_node->state); + send_reset(cm_node); break; } } - if (tcphdr_p->syn) { - if ( node_p->state == NES_CM_STATE_LISTENING ) { - /* do not exceed backlog */ - atomic_inc( &node_p->listen_p->pend_accepts_cnt ); - if ( atomic_read(&node_p->listen_p->pend_accepts_cnt) >= node_p->listen_p->backlog ) { - dprintk("%s(%d) drop syn due to backlog pressure \n", __FUNCTION__, __LINE__ ); - cm_backlog_drops++; - atomic_dec( &node_p->listen_p->pend_accepts_cnt ); - return 0; - } + if (tcph->syn) { + if (cm_node->state == NES_CM_STATE_LISTENING) { + /* do not exceed backlog */ + atomic_inc(&cm_node->listener->pend_accepts_cnt); + if (atomic_read(&cm_node->listener->pend_accepts_cnt) > + cm_node->listener->backlog) { + nes_debug(NES_DBG_CM, "drop syn due to backlog pressure \n"); + cm_backlog_drops++; + atomic_dec(&cm_node->listener->pend_accepts_cnt); + rem_ref_cm_node(cm_core, cm_node); + return 0; + } + cm_node->accept_pend = 1; } if (datasize == 0) - node_p->tcp_cntxt.rcv_nxt ++; - - dprintk("%s: Received SYN\n", __FUNCTION__); - if (node_p->state == NES_CM_STATE_LISTENING) { - node_p->state = NES_CM_STATE_SYN_RCVD; - send_syn(node_p, 1); - dprintk("%s:%s[%u] -- Sent syn_ack\n", - __FILE__, __FUNCTION__, __LINE__); + cm_node->tcp_cntxt.rcv_nxt ++; + + if (cm_node->state == NES_CM_STATE_LISTENING) { + cm_node->state = NES_CM_STATE_SYN_RCVD; + send_syn(cm_node, 1); } - if (node_p->state == NES_CM_STATE_ONE_SIDE_ESTABLISHED) { - node_p->state = NES_CM_STATE_ESTABLISHED; + if (cm_node->state == NES_CM_STATE_ONE_SIDE_ESTABLISHED) { + cm_node->state = NES_CM_STATE_ESTABLISHED; /* send final handshake ACK */ - ret = send_ack(node_p); + ret = send_ack(cm_node); if (ret < 0) - return (ret); + return ret; - if (node_p->conn_type == NES_CM_IWARP_CONN_TYPE) { - node_p->state = NES_CM_STATE_MPAREQ_SENT; - ret = send_mpa_request(node_p); + cm_node->state = NES_CM_STATE_MPAREQ_SENT; + ret = send_mpa_request(cm_node); if (ret < 0) - return (ret); - } else { - create_event(node_p, NES_CM_EVENT_CONNECTED); - node_p->state = NES_CM_STATE_TSA; - } + return ret; } } - if (tcphdr_p->fin) { - dprintk("%s: Received FIN\n", __FUNCTION__); - node_p->tcp_cntxt.rcv_nxt++; - switch (node_p->state) { + if (tcph->fin) { + cm_node->tcp_cntxt.rcv_nxt++; + switch (cm_node->state) { case NES_CM_STATE_SYN_RCVD: case NES_CM_STATE_SYN_SENT: case NES_CM_STATE_ONE_SIDE_ESTABLISHED: case NES_CM_STATE_ESTABLISHED: case NES_CM_STATE_ACCEPTING: case NES_CM_STATE_MPAREQ_SENT: - node_p->state = NES_CM_STATE_CLOSE_WAIT; - node_p->state = NES_CM_STATE_LAST_ACK; - ret = send_fin(node_p, NULL); + cm_node->state = NES_CM_STATE_CLOSE_WAIT; + cm_node->state = NES_CM_STATE_LAST_ACK; + ret = send_fin(cm_node, NULL); break; case NES_CM_STATE_FIN_WAIT1: - node_p->state = NES_CM_STATE_CLOSING; - ret = send_ack(node_p); + cm_node->state = NES_CM_STATE_CLOSING; + ret = send_ack(cm_node); break; case NES_CM_STATE_FIN_WAIT2: - node_p->state = NES_CM_STATE_TIME_WAIT; - node_p->tcp_cntxt.loc_seq_num ++; - ret = send_ack(node_p); + cm_node->state = NES_CM_STATE_TIME_WAIT; + cm_node->tcp_cntxt.loc_seq_num ++; + ret = send_ack(cm_node); /* need to schedule this to happen in 2MSL timeouts */ - node_p->state = NES_CM_STATE_CLOSED; + cm_node->state = NES_CM_STATE_CLOSED; break; case NES_CM_STATE_CLOSE_WAIT: case NES_CM_STATE_LAST_ACK: case NES_CM_STATE_CLOSING: case NES_CM_STATE_TSA: default: - dprintk(KERN_INFO PFX "Received a fin while in %x state\n", - node_p->state); + nes_debug(NES_DBG_CM, "Received a fin while in %x state\n", + cm_node->state); ret = -EINVAL; break; } } if (datasize) { - u8 *dataloc = skb_p->data; + u8 *dataloc = skb->data; /* figure out what state we are in and handle transition to next state */ - switch (node_p->state) { + switch (cm_node->state) { case NES_CM_STATE_LISTENING: case NES_CM_STATE_SYN_RCVD: case NES_CM_STATE_SYN_SENT: @@ -1526,27 +1521,29 @@ int process_packet(struct nes_cm_node *node_p, struct sk_buff *skb_p, break; case NES_CM_STATE_MPAREQ_SENT: /* recv the mpa res frame, ret=frame len (incl priv data) */ - ret = parse_mpa(node_p, dataloc, datasize); + ret = parse_mpa(cm_node, dataloc, datasize); if (ret < 0) break; /* set the req frame payload len in skb */ /* we are done handling this state, set node to a TSA state */ - node_p->state = NES_CM_STATE_TSA; - create_event(node_p, NES_CM_EVENT_CONNECTED); + cm_node->state = NES_CM_STATE_TSA; + send_ack(cm_node); + create_event(cm_node, NES_CM_EVENT_CONNECTED); break; case NES_CM_STATE_ESTABLISHED: /* we are expecting an MPA req frame */ - ret = parse_mpa(node_p, dataloc, datasize); - if (ret < 0) + ret = parse_mpa(cm_node, dataloc, datasize); + if (ret < 0) { break; - dprintk("%s[%u] -- MPA frame size = %u\n", __FILE__, __LINE__, ret); - node_p->state = NES_CM_STATE_TSA; + } + cm_node->state = NES_CM_STATE_TSA; + send_ack(cm_node); /* we got a valid MPA request, create an event */ - create_event(node_p, NES_CM_EVENT_MPA_REQ); + create_event(cm_node, NES_CM_EVENT_MPA_REQ); break; case NES_CM_STATE_TSA: - handle_exception_pkt(node_p, skb_p); + handle_exception_pkt(cm_node, skb); break; case NES_CM_STATE_UNKNOWN: case NES_CM_STATE_INITED: @@ -1555,148 +1552,163 @@ int process_packet(struct nes_cm_node *node_p, struct sk_buff *skb_p, } } - dprintk("%s[%u] Exit\n", __FUNCTION__, __LINE__); - return(ret); + return ret; } /** * mini_cm_listen - create a listen node with params */ -static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *core_p, - struct nes_vnic *nesvnic, struct nes_cm_info *nfo_p) +static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core, + struct nes_vnic *nesvnic, struct nes_cm_info *cm_info) { - struct nes_cm_listener *listen_p; + struct nes_cm_listener *listener; unsigned long flags; + nes_debug(NES_DBG_CM, "Search for 0x%08x : 0x%04x\n", + cm_info->loc_addr, cm_info->loc_port); + /* cannot have multiple matching listeners */ - listen_p = find_listener( core_p, htonl(nfo_p->loc_addr), htons(nfo_p->loc_port), NES_CM_LISTENER_EITHER_STATE ); - if ( listen_p && listen_p->listener_state == NES_CM_LISTENER_ACTIVE_STATE ) { - /* find automatically incs ref count ??? */ - atomic_dec(&listen_p->ref_count); - dprintk( "%s(%d) Not creating listener since it already exists\n", __FUNCTION__, __LINE__ ); - return NULL; + listener = find_listener(cm_core, htonl(cm_info->loc_addr), + htons(cm_info->loc_port), NES_CM_LISTENER_EITHER_STATE); + if (listener && listener->listener_state == NES_CM_LISTENER_ACTIVE_STATE) { + /* find automatically incs ref count ??? */ + atomic_dec(&listener->ref_count); + nes_debug(NES_DBG_CM, "Not creating listener since it already exists\n"); + return NULL; } - if ( !listen_p ) { - /* create a CM listen node (1/2 node to compare incoming traffic to) */ - listen_p = (struct nes_cm_listener *)kzalloc(sizeof(*listen_p), GFP_ATOMIC); - if (!listen_p) { - dprintk( "%s(%d) Not creating listener memory allocation failed\n", __FUNCTION__, __LINE__ ); - return NULL; - } + if (!listener) { + /* create a CM listen node (1/2 node to compare incoming traffic to) */ + listener = kzalloc(sizeof(*listener), GFP_ATOMIC); + if (!listener) { + nes_debug(NES_DBG_CM, "Not creating listener memory allocation failed\n"); + return NULL; + } - memset(listen_p, 0, sizeof(struct nes_cm_listener)); - listen_p->loc_addr = htonl(nfo_p->loc_addr); - listen_p->loc_port = htons(nfo_p->loc_port); - listen_p->reused_node = 0; + memset(listener, 0, sizeof(struct nes_cm_listener)); + listener->loc_addr = htonl(cm_info->loc_addr); + listener->loc_port = htons(cm_info->loc_port); + listener->reused_node = 0; - atomic_set(&listen_p->ref_count, 1); + atomic_set(&listener->ref_count, 1); } /* pasive case */ /* find already inc'ed the ref count */ else { - listen_p->reused_node = 1; + listener->reused_node = 1; } - listen_p->cm_id = nfo_p->cm_id; - atomic_set(&listen_p->pend_accepts_cnt, 0); - listen_p->core_p = core_p; - listen_p->nesvnic = nesvnic; - atomic_inc(&core_p->node_cnt); - atomic_inc(&core_p->session_id); + listener->cm_id = cm_info->cm_id; + atomic_set(&listener->pend_accepts_cnt, 0); + listener->cm_core = cm_core; + listener->nesvnic = nesvnic; + atomic_inc(&cm_core->node_cnt); + atomic_inc(&cm_core->session_id); - listen_p->session_id = (u32)(atomic_read(&core_p->session_id) + current->tgid); - listen_p->conn_type = nfo_p->conn_type; - listen_p->backlog = nfo_p->backlog; - listen_p->listener_state = NES_CM_LISTENER_ACTIVE_STATE; + listener->session_id = (u32)(atomic_read(&cm_core->session_id) + current->tgid); + listener->conn_type = cm_info->conn_type; + listener->backlog = cm_info->backlog; + listener->listener_state = NES_CM_LISTENER_ACTIVE_STATE; - if ( !listen_p->reused_node ) { - spin_lock_irqsave(&core_p->listen_list_lock, flags); - list_add(&listen_p->list, &core_p->listen_list.list); - spin_unlock_irqrestore(&core_p->listen_list_lock, flags); - atomic_inc(&core_p->listen_node_cnt); + if (!listener->reused_node) { + spin_lock_irqsave(&cm_core->listen_list_lock, flags); + list_add(&listener->list, &cm_core->listen_list.list); + spin_unlock_irqrestore(&cm_core->listen_list_lock, flags); + atomic_inc(&cm_core->listen_node_cnt); } - dprintk("%s[%u] -- Api - listen(): addr=0x%08X, port=0x%04x, listener = %p, backlog = %d, cm_id = %p.\n", - __FILE__,__LINE__, ntohl(nfo_p->loc_addr), ntohs(nfo_p->loc_port), - listen_p, listen_p->backlog, listen_p->cm_id); + nes_debug(NES_DBG_CM, "Api - listen(): addr=0x%08X, port=0x%04x," + " listener = %p, backlog = %d, cm_id = %p.\n", + cm_info->loc_addr, cm_info->loc_port, + listener, listener->backlog, listener->cm_id); - return(listen_p); + return listener; } /** * mini_cm_connect - make a connection node with params */ -struct nes_cm_node * mini_cm_connect(struct nes_cm_core *core_p, - struct nes_vnic *nesvnic, struct ietf_mpa_frame *mpa_frame_p, - struct nes_cm_info *nfo_p) +struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core, + struct nes_vnic *nesvnic, struct ietf_mpa_frame *mpa_frame, + struct nes_cm_info *cm_info) { int ret = 0; - struct nes_cm_node *node_p; + struct nes_cm_node *cm_node; struct nes_cm_listener *loopbackremotelistener; struct nes_cm_node *loopbackremotenode; + struct nes_cm_info loopback_cm_info; u16 mpa_frame_size = sizeof(struct ietf_mpa_frame) + - ntohs(mpa_frame_p->priv_data_len); + ntohs(mpa_frame->priv_data_len); - nfo_p->loc_addr = htonl(nfo_p->loc_addr); - nfo_p->rem_addr = htonl(nfo_p->rem_addr); - nfo_p->loc_port = htons(nfo_p->loc_port); - nfo_p->rem_port = htons(nfo_p->rem_port); + cm_info->loc_addr = htonl(cm_info->loc_addr); + cm_info->rem_addr = htonl(cm_info->rem_addr); + cm_info->loc_port = htons(cm_info->loc_port); + cm_info->rem_port = htons(cm_info->rem_port); /* create a CM connection node */ - node_p = make_cm_node(core_p, nesvnic, nfo_p, NULL); - if (!node_p) - return(NULL); - + cm_node = make_cm_node(cm_core, nesvnic, cm_info, NULL); + if (!cm_node) + return NULL; // set our node side to client (active) side - node_p->tcp_cntxt.client = 1; + cm_node->tcp_cntxt.client = 1; + cm_node->tcp_cntxt.rcv_wscale = NES_CM_DEFAULT_RCV_WND_SCALE; + + if (cm_info->loc_addr == cm_info->rem_addr) { + loopbackremotelistener = find_listener(cm_core, cm_node->rem_addr, + cm_node->rem_port, NES_CM_LISTENER_ACTIVE_STATE); + if (loopbackremotelistener == NULL) { + create_event(cm_node, NES_CM_EVENT_ABORTED); + } else { + atomic_inc(&cm_loopbacks); + loopback_cm_info = *cm_info; + loopback_cm_info.loc_port = cm_info->rem_port; + loopback_cm_info.rem_port = cm_info->loc_port; + loopback_cm_info.cm_id = loopbackremotelistener->cm_id; + loopbackremotenode = make_cm_node(cm_core, nesvnic, &loopback_cm_info, + loopbackremotelistener); + loopbackremotenode->loopbackpartner = cm_node; + loopbackremotenode->tcp_cntxt.rcv_wscale = NES_CM_DEFAULT_RCV_WND_SCALE; + cm_node->loopbackpartner = loopbackremotenode; + memcpy(loopbackremotenode->mpa_frame_buf, &mpa_frame->priv_data, + mpa_frame_size); + loopbackremotenode->mpa_frame_size = mpa_frame_size - + sizeof(struct ietf_mpa_frame); - if(nfo_p->loc_addr == nfo_p->rem_addr) { - loopbackremotelistener = find_listener( - core_p, node_p->rem_addr, node_p->rem_port, NES_CM_LISTENER_ACTIVE_STATE ); - if(NULL == loopbackremotelistener) { - create_event(node_p, NES_CM_EVENT_ABORTED); - } - else { - u16 temp; - dprintk("loopback connection\n"); - temp = nfo_p->loc_port; - nfo_p->loc_port = nfo_p->rem_port; - nfo_p->rem_port = temp; - loopbackremotenode = make_cm_node(core_p, nesvnic, nfo_p, loopbackremotelistener); - loopbackremotenode->loopbackpartner = node_p; - node_p->loopbackpartner = loopbackremotenode; - memcpy(loopbackremotenode->mpa_frame_b, &mpa_frame_p->priv_data, mpa_frame_size); - loopbackremotenode->mpa_frame_size = mpa_frame_size - sizeof(struct ietf_mpa_frame); + // we are done handling this state, set node to a TSA state + cm_node->state = NES_CM_STATE_TSA; + cm_node->tcp_cntxt.rcv_nxt = loopbackremotenode->tcp_cntxt.loc_seq_num; + loopbackremotenode->tcp_cntxt.rcv_nxt = cm_node->tcp_cntxt.loc_seq_num; + cm_node->tcp_cntxt.max_snd_wnd = loopbackremotenode->tcp_cntxt.rcv_wnd; + loopbackremotenode->tcp_cntxt.max_snd_wnd = cm_node->tcp_cntxt.rcv_wnd; + cm_node->tcp_cntxt.snd_wnd = loopbackremotenode->tcp_cntxt.rcv_wnd; + loopbackremotenode->tcp_cntxt.snd_wnd = cm_node->tcp_cntxt.rcv_wnd; + cm_node->tcp_cntxt.snd_wscale = loopbackremotenode->tcp_cntxt.rcv_wscale; + loopbackremotenode->tcp_cntxt.snd_wscale = cm_node->tcp_cntxt.rcv_wscale; create_event(loopbackremotenode, NES_CM_EVENT_MPA_REQ); - // we are done handling this state, set node to a TSA state - node_p->state = NES_CM_STATE_TSA; } - return node_p; + return cm_node; } /* set our node side to client (active) side */ - node_p->tcp_cntxt.client = 1; + cm_node->tcp_cntxt.client = 1; /* init our MPA frame ptr */ - nes_dump_mem(mpa_frame_p, mpa_frame_size); - memcpy(&node_p->mpa_frame_p, mpa_frame_p, mpa_frame_size); - node_p->mpa_frame_size = mpa_frame_size; + memcpy(&cm_node->mpa_frame, mpa_frame, mpa_frame_size); + cm_node->mpa_frame_size = mpa_frame_size; /* send a syn and goto syn sent state */ - node_p->state = NES_CM_STATE_SYN_SENT; - ret = send_syn(node_p, 0); + cm_node->state = NES_CM_STATE_SYN_SENT; + ret = send_syn(cm_node, 0); - dprintk("%s[%u] -- Exit\n", __FUNCTION__,__LINE__); - dprintk("%s[%u] -- Api - connect(): dest addr=0x%08X, port=0x%04x, node_p=%p, cm_id = %p.\n", - __FILE__,__LINE__, node_p->rem_addr, node_p->rem_port, - node_p, node_p->cm_id); + nes_debug(NES_DBG_CM, "Api - connect(): dest addr=0x%08X, port=0x%04x," + " cm_node=%p, cm_id = %p.\n", + cm_node->rem_addr, cm_node->rem_port, cm_node, cm_node->cm_id); - return(node_p); + return cm_node; } @@ -1704,59 +1716,58 @@ struct nes_cm_node * mini_cm_connect(struct nes_cm_core *core_p, * mini_cm_accept - accept a connection * This function is never called */ -int mini_cm_accept(struct nes_cm_core *core_p, struct ietf_mpa_frame *mpa_frame_p, - struct nes_cm_node *node_p) +int mini_cm_accept(struct nes_cm_core *cm_core, struct ietf_mpa_frame *mpa_frame, + struct nes_cm_node *cm_node) { - return(0); + return 0; } /** * mini_cm_reject - reject and teardown a connection */ -int mini_cm_reject(struct nes_cm_core *core_p, - struct ietf_mpa_frame *mpa_frame_p, - struct nes_cm_node *node_p) +int mini_cm_reject(struct nes_cm_core *cm_core, + struct ietf_mpa_frame *mpa_frame, + struct nes_cm_node *cm_node) { int ret = 0; - struct sk_buff *skb_p; + struct sk_buff *skb; u16 mpa_frame_size = sizeof(struct ietf_mpa_frame) + - ntohs(mpa_frame_p->priv_data_len); + ntohs(mpa_frame->priv_data_len); - skb_p = get_free_pkt(node_p); - if (!skb_p) { - dprintk("%s:%s[%u] -- Failed to get a Free pkt\n",__FILE__, __FUNCTION__, __LINE__); - return (-1); + skb = get_free_pkt(cm_node); + if (!skb) { + nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n"); + return -1; } /* send an MPA Request frame */ - form_cm_frame(skb_p, node_p, NULL, 0, mpa_frame_p, mpa_frame_size, SET_ACK | SET_FIN); - ret = schedule_nes_timer(node_p, skb_p, NES_TIMER_TYPE_SEND, 1, 0); + form_cm_frame(skb, cm_node, NULL, 0, mpa_frame, mpa_frame_size, SET_ACK | SET_FIN); + ret = schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0); - node_p->state = NES_CM_STATE_CLOSED; - ret = send_fin(node_p, NULL); + cm_node->state = NES_CM_STATE_CLOSED; + ret = send_fin(cm_node, NULL); if (ret < 0) { printk(KERN_INFO PFX "failed to send MPA Reply (reject)\n"); - return (ret); + return ret; } - dprintk("%s[%u] -- \n", __FILE__, __LINE__); - return(ret); + return ret; } /** * mini_cm_close */ -int mini_cm_close(struct nes_cm_core *core_p, struct nes_cm_node *node_p) +int mini_cm_close(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node) { int ret = 0; - if (!core_p || !node_p) - return(-EINVAL); + if (!cm_core || !cm_node) + return -EINVAL; - switch (node_p->state) { + switch (cm_node->state) { /* if passed in node is null, create a reference key node for node search */ /* check if we found an owner node for this pkt */ case NES_CM_STATE_SYN_RCVD: @@ -1765,12 +1776,12 @@ int mini_cm_close(struct nes_cm_core *core_p, struct nes_cm_node *node_p) case NES_CM_STATE_ESTABLISHED: case NES_CM_STATE_ACCEPTING: case NES_CM_STATE_MPAREQ_SENT: - node_p->state = NES_CM_STATE_FIN_WAIT1; - send_fin(node_p, NULL); + cm_node->state = NES_CM_STATE_FIN_WAIT1; + send_fin(cm_node, NULL); break; case NES_CM_STATE_CLOSE_WAIT: - node_p->state = NES_CM_STATE_LAST_ACK; - send_fin(node_p, NULL); + cm_node->state = NES_CM_STATE_LAST_ACK; + send_fin(cm_node, NULL); break; case NES_CM_STATE_FIN_WAIT1: case NES_CM_STATE_FIN_WAIT2: @@ -1784,11 +1795,11 @@ int mini_cm_close(struct nes_cm_core *core_p, struct nes_cm_node *node_p) case NES_CM_STATE_INITED: case NES_CM_STATE_CLOSED: case NES_CM_STATE_TSA: - ret = rem_ref_cm_node(core_p, node_p); + ret = rem_ref_cm_node(cm_core, cm_node); break; } - node_p->cm_id = NULL; - return(ret); + cm_node->cm_id = NULL; + return ret; } @@ -1796,69 +1807,90 @@ int mini_cm_close(struct nes_cm_core *core_p, struct nes_cm_node *node_p) * recv_pkt - recv an ETHERNET packet, and process it through CM * node state machine */ -int mini_cm_recv_pkt(struct nes_cm_core *core_p, struct nes_vnic *nesvnic, - struct sk_buff *skb_p) +int mini_cm_recv_pkt(struct nes_cm_core *cm_core, struct nes_vnic *nesvnic, + struct sk_buff *skb) { - struct nes_cm_node *node_p = NULL; + struct nes_cm_node *cm_node = NULL; struct nes_cm_listener *listener = NULL; - struct iphdr *iphdr_p; - struct tcphdr *tcphdr_p; + struct iphdr *iph; + struct tcphdr *tcph; struct nes_cm_info nfo; + int ret = 0; - if (!skb_p || skb_p->len < sizeof(struct iphdr) + sizeof(struct tcphdr)) - return(-EINVAL); - - iphdr_p = (struct iphdr *)skb_p->data; - tcphdr_p = (struct tcphdr *)(skb_p->data + sizeof(struct iphdr)); -#ifdef OFED_1_2 - skb_p->nh.iph = iphdr_p; - skb_p->h.th = tcphdr_p; -#else - skb_reset_network_header(skb_p); - skb_set_transport_header(skb_p, sizeof(*tcphdr_p)); -#endif - skb_p->len = htons(iphdr_p->tot_len); + if (!skb || skb->len < sizeof(struct iphdr) + sizeof(struct tcphdr)) { + ret = -EINVAL; + goto out; + } + + iph = (struct iphdr *)skb->data; + tcph = (struct tcphdr *)(skb->data + sizeof(struct iphdr)); + skb_reset_network_header(skb); + skb_set_transport_header(skb, sizeof(*tcph)); + skb->len = ntohs(iph->tot_len); + + nfo.loc_addr = ntohl(iph->daddr); + nfo.loc_port = ntohs(tcph->dest); + nfo.rem_addr = ntohl(iph->saddr); + nfo.rem_port = ntohs(tcph->source); - nfo.loc_addr = ntohl(iphdr_p->daddr); - nfo.loc_port = ntohs(tcphdr_p->dest); - nfo.rem_addr = ntohl(iphdr_p->saddr); - nfo.rem_port = ntohs(tcphdr_p->source); + nes_debug(NES_DBG_CM, "Received packet: dest=0x%08X:0x%04X src=0x%08X:0x%04X\n", + iph->daddr, tcph->dest, iph->saddr, tcph->source); - /* note: this call is going to increment node_p ref count */ - node_p = find_node(core_p, + /* note: this call is going to increment cm_node ref count */ + cm_node = find_node(cm_core, nfo.rem_port, nfo.rem_addr, nfo.loc_port, nfo.loc_addr); - if (!node_p) { - listener = find_listener(core_p, nfo.loc_addr, nfo.loc_port, NES_CM_LISTENER_ACTIVE_STATE ); + if (!cm_node) { + listener = find_listener(cm_core, nfo.loc_addr, nfo.loc_port, + NES_CM_LISTENER_ACTIVE_STATE); if (listener) { nfo.cm_id = listener->cm_id; nfo.conn_type = listener->conn_type; - } - else { + } else { nfo.cm_id = NULL; nfo.conn_type = 0; } - node_p = make_cm_node(core_p, nesvnic, &nfo, listener); - if(!node_p) { - printk(KERN_ERR PFX "Unable to allocate node\n"); - return (-1); + cm_node = make_cm_node(cm_core, nesvnic, &nfo, listener); + if (!cm_node) { + nes_debug(NES_DBG_CM, "Unable to allocate node\n"); + if (listener) { + nes_debug(NES_DBG_CM, "unable to allocate node and decrementing listener refcount\n"); + atomic_dec(&listener->ref_count); + } + ret = -1; + goto out; } - add_ref_cm_node(node_p); if (!listener) { - printk(KERN_ERR PFX "Packet found for unknown port %x\n", nfo.loc_port); - send_reset(node_p); - return (-1); + nes_debug(NES_DBG_CM, "Packet found for unknown port %x refcnt=%d\n", + nfo.loc_port, atomic_read(&cm_node->ref_count)); + if (!tcph->rst) { + nes_debug(NES_DBG_CM, "Packet found for unknown port=%d" + " rem_port=%d refcnt=%d\n", + nfo.loc_port, nfo.rem_port, atomic_read(&cm_node->ref_count)); + + cm_node->tcp_cntxt.rcv_nxt = ntohl(tcph->seq); + cm_node->tcp_cntxt.loc_seq_num = ntohl(tcph->ack_seq); + send_reset(cm_node); + } + rem_ref_cm_node(cm_core, cm_node); + ret = -1; + goto out; } - node_p->state = NES_CM_STATE_LISTENING; + add_ref_cm_node(cm_node); + cm_node->state = NES_CM_STATE_LISTENING; } - schedule_nes_timer(node_p, skb_p, NES_TIMER_TYPE_RECV, 0, 0); + nes_debug(NES_DBG_CM, "Processing Packet for node %p, data = (%p):\n", + cm_node, skb->data); + process_packet(cm_node, skb, cm_core); - rem_ref_cm_node(core_p, node_p); - - return(0); + rem_ref_cm_node(cm_core, cm_node); + out: + if (skb) + dev_kfree_skb_any(skb); + return ret; } @@ -1869,122 +1901,113 @@ struct nes_cm_core *nes_cm_alloc_core(void) { int i; - struct nes_cm_core *core_p; - struct sk_buff *skb_p = NULL; - - dprintk("%s[%u] -- Init CM Core: " __DATE__ ":" __TIME__ "\n", - __FILE__, __LINE__); + struct nes_cm_core *cm_core; + struct sk_buff *skb = NULL; /* setup the CM core */ /* alloc top level core control structure */ - core_p = kzalloc(sizeof(*core_p), GFP_KERNEL); - if (!core_p) - return(NULL); + cm_core = kzalloc(sizeof(*cm_core), GFP_KERNEL); + if (!cm_core) + return NULL; - INIT_LIST_HEAD(&core_p->connected_nodes); - init_timer(&core_p->tcp_timer); - core_p->tcp_timer.function = nes_cm_timer_tick; + INIT_LIST_HEAD(&cm_core->connected_nodes); + init_timer(&cm_core->tcp_timer); + cm_core->tcp_timer.function = nes_cm_timer_tick; - core_p->mtu = NES_CM_DEFAULT_MTU; - core_p->state = NES_CM_STATE_INITED; - core_p->free_tx_pkt_max = NES_CM_DEFAULT_FREE_PKTS; + cm_core->mtu = NES_CM_DEFAULT_MTU; + cm_core->state = NES_CM_STATE_INITED; + cm_core->free_tx_pkt_max = NES_CM_DEFAULT_FREE_PKTS; - atomic_set(&core_p->session_id, 0); - atomic_set(&core_p->events_posted, 0); + atomic_set(&cm_core->session_id, 0); + atomic_set(&cm_core->events_posted, 0); /* init the packet lists */ - skb_queue_head_init(&core_p->tx_free_list); + skb_queue_head_init(&cm_core->tx_free_list); - for (i=0; i < NES_CM_DEFAULT_FRAME_CNT; i++) { - skb_p = dev_alloc_skb(core_p->mtu); - if (!skb_p) { - kfree(core_p); - return(NULL); + for (i = 0; i < NES_CM_DEFAULT_FRAME_CNT; i++) { + skb = dev_alloc_skb(cm_core->mtu); + if (!skb) { + kfree(cm_core); + return NULL; } /* add 'raw' skb to free frame list */ - skb_queue_head(&core_p->tx_free_list, skb_p); + skb_queue_head(&cm_core->tx_free_list, skb); } - core_p->api = &nes_cm_api; + cm_core->api = &nes_cm_api; - spin_lock_init(&core_p->ht_lock); - spin_lock_init(&core_p->listen_list_lock); + spin_lock_init(&cm_core->ht_lock); + spin_lock_init(&cm_core->listen_list_lock); - INIT_LIST_HEAD(&core_p->listen_list.list); + INIT_LIST_HEAD(&cm_core->listen_list.list); - dprintk("%s[%u] -- Init CM Core completed -- core_p=%p\n", - __FILE__,__LINE__, core_p); + nes_debug(NES_DBG_CM, "Init CM Core completed -- cm_core=%p\n", cm_core); - dprintk("%s[%u] Enable QUEUE EVENTS\n", __FUNCTION__, __LINE__); - core_p->event_wq = create_singlethread_workqueue("nesewq"); - core_p->post_event = nes_cm_post_event; - dprintk("%s[%u] Enable QUEUE DISCONNECTS\n", __FUNCTION__, __LINE__); - core_p->disconn_wq = create_singlethread_workqueue("nesdwq"); + nes_debug(NES_DBG_CM, "Enable QUEUE EVENTS\n"); + cm_core->event_wq = create_singlethread_workqueue("nesewq"); + cm_core->post_event = nes_cm_post_event; + nes_debug(NES_DBG_CM, "Enable QUEUE DISCONNECTS\n"); + cm_core->disconn_wq = create_singlethread_workqueue("nesdwq"); - print_core(core_p); - return(core_p); + print_core(cm_core); + return cm_core; } /** * mini_cm_dealloc_core - deallocate a top level instance of a cm core */ -int mini_cm_dealloc_core(struct nes_cm_core *core_p) +int mini_cm_dealloc_core(struct nes_cm_core *cm_core) { - /* int i; */ - struct list_head *list_p, *list_p_temp; - struct nes_cm_node *node_p; - struct nes_cm_listener *listen_p; - - dprintk("%s[%u] -- De-Alloc CM Core (%p)\n", __FILE__, __LINE__, core_p); + nes_debug(NES_DBG_CM, "De-Alloc CM Core (%p)\n", cm_core); - if (!core_p) - return(-EINVAL); + if (!cm_core) + return -EINVAL; barrier(); - if(timer_pending(&core_p->tcp_timer)) { - del_timer(&core_p->tcp_timer); + if (timer_pending(&cm_core->tcp_timer)) { + del_timer(&cm_core->tcp_timer); } - destroy_workqueue(core_p->event_wq); - destroy_workqueue(core_p->disconn_wq); - dprintk("%s[%u] -- \n", __FILE__, __LINE__); - kfree(core_p); + destroy_workqueue(cm_core->event_wq); + destroy_workqueue(cm_core->disconn_wq); + nes_debug(NES_DBG_CM, "\n"); + kfree(cm_core); - return(0); + return 0; } /** * mini_cm_get */ -int mini_cm_get(struct nes_cm_core *core_p) +int mini_cm_get(struct nes_cm_core *cm_core) { - return(core_p->state); + return cm_core->state; } /** * mini_cm_set */ -int mini_cm_set(struct nes_cm_core *core_p, u32 type, u32 value) +int mini_cm_set(struct nes_cm_core *cm_core, u32 type, u32 value) { int ret = 0; switch (type) { case NES_CM_SET_PKT_SIZE: - core_p->mtu = value; + cm_core->mtu = value; break; case NES_CM_SET_FREE_PKT_Q_SIZE: - core_p->free_tx_pkt_max = value; + cm_core->free_tx_pkt_max = value; break; default: /* unknown set option */ ret = -EINVAL; } - return(ret); + return ret; } @@ -1992,66 +2015,68 @@ int mini_cm_set(struct nes_cm_core *core_p, u32 type, u32 value) * nes_cm_init_tsa_conn setup HW; MPA frames must be * successfully exchanged when this is called */ -static int nes_cm_init_tsa_conn(struct nes_qp *nesqp, struct nes_cm_node *node_p) +static int nes_cm_init_tsa_conn(struct nes_qp *nesqp, struct nes_cm_node *cm_node) { int ret = 0; if (!nesqp) - return(-EINVAL); + return -EINVAL; - nesqp->nesqp_context->misc |= NES_QPCONTEXT_MISC_IPV4 | + nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_IPV4 | NES_QPCONTEXT_MISC_NO_NAGLE | NES_QPCONTEXT_MISC_DO_NOT_FRAG | - NES_QPCONTEXT_MISC_DROS; - - if(node_p->tcp_cntxt.snd_wscale) - nesqp->nesqp_context->misc |= NES_QPCONTEXT_MISC_WSCALE; - - nesqp->nesqp_context->misc2 |= (0 << NES_QPCONTEXT_MISC2_TOS_SHIFT); - nesqp->nesqp_context->misc2 |= (64 << NES_QPCONTEXT_MISC2_TTL_SHIFT); - - nesqp->nesqp_context->mss |= ((u32)node_p->tcp_cntxt.mss) << 16; - - nesqp->nesqp_context->tcp_state_flow_label |= - (u32)NES_QPCONTEXT_TCPSTATE_EST << NES_QPCONTEXT_TCPFLOW_TCP_STATE_SHIFT; - - nesqp->nesqp_context->pd_index_wscale |= - (node_p->tcp_cntxt.snd_wscale << NES_QPCONTEXT_PDWSCALE_SND_WSCALE_SHIFT) & - NES_QPCONTEXT_PDWSCALE_SND_WSCALE_MASK; - - nesqp->nesqp_context->pd_index_wscale |= - (node_p->tcp_cntxt.rcv_wscale << NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_SHIFT) & - NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_MASK; - - nesqp->nesqp_context->keepalive = 0x80; - nesqp->nesqp_context->ts_recent = 0; - nesqp->nesqp_context->ts_age = 0; - nesqp->nesqp_context->snd_nxt = node_p->tcp_cntxt.loc_seq_num; - nesqp->nesqp_context->snd_wnd = node_p->tcp_cntxt.snd_wnd; - nesqp->nesqp_context->rcv_nxt = node_p->tcp_cntxt.rcv_nxt; - nesqp->nesqp_context->rcv_wnd = node_p->tcp_cntxt.rcv_wnd << node_p->tcp_cntxt.rcv_wscale; - nesqp->nesqp_context->snd_max = node_p->tcp_cntxt.loc_seq_num; - nesqp->nesqp_context->snd_una = node_p->tcp_cntxt.loc_seq_num; - nesqp->nesqp_context->srtt = 0; - nesqp->nesqp_context->rttvar = 0x6; - nesqp->nesqp_context->ssthresh = 0x3FFFC000; - nesqp->nesqp_context->cwnd = NES_CM_DEFAULT_RCV_WND; - nesqp->nesqp_context->snd_wl1 = node_p->tcp_cntxt.rcv_nxt; - nesqp->nesqp_context->snd_wl2 = node_p->tcp_cntxt.loc_seq_num; - nesqp->nesqp_context->max_snd_wnd = node_p->tcp_cntxt.max_snd_wnd; - - dprintk("%s: QP%u: rcv_nxt = 0x%08X, snd_nxt = 0x%08X, Setting MSS to %u, PDWscale = 0x%08X, rcv_wnd = %u, context misc = 0x%08X.\n",__FUNCTION__, - nesqp->hwqp.qp_id, nesqp->nesqp_context->rcv_nxt, nesqp->nesqp_context->snd_nxt, - node_p->tcp_cntxt.mss, nesqp->nesqp_context->pd_index_wscale, nesqp->nesqp_context->rcv_wnd, - nesqp->nesqp_context->misc); - dprintk(" snd_wnd = 0x%08X.\n", nesqp->nesqp_context->snd_wnd); - dprintk(" snd_cwnd = 0x%08X.\n", nesqp->nesqp_context->cwnd); - dprintk(" max_swnd = 0x%08X.\n", nesqp->nesqp_context->max_snd_wnd); - - dprintk("%s:%s[%u] -- Change node_p state to TSA\n", - __FILE__, __FUNCTION__, __LINE__); - node_p->state = NES_CM_STATE_TSA; - - return(ret); + NES_QPCONTEXT_MISC_DROS); + + if (cm_node->tcp_cntxt.snd_wscale || cm_node->tcp_cntxt.rcv_wscale) + nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_WSCALE); + + nesqp->nesqp_context->misc2 |= cpu_to_le32(64 << NES_QPCONTEXT_MISC2_TTL_SHIFT); + + nesqp->nesqp_context->mss |= cpu_to_le32(((u32)cm_node->tcp_cntxt.mss) << 16); + + nesqp->nesqp_context->tcp_state_flow_label |= cpu_to_le32( + (u32)NES_QPCONTEXT_TCPSTATE_EST << NES_QPCONTEXT_TCPFLOW_TCP_STATE_SHIFT); + + nesqp->nesqp_context->pd_index_wscale |= cpu_to_le32( + (cm_node->tcp_cntxt.snd_wscale << NES_QPCONTEXT_PDWSCALE_SND_WSCALE_SHIFT) & + NES_QPCONTEXT_PDWSCALE_SND_WSCALE_MASK); + + nesqp->nesqp_context->pd_index_wscale |= cpu_to_le32( + (cm_node->tcp_cntxt.rcv_wscale << NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_SHIFT) & + NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_MASK); + + nesqp->nesqp_context->keepalive = cpu_to_le32(0x80); + nesqp->nesqp_context->ts_recent = 0; + nesqp->nesqp_context->ts_age = 0; + nesqp->nesqp_context->snd_nxt = cpu_to_le32(cm_node->tcp_cntxt.loc_seq_num); + nesqp->nesqp_context->snd_wnd = cpu_to_le32(cm_node->tcp_cntxt.snd_wnd); + nesqp->nesqp_context->rcv_nxt = cpu_to_le32(cm_node->tcp_cntxt.rcv_nxt); + nesqp->nesqp_context->rcv_wnd = cpu_to_le32(cm_node->tcp_cntxt.rcv_wnd << + cm_node->tcp_cntxt.rcv_wscale); + nesqp->nesqp_context->snd_max = cpu_to_le32(cm_node->tcp_cntxt.loc_seq_num); + nesqp->nesqp_context->snd_una = cpu_to_le32(cm_node->tcp_cntxt.loc_seq_num); + nesqp->nesqp_context->srtt = 0; + nesqp->nesqp_context->rttvar = cpu_to_le32(0x6); + nesqp->nesqp_context->ssthresh = cpu_to_le32(0x3FFFC000); + nesqp->nesqp_context->cwnd = cpu_to_le32(2*cm_node->tcp_cntxt.mss); + nesqp->nesqp_context->snd_wl1 = cpu_to_le32(cm_node->tcp_cntxt.rcv_nxt); + nesqp->nesqp_context->snd_wl2 = cpu_to_le32(cm_node->tcp_cntxt.loc_seq_num); + nesqp->nesqp_context->max_snd_wnd = cpu_to_le32(cm_node->tcp_cntxt.max_snd_wnd); + + nes_debug(NES_DBG_CM, "QP%u: rcv_nxt = 0x%08X, snd_nxt = 0x%08X," + " Setting MSS to %u, PDWscale = 0x%08X, rcv_wnd = %u, context misc = 0x%08X.\n", + nesqp->hwqp.qp_id, le32_to_cpu(nesqp->nesqp_context->rcv_nxt), + le32_to_cpu(nesqp->nesqp_context->snd_nxt), + cm_node->tcp_cntxt.mss, le32_to_cpu(nesqp->nesqp_context->pd_index_wscale), + le32_to_cpu(nesqp->nesqp_context->rcv_wnd), + le32_to_cpu(nesqp->nesqp_context->misc)); + nes_debug(NES_DBG_CM, " snd_wnd = 0x%08X.\n", le32_to_cpu(nesqp->nesqp_context->snd_wnd)); + nes_debug(NES_DBG_CM, " snd_cwnd = 0x%08X.\n", le32_to_cpu(nesqp->nesqp_context->cwnd)); + nes_debug(NES_DBG_CM, " max_swnd = 0x%08X.\n", le32_to_cpu(nesqp->nesqp_context->max_snd_wnd)); + + nes_debug(NES_DBG_CM, "Change cm_node state to TSA\n"); + cm_node->state = NES_CM_STATE_TSA; + + return ret; } @@ -2062,36 +2087,33 @@ int nes_cm_disconn(struct nes_qp *nesqp) { unsigned long flags; - dprintk("%s[%u] -- \n", __FILE__, __LINE__); - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); - spin_lock_irqsave(&nesqp->lock, flags); - if (0==nesqp->disconn_pending) { + if (nesqp->disconn_pending == 0) { nesqp->disconn_pending++; spin_unlock_irqrestore(&nesqp->lock, flags); /* nes_add_ref(&nesqp->ibqp); */ /* init our disconnect work element, to */ - NES_INIT_WORK(&nesqp->disconn_work, nes_disconnect_worker, (void *)nesqp); + INIT_WORK(&nesqp->disconn_work, nes_disconnect_worker); - queue_work(g_cm_core_p->disconn_wq, &nesqp->disconn_work); + queue_work(g_cm_core->disconn_wq, &nesqp->disconn_work); } else { spin_unlock_irqrestore(&nesqp->lock, flags); nes_rem_ref(&nesqp->ibqp); } - dprintk("%s[%u] -- \n", __FILE__, __LINE__); - return(0); + + return 0; } /** * nes_disconnect_worker */ -void nes_disconnect_worker(void *parm) +void nes_disconnect_worker(struct work_struct *work) { - struct work_struct *work = parm; struct nes_qp *nesqp = container_of(work, struct nes_qp, disconn_work); - dprintk("%s: processing AEQE id 0x%04X for QP%u.\n", - __FUNCTION__, nesqp->last_aeq, nesqp->hwqp.qp_id); + + nes_debug(NES_DBG_CM, "processing AEQE id 0x%04X for QP%u.\n", + nesqp->last_aeq, nesqp->hwqp.qp_id); nes_cm_disconn_true(nesqp); } @@ -2112,8 +2134,7 @@ int nes_cm_disconn_true(struct nes_qp *nesqp) u8 issued_disconnect_reset = 0; if (!nesqp) { - dprintk("%s[%u] -- disconnect_worker nesqp is NULL\n", __FILE__,__LINE__); - nes_rem_ref(&nesqp->ibqp); + nes_debug(NES_DBG_CM, "disconnect_worker nesqp is NULL\n"); return -1; } @@ -2121,30 +2142,22 @@ int nes_cm_disconn_true(struct nes_qp *nesqp) cm_id = nesqp->cm_id; /* make sure we havent already closed this connection */ if (!cm_id) { - dprintk("%s[%u] -- QP%u disconnect_worker cmid is NULL\n", - __FILE__,__LINE__, nesqp->hwqp.qp_id); + nes_debug(NES_DBG_CM, "QP%u disconnect_worker cmid is NULL\n", + nesqp->hwqp.qp_id); spin_unlock_irqrestore(&nesqp->lock, flags); nes_rem_ref(&nesqp->ibqp); return -1; } nesvnic = to_nesvnic(nesqp->ibqp.device); - dprintk("%s:%u: Disconnecting QP%u\n", - __FUNCTION__, __LINE__, nesqp->hwqp.qp_id); + nes_debug(NES_DBG_CM, "Disconnecting QP%u\n", nesqp->hwqp.qp_id); original_hw_tcp_state = nesqp->hw_tcp_state; original_ibqp_state = nesqp->ibqp_state; last_ae = nesqp->last_aeq; - dprintk("%s:%u:QP%u: Last AEQ id = 0x%04X, cm_id = %p, tcp state = %d," - " ib qp state = %d, refcount = %u\n", - __FUNCTION__, __LINE__, nesqp->hwqp.qp_id, last_ae, cm_id, - original_hw_tcp_state, original_ibqp_state, atomic_read(&nesqp->refcount)); - - - dprintk("%s[%u] -- set ibqp_state=%u\n", - __FUNCTION__, __LINE__, nesqp->ibqp_state); + nes_debug(NES_DBG_CM, "set ibqp_state=%u\n", nesqp->ibqp_state); if ((nesqp->cm_id) && (cm_id->event_handler)) { if ((original_hw_tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) || @@ -2155,9 +2168,9 @@ int nes_cm_disconn_true(struct nes_qp *nesqp) if (last_ae == NES_AEQE_AEID_LLP_CONNECTION_RESET) { issued_disconnect_reset = 1; cm_event.status = IW_CM_EVENT_STATUS_RESET; - dprintk("%s: Generating a CM Disconnect Event (status reset) for " + nes_debug(NES_DBG_CM, "Generating a CM Disconnect Event (status reset) for " " QP%u, cm_id = %p. \n", - __FUNCTION__, nesqp->hwqp.qp_id, cm_id); + nesqp->hwqp.qp_id, cm_id); } else { cm_event.status = IW_CM_EVENT_STATUS_OK; } @@ -2167,36 +2180,35 @@ int nes_cm_disconn_true(struct nes_qp *nesqp) cm_event.private_data = NULL; cm_event.private_data_len = 0; - dprintk("%s: Generating a CM Disconnect Event for " - " QP%u, SQ Head = %u, SQ Tail = %u. cm_id = %p, refcount = %u. \n", - __FUNCTION__, nesqp->hwqp.qp_id, + nes_debug(NES_DBG_CM, "Generating a CM Disconnect Event for " + " QP%u, SQ Head = %u, SQ Tail = %u. cm_id = %p, refcount = %u.\n", + nesqp->hwqp.qp_id, nesqp->hwqp.sq_head, nesqp->hwqp.sq_tail, cm_id, atomic_read(&nesqp->refcount)); spin_unlock_irqrestore(&nesqp->lock, flags); ret = cm_id->event_handler(cm_id, &cm_event); if (ret) - dprintk("%s[%u] OFA CM event_handler returned, ret=%d\n", - __FUNCTION__, __LINE__, ret); + nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret); spin_lock_irqsave(&nesqp->lock, flags); } nesqp->disconn_pending = 0; - - if ((0 == issued_disconnect_reset) && (nesqp->cm_id) && - (((original_ibqp_state != IB_QPS_RTS) && - ((original_hw_tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) || - (original_hw_tcp_state == NES_AEQE_TCP_STATE_CLOSED))) || - (last_ae == NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE) || - (last_ae == NES_AEQE_AEID_LLP_CONNECTION_RESET) || - (nesqp->hw_iwarp_state == NES_AEQE_IWARP_STATE_CLOSING))) { + /* There might have been another AE while the lock was released */ + original_hw_tcp_state = nesqp->hw_tcp_state; + original_ibqp_state = nesqp->ibqp_state; + last_ae = nesqp->last_aeq; + + if ((issued_disconnect_reset == 0) && (nesqp->cm_id) && + ((original_hw_tcp_state == NES_AEQE_TCP_STATE_CLOSED) || + (original_hw_tcp_state == NES_AEQE_TCP_STATE_TIME_WAIT) || + (last_ae == NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE) || + (last_ae == NES_AEQE_AEID_LLP_CONNECTION_RESET))) { atomic_inc(&cm_closes); nesqp->cm_id = NULL; nesqp->in_disconnect = 0; spin_unlock_irqrestore(&nesqp->lock, flags); - nes_disconnect(nesqp, 1, ntohs(cm_id->local_addr.sin_port)); - - dprintk("%s[%u] -- \n", __FUNCTION__, __LINE__); + nes_disconnect(nesqp, 1); cm_id->provider_data = nesqp; /* Send up the close complete event */ @@ -2208,19 +2220,15 @@ int nes_cm_disconn_true(struct nes_qp *nesqp) cm_event.private_data = NULL; cm_event.private_data_len = 0; - dprintk("%s[%u] -- OFA CM upcall for QP%u, IW_CM_EVENT_CLOSE cm_id = %p." - " QP refcount = %d. nesadapter = %p\n", - __FUNCTION__, __LINE__, nesqp->hwqp.qp_id, cm_id, - atomic_read(&nesqp->refcount), nesvnic->nesdev->nesadapter); ret = cm_id->event_handler(cm_id, &cm_event); - if (ret) - dprintk("%s[%u] OFA CM event_handler returned, ret=%d\n", - __FUNCTION__, __LINE__, ret); + if (ret) { + nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret); + } cm_id->rem_ref(cm_id); spin_lock_irqsave(&nesqp->lock, flags); - if (0 == nesqp->flush_issued) { + if (nesqp->flush_issued == 0) { nesqp->flush_issued = 1; spin_unlock_irqrestore(&nesqp->lock, flags); flush_wqes(nesvnic->nesdev, nesqp, NES_CQP_FLUSH_RQ, 1); @@ -2237,9 +2245,9 @@ int nes_cm_disconn_true(struct nes_qp *nesqp) spin_unlock_irqrestore(&nesqp->lock, flags); /* check to see if the inbound reset beat the outbound reset */ if ((!cm_id) && (last_ae==NES_AEQE_AEID_RESET_SENT)) { - dprintk("%s[%u] QP%u: Decing refcount due to inbound reset" + nes_debug(NES_DBG_CM, "QP%u: Decing refcount due to inbound reset" " beating the outbound reset.\n", - __FUNCTION__, __LINE__, nesqp->hwqp.qp_id); + nesqp->hwqp.qp_id); nes_rem_ref(&nesqp->ibqp); } } @@ -2248,8 +2256,6 @@ int nes_cm_disconn_true(struct nes_qp *nesqp) spin_unlock_irqrestore(&nesqp->lock, flags); } nes_rem_ref(&nesqp->ibqp); - dprintk("%s[%u] Exiting. QP%u refcount = %d\n", - __FUNCTION__, __LINE__, nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount)); return 0; } @@ -2258,22 +2264,20 @@ int nes_cm_disconn_true(struct nes_qp *nesqp) /** * nes_disconnect */ -int nes_disconnect(struct nes_qp *nesqp, int abrupt, u16 local_port) +int nes_disconnect(struct nes_qp *nesqp, int abrupt) { int ret = 0; struct nes_vnic *nesvnic; struct nes_device *nesdev; - dprintk("%s[%u] -- Enter, QP%u\n", __FUNCTION__, __LINE__, nesqp->hwqp.qp_id); - nesvnic = to_nesvnic(nesqp->ibqp.device); if (!nesvnic) - return(-EINVAL); + return -EINVAL; nesdev = nesvnic->nesdev; - dprintk("%s: netdev refcnt = %u.\n", - __FUNCTION__, atomic_read(&nesvnic->netdev->refcnt)); + nes_debug(NES_DBG_CM, "netdev refcnt = %u.\n", + atomic_read(&nesvnic->netdev->refcnt)); if (nesqp->active_conn) { @@ -2289,15 +2293,14 @@ int nes_disconnect(struct nes_qp *nesqp, int abrupt, u16 local_port) } /* close the CM node down if it is still active */ - if (nesqp->cm_node_p) { - dprintk("%s[%u] -- Call close API\n", __FUNCTION__, __LINE__); + if (nesqp->cm_node) { + nes_debug(NES_DBG_CM, "Call close API\n"); - g_cm_core_p->api->close(g_cm_core_p, nesqp->cm_node_p); - nesqp->cm_node_p = NULL; + g_cm_core->api->close(g_cm_core, nesqp->cm_node); + nesqp->cm_node = NULL; } - dprintk("%s[%u] -- Exit, QP%u\n", __FUNCTION__, __LINE__, nesqp->hwqp.qp_id); - return(ret); + return ret; } @@ -2306,24 +2309,23 @@ int nes_disconnect(struct nes_qp *nesqp, int abrupt, u16 local_port) */ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) { + u64 u64temp; struct ib_qp *ibqp; struct nes_qp *nesqp; struct nes_vnic *nesvnic; struct nes_device *nesdev; - struct nes_cm_node *node_p; + struct nes_cm_node *cm_node; struct nes_adapter *adapter; struct ib_qp_attr attr; struct iw_cm_event cm_event; struct nes_hw_qp_wqe *wqe; struct nes_v4_quad nes_quad; + u32 crc_value; int ret; - dprintk("%s:%s:%u: data len = %u\n", - __FILE__, __FUNCTION__, __LINE__, conn_param->private_data_len); - ibqp = nes_get_qp(cm_id->device, conn_param->qpn); if (!ibqp) - return(-EINVAL); + return -EINVAL; /* get all our handles */ nesqp = to_nesqp(ibqp); @@ -2331,138 +2333,133 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) nesdev = nesvnic->nesdev; adapter = nesdev->nesadapter; + nes_debug(NES_DBG_CM, "nesvnic=%p, netdev=%p, %s\n", + nesvnic, nesvnic->netdev, nesvnic->netdev->name); + /* since this is from a listen, we were able to put node handle into cm_id */ - node_p = (struct nes_cm_node *)cm_id->provider_data; + cm_node = (struct nes_cm_node *)cm_id->provider_data; /* associate the node with the QP */ - nesqp->cm_node_p = (void *)node_p; + nesqp->cm_node = (void *)cm_node; - dprintk("%s: QP%u, node_p=%p\n", __FUNCTION__, nesqp->hwqp.qp_id, node_p); + nes_debug(NES_DBG_CM, "QP%u, cm_node=%p, jiffies = %lu\n", + nesqp->hwqp.qp_id, cm_node, jiffies); atomic_inc(&cm_accepts); - dprintk("%s: netdev refcnt = %u.\n", - __FUNCTION__, atomic_read(&nesvnic->netdev->refcnt)); + nes_debug(NES_DBG_CM, "netdev refcnt = %u.\n", + atomic_read(&nesvnic->netdev->refcnt)); - /* allocate the ietf frame and space for private data */ - nesqp->ietf_frame = pci_alloc_consistent(nesdev->pcidev, - sizeof(struct ietf_mpa_frame) + conn_param->private_data_len, - &nesqp->ietf_frame_pbase); + /* allocate the ietf frame and space for private data */ + nesqp->ietf_frame = pci_alloc_consistent(nesdev->pcidev, + sizeof(struct ietf_mpa_frame) + conn_param->private_data_len, + &nesqp->ietf_frame_pbase); - if (!nesqp->ietf_frame) { - dprintk(KERN_ERR PFX "%s: Unable to allocate memory for private data\n", - __FUNCTION__); - return(-ENOMEM); - } + if (!nesqp->ietf_frame) { + nes_debug(NES_DBG_CM, "Unable to allocate memory for private data\n"); + return -ENOMEM; + } - dprintk(PFX "%s: PCI consistent memory for " - "private data located @ %p (pa = 0x%08llX.) size = %u.\n", - __FUNCTION__, nesqp->ietf_frame, - (unsigned long long)nesqp->ietf_frame_pbase, - (u32)(conn_param->private_data_len + - sizeof(struct ietf_mpa_frame))); - /* setup the MPA frame */ - nesqp->private_data_len = conn_param->private_data_len; - memcpy(nesqp->ietf_frame->key, IEFT_MPA_KEY_REP, IETF_MPA_KEY_SIZE); + /* setup the MPA frame */ + nesqp->private_data_len = conn_param->private_data_len; + memcpy(nesqp->ietf_frame->key, IEFT_MPA_KEY_REP, IETF_MPA_KEY_SIZE); - memcpy(nesqp->ietf_frame->priv_data, conn_param->private_data, - conn_param->private_data_len); + memcpy(nesqp->ietf_frame->priv_data, conn_param->private_data, + conn_param->private_data_len); - nesqp->ietf_frame->priv_data_len = cpu_to_be16(conn_param->private_data_len); - nesqp->ietf_frame->rev = mpa_version; - nesqp->ietf_frame->flags = IETF_MPA_FLAGS_CRC; + nesqp->ietf_frame->priv_data_len = cpu_to_be16(conn_param->private_data_len); + nesqp->ietf_frame->rev = mpa_version; + nesqp->ietf_frame->flags = IETF_MPA_FLAGS_CRC; - dprintk("%s: Dump of ietf_frame=\n", __FUNCTION__); - nes_dump_mem(nesqp->ietf_frame, sizeof(struct ietf_mpa_frame) + - nesqp->private_data_len); - - /* setup our first outgoing iWarp send WQE (the IETF frame response) */ - wqe = &nesqp->hwqp.sq_vbase[0]; - - *((struct nes_qp **)&wqe->wqe_words[NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX]) = nesqp; - *((u64 *)&wqe->wqe_words[NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX]) |= - NES_SW_CONTEXT_ALIGN >> 1; - wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] = - cpu_to_le32(NES_IWARP_SQ_WQE_STREAMING | NES_IWARP_SQ_WQE_WRPDU); - wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = - cpu_to_le32(conn_param->private_data_len + sizeof(struct ietf_mpa_frame)); - wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] = - cpu_to_le32((u32)nesqp->ietf_frame_pbase); - wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] = - cpu_to_le32((u32)((u64)nesqp->ietf_frame_pbase >> 32)); - wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = - cpu_to_le32(conn_param->private_data_len + sizeof(struct ietf_mpa_frame)); - wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0; + /* setup our first outgoing iWarp send WQE (the IETF frame response) */ + wqe = &nesqp->hwqp.sq_vbase[0]; - nesqp->nesqp_context->ird_ord_sizes |= - NES_QPCONTEXT_ORDIRD_LSMM_PRESENT | NES_QPCONTEXT_ORDIRD_WRPDU; - nesqp->skip_lsmm = 1; + if (cm_id->remote_addr.sin_addr.s_addr != cm_id->local_addr.sin_addr.s_addr) { + u64temp = (unsigned long)nesqp; + u64temp |= NES_SW_CONTEXT_ALIGN>>1; + set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX, + u64temp); + wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] = + cpu_to_le32(NES_IWARP_SQ_WQE_STREAMING | NES_IWARP_SQ_WQE_WRPDU); + wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = + cpu_to_le32(conn_param->private_data_len + sizeof(struct ietf_mpa_frame)); + wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] = + cpu_to_le32((u32)nesqp->ietf_frame_pbase); + wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] = + cpu_to_le32((u32)((u64)nesqp->ietf_frame_pbase >> 32)); + wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = + cpu_to_le32(conn_param->private_data_len + sizeof(struct ietf_mpa_frame)); + wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0; + + nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32( + NES_QPCONTEXT_ORDIRD_LSMM_PRESENT | NES_QPCONTEXT_ORDIRD_WRPDU); + } else { + nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32((NES_QPCONTEXT_ORDIRD_LSMM_PRESENT | + NES_QPCONTEXT_ORDIRD_WRPDU | NES_QPCONTEXT_ORDIRD_ALSMM)); + } + nesqp->skip_lsmm = 1; /* Cache the cm_id in the qp */ nesqp->cm_id = cm_id; - node_p->cm_id = cm_id; + cm_node->cm_id = cm_id; - /* nesqp->cm_node_p = (void *)cm_id->provider_data; */ + /* nesqp->cm_node = (void *)cm_id->provider_data; */ cm_id->provider_data = nesqp; nesqp->active_conn = 0; - nes_cm_init_tsa_conn(nesqp, node_p); + nes_cm_init_tsa_conn(nesqp, cm_node); - nesqp->nesqp_context->tcpPorts = ntohs(cm_id->remote_addr.sin_port) << 16; - nesqp->nesqp_context->tcpPorts += ntohs(cm_id->local_addr.sin_port); - nesqp->nesqp_context->ip0 = ntohl(cm_id->remote_addr.sin_addr.s_addr); + nesqp->nesqp_context->tcpPorts[0] = cpu_to_le16(ntohs(cm_id->local_addr.sin_port)); + nesqp->nesqp_context->tcpPorts[1] = cpu_to_le16(ntohs(cm_id->remote_addr.sin_port)); + nesqp->nesqp_context->ip0 = cpu_to_le32(ntohl(cm_id->remote_addr.sin_addr.s_addr)); - nesqp->nesqp_context->misc2 |= - (u32)PCI_FUNC(nesdev->pcidev->devfn) << NES_QPCONTEXT_MISC2_SRC_IP_SHIFT; + nesqp->nesqp_context->misc2 |= cpu_to_le32( + (u32)PCI_FUNC(nesdev->pcidev->devfn) << NES_QPCONTEXT_MISC2_SRC_IP_SHIFT); - nesqp->nesqp_context->arp_index_vlan |= - nes_arp_table(nesdev, nesqp->nesqp_context->ip0, NULL, - NES_ARP_RESOLVE) << 16; + nesqp->nesqp_context->arp_index_vlan |= cpu_to_le32( + nes_arp_table(nesdev, le32_to_cpu(nesqp->nesqp_context->ip0), NULL, + NES_ARP_RESOLVE) << 16); - nesqp->nesqp_context->ts_val_delta = - jiffies - nes_read_indexed(nesdev, NES_IDX_TCP_NOW); + nesqp->nesqp_context->ts_val_delta = cpu_to_le32( + jiffies - nes_read_indexed(nesdev, NES_IDX_TCP_NOW)); - nesqp->nesqp_context->ird_index = nesqp->hwqp.qp_id; + nesqp->nesqp_context->ird_index = cpu_to_le32(nesqp->hwqp.qp_id); - nesqp->nesqp_context->ird_ord_sizes |= - ((u32)1 << NES_QPCONTEXT_ORDIRD_IWARP_MODE_SHIFT); - nesqp->nesqp_context->ird_ord_sizes |= (u32)conn_param->ord; + nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32( + ((u32)1 << NES_QPCONTEXT_ORDIRD_IWARP_MODE_SHIFT)); + nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32((u32)conn_param->ord); memset(&nes_quad, 0, sizeof(nes_quad)); - - nes_quad.DstIpAdrIndex = (u32)PCI_FUNC(nesdev->pcidev->devfn) << 27; + nes_quad.DstIpAdrIndex = cpu_to_le32((u32)PCI_FUNC(nesdev->pcidev->devfn) << 24); nes_quad.SrcIpadr = cm_id->remote_addr.sin_addr.s_addr; - nes_quad.TcpPorts = cm_id->remote_addr.sin_port; - nes_quad.TcpPorts |= (u32)cm_id->local_addr.sin_port << 16; + nes_quad.TcpPorts[0] = cm_id->remote_addr.sin_port; + nes_quad.TcpPorts[1] = cm_id->local_addr.sin_port; /* Produce hash key */ - nesqp->hte_index = nes_crc32(1, NES_HASH_CRC_INITAL_VALUE, - NES_HASH_CRC_FINAL_XOR, sizeof(nes_quad), - (u8 *)&nes_quad, ORDER, REFIN, REFOUT); - - dprintk("%s: HTE Index = 0x%08X, CRC = 0x%08X\n", - __FUNCTION__, nesqp->hte_index, - nesqp->hte_index & adapter->hte_index_mask); + crc_value = get_crc_value(&nes_quad); + nesqp->hte_index = cpu_to_be32(crc_value ^ 0xffffffff); + nes_debug(NES_DBG_CM, "HTE Index = 0x%08X, CRC = 0x%08X\n", + nesqp->hte_index, nesqp->hte_index & adapter->hte_index_mask); nesqp->hte_index &= adapter->hte_index_mask; - nesqp->nesqp_context->hte_index = nesqp->hte_index; + nesqp->nesqp_context->hte_index = cpu_to_le32(nesqp->hte_index); - node_p->core_p->api->accelerated(node_p->core_p, node_p); + cm_node->cm_core->api->accelerated(cm_node->cm_core, cm_node); - dprintk("%s: QP%u, Destination IP = 0x%08X:0x%04X, local = 0x%08X:0x%04X," - " rcv_nxt=0x%08X, snd_nxt=0x%08X, mpa + private data length=%lu.\n", - __FUNCTION__, nesqp->hwqp.qp_id, + nes_debug(NES_DBG_CM, "QP%u, Destination IP = 0x%08X:0x%04X, local = 0x%08X:0x%04X," + " rcv_nxt=0x%08X, snd_nxt=0x%08X, mpa + private data length=%zu.\n", + nesqp->hwqp.qp_id, ntohl(cm_id->remote_addr.sin_addr.s_addr), ntohs(cm_id->remote_addr.sin_port), ntohl(cm_id->local_addr.sin_addr.s_addr), ntohs(cm_id->local_addr.sin_port), - nesqp->nesqp_context->rcv_nxt, - nesqp->nesqp_context->snd_nxt, + le32_to_cpu(nesqp->nesqp_context->rcv_nxt), + le32_to_cpu(nesqp->nesqp_context->snd_nxt), conn_param->private_data_len+sizeof(struct ietf_mpa_frame)); attr.qp_state = IB_QPS_RTS; - nes_modify_qp(&nesqp->ibqp, &attr, IB_QP_STATE, NULL ); + nes_modify_qp(&nesqp->ibqp, &attr, IB_QP_STATE, NULL); /* notify OF layer that accept event was successfull */ cm_id->add_ref(cm_id); @@ -2475,13 +2472,18 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) cm_event.private_data = NULL; cm_event.private_data_len = 0; ret = cm_id->event_handler(cm_id, &cm_event); - dprintk("%s[%u] OFA CM event_handler returned, ret=%d\n", - __FUNCTION__, __LINE__, ret); + if (cm_node->loopbackpartner) { + cm_node->loopbackpartner->mpa_frame_size = nesqp->private_data_len; + /* copy entire MPA frame to our cm_node's frame */ + memcpy(cm_node->loopbackpartner->mpa_frame_buf, nesqp->ietf_frame->priv_data, + nesqp->private_data_len); + create_event(cm_node->loopbackpartner, NES_CM_EVENT_CONNECTED); + } if (ret) printk("%s[%u] OFA CM event_handler returned, ret=%d\n", __FUNCTION__, __LINE__, ret); - return(0); + return 0; } @@ -2490,24 +2492,24 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) */ int nes_reject(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len) { - struct nes_cm_node *node_p; - struct nes_cm_core *cm_core_p; + struct nes_cm_node *cm_node; + struct nes_cm_core *cm_core; atomic_inc(&cm_rejects); - node_p = (struct nes_cm_node *) cm_id->provider_data; - cm_core_p = node_p->core_p; - node_p->mpa_frame_size = sizeof(struct ietf_mpa_frame) + pdata_len; + cm_node = (struct nes_cm_node *) cm_id->provider_data; + cm_core = cm_node->cm_core; + cm_node->mpa_frame_size = sizeof(struct ietf_mpa_frame) + pdata_len; - strcpy(&node_p->mpa_frame_p.key[0], IEFT_MPA_KEY_REP); - memcpy(&node_p->mpa_frame_p.priv_data, pdata, pdata_len); + strcpy(&cm_node->mpa_frame.key[0], IEFT_MPA_KEY_REP); + memcpy(&cm_node->mpa_frame.priv_data, pdata, pdata_len); - node_p->mpa_frame_p.priv_data_len = cpu_to_be16(pdata_len); - node_p->mpa_frame_p.rev = mpa_version; - node_p->mpa_frame_p.flags = IETF_MPA_FLAGS_CRC | IETF_MPA_FLAGS_REJECT; + cm_node->mpa_frame.priv_data_len = cpu_to_be16(pdata_len); + cm_node->mpa_frame.rev = mpa_version; + cm_node->mpa_frame.flags = IETF_MPA_FLAGS_CRC | IETF_MPA_FLAGS_REJECT; - cm_core_p->api->reject(cm_core_p, &node_p->mpa_frame_p, node_p); + cm_core->api->reject(cm_core, &cm_node->mpa_frame, cm_node); - return(0); + return 0; } @@ -2521,76 +2523,39 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) struct nes_qp *nesqp; struct nes_vnic *nesvnic; struct nes_device *nesdev; - struct nes_cm_node *cm_node_p; + struct nes_cm_node *cm_node; struct nes_cm_info cm_info; -#ifdef NES_BIND_SOCK - int err; - struct sockaddr_in kinet_addr; -#endif - struct socket *ksock = NULL; - - - dprintk("%s[%u] data len = %u, cm_id = %p, event handler = %p.\n", - __FILE__, __LINE__, conn_param->private_data_len, - cm_id, cm_id->event_handler); - ibqp = nes_get_qp(cm_id->device, conn_param->qpn); if (!ibqp) - return(-EINVAL); + return -EINVAL; nesqp = to_nesqp(ibqp); if (!nesqp) - return(-EINVAL); + return -EINVAL; nesvnic = to_nesvnic(nesqp->ibqp.device); if (!nesvnic) - return(-EINVAL); + return -EINVAL; nesdev = nesvnic->nesdev; if (!nesdev) - return(-EINVAL); + return -EINVAL; - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); atomic_inc(&cm_connects); nesqp->ietf_frame = kzalloc(sizeof(struct ietf_mpa_frame) + conn_param->private_data_len, GFP_KERNEL); if (!nesqp->ietf_frame) - return(-ENOMEM); + return -ENOMEM; /* set qp as having an active connection */ nesqp->active_conn = 1; - dprintk("%s: QP%u, Destination IP = 0x%08X:0x%04X, local = 0x%08X:0x%04X.\n", - __FUNCTION__, nesqp->hwqp.qp_id, + nes_debug(NES_DBG_CM, "QP%u, Destination IP = 0x%08X:0x%04X, local = 0x%08X:0x%04X.\n", + nesqp->hwqp.qp_id, ntohl(cm_id->remote_addr.sin_addr.s_addr), ntohs(cm_id->remote_addr.sin_port), ntohl(cm_id->local_addr.sin_addr.s_addr), ntohs(cm_id->local_addr.sin_port)); -#ifdef NES_BIND_SOCK - err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &ksock); - if (err < 0) { - printk("kernel create socket call returned %d.\n", err ); - return (err); - } - memset( &kinet_addr, 0, sizeof(kinet_addr) ); - kinet_addr.sin_family = AF_INET; - kinet_addr.sin_port = cm_id->local_addr.sin_port; - kinet_addr.sin_addr.s_addr = cm_id->local_addr.sin_addr.s_addr; - - /* Do our bind to prevent other apps from accessing the port we are using */ - err = ksock->ops->bind(ksock, - (struct sockaddr *)&kinet_addr, sizeof(kinet_addr)); - if (err < 0) { - printk("kernel bind call returned %d for port 0x%04X.\n", err, - ntohs(cm_id->local_addr.sin_port)); - sock_release(ksock); - kfree(nesqp->ietf_frame); - nesqp->ietf_frame = NULL; - return (err); - } - -#endif - /* cache the cm_id in the qp */ nesqp->cm_id = cm_id; @@ -2599,28 +2564,22 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) /* copy the private data */ if (conn_param->private_data_len) { memcpy(nesqp->ietf_frame->priv_data, conn_param->private_data, - conn_param->private_data_len); + conn_param->private_data_len); } nesqp->private_data_len = conn_param->private_data_len; - nesqp->nesqp_context->ird_ord_sizes |= (u32)conn_param->ord; - dprintk("%s:requested ord = 0x%08X.\n", - __FUNCTION__, (u32)conn_param->ord); - dprintk("%s:mpa private data len =%u\n", - __FUNCTION__, conn_param->private_data_len); + nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32((u32)conn_param->ord); + nes_debug(NES_DBG_CM, "requested ord = 0x%08X.\n", (u32)conn_param->ord); + nes_debug(NES_DBG_CM, "mpa private data len =%u\n", conn_param->private_data_len); strcpy(&nesqp->ietf_frame->key[0], IEFT_MPA_KEY_REQ); nesqp->ietf_frame->flags = IETF_MPA_FLAGS_CRC; nesqp->ietf_frame->rev = IETF_MPA_VERSION; nesqp->ietf_frame->priv_data_len = htons(conn_param->private_data_len); - dprintk("%s:[%u] priv_data_len = %u\n", __FILE__, __LINE__, - ntohs(nesqp->ietf_frame->priv_data_len)); - - dprintk("%s:%s[%u] set bit in APBVT\n", __FILE__, __FUNCTION__, __LINE__); - - nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port), - PCI_FUNC(nesdev->pcidev->devfn), NES_MANAGE_APBVT_ADD); + if (cm_id->local_addr.sin_addr.s_addr != cm_id->remote_addr.sin_addr.s_addr) + nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port), + PCI_FUNC(nesdev->pcidev->devfn), NES_MANAGE_APBVT_ADD); /* set up the connection params for the node */ cm_info.loc_addr = (cm_id->local_addr.sin_addr.s_addr); @@ -2631,25 +2590,25 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) cm_info.conn_type = NES_CM_IWARP_CONN_TYPE; cm_id->add_ref(cm_id); + nes_add_ref(&nesqp->ibqp); /* create a connect CM node connection */ - cm_node_p = g_cm_core_p->api->connect(g_cm_core_p, nesvnic, nesqp->ietf_frame, &cm_info); - if (!cm_node_p) { -#ifdef NES_BIND_SOCK - sock_release(ksock); -#endif + cm_node = g_cm_core->api->connect(g_cm_core, nesvnic, nesqp->ietf_frame, &cm_info); + if (!cm_node) { + if (cm_id->local_addr.sin_addr.s_addr != cm_id->remote_addr.sin_addr.s_addr) + nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port), + PCI_FUNC(nesdev->pcidev->devfn), NES_MANAGE_APBVT_DEL); + nes_rem_ref(&nesqp->ibqp); kfree(nesqp->ietf_frame); nesqp->ietf_frame = NULL; cm_id->rem_ref(cm_id); - return(-ENOMEM); + return -ENOMEM; } - nesqp->cm_node_p = cm_node_p; - cm_node_p->ksock = ksock; + cm_node->apbvt_set = 1; + nesqp->cm_node = cm_node; - ///dprintk("kernel socket = %p.\n", cm_node_p->ksock ); - - return(0); + return 0; } @@ -2659,96 +2618,59 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) int nes_create_listen(struct iw_cm_id *cm_id, int backlog) { struct nes_vnic *nesvnic; - struct nes_cm_listener *cm_node_p; + struct nes_cm_listener *cm_node; struct nes_cm_info cm_info; struct nes_adapter *adapter; - int err; -#ifdef NES_BIND_SOCK - struct sockaddr_in kinet_addr; -#endif - struct socket *ksock = NULL; - dprintk("%s[%u] Enter\n", __FUNCTION__, __LINE__); - dprintk("%s[%u] cm_id = %p, local port = 0x%04X.\n", __FUNCTION__, __LINE__, + nes_debug(NES_DBG_CM, "cm_id = %p, local port = 0x%04X.\n", cm_id, ntohs(cm_id->local_addr.sin_port)); - nesvnic = to_nesvnic(cm_id->device); if (!nesvnic) - return(-EINVAL); + return -EINVAL; adapter = nesvnic->nesdev->nesadapter; + nes_debug(NES_DBG_CM, "nesvnic=%p, netdev=%p, %s\n", + nesvnic, nesvnic->netdev, nesvnic->netdev->name); + + nes_debug(NES_DBG_CM, "nesvnic->local_ipaddr=0x%08x, sin_addr.s_addr=0x%08x\n", + nesvnic->local_ipaddr, cm_id->local_addr.sin_addr.s_addr); /* setup listen params in our api call struct */ - cm_info.loc_addr = cm_id->local_addr.sin_addr.s_addr; + cm_info.loc_addr = nesvnic->local_ipaddr; cm_info.loc_port = cm_id->local_addr.sin_port; cm_info.backlog = backlog; cm_info.cm_id = cm_id; cm_info.conn_type = NES_CM_IWARP_CONN_TYPE; -#ifdef NES_BIND_SOCK - /* We now bind to our port to prevent other apps & services - from attaching to the same port */ - err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &ksock); - if (err < 0) { - printk("kernel socket create call returned %d.\n", err ); - return (err); - } - memset( &kinet_addr, 0, sizeof(kinet_addr) ); - kinet_addr.sin_family = AF_INET; - kinet_addr.sin_port = cm_id->local_addr.sin_port; - kinet_addr.sin_addr.s_addr = cm_id->local_addr.sin_addr.s_addr; - - err = ksock->ops->bind(ksock, - (struct sockaddr *)&kinet_addr, sizeof(kinet_addr)); - if (err < 0) { - printk("kernel bind call returned %d for port 0x%04X.\n", err, - ntohs(cm_id->local_addr.sin_port)); - sock_release(ksock); - return (err); - } -#endif - - cm_node_p = g_cm_core_p->api->listen(g_cm_core_p, nesvnic, &cm_info); - if (!cm_node_p) { + cm_node = g_cm_core->api->listen(g_cm_core, nesvnic, &cm_info); + if (!cm_node) { printk("%s[%u] Error returned from listen API call\n", __FUNCTION__, __LINE__); -#ifdef NES_BIND_SOCK - sock_release(ksock); -#endif - return(-ENOMEM); + return -ENOMEM; } - cm_node_p->ksock = ksock; - cm_id->provider_data = cm_node_p; - - //dprintk("kernel socket = %p.\n", cm_node_p->ksock ); - + cm_id->provider_data = cm_node; - if ( !cm_node_p->reused_node ) { - err = nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port), - PCI_FUNC(nesvnic->nesdev->pcidev->devfn), NES_MANAGE_APBVT_ADD); - if (err) { - printk("nes_manage_apbvt call returned %d.\n", err ); - cm_node_p->ksock = NULL; -#ifdef NES_BIND_SOCK - sock_release(ksock); -#endif - g_cm_core_p->api->stop_listener(g_cm_core_p, (void *)cm_node_p); - return (err); - } - cm_listens_created++; + if (!cm_node->reused_node) { + err = nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port), + PCI_FUNC(nesvnic->nesdev->pcidev->devfn), NES_MANAGE_APBVT_ADD); + if (err) { + printk("nes_manage_apbvt call returned %d.\n", err); + g_cm_core->api->stop_listener(g_cm_core, (void *)cm_node); + return err; + } + cm_listens_created++; } cm_id->add_ref(cm_id); - cm_id->provider_data = (void *)cm_node_p; + cm_id->provider_data = (void *)cm_node; - dprintk("%s[%u] Exiting create listen, netdev->refcnt = %u.\n", - __FUNCTION__, __LINE__, atomic_read(&nesvnic->netdev->refcnt)); - return(0); + + return 0; } @@ -2757,30 +2679,31 @@ int nes_create_listen(struct iw_cm_id *cm_id, int backlog) */ int nes_destroy_listen(struct iw_cm_id *cm_id) { - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); - if (cm_id->provider_data) - g_cm_core_p->api->stop_listener(g_cm_core_p, cm_id->provider_data); + g_cm_core->api->stop_listener(g_cm_core, cm_id->provider_data); else - dprintk("cm_id->provider_data was NULL\n"); + nes_debug(NES_DBG_CM, "cm_id->provider_data was NULL\n"); + cm_id->rem_ref(cm_id); - return(0); + return 0; } /** * nes_cm_recv */ -int nes_cm_recv(struct sk_buff *skb_p, struct net_device *netdevice) +int nes_cm_recv(struct sk_buff *skb, struct net_device *netdevice) { cm_packets_received++; - if ((g_cm_core_p)&&(g_cm_core_p->api)) { - g_cm_core_p->api->recv_pkt(g_cm_core_p, netdev_priv(netdevice), skb_p); + if ((g_cm_core) && (g_cm_core->api)) { + g_cm_core->api->recv_pkt(g_cm_core, netdev_priv(netdevice), skb); } else { - printk("%s: Unable to process packet for CM, cm is not setup properly.\n", __FUNCTION__); + nes_debug(NES_DBG_CM, "Unable to process packet for CM," + " cm is not setup properly.\n"); } - return(0); + + return 0; } @@ -2790,15 +2713,14 @@ int nes_cm_recv(struct sk_buff *skb_p, struct net_device *netdevice) */ int nes_cm_start(void) { - dprintk("%s:%s[%u]\n", __FILE__, __FUNCTION__, __LINE__); + nes_debug(NES_DBG_CM, "\n"); /* create the primary CM core, pass this handle to subsequent core inits */ - g_cm_core_p = nes_cm_alloc_core(); - if (g_cm_core_p) { - return (0); + g_cm_core = nes_cm_alloc_core(); + if (g_cm_core) { + return 0; } else { - return (-ENOMEM); + return -ENOMEM; } - } @@ -2808,8 +2730,8 @@ int nes_cm_start(void) */ int nes_cm_stop(void) { - g_cm_core_p->api->destroy_cm_core(g_cm_core_p); - return (0); + g_cm_core->api->destroy_cm_core(g_cm_core); + return 0; } @@ -2817,101 +2739,108 @@ int nes_cm_stop(void) * cm_event_connected * handle a connected event, setup QPs and HW */ -void cm_event_connected(struct nes_cm_event *event_p) +void cm_event_connected(struct nes_cm_event *event) { - int ret; + u64 u64temp; struct nes_qp *nesqp; struct nes_vnic *nesvnic; struct nes_device *nesdev; - struct nes_cm_node *node_p; + struct nes_cm_node *cm_node; struct nes_adapter *nesadapter; struct ib_qp_attr attr; struct iw_cm_id *cm_id; struct iw_cm_event cm_event; struct nes_hw_qp_wqe *wqe; struct nes_v4_quad nes_quad; + u32 crc_value; + int ret; /* get all our handles */ - node_p = event_p->node_p; - cm_id = node_p->cm_id; - dprintk("%s[%u] cm_event_connected - %p - cm_id = %p\n", - __FUNCTION__, __LINE__, node_p, cm_id); + cm_node = event->cm_node; + cm_id = cm_node->cm_id; + nes_debug(NES_DBG_CM, "cm_event_connected - %p - cm_id = %p\n", cm_node, cm_id); nesqp = (struct nes_qp *)cm_id->provider_data; nesvnic = to_nesvnic(nesqp->ibqp.device); nesdev = nesvnic->nesdev; nesadapter = nesdev->nesadapter; + if (nesqp->destroyed) { + return; + } atomic_inc(&cm_connecteds); - dprintk("%s[%u] Attempting to connect to 0x%08X:0x%04X on local port 0x%04X.\n", - __FUNCTION__, __LINE__, + nes_debug(NES_DBG_CM, "QP%u attempting to connect to 0x%08X:0x%04X on" + " local port 0x%04X. jiffies = %lu.\n", + nesqp->hwqp.qp_id, ntohl(cm_id->remote_addr.sin_addr.s_addr), ntohs(cm_id->remote_addr.sin_port), - ntohs(cm_id->local_addr.sin_port)); + ntohs(cm_id->local_addr.sin_port), + jiffies); - nes_cm_init_tsa_conn(nesqp, node_p); + nes_cm_init_tsa_conn(nesqp, cm_node); /* set the QP tsa context */ - nesqp->nesqp_context->tcpPorts = ntohs(cm_id->remote_addr.sin_port) << 16; - nesqp->nesqp_context->tcpPorts += ntohs(cm_id->local_addr.sin_port); - nesqp->nesqp_context->ip0 = ntohl(cm_id->remote_addr.sin_addr.s_addr); - - nesqp->nesqp_context->misc2 |= - (u32)PCI_FUNC(nesdev->pcidev->devfn) << NES_QPCONTEXT_MISC2_SRC_IP_SHIFT; - nesqp->nesqp_context->arp_index_vlan |= - nes_arp_table(nesdev, nesqp->nesqp_context->ip0, - NULL, NES_ARP_RESOLVE) << 16; - nesqp->nesqp_context->ts_val_delta = - jiffies - nes_read_indexed(nesdev, NES_IDX_TCP_NOW); - nesqp->nesqp_context->ird_index = nesqp->hwqp.qp_id; + nesqp->nesqp_context->tcpPorts[0] = cpu_to_le16(ntohs(cm_id->local_addr.sin_port)); + nesqp->nesqp_context->tcpPorts[1] = cpu_to_le16(ntohs(cm_id->remote_addr.sin_port)); + nesqp->nesqp_context->ip0 = cpu_to_le32(ntohl(cm_id->remote_addr.sin_addr.s_addr)); + + nesqp->nesqp_context->misc2 |= cpu_to_le32( + (u32)PCI_FUNC(nesdev->pcidev->devfn) << NES_QPCONTEXT_MISC2_SRC_IP_SHIFT); + nesqp->nesqp_context->arp_index_vlan |= cpu_to_le32( + nes_arp_table(nesdev, le32_to_cpu(nesqp->nesqp_context->ip0), + NULL, NES_ARP_RESOLVE) << 16); + nesqp->nesqp_context->ts_val_delta = cpu_to_le32( + jiffies - nes_read_indexed(nesdev, NES_IDX_TCP_NOW)); + nesqp->nesqp_context->ird_index = cpu_to_le32(nesqp->hwqp.qp_id); nesqp->nesqp_context->ird_ord_sizes |= - (u32)1 << NES_QPCONTEXT_ORDIRD_IWARP_MODE_SHIFT; + cpu_to_le32((u32)1 << NES_QPCONTEXT_ORDIRD_IWARP_MODE_SHIFT); /* Adjust tail for not having a LSMM */ nesqp->hwqp.sq_tail = 1; #if defined(NES_SEND_FIRST_WRITE) - if (node_p->send_write0) { - wqe = &nesqp->hwqp.sq_vbase[0]; - *((struct nes_qp **)&wqe->wqe_words[NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX]) = nesqp; - *((u64 *)&wqe->wqe_words[NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX]) |= - NES_SW_CONTEXT_ALIGN>>1; - wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] = cpu_to_le32(NES_IWARP_SQ_OP_RDMAW); - wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = 0; - wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] = 0; - wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] = 0; - wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = 0; - wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0; - - /* use the reserved spot on the WQ for the extra first WQE */ - nesqp->nesqp_context->ird_ord_sizes &= ~(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT | - NES_QPCONTEXT_ORDIRD_WRPDU | NES_QPCONTEXT_ORDIRD_ALSMM); - nesqp->skip_lsmm = 1; - nesqp->hwqp.sq_tail = 0; - nes_write32(nesdev->regs + NES_WQE_ALLOC, - (1 << 24) | 0x00800000 | nesqp->hwqp.qp_id); - } + if (cm_node->send_write0) { + nes_debug(NES_DBG_CM, "Sending first write.\n"); + wqe = &nesqp->hwqp.sq_vbase[0]; + u64temp = (unsigned long)nesqp; + u64temp |= NES_SW_CONTEXT_ALIGN>>1; + set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX, + u64temp); + wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] = cpu_to_le32(NES_IWARP_SQ_OP_RDMAW); + wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = 0; + wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] = 0; + wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] = 0; + wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = 0; + wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0; + + /* use the reserved spot on the WQ for the extra first WQE */ + nesqp->nesqp_context->ird_ord_sizes &= cpu_to_le32(~(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT | + NES_QPCONTEXT_ORDIRD_WRPDU | NES_QPCONTEXT_ORDIRD_ALSMM)); + nesqp->skip_lsmm = 1; + nesqp->hwqp.sq_tail = 0; + nes_write32(nesdev->regs + NES_WQE_ALLOC, + (1 << 24) | 0x00800000 | nesqp->hwqp.qp_id); + } #endif memset(&nes_quad, 0, sizeof(nes_quad)); - nes_quad.DstIpAdrIndex = (u32)PCI_FUNC(nesdev->pcidev->devfn) << 27; + nes_quad.DstIpAdrIndex = cpu_to_le32((u32)PCI_FUNC(nesdev->pcidev->devfn) << 24); nes_quad.SrcIpadr = cm_id->remote_addr.sin_addr.s_addr; - nes_quad.TcpPorts = cm_id->remote_addr.sin_port; - nes_quad.TcpPorts |= (u32)cm_id->local_addr.sin_port << 16; + nes_quad.TcpPorts[0] = cm_id->remote_addr.sin_port; + nes_quad.TcpPorts[1] = cm_id->local_addr.sin_port; - nesqp->hte_index = nes_crc32( 1, NES_HASH_CRC_INITAL_VALUE, - NES_HASH_CRC_FINAL_XOR, sizeof(nes_quad), (u8 *)&nes_quad, - ORDER, REFIN, REFOUT); - - dprintk("%s: HTE Index = 0x%08X, CRC = 0x%08X\n", __FUNCTION__, + /* Produce hash key */ + crc_value = get_crc_value(&nes_quad); + nesqp->hte_index = cpu_to_be32(crc_value ^ 0xffffffff); + nes_debug(NES_DBG_CM, "HTE Index = 0x%08X, After CRC = 0x%08X\n", nesqp->hte_index, nesqp->hte_index & nesadapter->hte_index_mask); nesqp->hte_index &= nesadapter->hte_index_mask; - nesqp->nesqp_context->hte_index = nesqp->hte_index; + nesqp->nesqp_context->hte_index = cpu_to_le32(nesqp->hte_index); - nesqp->ietf_frame = &node_p->mpa_frame_p; - nesqp->private_data_len = (u8) node_p->mpa_frame_size; - node_p->core_p->api->accelerated(node_p->core_p, node_p); + nesqp->ietf_frame = &cm_node->mpa_frame; + nesqp->private_data_len = (u8) cm_node->mpa_frame_size; + cm_node->cm_core->api->accelerated(cm_node->cm_core, cm_node); /* modify QP state to rts */ attr.qp_state = IB_QPS_RTS; @@ -2925,19 +2854,20 @@ void cm_event_connected(struct nes_cm_event *event_p) cm_event.local_addr.sin_port = cm_id->local_addr.sin_port; cm_event.remote_addr = cm_id->remote_addr; - cm_event.private_data = (void *) event_p->node_p->mpa_frame_b; - cm_event.private_data_len = (u8) event_p->node_p->mpa_frame_size; + cm_event.private_data = (void *)event->cm_node->mpa_frame_buf; + cm_event.private_data_len = (u8) event->cm_node->mpa_frame_size; - cm_event.local_addr.sin_addr.s_addr = event_p->cm_info.rem_addr; + cm_event.local_addr.sin_addr.s_addr = event->cm_info.rem_addr; ret = cm_id->event_handler(cm_id, &cm_event); - dprintk("%s[%u] OFA CM event_handler returned, ret=%d\n", - __FUNCTION__, __LINE__, ret); + nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret); if (ret) printk("%s[%u] OFA CM event_handler returned, ret=%d\n", __FUNCTION__, __LINE__, ret); - dprintk("%s: Exiting connect thread for QP%u\n", - __FUNCTION__, nesqp->hwqp.qp_id ); + nes_debug(NES_DBG_CM, "Exiting connect thread for QP%u. jiffies = %lu\n", + nesqp->hwqp.qp_id, jiffies ); + + nes_rem_ref(&nesqp->ibqp); return; } @@ -2946,7 +2876,7 @@ void cm_event_connected(struct nes_cm_event *event_p) /** * cm_event_connect_error */ -void cm_event_connect_error(struct nes_cm_event *event_p) +void cm_event_connect_error(struct nes_cm_event *event) { struct nes_qp *nesqp; struct iw_cm_id *cm_id; @@ -2954,18 +2884,20 @@ void cm_event_connect_error(struct nes_cm_event *event_p) /* struct nes_cm_info cm_info; */ int ret; - if (!event_p->node_p) + if (!event->cm_node) return; - cm_id = event_p->node_p->cm_id; - if(!cm_id) + cm_id = event->cm_node->cm_id; + if (!cm_id) { return; + } - dprintk("%s: - %p - cm_id = %p\n", __FUNCTION__, event_p->node_p, cm_id); + nes_debug(NES_DBG_CM, "cm_node=%p, cm_id=%p\n", event->cm_node, cm_id); nesqp = cm_id->provider_data; - if(!nesqp) + if (!nesqp) { return; + } /* notify OF layer about this connection error event */ /* cm_id->rem_ref(cm_id); */ @@ -2979,13 +2911,16 @@ void cm_event_connect_error(struct nes_cm_event *event_p) cm_event.private_data = NULL; cm_event.private_data_len = 0; - cm_id->rem_ref(cm_id); + nes_debug(NES_DBG_CM, "call CM_EVENT REJECTED, local_addr=%08x, remove_addr=%08x\n", + cm_event.local_addr.sin_addr.s_addr, cm_event.remote_addr.sin_addr.s_addr); + ret = cm_id->event_handler(cm_id, &cm_event); - dprintk("%s[%u] OFA CM event_handler returned, ret=%d\n", - __FUNCTION__, __LINE__, ret); + nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret); if (ret) printk("%s[%u] OFA CM event_handler returned, ret=%d\n", __FUNCTION__, __LINE__, ret); + nes_rem_ref(&nesqp->ibqp); + cm_id->rem_ref(cm_id); return; } @@ -2994,7 +2929,7 @@ void cm_event_connect_error(struct nes_cm_event *event_p) /** * cm_event_reset */ -void cm_event_reset(struct nes_cm_event *event_p) +void cm_event_reset(struct nes_cm_event *event) { struct nes_qp *nesqp; struct iw_cm_id *cm_id; @@ -3002,16 +2937,17 @@ void cm_event_reset(struct nes_cm_event *event_p) /* struct nes_cm_info cm_info; */ int ret; - if (!event_p->node_p) + if (!event->cm_node) + return; + + if (!event->cm_node->cm_id) return; - cm_id = event_p->node_p->cm_id; + cm_id = event->cm_node->cm_id; - dprintk("%s: - %p - cm_id = %p\n", __FUNCTION__, event_p->node_p, cm_id); + nes_debug(NES_DBG_CM, "%p - cm_id = %p\n", event->cm_node, cm_id); nesqp = cm_id->provider_data; - /* notify OF layer about this connection error event */ - cm_id->rem_ref(cm_id); nesqp->cm_id = NULL; /* cm_id->provider_data = NULL; */ cm_event.event = IW_CM_EVENT_DISCONNECT; @@ -3023,8 +2959,11 @@ void cm_event_reset(struct nes_cm_event *event_p) cm_event.private_data_len = 0; ret = cm_id->event_handler(cm_id, &cm_event); - dprintk("%s[%u] OFA CM event_handler returned, ret=%d\n", - __FUNCTION__, __LINE__, ret); + nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret); + + + /* notify OF layer about this connection error event */ + cm_id->rem_ref(cm_id); return; } @@ -3033,36 +2972,36 @@ void cm_event_reset(struct nes_cm_event *event_p) /** * cm_event_mpa_req */ -void cm_event_mpa_req(struct nes_cm_event *event_p) +void cm_event_mpa_req(struct nes_cm_event *event) { struct iw_cm_id *cm_id; struct iw_cm_event cm_event; int ret; - struct nes_cm_node *node_p; + struct nes_cm_node *cm_node; - node_p = event_p->node_p; - if (!node_p) + cm_node = event->cm_node; + if (!cm_node) return; - cm_id = node_p->cm_id; + cm_id = cm_node->cm_id; atomic_inc(&cm_connect_reqs); - dprintk("%s[%u] cm_event_mpa_req - %p - cm_id = %p\n", - __FUNCTION__, __LINE__, node_p, cm_id); + nes_debug(NES_DBG_CM, "cm_node = %p - cm_id = %p, jiffies = %lu\n", + cm_node, cm_id, jiffies); cm_event.event = IW_CM_EVENT_CONNECT_REQUEST; cm_event.status = IW_CM_EVENT_STATUS_OK; - cm_event.provider_data = (void *)node_p; + cm_event.provider_data = (void *)cm_node; cm_event.local_addr.sin_family = AF_INET; - cm_event.local_addr.sin_port = htons(event_p->cm_info.loc_port); - cm_event.local_addr.sin_addr.s_addr = htonl(event_p->cm_info.loc_addr); + cm_event.local_addr.sin_port = htons(event->cm_info.loc_port); + cm_event.local_addr.sin_addr.s_addr = htonl(event->cm_info.loc_addr); cm_event.remote_addr.sin_family = AF_INET; - cm_event.remote_addr.sin_port = htons(event_p->cm_info.rem_port); - cm_event.remote_addr.sin_addr.s_addr = htonl(event_p->cm_info.rem_addr); + cm_event.remote_addr.sin_port = htons(event->cm_info.rem_port); + cm_event.remote_addr.sin_addr.s_addr = htonl(event->cm_info.rem_addr); - cm_event.private_data = node_p->mpa_frame_b; - cm_event.private_data_len = (u8) node_p->mpa_frame_size; + cm_event.private_data = cm_node->mpa_frame_buf; + cm_event.private_data_len = (u8) cm_node->mpa_frame_size; ret = cm_id->event_handler(cm_id, &cm_event); if (ret) @@ -3073,24 +3012,24 @@ void cm_event_mpa_req(struct nes_cm_event *event_p) } -static void nes_cm_event_handler(void *parm); +static void nes_cm_event_handler(struct work_struct *); /** * nes_cm_post_event * post an event to the cm event handler */ -int nes_cm_post_event(struct nes_cm_event *event_p) +int nes_cm_post_event(struct nes_cm_event *event) { - atomic_inc(&event_p->node_p->core_p->events_posted); - add_ref_cm_node(event_p->node_p); - event_p->cm_info.cm_id->add_ref(event_p->cm_info.cm_id); - NES_INIT_WORK(&event_p->event_work, nes_cm_event_handler, (void *)event_p); - dprintk("%s[%u] queue_work, event_p=%p\n", __FUNCTION__, __LINE__, event_p); + atomic_inc(&event->cm_node->cm_core->events_posted); + add_ref_cm_node(event->cm_node); + event->cm_info.cm_id->add_ref(event->cm_info.cm_id); + INIT_WORK(&event->event_work, nes_cm_event_handler); + nes_debug(NES_DBG_CM, "queue_work, event=%p\n", event); - queue_work(event_p->node_p->core_p->event_wq, &event_p->event_work); + queue_work(event->cm_node->cm_core->event_wq, &event->event_work); - dprintk("%s[%u] Exit\n", __FUNCTION__, __LINE__); - return(0); + nes_debug(NES_DBG_CM, "Exit\n"); + return 0; } @@ -3099,60 +3038,54 @@ int nes_cm_post_event(struct nes_cm_event *event_p) * worker function to handle cm events * will free instance of nes_cm_event */ -static void nes_cm_event_handler(void *parm) +static void nes_cm_event_handler(struct work_struct *work) { - struct work_struct *work = parm; - struct nes_cm_event *event_p = container_of(work, struct nes_cm_event, event_work); - struct nes_cm_core *core_p; + struct nes_cm_event *event = container_of(work, struct nes_cm_event, event_work); + struct nes_cm_core *cm_core; - dprintk("%s[%u] Enter\n", __FUNCTION__, __LINE__); - - if (!event_p) + if ((!event) || (!event->cm_node) || (!event->cm_node->cm_core)) { return; - core_p = event_p->node_p->core_p; - dprintk("%s[%u] event_p=%p, event_p->type=%u, events posted=%u\n", - __FUNCTION__, __LINE__, - event_p, event_p->type, atomic_read(&core_p->events_posted)); + } + cm_core = event->cm_node->cm_core; + nes_debug(NES_DBG_CM, "event=%p, event->type=%u, events posted=%u\n", + event, event->type, atomic_read(&cm_core->events_posted)); - switch (event_p->type) { + switch (event->type) { case NES_CM_EVENT_MPA_REQ: - cm_event_mpa_req(event_p); - dprintk("%s:%s[%u] -- CM Event: MPA REQUEST\n", - __FILE__, __FUNCTION__, __LINE__); + cm_event_mpa_req(event); + nes_debug(NES_DBG_CM, "CM Event: MPA REQUEST\n"); break; case NES_CM_EVENT_RESET: - dprintk("%s:%s[%u] -- CM Event: RESET\n", - __FILE__, __FUNCTION__, __LINE__); - cm_event_reset(event_p); + nes_debug(NES_DBG_CM, "CM Event: RESET\n"); + cm_event_reset(event); break; case NES_CM_EVENT_CONNECTED: - cm_event_connected(event_p); - dprintk("%s:%s[%u] -- CM Event: CONNECTED\n", - __FILE__, __FUNCTION__, __LINE__); + if ((!event->cm_node->cm_id) || + (event->cm_node->state != NES_CM_STATE_TSA)) { + break; + } + cm_event_connected(event); + nes_debug(NES_DBG_CM, "CM Event: CONNECTED\n"); break; case NES_CM_EVENT_ABORTED: - cm_event_connect_error(event_p); - dprintk("%s:%s[%u] -- CM Event: ABORTED\n", - __FILE__, __FUNCTION__, __LINE__); + if ((!event->cm_node->cm_id) || (event->cm_node->state == NES_CM_STATE_TSA)) { + break; + } + cm_event_connect_error(event); + nes_debug(NES_DBG_CM, "CM Event: ABORTED\n"); break; case NES_CM_EVENT_DROPPED_PKT: - dprintk("%s:%s[%u] -- CM Event: DROPPED PKT\n", - __FILE__, __FUNCTION__, __LINE__); + nes_debug(NES_DBG_CM, "CM Event: DROPPED PKT\n"); break; default: - dprintk("%s:%s[%u] -- CM Event: UNKNOWN EVENT TYPE\n", - __FILE__, __FUNCTION__, __LINE__); + nes_debug(NES_DBG_CM, "CM Event: UNKNOWN EVENT TYPE\n"); break; } - dprintk("%s[%u] decrement events_posted, =%u\n", - __FUNCTION__, __LINE__, atomic_read(&core_p->events_posted)); - atomic_dec(&core_p->events_posted); - dprintk("%s[%u] free event_p=%p\n", __FUNCTION__, __LINE__, event_p); - event_p->cm_info.cm_id->rem_ref(event_p->cm_info.cm_id); - rem_ref_cm_node(core_p, event_p->node_p); - kfree(event_p); - dprintk("%s[%u] Exit\n", __FUNCTION__, __LINE__); + atomic_dec(&cm_core->events_posted); + event->cm_info.cm_id->rem_ref(event->cm_info.cm_id); + rem_ref_cm_node(cm_core, event->cm_node); + kfree(event); return; } diff --git a/drivers/infiniband/hw/nes/nes_cm.h b/drivers/infiniband/hw/nes/nes_cm.h index 604ef70..a59f0a7 100644 --- a/drivers/infiniband/hw/nes/nes_cm.h +++ b/drivers/infiniband/hw/nes/nes_cm.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2007 NetEffect, Inc. All rights reserved. + * Copyright (c) 2006 - 2008 NetEffect, Inc. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -43,7 +43,7 @@ #define IEFT_MPA_KEY_REQ "MPA ID Req Frame" #define IEFT_MPA_KEY_REP "MPA ID Rep Frame" #define IETF_MPA_KEY_SIZE 16 -#define IETF_MPA_VERSION 1 +#define IETF_MPA_VERSION 1 enum ietf_mpa_flags { IETF_MPA_FLAGS_MARKERS = 0x80, /* receive Markers */ @@ -55,7 +55,7 @@ struct ietf_mpa_frame { u8 key[IETF_MPA_KEY_SIZE]; u8 flags; u8 rev; - u16 priv_data_len; + __be16 priv_data_len; u8 priv_data[0]; }; @@ -63,14 +63,13 @@ struct ietf_mpa_frame { struct nes_v4_quad { u32 rsvd0; - u32 DstIpAdrIndex; /* Only most significant 5 bits are valid */ - u32 SrcIpadr; - u32 TcpPorts; /* src is low, dest is high */ + __le32 DstIpAdrIndex; /* Only most significant 5 bits are valid */ + __be32 SrcIpadr; + __be16 TcpPorts[2]; /* src is low, dest is high */ }; struct nes_cm_node; -enum nes_timer_type -{ +enum nes_timer_type { NES_TIMER_TYPE_SEND, NES_TIMER_TYPE_RECV, NES_TIMER_NODE_CLEANUP, @@ -102,7 +101,7 @@ enum option_numbers { struct option_mss { u8 optionnum; u8 length; - u16 mss; + __be16 mss; }; struct option_windowscale { @@ -111,20 +110,19 @@ struct option_windowscale { u8 shiftcount; }; -union all_known_options{ +union all_known_options { char as_end; struct option_base as_base; struct option_mss as_mss; struct option_windowscale as_windowscale; }; -struct nes_timer_entry -{ +struct nes_timer_entry { struct list_head list; unsigned long timetosend; /* jiffies */ struct sk_buff *skb; u32 type; - u32 retrycount; + u32 retrycount; u32 retranscount; u32 context; u32 seq_num; @@ -133,28 +131,34 @@ struct nes_timer_entry struct net_device *netdev; }; -#define NES_DEFAULT_RETRYS 64 +#define NES_DEFAULT_RETRYS 64 #define NES_DEFAULT_RETRANS 8 -#define NES_RETRY_TIMEOUT (1000*HZ/1000) -#define NES_SHORT_TIME (10) -#define NES_LONG_TIME (2000*HZ/1000) - -#define NES_CM_HASHTABLE_SIZE 1024 -#define NES_CM_TCP_TIMER_INTERVAL 3000 -#define NES_CM_DEFAULT_MTU 1540 +#ifdef CONFIG_INFINIBAND_NES_DEBUG +#define NES_RETRY_TIMEOUT (1000*HZ/1000) +#else +#define NES_RETRY_TIMEOUT (3000*HZ/1000) +#endif +#define NES_SHORT_TIME (10) +#define NES_LONG_TIME (2000*HZ/1000) + +#define NES_CM_HASHTABLE_SIZE 1024 +#define NES_CM_TCP_TIMER_INTERVAL 3000 +#define NES_CM_DEFAULT_MTU 1540 #define NES_CM_DEFAULT_FRAME_CNT 10 -#define NES_CM_THREAD_STACK_SIZE 256 -#define NES_CM_DEFAULT_RCV_WND 64240 // before we know that window scaling is allowed -#define NES_CM_DEFAULT_RCV_WND_SCALED 256960 // after we know that window scaling is allowed -#define NES_CM_DEFAULT_RCV_WND_SCALE 2 -#define NES_CM_DEFAULT_FREE_PKTS 0x000A -#define NES_CM_FREE_PKT_LO_WATERMARK 2 +#define NES_CM_THREAD_STACK_SIZE 256 +#define NES_CM_DEFAULT_RCV_WND 64240 // before we know that window scaling is allowed +#define NES_CM_DEFAULT_RCV_WND_SCALED 256960 // after we know that window scaling is allowed +#define NES_CM_DEFAULT_RCV_WND_SCALE 2 +#define NES_CM_DEFAULT_FREE_PKTS 0x000A +#define NES_CM_FREE_PKT_LO_WATERMARK 2 + +#define NES_CM_DEFAULT_MSS 536 -#define NES_CM_DEF_SEQ 0x159bf75f -#define NES_CM_DEF_LOCAL_ID 0x3b47 +#define NES_CM_DEF_SEQ 0x159bf75f +#define NES_CM_DEF_LOCAL_ID 0x3b47 -#define NES_CM_DEF_SEQ2 0x18ed5740 -#define NES_CM_DEF_LOCAL_ID2 0xb807 +#define NES_CM_DEF_SEQ2 0x18ed5740 +#define NES_CM_DEF_LOCAL_ID2 0xb807 typedef u32 nes_addr_t; @@ -190,15 +194,15 @@ enum nes_cm_conn_type { /* CM context params */ struct nes_cm_tcp_context { - u8 client; + u8 client; - u32 loc_seq_num; - u32 loc_ack_num; - u32 rem_ack_num; - u32 rcv_nxt; + u32 loc_seq_num; + u32 loc_ack_num; + u32 rem_ack_num; + u32 rcv_nxt; - u32 loc_id; - u32 rem_id; + u32 loc_id; + u32 rem_id; u32 snd_wnd; u32 max_snd_wnd; @@ -208,80 +212,79 @@ struct nes_cm_tcp_context { u8 snd_wscale; u8 rcv_wscale; - struct nes_cm_tsa_context tsa_cntxt; - struct timeval sent_ts; + struct nes_cm_tsa_context tsa_cntxt; + struct timeval sent_ts; }; enum nes_cm_listener_state { - NES_CM_LISTENER_PASSIVE_STATE=1, - NES_CM_LISTENER_ACTIVE_STATE=2, - NES_CM_LISTENER_EITHER_STATE=3 + NES_CM_LISTENER_PASSIVE_STATE=1, + NES_CM_LISTENER_ACTIVE_STATE=2, + NES_CM_LISTENER_EITHER_STATE=3 }; struct nes_cm_listener { - struct list_head list; - u64 session_id; - struct nes_cm_core *core_p; - u8 loc_mac[ETH_ALEN]; - nes_addr_t loc_addr; - u16 loc_port; - struct iw_cm_id *cm_id; - enum nes_cm_conn_type conn_type; - atomic_t ref_count; - struct nes_vnic *nesvnic; - atomic_t pend_accepts_cnt; - int backlog; - struct socket *ksock; /* added 8-15-07 for socket locking DG */ - enum nes_cm_listener_state listener_state; - u32 reused_node; + struct list_head list; + u64 session_id; + struct nes_cm_core *cm_core; + u8 loc_mac[ETH_ALEN]; + nes_addr_t loc_addr; + u16 loc_port; + struct iw_cm_id *cm_id; + enum nes_cm_conn_type conn_type; + atomic_t ref_count; + struct nes_vnic *nesvnic; + atomic_t pend_accepts_cnt; + int backlog; + enum nes_cm_listener_state listener_state; + u32 reused_node; }; /* per connection node and node state information */ struct nes_cm_node { - u64 session_id; - u32 hashkey; - - nes_addr_t loc_addr, rem_addr; - u16 loc_port, rem_port; - - - u8 loc_mac[ETH_ALEN]; - u8 rem_mac[ETH_ALEN]; - - enum nes_cm_node_state state; - struct nes_cm_tcp_context tcp_cntxt; - struct nes_cm_core *core_p; - struct sk_buff_head resend_list; - atomic_t ref_count; - struct net_device *netdev_p; - - struct nes_cm_node *loopbackpartner ; - struct list_head retrans_list; - spinlock_t retrans_list_lock; - struct list_head recv_list; - spinlock_t recv_list_lock; - - int send_write0; + u64 session_id; + u32 hashkey; + + nes_addr_t loc_addr, rem_addr; + u16 loc_port, rem_port; + + u8 loc_mac[ETH_ALEN]; + u8 rem_mac[ETH_ALEN]; + + enum nes_cm_node_state state; + struct nes_cm_tcp_context tcp_cntxt; + struct nes_cm_core *cm_core; + struct sk_buff_head resend_list; + atomic_t ref_count; + struct net_device *netdev; + + struct nes_cm_node *loopbackpartner; + struct list_head retrans_list; + spinlock_t retrans_list_lock; + struct list_head recv_list; + spinlock_t recv_list_lock; + + int send_write0; union { - struct ietf_mpa_frame mpa_frame_p; - u8 mpa_frame_b[NES_CM_DEFAULT_MTU]; + struct ietf_mpa_frame mpa_frame; + u8 mpa_frame_buf[NES_CM_DEFAULT_MTU]; }; - u16 mpa_frame_size; - struct iw_cm_id *cm_id; - struct list_head list; - int accelerated; - struct nes_cm_listener *listen_p; - enum nes_cm_conn_type conn_type; - struct nes_vnic *nesvnic; - struct socket *ksock; /* added 8-15-07 for socket locking DG */ + u16 mpa_frame_size; + struct iw_cm_id *cm_id; + struct list_head list; + int accelerated; + struct nes_cm_listener *listener; + enum nes_cm_conn_type conn_type; + struct nes_vnic *nesvnic; + int apbvt_set; + int accept_pend; }; /* structure for client or CM to fill when making CM api calls. */ /* - only need to set relevant data, based on op. */ struct nes_cm_info { union { - struct iw_cm_id *cm_id; + struct iw_cm_id *cm_id; struct net_device *netdev; }; @@ -291,7 +294,7 @@ struct nes_cm_info { nes_addr_t rem_addr; enum nes_cm_conn_type conn_type; - int backlog; + int backlog; }; /* CM event codes */ @@ -319,40 +322,40 @@ struct nes_cm_event { struct nes_cm_info cm_info; struct work_struct event_work; - struct nes_cm_node *node_p; + struct nes_cm_node *cm_node; }; struct nes_cm_core { - enum nes_cm_node_state state; - atomic_t session_id; - - atomic_t listen_node_cnt; - struct nes_cm_node listen_list; - spinlock_t listen_list_lock; - - u32 mtu; - u32 free_tx_pkt_max; - u32 rx_pkt_posted; - struct sk_buff_head tx_free_list; - atomic_t ht_node_cnt; - struct list_head connected_nodes; + enum nes_cm_node_state state; + atomic_t session_id; + + atomic_t listen_node_cnt; + struct nes_cm_node listen_list; + spinlock_t listen_list_lock; + + u32 mtu; + u32 free_tx_pkt_max; + u32 rx_pkt_posted; + struct sk_buff_head tx_free_list; + atomic_t ht_node_cnt; + struct list_head connected_nodes; /* struct list_head hashtable[NES_CM_HASHTABLE_SIZE]; */ - spinlock_t ht_lock; + spinlock_t ht_lock; - struct timer_list tcp_timer; + struct timer_list tcp_timer; - struct nes_cm_ops *api; + struct nes_cm_ops *api; - int (*post_event)(struct nes_cm_event *event_p); - atomic_t events_posted; + int (*post_event)(struct nes_cm_event *event); + atomic_t events_posted; struct workqueue_struct *event_wq; struct workqueue_struct *disconn_wq; - atomic_t node_cnt; - u64 aborted_connects; - u32 options; + atomic_t node_cnt; + u64 aborted_connects; + u32 options; - struct nes_cm_node *current_listen_node; + struct nes_cm_node *current_listen_node; }; @@ -361,46 +364,41 @@ struct nes_cm_core { /* CM ops/API for client interface */ struct nes_cm_ops { - int (*accelerated)(struct nes_cm_core *cm_core_p, - struct nes_cm_node *node_p); - struct nes_cm_listener * (*listen)(struct nes_cm_core *cm_core_p, - struct nes_vnic *nesvnic, struct nes_cm_info *nfo_p); - int (*stop_listener)(struct nes_cm_core *core_p, - struct nes_cm_listener *cm_core_p); - struct nes_cm_node * (*connect)(struct nes_cm_core *cm_core_p, - struct nes_vnic *nesvnic, struct ietf_mpa_frame *mpa_frame_p, - struct nes_cm_info *nfo_p); - int (*close)(struct nes_cm_core *cm_core_p, struct nes_cm_node *node_p); - int (*accept)(struct nes_cm_core *cm_core_p, struct ietf_mpa_frame *mpa_frame_p, - struct nes_cm_node *node_p); - int (*reject)(struct nes_cm_core *cm_core_p, struct ietf_mpa_frame *mpa_frame_p, - struct nes_cm_node *node_p); - int (*recv_pkt)(struct nes_cm_core *cm_core_p, struct nes_vnic *nesvnic, - struct sk_buff *skb_p); - int (*destroy_cm_core)(struct nes_cm_core *core_p); - int (*get)(struct nes_cm_core *cm_core_p); - int (*set)(struct nes_cm_core *core_p, u32 type, u32 value); + int (*accelerated)(struct nes_cm_core *, struct nes_cm_node *); + struct nes_cm_listener * (*listen)(struct nes_cm_core *, struct nes_vnic *, + struct nes_cm_info *); + int (*stop_listener)(struct nes_cm_core *, struct nes_cm_listener *); + struct nes_cm_node * (*connect)(struct nes_cm_core *, + struct nes_vnic *, struct ietf_mpa_frame *, + struct nes_cm_info *); + int (*close)(struct nes_cm_core *, struct nes_cm_node *); + int (*accept)(struct nes_cm_core *, struct ietf_mpa_frame *, + struct nes_cm_node *); + int (*reject)(struct nes_cm_core *, struct ietf_mpa_frame *, + struct nes_cm_node *); + int (*recv_pkt)(struct nes_cm_core *, struct nes_vnic *, + struct sk_buff *); + int (*destroy_cm_core)(struct nes_cm_core *); + int (*get)(struct nes_cm_core *); + int (*set)(struct nes_cm_core *, u32, u32); }; int send_mpa_request(struct nes_cm_node *); struct sk_buff *form_cm_frame(struct sk_buff *, struct nes_cm_node *, void *, u32, void *, u32, u8); -int schedule_nes_timer(struct nes_cm_node *node_p, struct sk_buff *skb_p, - enum nes_timer_type type, int retransmit, - int close_when_complete); +int schedule_nes_timer(struct nes_cm_node *, struct sk_buff *, + enum nes_timer_type, int, int); void nes_cm_timer_tick(unsigned long); int send_syn(struct nes_cm_node *, u32); int send_reset(struct nes_cm_node *); int send_ack(struct nes_cm_node *); int send_fin(struct nes_cm_node *, struct sk_buff *); struct sk_buff *get_free_pkt(struct nes_cm_node *); -int process_packet(struct nes_cm_node *node_p, struct sk_buff *skb_p, - struct nes_cm_core *core_p); +int process_packet(struct nes_cm_node *, struct sk_buff *, struct nes_cm_core *); -struct nes_cm_node * mini_cm_connect(struct nes_cm_core *core_p, - struct nes_vnic *nesvnic, struct ietf_mpa_frame *mpa_frame_p, - struct nes_cm_info *nfo_p); +struct nes_cm_node * mini_cm_connect(struct nes_cm_core *, + struct nes_vnic *, struct ietf_mpa_frame *, struct nes_cm_info *); int mini_cm_accept(struct nes_cm_core *, struct ietf_mpa_frame *, struct nes_cm_node *); int mini_cm_reject(struct nes_cm_core *, struct ietf_mpa_frame *, struct nes_cm_node *); int mini_cm_close(struct nes_cm_core *, struct nes_cm_node *); @@ -410,16 +408,16 @@ int mini_cm_dealloc_core(struct nes_cm_core *); int mini_cm_get(struct nes_cm_core *); int mini_cm_set(struct nes_cm_core *, u32, u32); -int nes_cm_disconn(struct nes_qp *nesqp); -void nes_disconnect_worker(void *); +int nes_cm_disconn(struct nes_qp *); +void nes_disconnect_worker(struct work_struct *); int nes_cm_disconn_true(struct nes_qp *); -int nes_disconnect(struct nes_qp *nesqp, int abrupt, u16 local_port); +int nes_disconnect(struct nes_qp *, int); -int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param); -int nes_reject(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len); -int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param); -int nes_create_listen(struct iw_cm_id *cm_id, int backlog); -int nes_destroy_listen(struct iw_cm_id *cm_id); +int nes_accept(struct iw_cm_id *, struct iw_cm_conn_param *); +int nes_reject(struct iw_cm_id *, const void *, u8); +int nes_connect(struct iw_cm_id *, struct iw_cm_conn_param *); +int nes_create_listen(struct iw_cm_id *, int); +int nes_destroy_listen(struct iw_cm_id *); int nes_cm_recv(struct sk_buff *, struct net_device *); int nes_cm_start(void); @@ -433,4 +431,3 @@ void cm_event_mpa_req(struct nes_cm_event *); int nes_cm_post_event(struct nes_cm_event *); #endif /* NES_CM_H */ - diff --git a/drivers/infiniband/hw/nes/nes_context.h b/drivers/infiniband/hw/nes/nes_context.h index 03e5871..da9daba 100644 --- a/drivers/infiniband/hw/nes/nes_context.h +++ b/drivers/infiniband/hw/nes/nes_context.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 NetEffect, Inc. All rights reserved. + * Copyright (c) 2006 - 2008 NetEffect, Inc. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -34,50 +34,50 @@ #define NES_CONTEXT_H struct nes_qp_context { - u32 misc; - u32 cqs; - u32 sq_addr_low; - u32 sq_addr_high; - u32 rq_addr_low; - u32 rq_addr_high; - u32 misc2; - u32 tcpPorts; - u32 ip0; - u32 ip1; - u32 ip2; - u32 ip3; - u32 mss; - u32 arp_index_vlan; - u32 tcp_state_flow_label; - u32 pd_index_wscale; - u32 keepalive; + __le32 misc; + __le32 cqs; + __le32 sq_addr_low; + __le32 sq_addr_high; + __le32 rq_addr_low; + __le32 rq_addr_high; + __le32 misc2; + __le16 tcpPorts[2]; + __le32 ip0; + __le32 ip1; + __le32 ip2; + __le32 ip3; + __le32 mss; + __le32 arp_index_vlan; + __le32 tcp_state_flow_label; + __le32 pd_index_wscale; + __le32 keepalive; u32 ts_recent; u32 ts_age; - u32 snd_nxt; - u32 snd_wnd; - u32 rcv_nxt; - u32 rcv_wnd; - u32 snd_max; - u32 snd_una; + __le32 snd_nxt; + __le32 snd_wnd; + __le32 rcv_nxt; + __le32 rcv_wnd; + __le32 snd_max; + __le32 snd_una; u32 srtt; - u32 rttvar; - u32 ssthresh; - u32 cwnd; - u32 snd_wl1; - u32 snd_wl2; - u32 max_snd_wnd; - u32 ts_val_delta; + __le32 rttvar; + __le32 ssthresh; + __le32 cwnd; + __le32 snd_wl1; + __le32 snd_wl2; + __le32 max_snd_wnd; + __le32 ts_val_delta; u32 retransmit; u32 probe_cnt; u32 hte_index; - u32 q2_addr_low; - u32 q2_addr_high; - u32 ird_index; + __le32 q2_addr_low; + __le32 q2_addr_high; + __le32 ird_index; u32 Rsvd3; - u32 ird_ord_sizes; + __le32 ird_ord_sizes; u32 mrkr_offset; - u32 aeq_token_low; - u32 aeq_token_high; + __le32 aeq_token_low; + __le32 aeq_token_high; }; /* QP Context Misc Field */ diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c index 6bb00ca..404c343 100644 --- a/drivers/infiniband/hw/nes/nes_hw.c +++ b/drivers/infiniband/hw/nes/nes_hw.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2007 NetEffect, Inc. All rights reserved. + * Copyright (c) 2006 - 2008 NetEffect, Inc. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -19,7 +19,7 @@ * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. -* + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -39,14 +39,22 @@ #include <linux/tcp.h> #include <linux/if_vlan.h> - #include "nes.h" + u32 crit_err_count = 0; +u32 int_mod_timer_init; +u32 int_mod_cq_depth_256; +u32 int_mod_cq_depth_128; +u32 int_mod_cq_depth_32; +u32 int_mod_cq_depth_24; +u32 int_mod_cq_depth_16; +u32 int_mod_cq_depth_4; +u32 int_mod_cq_depth_1; #include "nes_cm.h" -#ifdef NES_DEBUG +#ifdef CONFIG_INFINIBAND_NES_DEBUG static unsigned char *nes_iwarp_state_str[] = { "Non-Existant", "Idle", @@ -78,6 +86,137 @@ static unsigned char *nes_tcp_state_str[] = { }; #endif + +/** + * nes_nic_init_timer_defaults + */ +void nes_nic_init_timer_defaults(struct nes_device *nesdev, u8 jumbomode) +{ + unsigned long flags; + struct nes_adapter *nesadapter = nesdev->nesadapter; + struct nes_hw_tune_timer *shared_timer = &nesadapter->tune_timer; + + spin_lock_irqsave(&nesadapter->periodic_timer_lock, flags); + + shared_timer->timer_in_use_min = NES_NIC_FAST_TIMER_LOW; + shared_timer->timer_in_use_max = NES_NIC_FAST_TIMER_HIGH; + if (jumbomode) { + shared_timer->threshold_low = DEFAULT_JUMBO_NES_QL_LOW; + shared_timer->threshold_target = DEFAULT_JUMBO_NES_QL_TARGET; + shared_timer->threshold_high = DEFAULT_JUMBO_NES_QL_HIGH; + } else { + shared_timer->threshold_low = DEFAULT_NES_QL_LOW; + shared_timer->threshold_target = DEFAULT_NES_QL_TARGET; + shared_timer->threshold_high = DEFAULT_NES_QL_HIGH; + } + + /* todo use netdev->mtu to set thresholds */ + spin_unlock_irqrestore(&nesadapter->periodic_timer_lock, flags); +} + + +/** + * nes_nic_init_timer + */ +static void nes_nic_init_timer(struct nes_device *nesdev) +{ + unsigned long flags; + struct nes_adapter *nesadapter = nesdev->nesadapter; + struct nes_hw_tune_timer *shared_timer = &nesadapter->tune_timer; + + spin_lock_irqsave(&nesadapter->periodic_timer_lock, flags); + + if (shared_timer->timer_in_use_old == 0) { + nesdev->deepcq_count = 0; + shared_timer->timer_direction_upward = 0; + shared_timer->timer_direction_downward = 0; + shared_timer->timer_in_use = NES_NIC_FAST_TIMER; + shared_timer->timer_in_use_old = 0; + + } + if (shared_timer->timer_in_use != shared_timer->timer_in_use_old) { + shared_timer->timer_in_use_old = shared_timer->timer_in_use; + nes_write32(nesdev->regs+NES_PERIODIC_CONTROL, + 0x80000000 | ((u32)(shared_timer->timer_in_use*8))); + } + /* todo use netdev->mtu to set thresholds */ + spin_unlock_irqrestore(&nesadapter->periodic_timer_lock, flags); +} + + +/** + * nes_nic_tune_timer + */ +static void nes_nic_tune_timer(struct nes_device *nesdev) +{ + unsigned long flags; + struct nes_adapter *nesadapter = nesdev->nesadapter; + struct nes_hw_tune_timer *shared_timer = &nesadapter->tune_timer; + u16 cq_count = nesdev->currcq_count; + + spin_lock_irqsave(&nesadapter->periodic_timer_lock, flags); + + if (shared_timer->cq_count_old <= cq_count) + shared_timer->cq_direction_downward = 0; + else + shared_timer->cq_direction_downward++; + shared_timer->cq_count_old = cq_count; + if (shared_timer->cq_direction_downward > NES_NIC_CQ_DOWNWARD_TREND) { + if (cq_count <= shared_timer->threshold_low && (shared_timer->threshold_low > 4)) { + shared_timer->threshold_low = shared_timer->threshold_low/2; + shared_timer->cq_direction_downward=0; + nesdev->currcq_count = 0; + spin_unlock_irqrestore(&nesadapter->periodic_timer_lock, flags); + return; + } + } + + if (cq_count > 1) { + nesdev->deepcq_count += cq_count; + if (cq_count <= shared_timer->threshold_low) { /* increase timer gently */ + shared_timer->timer_direction_upward++; + shared_timer->timer_direction_downward = 0; + } else if (cq_count <= shared_timer->threshold_target) { /* balanced */ + shared_timer->timer_direction_upward = 0; + shared_timer->timer_direction_downward = 0; + } else if (cq_count <= shared_timer->threshold_high) { /* decrease timer gently */ + shared_timer->timer_direction_downward++; + shared_timer->timer_direction_upward = 0; + } else if (cq_count <= (shared_timer->threshold_high) * 2) { + shared_timer->timer_in_use -= 2; + shared_timer->timer_direction_upward = 0; + shared_timer->timer_direction_downward++; + } else { + shared_timer->timer_in_use -= 4; + shared_timer->timer_direction_upward = 0; + shared_timer->timer_direction_downward++; + } + + if (shared_timer->timer_direction_upward > 3) { /* using history */ + shared_timer->timer_in_use += 3; + shared_timer->timer_direction_upward = 0; + shared_timer->timer_direction_downward = 0; + } + if (shared_timer->timer_direction_downward > 5) { /* using history */ + shared_timer->timer_in_use -= 4 ; + shared_timer->timer_direction_downward = 0; + shared_timer->timer_direction_upward = 0; + } + } + + /* boundary checking */ + if (shared_timer->timer_in_use > NES_NIC_FAST_TIMER_HIGH) + shared_timer->timer_in_use = NES_NIC_FAST_TIMER_HIGH; + else if (shared_timer->timer_in_use < NES_NIC_FAST_TIMER_LOW) { + shared_timer->timer_in_use = NES_NIC_FAST_TIMER_LOW; + } + + nesdev->currcq_count = 0; + + spin_unlock_irqrestore(&nesadapter->periodic_timer_lock, flags); +} + + /** * nes_init_adapter - initialize adapter */ @@ -97,69 +236,62 @@ struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) { u32 hte_index_mask; u32 adapter_size; u32 arp_table_size; + u16 vendor_id; u8 OneG_Mode; + u8 func_index; /* search the list of existing adapters */ list_for_each_entry(nesadapter, &nes_adapter_list, list) { - dprintk("Searching Adapter list for PCI devfn = 0x%X," + nes_debug(NES_DBG_INIT, "Searching Adapter list for PCI devfn = 0x%X," " adapter PCI slot/bus = %u/%u, pci devices PCI slot/bus = %u/%u, .\n", nesdev->pcidev->devfn, PCI_SLOT(nesadapter->devfn), nesadapter->bus_number, PCI_SLOT(nesdev->pcidev->devfn), - nesdev->pcidev->bus->number ); + nesdev->pcidev->bus->number); if ((PCI_SLOT(nesadapter->devfn) == PCI_SLOT(nesdev->pcidev->devfn)) && - (nesadapter->bus_number == nesdev->pcidev->bus->number)) { + (nesadapter->bus_number == nesdev->pcidev->bus->number)) { nesadapter->ref_count++; - return(nesadapter); + return nesadapter; } } /* no adapter found */ - num_pds = pci_resource_len(nesdev->pcidev, BAR_1) / 4096; - if (hw_rev != NE020_REV) { - dprintk("%s: NE020 driver detected unknown hardware revision 0x%x\n", - __FUNCTION__, hw_rev); - return(NULL); + num_pds = pci_resource_len(nesdev->pcidev, BAR_1) >> PAGE_SHIFT; + if ((hw_rev != NE020_REV) && (hw_rev != NE020_REV1)) { + nes_debug(NES_DBG_INIT, "NE020 driver detected unknown hardware revision 0x%x\n", + hw_rev); + return NULL; } - dprintk("%s:%u Determine Soft Reset, QP_control=0x%x, CPU0=0x%x, CPU1=0x%x, CPU2=0x%x\n", - __FUNCTION__, __LINE__, + nes_debug(NES_DBG_INIT, "Determine Soft Reset, QP_control=0x%x, CPU0=0x%x, CPU1=0x%x, CPU2=0x%x\n", nes_read_indexed(nesdev, NES_IDX_QP_CONTROL + PCI_FUNC(nesdev->pcidev->devfn) * 8), nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS), - nes_read_indexed(nesdev, 0x00A4), - nes_read_indexed(nesdev, 0x00A8)); + nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS + 4), + nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS + 8)); - dprintk("%s: Reset and init NE020\n", __FUNCTION__); - if ((port_count = nes_reset_adapter_ne020(nesdev, &OneG_Mode)) == 0) { - return(NULL); - } - if (nes_init_serdes(nesdev, port_count)) { - return(NULL); - } - nes_init_csr_ne020(nesdev, hw_rev, port_count); + nes_debug(NES_DBG_INIT, "Reset and init NE020\n"); - /* Setup and enable the periodic timer */ - nesdev->et_rx_coalesce_usecs_irq = interrupt_mod_interval; - if (nesdev->et_rx_coalesce_usecs_irq) { - nes_write32(nesdev->regs+NES_PERIODIC_CONTROL, 0x80000000 | - ((u32)(nesdev->et_rx_coalesce_usecs_irq * 8))); - } else { - nes_write32(nesdev->regs+NES_PERIODIC_CONTROL, 0x00000000); - } + + if ((port_count = nes_reset_adapter_ne020(nesdev, &OneG_Mode)) == 0) + return NULL; + if (nes_init_serdes(nesdev, hw_rev, port_count, OneG_Mode)) + return NULL; + nes_init_csr_ne020(nesdev, hw_rev, port_count); max_qp = nes_read_indexed(nesdev, NES_IDX_QP_CTX_SIZE); - dprintk("%s: QP_CTX_SIZE=%u\n", __FUNCTION__, max_qp); + nes_debug(NES_DBG_INIT, "QP_CTX_SIZE=%u\n", max_qp); u32temp = nes_read_indexed(nesdev, NES_IDX_QUAD_HASH_TABLE_SIZE); if (max_qp > ((u32)1 << (u32temp & 0x001f))) { - dprintk("Reducing Max QPs to %u due to hash table size = 0x%08X\n", + nes_debug(NES_DBG_INIT, "Reducing Max QPs to %u due to hash table size = 0x%08X\n", max_qp, u32temp); max_qp = (u32)1 << (u32temp & 0x001f); } hte_index_mask = ((u32)1 << ((u32temp & 0x001f)+1))-1; - dprintk("Max QP = %u, hte_index_mask = 0x%08X.\n", max_qp, hte_index_mask); + nes_debug(NES_DBG_INIT, "Max QP = %u, hte_index_mask = 0x%08X.\n", + max_qp, hte_index_mask); u32temp = nes_read_indexed(nesdev, NES_IDX_IRRQ_COUNT); @@ -167,7 +299,8 @@ struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) { if (max_qp > max_irrq) { max_qp = max_irrq; - dprintk("Reducing Max QPs to %u due to Available Q1s.\n", max_qp); + nes_debug(NES_DBG_INIT, "Reducing Max QPs to %u due to Available Q1s.\n", + max_qp); } /* there should be no reason to allocate more pds than qps */ @@ -195,12 +328,12 @@ struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) { adapter_size += sizeof(struct nes_qp **) * max_qp; /* allocate a new adapter struct */ - nesadapter = kmalloc(adapter_size, GFP_KERNEL); + nesadapter = kzalloc(adapter_size, GFP_KERNEL); if (nesadapter == NULL) { - return(NULL); + return NULL; } - memset(nesadapter, 0, adapter_size); - dprintk("Allocating new nesadapter @ %p, size = %u (actual size = %u).\n", + + nes_debug(NES_DBG_INIT, "Allocating new nesadapter @ %p, size = %u (actual size = %u).\n", nesadapter, (u32)sizeof(struct nes_adapter), adapter_size); /* populate the new nesadapter */ @@ -209,6 +342,7 @@ struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) { nesadapter->ref_count = 1; nesadapter->timer_int_req = 0xffff0000; nesadapter->OneG_Mode = OneG_Mode; + nesadapter->doorbell_start = nesdev->doorbell_region; /* nesadapter->tick_delta = clk_divisor; */ nesadapter->hw_rev = hw_rev; @@ -225,6 +359,25 @@ struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) { nesadapter->free_4kpbl = max_4kpbl - 1; nesadapter->max_pd = num_pds; nesadapter->arp_table_size = arp_table_size; + + nesadapter->et_pkt_rate_low = NES_TIMER_ENABLE_LIMIT; + if (nes_drv_opt & NES_DRV_OPT_DISABLE_INT_MOD) { + nesadapter->et_use_adaptive_rx_coalesce = 0; + nesadapter->timer_int_limit = NES_TIMER_INT_LIMIT; + nesadapter->et_rx_coalesce_usecs_irq = interrupt_mod_interval; + } else { + nesadapter->et_use_adaptive_rx_coalesce = 1; + nesadapter->timer_int_limit = NES_TIMER_INT_LIMIT_DYNAMIC; + nesadapter->et_rx_coalesce_usecs_irq = 0; + printk(PFX "%s: Using Adaptive Interrupt Moderation\n", __FUNCTION__); + } + /* Setup and enable the periodic timer */ + if (nesadapter->et_rx_coalesce_usecs_irq) + nes_write32(nesdev->regs+NES_PERIODIC_CONTROL, 0x80000000 | + ((u32)(nesadapter->et_rx_coalesce_usecs_irq * 8))); + else + nes_write32(nesdev->regs+NES_PERIODIC_CONTROL, 0x00000000); + nesadapter->base_pd = 1; nesadapter->device_cap_flags = @@ -245,6 +398,8 @@ struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) { set_bit(u32temp, nesadapter->allocated_cqs); } + for (u32temp = 0; u32temp < 20; u32temp++) + set_bit(u32temp, nesadapter->allocated_pds); u32temp = nes_read_indexed(nesdev, NES_IDX_QP_MAX_CFG_SIZES); max_rq_wrs = ((u32temp >> 8) & 3); @@ -279,11 +434,7 @@ struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) { break; } nesadapter->max_qp_wr = min(max_rq_wrs, max_sq_wrs); - dprintk("Max wqes = %u.\n", nesadapter->max_qp_wr); - nesadapter->max_irrq_wr = (u32temp >> 16) & 3; - dprintk("%s: Max IRRQ wqes = %u.\n", __FUNCTION__, nesadapter->max_irrq_wr); - nesadapter->max_sge = 4; nesadapter->max_cqe = 32767; @@ -291,53 +442,140 @@ struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) { if (nes_read_eeprom_values(nesdev, nesadapter)) { printk(KERN_ERR PFX "Unable to read EEPROM data.\n"); kfree(nesadapter); - return(NULL); + return NULL; } u32temp = nes_read_indexed(nesdev, NES_IDX_TCP_TIMER_CONFIG); nes_write_indexed(nesdev, NES_IDX_TCP_TIMER_CONFIG, (u32temp & 0xff000000) | (nesadapter->tcp_timer_core_clk_divisor & 0x00ffffff)); - dprintk("%s: TCP Timer Config0=%08x\n", __FUNCTION__, - nes_read_indexed(nesdev, NES_IDX_TCP_TIMER_CONFIG)); /* setup port configuration */ if (nesadapter->port_count == 1) { u32temp = 0x00000000; - if (nes_drv_opt & NES_DRV_OPT_DUAL_LOGICAL_PORT) { + if (nes_drv_opt & NES_DRV_OPT_DUAL_LOGICAL_PORT) nes_write_indexed(nesdev, NES_IDX_TX_POOL_SIZE, 0x00000002); - } else { + else nes_write_indexed(nesdev, NES_IDX_TX_POOL_SIZE, 0x00000003); - } } else { - if (nesadapter->port_count == 2) { + if (nesadapter->port_count == 2) u32temp = 0x00000044; - } else { + else u32temp = 0x000000e4; - } nes_write_indexed(nesdev, NES_IDX_TX_POOL_SIZE, 0x00000003); } nes_write_indexed(nesdev, NES_IDX_NIC_LOGPORT_TO_PHYPORT, u32temp); - dprintk("%s: Probe time, LOG2PHY=%u\n", __FUNCTION__, + nes_debug(NES_DBG_INIT, "Probe time, LOG2PHY=%u\n", nes_read_indexed(nesdev, NES_IDX_NIC_LOGPORT_TO_PHYPORT)); spin_lock_init(&nesadapter->resource_lock); spin_lock_init(&nesadapter->phy_lock); - - init_timer(&nesadapter->mh_timer); - nesadapter->mh_timer.function = nes_mh_fix; - nesadapter->mh_timer.expires = jiffies + (HZ/5); /* 1 second */ - nesadapter->mh_timer.data = (unsigned long)nesdev; - add_timer(&nesadapter->mh_timer); + spin_lock_init(&nesadapter->pbl_lock); + spin_lock_init(&nesadapter->periodic_timer_lock); INIT_LIST_HEAD(&nesadapter->nesvnic_list[0]); INIT_LIST_HEAD(&nesadapter->nesvnic_list[1]); INIT_LIST_HEAD(&nesadapter->nesvnic_list[2]); INIT_LIST_HEAD(&nesadapter->nesvnic_list[3]); + if ((!nesadapter->OneG_Mode) && (nesadapter->port_count == 2)) { + u32 pcs_control_status0, pcs_control_status1; + u32 reset_value; + u32 i = 0; + u32 int_cnt = 0; + u32 ext_cnt = 0; + unsigned long flags; + u32 j = 0; + + pcs_control_status0 = nes_read_indexed(nesdev, + NES_IDX_PHY_PCS_CONTROL_STATUS0); + pcs_control_status1 = nes_read_indexed(nesdev, + NES_IDX_PHY_PCS_CONTROL_STATUS0 + 0x200); + + for (i = 0; i < NES_MAX_LINK_CHECK; i++) { + pcs_control_status0 = nes_read_indexed(nesdev, + NES_IDX_PHY_PCS_CONTROL_STATUS0); + pcs_control_status1 = nes_read_indexed(nesdev, + NES_IDX_PHY_PCS_CONTROL_STATUS0 + 0x200); + if ((0x0F000100 == (pcs_control_status0 & 0x0F000100)) + || (0x0F000100 == (pcs_control_status1 & 0x0F000100))) + int_cnt++; + msleep(1); + } + if (int_cnt > 1) { + spin_lock_irqsave(&nesadapter->phy_lock, flags); + nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x0000F088); + mh_detected++; + reset_value = nes_read32(nesdev->regs+NES_SOFTWARE_RESET); + reset_value |= 0x0000003d; + nes_write32(nesdev->regs+NES_SOFTWARE_RESET, reset_value); + + while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET) + & 0x00000040) != 0x00000040) && (j++ < 5000)); + spin_unlock_irqrestore(&nesadapter->phy_lock, flags); + + pcs_control_status0 = nes_read_indexed(nesdev, + NES_IDX_PHY_PCS_CONTROL_STATUS0); + pcs_control_status1 = nes_read_indexed(nesdev, + NES_IDX_PHY_PCS_CONTROL_STATUS0 + 0x200); + + for (i = 0; i < NES_MAX_LINK_CHECK; i++) { + pcs_control_status0 = nes_read_indexed(nesdev, + NES_IDX_PHY_PCS_CONTROL_STATUS0); + pcs_control_status1 = nes_read_indexed(nesdev, + NES_IDX_PHY_PCS_CONTROL_STATUS0 + 0x200); + if ((0x0F000100 == (pcs_control_status0 & 0x0F000100)) + || (0x0F000100 == (pcs_control_status1 & 0x0F000100))) { + if (++ext_cnt > int_cnt) { + spin_lock_irqsave(&nesadapter->phy_lock, flags); + nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, + 0x0000F0C8); + mh_detected++; + reset_value = nes_read32(nesdev->regs+NES_SOFTWARE_RESET); + reset_value |= 0x0000003d; + nes_write32(nesdev->regs+NES_SOFTWARE_RESET, reset_value); + + while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET) + & 0x00000040) != 0x00000040) && (j++ < 5000)); + spin_unlock_irqrestore(&nesadapter->phy_lock, flags); + break; + } + } + msleep(1); + } + } + } + + if (nesadapter->hw_rev == NE020_REV) { + init_timer(&nesadapter->mh_timer); + nesadapter->mh_timer.function = nes_mh_fix; + nesadapter->mh_timer.expires = jiffies + (HZ/5); /* 1 second */ + nesadapter->mh_timer.data = (unsigned long)nesdev; + add_timer(&nesadapter->mh_timer); + } else { + nes_write32(nesdev->regs+NES_INTF_INT_STAT, 0x0f000000); + } + + init_timer(&nesadapter->lc_timer); + nesadapter->lc_timer.function = nes_clc; + nesadapter->lc_timer.expires = jiffies + 3600 * HZ; /* 1 hour */ + nesadapter->lc_timer.data = (unsigned long)nesdev; + add_timer(&nesadapter->lc_timer); + list_add_tail(&nesadapter->list, &nes_adapter_list); - return(nesadapter); + for (func_index = 0; func_index < 8; func_index++) { + pci_bus_read_config_word(nesdev->pcidev->bus, + PCI_DEVFN(PCI_SLOT(nesdev->pcidev->devfn), + func_index), 0, &vendor_id); + if (vendor_id == 0xffff) + break; + } + nes_debug(NES_DBG_INIT, "%s %d functions found for %s.\n", __FUNCTION__, + func_index, pci_name(nesdev->pcidev)); + nesadapter->adapter_fcn_count = func_index; + + return nesadapter; } @@ -354,10 +592,10 @@ unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode) port_count = ((u32temp & 0x00000300) >> 8) + 1; /* TODO: assuming that both SERDES are set the same for now */ *OneG_Mode = (u32temp & 0x00003c00) ? 0 : 1; - dprintk("%s: Initial Software Reset = 0x%08X, port_count=%u\n", __FUNCTION__, u32temp, port_count); - if (*OneG_Mode) { - dprintk("%s: Running in 1G mode.\n", __FUNCTION__); - } + nes_debug(NES_DBG_INIT, "Initial Software Reset = 0x%08X, port_count=%u\n", + u32temp, port_count); + if (*OneG_Mode) + nes_debug(NES_DBG_INIT, "Running in 1G mode.\n"); u32temp &= 0xff00ffc0; switch (port_count) { case 1: @@ -370,22 +608,21 @@ unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode) u32temp |= 0x00000000; break; default: - return (0); + return 0; break; } /* check and do full reset if needed */ if (nes_read_indexed(nesdev, NES_IDX_QP_CONTROL+(PCI_FUNC(nesdev->pcidev->devfn)*8))) { - dprintk("Issuing Full Soft reset = 0x%08X\n", u32temp | 0xd); + nes_debug(NES_DBG_INIT, "Issuing Full Soft reset = 0x%08X\n", u32temp | 0xd); nes_write32(nesdev->regs+NES_SOFTWARE_RESET, u32temp | 0xd); i = 0; - while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET) & 0x00000040) == 0) && i++ < 10000) { + while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET) & 0x00000040) == 0) && i++ < 10000) mdelay(1); - } if (i >= 10000) { - dprintk("Did not see full soft reset done.\n"); - return (0); + nes_debug(NES_DBG_INIT, "Did not see full soft reset done.\n"); + return 0; } } @@ -402,107 +639,119 @@ unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode) break; } - dprintk("Issuing Port Soft reset = 0x%08X\n", u32temp | 0xd); + nes_debug(NES_DBG_INIT, "Issuing Port Soft reset = 0x%08X\n", u32temp | 0xd); nes_write32(nesdev->regs+NES_SOFTWARE_RESET, u32temp | 0xd); i = 0; - while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET) & 0x00000040) == 0) && i++ < 10000) { + while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET) & 0x00000040) == 0) && i++ < 10000) mdelay(1); - } if (i >= 10000) { - dprintk("Did not see port soft reset done.\n"); - return (0); + nes_debug(NES_DBG_INIT, "Did not see port soft reset done.\n"); + return 0; } /* serdes 0 */ i = 0; while (((u32temp = (nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS0) - & 0x0000000f)) != 0x0000000f) && i++ < 5000) { + & 0x0000000f)) != 0x0000000f) && i++ < 5000) mdelay(1); - } if (i >= 5000) { - dprintk("Serdes 0 not ready, status=%x\n", u32temp); - return (0); + nes_debug(NES_DBG_INIT, "Serdes 0 not ready, status=%x\n", u32temp); + return 0; } /* serdes 1 */ if (port_count > 1) { i = 0; while (((u32temp = (nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS1) - & 0x0000000f)) != 0x0000000f) && i++ < 5000) { + & 0x0000000f)) != 0x0000000f) && i++ < 5000) mdelay(1); - } if (i >= 5000) { - dprintk("Serdes 1 not ready, status=%x\n", u32temp); - return (0); + nes_debug(NES_DBG_INIT, "Serdes 1 not ready, status=%x\n", u32temp); + return 0; } } + + i = 0; - while ((nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS) != 0x80) && i++ < 10000) { + while ((nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS) != 0x80) && i++ < 10000) mdelay(1); - } - dprintk("%s:%u CPU_STATUS loops=%u\n", __FUNCTION__, __LINE__, i); if (i >= 10000) { printk(KERN_ERR PFX "Internal CPU not ready, status = %02X\n", nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS)); - return (0); + return 0; } - return (port_count); + return port_count; } /** * nes_init_serdes */ -int nes_init_serdes(struct nes_device *nesdev, u8 port_count) +int nes_init_serdes(struct nes_device *nesdev, u8 hw_rev, u8 port_count, u8 OneG_Mode) { int i; u32 u32temp; - /* init serdes 0 */ - nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0, 0x00000008); - i = 0; - while (((u32temp = (nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS0) - & 0x0000000f)) != 0x0000000f) && i++ < 5000) { - mdelay(1); - } - if (i >= 5000) { - dprintk("Init: serdes 0 not ready, status=%x\n", u32temp); - return (1); - } - nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP0, 0x000bdef7); - nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_DRIVE0, 0x9ce73000); - nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_MODE0, 0x0ff00000); - nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_SIGDET0, 0x00000000); - nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_BYPASS0, 0x00000000); - nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_LOOPBACK_CONTROL0, 0x00000000); - nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_EQ_CONTROL0, 0xf0002222); - nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000000ff); - - if (port_count > 1) { - /* init serdes 1 */ - nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x00000048); + if (hw_rev != NE020_REV) { + /* init serdes 0 */ + + nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000000FF); + if (!OneG_Mode) + nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_HIGHZ_LANE_MODE0, 0x11110000); + if (port_count > 1) { + /* init serdes 1 */ + nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL1, 0x000000FF); + if (!OneG_Mode) + nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_HIGHZ_LANE_MODE1, 0x11110000); + } + } else { + /* init serdes 0 */ + nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0, 0x00000008); i = 0; - while (((u32temp = (nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS1) & 0x0000000f)) != 0x0000000f) && - (i++ < 5000)) { + while (((u32temp = (nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS0) + & 0x0000000f)) != 0x0000000f) && i++ < 5000) mdelay(1); - } if (i >= 5000) { - printk("%s: Init: serdes 1 not ready, status=%x\n", __FUNCTION__, u32temp); - /* return 1; */ + nes_debug(NES_DBG_PHY, "Init: serdes 0 not ready, status=%x\n", u32temp); + return 1; + } + nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP0, 0x000bdef7); + nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_DRIVE0, 0x9ce73000); + nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_MODE0, 0x0ff00000); + nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_SIGDET0, 0x00000000); + nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_BYPASS0, 0x00000000); + nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_LOOPBACK_CONTROL0, 0x00000000); + if (OneG_Mode) + nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_EQ_CONTROL0, 0xf0182222); + else + nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_EQ_CONTROL0, 0xf0042222); + + nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000000ff); + if (port_count > 1) { + /* init serdes 1 */ + nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x00000048); + i = 0; + while (((u32temp = (nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS1) + & 0x0000000f)) != 0x0000000f) && (i++ < 5000)) + mdelay(1); + if (i >= 5000) { + printk("%s: Init: serdes 1 not ready, status=%x\n", __FUNCTION__, u32temp); + /* return 1; */ + } + nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP1, 0x000bdef7); + nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_DRIVE1, 0x9ce73000); + nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_MODE1, 0x0ff00000); + nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_SIGDET1, 0x00000000); + nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_BYPASS1, 0x00000000); + nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_LOOPBACK_CONTROL1, 0x00000000); + nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_EQ_CONTROL1, 0xf0002222); + nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL1, 0x000000ff); } - nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP1, 0x000bdef7); - nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_DRIVE1, 0x9ce73000); - nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_MODE1, 0x0ff00000); - nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_SIGDET1, 0x00000000); - nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_BYPASS1, 0x00000000); - nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_LOOPBACK_CONTROL1, 0x00000000); - nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_EQ_CONTROL1, 0xf0002222); - nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL1, 0x000000ff); - } - return (0); + } + return 0; } @@ -512,64 +761,79 @@ int nes_init_serdes(struct nes_device *nesdev, u8 port_count) */ void nes_init_csr_ne020(struct nes_device *nesdev, u8 hw_rev, u8 port_count) { + u32 u32temp; + + nes_debug(NES_DBG_INIT, "port_count=%d\n", port_count); - nes_write_indexed(nesdev, 0x000001E4, 0x00000007); - /* nes_write_indexed(nesdev, 0x000001E8, 0x000208C4); */ - nes_write_indexed(nesdev, 0x000001E8, 0x00020844); - nes_write_indexed(nesdev, 0x000001D8, 0x00048002); - /* nes_write_indexed(nesdev, 0x000001D8, 0x0004B002); */ - nes_write_indexed(nesdev, 0x000001FC, 0x00050005); - nes_write_indexed(nesdev, 0x00000600, 0x55555555); - nes_write_indexed(nesdev, 0x00000604, 0x55555555); + nes_write_indexed(nesdev, 0x000001E4, 0x00000007); + /* nes_write_indexed(nesdev, 0x000001E8, 0x000208C4); */ + nes_write_indexed(nesdev, 0x000001E8, 0x00020874); + nes_write_indexed(nesdev, 0x000001D8, 0x00048002); + /* nes_write_indexed(nesdev, 0x000001D8, 0x0004B002); */ + nes_write_indexed(nesdev, 0x000001FC, 0x00050005); + nes_write_indexed(nesdev, 0x00000600, 0x55555555); + nes_write_indexed(nesdev, 0x00000604, 0x55555555); /* TODO: move these MAC register settings to NIC bringup */ - nes_write_indexed(nesdev, 0x00002000, 0x00000001); - nes_write_indexed(nesdev, 0x00002004, 0x00000001); - nes_write_indexed(nesdev, 0x00002008, 0x0000FFFF); - nes_write_indexed(nesdev, 0x0000200C, 0x00000001); - nes_write_indexed(nesdev, 0x00002010, 0x000003c1); - nes_write_indexed(nesdev, 0x0000201C, 0x75345678); + nes_write_indexed(nesdev, 0x00002000, 0x00000001); + nes_write_indexed(nesdev, 0x00002004, 0x00000001); + nes_write_indexed(nesdev, 0x00002008, 0x0000FFFF); + nes_write_indexed(nesdev, 0x0000200C, 0x00000001); + nes_write_indexed(nesdev, 0x00002010, 0x000003c1); + nes_write_indexed(nesdev, 0x0000201C, 0x75345678); if (port_count > 1) { - nes_write_indexed(nesdev, 0x00002200, 0x00000001); - nes_write_indexed(nesdev, 0x00002204, 0x00000001); - nes_write_indexed(nesdev, 0x00002208, 0x0000FFFF); - nes_write_indexed(nesdev, 0x0000220C, 0x00000001); - nes_write_indexed(nesdev, 0x00002210, 0x000003c1); - nes_write_indexed(nesdev, 0x0000221C, 0x75345678); + nes_write_indexed(nesdev, 0x00002200, 0x00000001); + nes_write_indexed(nesdev, 0x00002204, 0x00000001); + nes_write_indexed(nesdev, 0x00002208, 0x0000FFFF); + nes_write_indexed(nesdev, 0x0000220C, 0x00000001); + nes_write_indexed(nesdev, 0x00002210, 0x000003c1); + nes_write_indexed(nesdev, 0x0000221C, 0x75345678); + nes_write_indexed(nesdev, 0x00000908, 0x20000001); } if (port_count > 2) { - nes_write_indexed(nesdev, 0x00002400, 0x00000001); - nes_write_indexed(nesdev, 0x00002404, 0x00000001); - nes_write_indexed(nesdev, 0x00002408, 0x0000FFFF); - nes_write_indexed(nesdev, 0x0000240C, 0x00000001); - nes_write_indexed(nesdev, 0x00002410, 0x000003c1); - nes_write_indexed(nesdev, 0x0000241C, 0x75345678); - - nes_write_indexed(nesdev, 0x00002600, 0x00000001); - nes_write_indexed(nesdev, 0x00002604, 0x00000001); - nes_write_indexed(nesdev, 0x00002608, 0x0000FFFF); - nes_write_indexed(nesdev, 0x0000260C, 0x00000001); - nes_write_indexed(nesdev, 0x00002610, 0x000003c1); - nes_write_indexed(nesdev, 0x0000261C, 0x75345678); - } - - nes_write_indexed(nesdev, 0x00005000, 0x00018000); - /* nes_write_indexed(nesdev, 0x00005000, 0x00010000); */ - nes_write_indexed(nesdev, 0x00005004, 0x00020001); - nes_write_indexed(nesdev, 0x00005008, 0x1F1F1F1F); - nes_write_indexed(nesdev, 0x00005010, 0x1F1F1F1F); - nes_write_indexed(nesdev, 0x00005018, 0x1F1F1F1F); - nes_write_indexed(nesdev, 0x00005020, 0x1F1F1F1F); - nes_write_indexed(nesdev, 0x00006090, 0xFFFFFFFF); + nes_write_indexed(nesdev, 0x00002400, 0x00000001); + nes_write_indexed(nesdev, 0x00002404, 0x00000001); + nes_write_indexed(nesdev, 0x00002408, 0x0000FFFF); + nes_write_indexed(nesdev, 0x0000240C, 0x00000001); + nes_write_indexed(nesdev, 0x00002410, 0x000003c1); + nes_write_indexed(nesdev, 0x0000241C, 0x75345678); + nes_write_indexed(nesdev, 0x00000910, 0x20000001); + + nes_write_indexed(nesdev, 0x00002600, 0x00000001); + nes_write_indexed(nesdev, 0x00002604, 0x00000001); + nes_write_indexed(nesdev, 0x00002608, 0x0000FFFF); + nes_write_indexed(nesdev, 0x0000260C, 0x00000001); + nes_write_indexed(nesdev, 0x00002610, 0x000003c1); + nes_write_indexed(nesdev, 0x0000261C, 0x75345678); + nes_write_indexed(nesdev, 0x00000918, 0x20000001); + } + + nes_write_indexed(nesdev, 0x00005000, 0x00018000); + /* nes_write_indexed(nesdev, 0x00005000, 0x00010000); */ + nes_write_indexed(nesdev, 0x00005004, 0x00020001); + nes_write_indexed(nesdev, 0x00005008, 0x1F1F1F1F); + nes_write_indexed(nesdev, 0x00005010, 0x1F1F1F1F); + nes_write_indexed(nesdev, 0x00005018, 0x1F1F1F1F); + nes_write_indexed(nesdev, 0x00005020, 0x1F1F1F1F); + nes_write_indexed(nesdev, 0x00006090, 0xFFFFFFFF); /* TODO: move this to code, get from EEPROM */ - nes_write_indexed(nesdev, 0x00000900, 0x20000001); - nes_write_indexed(nesdev, 0x000060C0, 0x0000028e); - nes_write_indexed(nesdev, 0x000060C8, 0x00000020); + nes_write_indexed(nesdev, 0x00000900, 0x20000001); + nes_write_indexed(nesdev, 0x000060C0, 0x0000028e); + nes_write_indexed(nesdev, 0x000060C8, 0x00000020); + // + nes_write_indexed(nesdev, 0x000001EC, 0x7b2625a0); + /* nes_write_indexed(nesdev, 0x000001EC, 0x5f2625a0); */ - nes_write_indexed(nesdev, 0x000001EC, 0x5b2625a0); - /* nes_write_indexed(nesdev, 0x000001EC, 0x5f2625a0); */ - + if (hw_rev != NE020_REV) { + u32temp = nes_read_indexed(nesdev, 0x000008e8); + u32temp |= 0x80000000; + nes_write_indexed(nesdev, 0x000008e8, u32temp); + u32temp = nes_read_indexed(nesdev, 0x000021f8); + u32temp &= 0x7fffffff; + u32temp |= 0x7fff0010; + nes_write_indexed(nesdev, 0x000021f8, u32temp); + } } @@ -581,19 +845,20 @@ void nes_destroy_adapter(struct nes_adapter *nesadapter) struct nes_adapter *tmp_adapter; list_for_each_entry(tmp_adapter, &nes_adapter_list, list) { - dprintk("%s: Nes Adapter list entry = 0x%p.\n", __FUNCTION__, tmp_adapter); + nes_debug(NES_DBG_SHUTDOWN, "Nes Adapter list entry = 0x%p.\n", + tmp_adapter); } nesadapter->ref_count--; if (!nesadapter->ref_count) { + if (nesadapter->hw_rev == NE020_REV) { del_timer(&nesadapter->mh_timer); + } + del_timer(&nesadapter->lc_timer); - dprintk("nes_destroy_adapter: Deleting adapter from adapter list.\n"); list_del(&nesadapter->list); - dprintk("nes_destroy_adapter: Freeing adapter structure.\n"); kfree(nesadapter); } - dprintk("%s: Done.\n", __FUNCTION__); } @@ -615,10 +880,6 @@ int nes_init_cqp(struct nes_device *nesdev) u64 u64temp; u32 u32temp; -#define NES_NIC_CEQ_SIZE 8 -/* NICs will be on a separate CQ */ -#define NES_CCEQ_SIZE ((nesadapter->max_cq / nesadapter->port_count) - 32) - /* allocate CQP memory */ /* Need to add max_cq to the aeq size once cq overflow checking is added back */ /* SQ is 512 byte aligned, others are 256 byte aligned */ @@ -633,31 +894,30 @@ int nes_init_cqp(struct nes_device *nesdev) nesdev->cqp_vbase = pci_alloc_consistent(nesdev->pcidev, nesdev->cqp_mem_size, &nesdev->cqp_pbase); if (!nesdev->cqp_vbase) { - dprintk(KERN_ERR PFX "Unable to allocate memory for host descriptor rings\n"); - return(-ENOMEM); + nes_debug(NES_DBG_INIT, "Unable to allocate memory for host descriptor rings\n"); + return -ENOMEM; } memset(nesdev->cqp_vbase, 0, nesdev->cqp_mem_size); /* Allocate a twice the number of CQP requests as the SQ size */ - nesdev->nes_cqp_requests = kmalloc(sizeof(struct nes_cqp_request) * + nesdev->nes_cqp_requests = kzalloc(sizeof(struct nes_cqp_request) * 2 * NES_CQP_SQ_SIZE, GFP_KERNEL); - if (NULL == nesdev->nes_cqp_requests) { - dprintk(KERN_ERR PFX "Unable to allocate memory CQP request entries.\n"); + if (nesdev->nes_cqp_requests == NULL) { + nes_debug(NES_DBG_INIT, "Unable to allocate memory CQP request entries.\n"); pci_free_consistent(nesdev->pcidev, nesdev->cqp_mem_size, nesdev->cqp.sq_vbase, nesdev->cqp.sq_pbase); - return(-ENOMEM); + return -ENOMEM; } - memset(nesdev->nes_cqp_requests, 0, sizeof(struct nes_cqp_request) * - 2 * NES_CQP_SQ_SIZE); - dprintk("Allocated CQP structures at %p (phys = %016lX), size = %u.\n", + + nes_debug(NES_DBG_INIT, "Allocated CQP structures at %p (phys = %016lX), size = %u.\n", nesdev->cqp_vbase, (unsigned long)nesdev->cqp_pbase, nesdev->cqp_mem_size); spin_lock_init(&nesdev->cqp.lock); init_waitqueue_head(&nesdev->cqp.waitq); /* Setup Various Structures */ - vmem = (void *)(((unsigned long long)nesdev->cqp_vbase + (512 - 1)) & - ~(unsigned long long)(512 - 1)); + vmem = (void *)(((unsigned long)nesdev->cqp_vbase + (512 - 1)) & + ~(unsigned long)(512 - 1)); pmem = (dma_addr_t)(((unsigned long long)nesdev->cqp_pbase + (512 - 1)) & ~(unsigned long long)(512 - 1)); @@ -667,8 +927,6 @@ int nes_init_cqp(struct nes_device *nesdev) nesdev->cqp.sq_head = 0; nesdev->cqp.sq_tail = 0; nesdev->cqp.qp_id = PCI_FUNC(nesdev->pcidev->devfn); - dprintk("CQP at %p (phys = %016lX).\n", - nesdev->cqp.sq_vbase, (unsigned long)nesdev->cqp.sq_pbase); vmem += (sizeof(struct nes_hw_cqp_wqe) * nesdev->cqp.sq_size); pmem += (sizeof(struct nes_hw_cqp_wqe) * nesdev->cqp.sq_size); @@ -679,8 +937,6 @@ int nes_init_cqp(struct nes_device *nesdev) nesdev->ccq.cq_head = 0; nesdev->ccq.ce_handler = nes_cqp_ce_handler; nesdev->ccq.cq_number = PCI_FUNC(nesdev->pcidev->devfn); - dprintk("CCQ at %p (phys = %016lX).\n", - nesdev->ccq.cq_vbase, (unsigned long)nesdev->ccq.cq_pbase); vmem += (sizeof(struct nes_hw_cqe) * nesdev->ccq.cq_size); pmem += (sizeof(struct nes_hw_cqe) * nesdev->ccq.cq_size); @@ -691,8 +947,6 @@ int nes_init_cqp(struct nes_device *nesdev) ceq->ceq_pbase = pmem; ceq->ceq_size = NES_CCEQ_SIZE; ceq->ceq_head = 0; - dprintk("CEQ at %p (phys = %016lX).\n", - ceq->ceq_vbase, (unsigned long)ceq->ceq_pbase); vmem += max(((u32)sizeof(struct nes_hw_ceqe) * ceq->ceq_size), (u32)256); pmem += max(((u32)sizeof(struct nes_hw_ceqe) * ceq->ceq_size), (u32)256); @@ -703,8 +957,6 @@ int nes_init_cqp(struct nes_device *nesdev) nic_ceq->ceq_pbase = pmem; nic_ceq->ceq_size = NES_NIC_CEQ_SIZE; nic_ceq->ceq_head = 0; - dprintk("NIC CEQ at %p (phys = %016lX).\n", - nic_ceq->ceq_vbase, (unsigned long)nic_ceq->ceq_pbase); vmem += max(((u32)sizeof(struct nes_hw_ceqe) * nic_ceq->ceq_size), (u32)256); pmem += max(((u32)sizeof(struct nes_hw_ceqe) * nic_ceq->ceq_size), (u32)256); @@ -714,24 +966,18 @@ int nes_init_cqp(struct nes_device *nesdev) aeq->aeq_pbase = pmem; aeq->aeq_size = nesadapter->max_qp; aeq->aeq_head = 0; - dprintk("AEQ at %p (phys = %016lX).\n", - aeq->aeq_vbase, (unsigned long)aeq->aeq_pbase); /* Setup QP Context */ vmem += (sizeof(struct nes_hw_aeqe) * aeq->aeq_size); pmem += (sizeof(struct nes_hw_aeqe) * aeq->aeq_size); cqp_qp_context = vmem; - cqp_qp_context->context_words[0] = (PCI_FUNC(nesdev->pcidev->devfn) << 12) + (2 << 10); + cqp_qp_context->context_words[0] = + cpu_to_le32((PCI_FUNC(nesdev->pcidev->devfn) << 12) + (2 << 10)); cqp_qp_context->context_words[1] = 0; - cqp_qp_context->context_words[2] = (u32)nesdev->cqp.sq_pbase; - cqp_qp_context->context_words[3] = ((u64)nesdev->cqp.sq_pbase) >> 32; + cqp_qp_context->context_words[2] = cpu_to_le32((u32)nesdev->cqp.sq_pbase); + cqp_qp_context->context_words[3] = cpu_to_le32(((u64)nesdev->cqp.sq_pbase) >> 32); - dprintk("Address of CQP Context = %p.\n", cqp_qp_context); - for (count=0;count<4 ; count++) { - dprintk("CQP Context, Line %u = %08X.\n", - count, cqp_qp_context->context_words[count]); - } /* Write the address to Create CQP */ if ((sizeof(dma_addr_t) > 4)) { @@ -746,82 +992,63 @@ int nes_init_cqp(struct nes_device *nesdev) NES_IDX_CREATE_CQP_LOW + (PCI_FUNC(nesdev->pcidev->devfn) * 8), (u32)pmem); - dprintk("Address of CQP SQ = %p.\n", nesdev->cqp.sq_vbase); - INIT_LIST_HEAD(&nesdev->cqp_avail_reqs); INIT_LIST_HEAD(&nesdev->cqp_pending_reqs); - for (count=0; count<2*NES_CQP_SQ_SIZE; count++) { + for (count = 0; count < 2*NES_CQP_SQ_SIZE; count++) { init_waitqueue_head(&nesdev->nes_cqp_requests[count].waitq); list_add_tail(&nesdev->nes_cqp_requests[count].list, &nesdev->cqp_avail_reqs); - /* dprintk("Adding cqp request %p to the available list \n", - &nesdev->nes_cqp_requests[count]); */ } /* Write Create CCQ WQE */ cqp_head = nesdev->cqp.sq_head++; cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head]; - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_CREATE_CQ | NES_CQP_CQ_CEQ_VALID | - NES_CQP_CQ_CHK_OVERFLOW | ((u32)nesdev->ccq.cq_size << 16)); - cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(nesdev->ccq.cq_number | - ((u32)nesdev->ceq_index<<16)); - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX] = 0; - *((struct nes_hw_cqp **)&cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_LOW_IDX]) = &nesdev->cqp; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] = 0; + nes_fill_init_cqp_wqe(cqp_wqe, nesdev); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, + (NES_CQP_CREATE_CQ | NES_CQP_CQ_CEQ_VALID | + NES_CQP_CQ_CHK_OVERFLOW | ((u32)nesdev->ccq.cq_size << 16))); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX, + (nesdev->ccq.cq_number | + ((u32)nesdev->ceq_index << 16))); u64temp = (u64)nesdev->ccq.cq_pbase; - cqp_wqe->wqe_words[NES_CQP_CQ_WQE_PBL_LOW_IDX] = cpu_to_le32((u32)u64temp); - cqp_wqe->wqe_words[NES_CQP_CQ_WQE_PBL_HIGH_IDX] = cpu_to_le32((u32)(u64temp >> 32)); + set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp); cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] = 0; - /* TODO: the following 2 lines likely have endian issues */ - *((struct nes_hw_cq **)&cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_LOW_IDX]) = &nesdev->ccq; - *((u64 *)&cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_LOW_IDX]) >>= 1; - dprintk("%s: CQ%u context = 0x%08X:0x%08X.\n", __FUNCTION__, nesdev->ccq.cq_number, - cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX], - cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_LOW_IDX]); - + u64temp = (unsigned long)&nesdev->ccq; + cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_LOW_IDX] = + cpu_to_le32((u32)(u64temp >> 1)); + cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] = + cpu_to_le32(((u32)((u64temp) >> 33)) & 0x7FFFFFFF); cqp_wqe->wqe_words[NES_CQP_CQ_WQE_DOORBELL_INDEX_HIGH_IDX] = 0; /* Write Create CEQ WQE */ cqp_head = nesdev->cqp.sq_head++; cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head]; - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_CREATE_CEQ + - ((u32)nesdev->ceq_index << 8)); - cqp_wqe->wqe_words[NES_CQP_CEQ_WQE_ELEMENT_COUNT_IDX] = cpu_to_le32(ceq->ceq_size); - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX] = 0; - *((struct nes_hw_cqp **)&cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_LOW_IDX]) = &nesdev->cqp; - *((struct nes_cqp_request **)&cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX]) = NULL; + nes_fill_init_cqp_wqe(cqp_wqe, nesdev); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, + (NES_CQP_CREATE_CEQ + ((u32)nesdev->ceq_index << 8))); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_CEQ_WQE_ELEMENT_COUNT_IDX, ceq->ceq_size); u64temp = (u64)ceq->ceq_pbase; - cqp_wqe->wqe_words[NES_CQP_CEQ_WQE_PBL_LOW_IDX] = cpu_to_le32((u32)u64temp); - cqp_wqe->wqe_words[NES_CQP_CEQ_WQE_PBL_HIGH_IDX] = cpu_to_le32((u32)(u64temp >> 32)); + set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp); /* Write Create AEQ WQE */ cqp_head = nesdev->cqp.sq_head++; cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head]; - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_CREATE_AEQ + - ((u32)PCI_FUNC(nesdev->pcidev->devfn) << 8)); - cqp_wqe->wqe_words[NES_CQP_AEQ_WQE_ELEMENT_COUNT_IDX] = cpu_to_le32(aeq->aeq_size); - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX] = 0; - *((struct nes_hw_cqp **)&cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_LOW_IDX]) = &nesdev->cqp; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] = 0; + nes_fill_init_cqp_wqe(cqp_wqe, nesdev); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, + (NES_CQP_CREATE_AEQ + ((u32)PCI_FUNC(nesdev->pcidev->devfn) << 8))); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_AEQ_WQE_ELEMENT_COUNT_IDX, aeq->aeq_size); u64temp = (u64)aeq->aeq_pbase; - cqp_wqe->wqe_words[NES_CQP_AEQ_WQE_PBL_LOW_IDX] = cpu_to_le32((u32)u64temp); - cqp_wqe->wqe_words[NES_CQP_AEQ_WQE_PBL_HIGH_IDX] = cpu_to_le32((u32)(u64temp >> 32)); + set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp); - /* Write Create CEQ WQE */ + /* Write Create NIC CEQ WQE */ cqp_head = nesdev->cqp.sq_head++; cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head]; - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_CREATE_CEQ + - ((u32)nesdev->nic_ceq_index << 8)); - cqp_wqe->wqe_words[NES_CQP_CEQ_WQE_ELEMENT_COUNT_IDX] = cpu_to_le32(nic_ceq->ceq_size); - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX] = 0; - *((struct nes_hw_cqp **)&cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_LOW_IDX]) = &nesdev->cqp; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] = 0; + nes_fill_init_cqp_wqe(cqp_wqe, nesdev); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, + (NES_CQP_CREATE_CEQ + ((u32)nesdev->nic_ceq_index << 8))); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_CEQ_WQE_ELEMENT_COUNT_IDX, nic_ceq->ceq_size); u64temp = (u64)nic_ceq->ceq_pbase; - cqp_wqe->wqe_words[NES_CQP_CEQ_WQE_PBL_LOW_IDX] = cpu_to_le32((u32)u64temp); - cqp_wqe->wqe_words[NES_CQP_CEQ_WQE_PBL_HIGH_IDX] = cpu_to_le32((u32)(u64temp >> 32)); + set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp); /* Poll until CCQP done */ count = 0; @@ -830,13 +1057,13 @@ int nes_init_cqp(struct nes_device *nesdev) printk(KERN_ERR PFX "Error creating CQP\n"); pci_free_consistent(nesdev->pcidev, nesdev->cqp_mem_size, nesdev->cqp_vbase, nesdev->cqp_pbase); - return(-1); + return -1; } udelay(10); } while (!(nes_read_indexed(nesdev, NES_IDX_QP_CONTROL + (PCI_FUNC(nesdev->pcidev->devfn) * 8)) & (1 << 8))); - dprintk("CQP Status = 0x%08X\n", nes_read_indexed(nesdev, + nes_debug(NES_DBG_INIT, "CQP Status = 0x%08X\n", nes_read_indexed(nesdev, NES_IDX_QP_CONTROL+(PCI_FUNC(nesdev->pcidev->devfn)*8))); u32temp = 0x04800000; @@ -849,19 +1076,19 @@ int nes_init_cqp(struct nes_device *nesdev) printk(KERN_ERR PFX "Error creating CCQ, CEQ, and AEQ\n"); pci_free_consistent(nesdev->pcidev, nesdev->cqp_mem_size, nesdev->cqp_vbase, nesdev->cqp_pbase); - return(-1); + return -1; } udelay(10); } while (((nes_read_indexed(nesdev, - NES_IDX_QP_CONTROL + (PCI_FUNC(nesdev->pcidev->devfn)*8)) & (15<<8)) != (15<<8))); + NES_IDX_QP_CONTROL+(PCI_FUNC(nesdev->pcidev->devfn)*8)) & (15<<8)) != (15<<8))); /* dump the QP status value */ - dprintk("QP Status = 0x%08X\n", nes_read_indexed(nesdev, + nes_debug(NES_DBG_INIT, "QP Status = 0x%08X\n", nes_read_indexed(nesdev, NES_IDX_QP_CONTROL+(PCI_FUNC(nesdev->pcidev->devfn)*8))); nesdev->cqp.sq_tail++; - return (0); + return 0; } @@ -871,13 +1098,13 @@ int nes_init_cqp(struct nes_device *nesdev) int nes_destroy_cqp(struct nes_device *nesdev) { struct nes_hw_cqp_wqe *cqp_wqe; - u32 count=0; + u32 count = 0; u32 cqp_head; unsigned long flags; - dprintk("Waiting for CQP work to complete.\n"); do { - if (count++ > 1000) break; + if (count++ > 1000) + break; udelay(10); } while (!(nesdev->cqp.sq_head == nesdev->cqp.sq_tail)); @@ -887,46 +1114,51 @@ int nes_destroy_cqp(struct nes_device *nesdev) /* Disable device interrupts */ nes_write32(nesdev->regs+NES_INT_MASK, 0x7fffffff); - /* Destroy the AEQ */ + spin_lock_irqsave(&nesdev->cqp.lock, flags); + + /* Destroy the AEQ */ cqp_head = nesdev->cqp.sq_head++; nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1; cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head]; cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_DESTROY_AEQ | - ((u32)PCI_FUNC(nesdev->pcidev->devfn)<<8)); + ((u32)PCI_FUNC(nesdev->pcidev->devfn) << 8)); cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX] = 0; + /* Destroy the NIC CEQ */ cqp_head = nesdev->cqp.sq_head++; nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1; cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head]; cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_DESTROY_CEQ | - ((u32)nesdev->nic_ceq_index<<8)); + ((u32)nesdev->nic_ceq_index << 8)); + /* Destroy the CEQ */ cqp_head = nesdev->cqp.sq_head++; nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1; cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head]; cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_DESTROY_CEQ | - (nesdev->ceq_index<<8)); + (nesdev->ceq_index << 8)); + /* Destroy the CCQ */ cqp_head = nesdev->cqp.sq_head++; nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1; cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head]; - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_DESTROY_CQ); - cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32( nesdev->ccq.cq_number || - ((u32)nesdev->ceq_index<<16)); + cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_DESTROY_CQ); + cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(nesdev->ccq.cq_number | + ((u32)nesdev->ceq_index << 16)); + /* Destroy CQP */ cqp_head = nesdev->cqp.sq_head++; nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1; cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head]; cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_DESTROY_QP | NES_CQP_QP_TYPE_CQP); - cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(nesdev->cqp.qp_id); + cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(nesdev->cqp.qp_id); barrier(); - /* Ring doorbell (4 WQEs) */ + /* Ring doorbell (5 WQEs) */ nes_write32(nesdev->regs+NES_WQE_ALLOC, 0x05800000 | nesdev->cqp.qp_id); - /* Wait for the destroy to complete */ spin_unlock_irqrestore(&nesdev->cqp.lock, flags); /* wait for the CCQ, CEQ, and AEQ to get destroyed */ @@ -939,10 +1171,10 @@ int nes_destroy_cqp(struct nes_device *nesdev) } udelay(10); } while (((nes_read_indexed(nesdev, - NES_IDX_QP_CONTROL + (PCI_FUNC(nesdev->pcidev->devfn)*8)) & (15<<8)) != 0)); + NES_IDX_QP_CONTROL + (PCI_FUNC(nesdev->pcidev->devfn)*8)) & (15 << 8)) != 0)); /* dump the QP status value */ - dprintk("Function%d: QP Status = 0x%08X\n", + nes_debug(NES_DBG_SHUTDOWN, "Function%d: QP Status = 0x%08X\n", PCI_FUNC(nesdev->pcidev->devfn), nes_read_indexed(nesdev, NES_IDX_QP_CONTROL+(PCI_FUNC(nesdev->pcidev->devfn)*8))); @@ -953,7 +1185,7 @@ int nes_destroy_cqp(struct nes_device *nesdev) pci_free_consistent(nesdev->pcidev, nesdev->cqp_mem_size, nesdev->cqp.sq_vbase, nesdev->cqp.sq_pbase); - return (0); + return 0; } @@ -965,14 +1197,21 @@ int nes_init_phy(struct nes_device *nesdev) struct nes_adapter *nesadapter = nesdev->nesadapter; u32 counter = 0; u32 mac_index = nesdev->mac_index; + u32 tx_config; u16 phy_data; if (nesadapter->OneG_Mode) { - dprintk("1G PHY, mac_index = %d.\n", mac_index); + nes_debug(NES_DBG_PHY, "1G PHY, mac_index = %d.\n", mac_index); + if (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_1G) { + printk(PFX "%s: Programming mdc config for 1G\n", __FUNCTION__); + tx_config = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONFIG); + tx_config |= 0x04; + nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG, tx_config); + } + nes_read_1G_phy_reg(nesdev, 1, nesadapter->phy_index[mac_index], &phy_data); - dprintk("Phy data from register 1 phy address %u = 0x%X.\n", + nes_debug(NES_DBG_PHY, "Phy data from register 1 phy address %u = 0x%X.\n", nesadapter->phy_index[mac_index], phy_data); - nes_write_1G_phy_reg(nesdev, 23, nesadapter->phy_index[mac_index], 0xb000); /* Reset the PHY */ @@ -981,7 +1220,7 @@ int nes_init_phy(struct nes_device *nesdev) counter = 0; do { nes_read_1G_phy_reg(nesdev, 0, nesadapter->phy_index[mac_index], &phy_data); - dprintk("Phy data from register 0 = 0x%X.\n", phy_data); + nes_debug(NES_DBG_PHY, "Phy data from register 0 = 0x%X.\n", phy_data); if (counter++ > 100) break; } while (phy_data & 0x8000); @@ -990,46 +1229,57 @@ int nes_init_phy(struct nes_device *nesdev) phy_data |= 0x1140; nes_write_1G_phy_reg(nesdev, 0, nesadapter->phy_index[mac_index], phy_data); nes_read_1G_phy_reg(nesdev, 0, nesadapter->phy_index[mac_index], &phy_data); - dprintk("Phy data from register 0 = 0x%X.\n", phy_data); + nes_debug(NES_DBG_PHY, "Phy data from register 0 = 0x%X.\n", phy_data); nes_read_1G_phy_reg(nesdev, 0x17, nesadapter->phy_index[mac_index], &phy_data); - dprintk("Phy data from register 0x17 = 0x%X.\n", phy_data); + nes_debug(NES_DBG_PHY, "Phy data from register 0x17 = 0x%X.\n", phy_data); nes_read_1G_phy_reg(nesdev, 0x1e, nesadapter->phy_index[mac_index], &phy_data); - dprintk("Phy data from register 0x1e = 0x%X.\n", phy_data); + nes_debug(NES_DBG_PHY, "Phy data from register 0x1e = 0x%X.\n", phy_data); /* Setting the interrupt mask */ nes_read_1G_phy_reg(nesdev, 0x19, nesadapter->phy_index[mac_index], &phy_data); - dprintk("Phy data from register 0x19 = 0x%X.\n", phy_data); + nes_debug(NES_DBG_PHY, "Phy data from register 0x19 = 0x%X.\n", phy_data); nes_write_1G_phy_reg(nesdev, 0x19, nesadapter->phy_index[mac_index], 0xffee); nes_read_1G_phy_reg(nesdev, 0x19, nesadapter->phy_index[mac_index], &phy_data); - dprintk("Phy data from register 0x19 = 0x%X.\n", phy_data); + nes_debug(NES_DBG_PHY, "Phy data from register 0x19 = 0x%X.\n", phy_data); /* turning on flow control */ nes_read_1G_phy_reg(nesdev, 4, nesadapter->phy_index[mac_index], &phy_data); - dprintk("Phy data from register 0x4 = 0x%X.\n", phy_data); + nes_debug(NES_DBG_PHY, "Phy data from register 0x4 = 0x%X.\n", phy_data); nes_write_1G_phy_reg(nesdev, 4, nesadapter->phy_index[mac_index], (phy_data & ~(0x03E0)) | 0xc00); /* nes_write_1G_phy_reg(nesdev, 4, nesadapter->phy_index[mac_index], phy_data | 0xc00); */ nes_read_1G_phy_reg(nesdev, 4, nesadapter->phy_index[mac_index], &phy_data); - dprintk("Phy data from register 0x4 = 0x%X.\n", phy_data); + nes_debug(NES_DBG_PHY, "Phy data from register 0x4 = 0x%X.\n", phy_data); nes_read_1G_phy_reg(nesdev, 9, nesadapter->phy_index[mac_index], &phy_data); - dprintk("Phy data from register 0x9 = 0x%X.\n", phy_data); + nes_debug(NES_DBG_PHY, "Phy data from register 0x9 = 0x%X.\n", phy_data); /* Clear Half duplex */ nes_write_1G_phy_reg(nesdev, 9, nesadapter->phy_index[mac_index], phy_data & ~(0x0100)); nes_read_1G_phy_reg(nesdev, 9, nesadapter->phy_index[mac_index], &phy_data); - dprintk("Phy data from register 0x9 = 0x%X.\n", phy_data); + nes_debug(NES_DBG_PHY, "Phy data from register 0x9 = 0x%X.\n", phy_data); nes_read_1G_phy_reg(nesdev, 0, nesadapter->phy_index[mac_index], &phy_data); nes_write_1G_phy_reg(nesdev, 0, nesadapter->phy_index[mac_index], phy_data | 0x0300); + } else { + if (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_IRIS) { + /* setup 10G MDIO operation */ + tx_config = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONFIG); + tx_config |= 0x14; + nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG, tx_config); + } } - return (0); + return 0; } + +/** + * nes_replenish_nic_rq + */ static void nes_replenish_nic_rq(struct nes_vnic *nesvnic) { unsigned long flags; @@ -1043,10 +1293,22 @@ static void nes_replenish_nic_rq(struct nes_vnic *nesvnic) nesnic = &nesvnic->nic; nesdev = nesvnic->nesdev; spin_lock_irqsave(&nesnic->rq_lock, flags); + if (nesnic->replenishing_rq != 0) { + if (((nesnic->rq_size-1) == atomic_read(&nesvnic->rx_skbs_needed)) && + (atomic_read(&nesvnic->rx_skb_timer_running) == 0)) { + atomic_set(&nesvnic->rx_skb_timer_running, 1); + spin_unlock_irqrestore(&nesnic->rq_lock, flags); + nesvnic->rq_wqes_timer.expires = jiffies + (HZ/2); /* 1/2 second */ + add_timer(&nesvnic->rq_wqes_timer); + } else + spin_unlock_irqrestore(&nesnic->rq_lock, flags); + return; + } + nesnic->replenishing_rq = 1; + spin_unlock_irqrestore(&nesnic->rq_lock, flags); do { skb = dev_alloc_skb(nesvnic->max_frame_size); if (skb) { - /* dprintk("skb %p added to the RQ at index %u.\n", skb, nesnic->rq_head); */ skb->dev = nesvnic->netdev; bus_address = pci_map_single(nesdev->pcidev, @@ -1064,32 +1326,34 @@ static void nes_replenish_nic_rq(struct nes_vnic *nesvnic) nesnic->rq_head++; nesnic->rq_head &= nesnic->rq_size - 1; atomic_dec(&nesvnic->rx_skbs_needed); - if (++rx_wqes_posted==255) { + barrier(); + if (++rx_wqes_posted == 255) { nes_write32(nesdev->regs+NES_WQE_ALLOC, (rx_wqes_posted << 24) | nesnic->qp_id); rx_wqes_posted = 0; } } else { - printk("%s[%u] alloc_skb failed! %u wqes still needed.\n", __FUNCTION__, __LINE__, - atomic_read(&nesvnic->rx_skbs_needed)); - if (((nesnic->rq_size-1) == atomic_read(&nesvnic->rx_skbs_needed)) && - (0 == atomic_read(&nesvnic->rx_skb_timer_running))) { - printk("%s[%u] Starting Timer.\n", __FUNCTION__, __LINE__); + spin_lock_irqsave(&nesnic->rq_lock, flags); + if (((nesnic->rq_size-1) == atomic_read(&nesvnic->rx_skbs_needed)) && + (atomic_read(&nesvnic->rx_skb_timer_running) == 0)) { atomic_set(&nesvnic->rx_skb_timer_running, 1); - nesvnic->rq_wqes_timer.expires = jiffies + (HZ/2); /* 1/2 second */ + spin_unlock_irqrestore(&nesnic->rq_lock, flags); + nesvnic->rq_wqes_timer.expires = jiffies + (HZ/2); /* 1/2 second */ add_timer(&nesvnic->rq_wqes_timer); - /* TODO: Need to deal with the case where the vnic is destroyed and the timer is running */ - } + } else + spin_unlock_irqrestore(&nesnic->rq_lock, flags); break; } - } while ( atomic_read(&nesvnic->rx_skbs_needed) ); - if (rx_wqes_posted) { + } while (atomic_read(&nesvnic->rx_skbs_needed)); + barrier(); + if (rx_wqes_posted) nes_write32(nesdev->regs+NES_WQE_ALLOC, (rx_wqes_posted << 24) | nesnic->qp_id); - } - spin_unlock_irqrestore(&nesnic->rq_lock, flags); - + nesnic->replenishing_rq = 0; } +/** + * nes_rq_wqes_timeout + */ static void nes_rq_wqes_timeout(unsigned long parm) { struct nes_vnic *nesvnic = (struct nes_vnic *)parm; @@ -1099,6 +1363,7 @@ static void nes_rq_wqes_timeout(unsigned long parm) nes_replenish_nic_rq(nesvnic); } + /** * nes_init_nic_qp */ @@ -1118,6 +1383,7 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev) u32 cqp_head; u32 counter; u32 wqe_count; + u8 jumbomode=0; /* Allocate fragment, SQ, RQ, and CQ; Reuse CEQ based on the PCI function */ nesvnic->nic_mem_size = 256 + @@ -1130,21 +1396,18 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev) nesvnic->nic_vbase = pci_alloc_consistent(nesdev->pcidev, nesvnic->nic_mem_size, &nesvnic->nic_pbase); if (!nesvnic->nic_vbase) { - dprintk(KERN_ERR PFX "Unable to allocate memory for NIC host descriptor rings\n"); - return(-ENOMEM); + nes_debug(NES_DBG_INIT, "Unable to allocate memory for NIC host descriptor rings\n"); + return -ENOMEM; } memset(nesvnic->nic_vbase, 0, nesvnic->nic_mem_size); - dprintk("Allocated NIC QP structures at %p (phys = %016lX), size = %u.\n", + nes_debug(NES_DBG_INIT, "Allocated NIC QP structures at %p (phys = %016lX), size = %u.\n", nesvnic->nic_vbase, (unsigned long)nesvnic->nic_pbase, nesvnic->nic_mem_size); - vmem = (void *)(((unsigned long long)nesvnic->nic_vbase + (256 - 1)) & - ~(unsigned long long)(256 - 1)); + vmem = (void *)(((unsigned long)nesvnic->nic_vbase + (256 - 1)) & + ~(unsigned long)(256 - 1)); pmem = (dma_addr_t)(((unsigned long long)nesvnic->nic_pbase + (256 - 1)) & ~(unsigned long long)(256 - 1)); - dprintk("%s:%u vmem=%p, pmem=%016lX\n", - __FUNCTION__, __LINE__, vmem, (long unsigned int)pmem); - /* Setup the first Fragment buffers */ nesvnic->nic.first_frag_vbase = vmem; @@ -1155,8 +1418,6 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev) /* setup the SQ */ vmem += (NES_NIC_WQ_SIZE * sizeof(struct nes_first_frag)); - dprintk("%s:%u vmem=%p, pmem=%016lX\n", - __FUNCTION__, __LINE__, vmem, (long unsigned int)pmem); nesvnic->nic.sq_vbase = (void *)vmem; nesvnic->nic.sq_pbase = pmem; @@ -1165,16 +1426,21 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev) nesvnic->nic.sq_size = NES_NIC_WQ_SIZE; for (counter = 0; counter < NES_NIC_WQ_SIZE; counter++) { nic_sqe = &nesvnic->nic.sq_vbase[counter]; - nic_sqe->wqe_words[NES_NIC_SQ_WQE_MISC_IDX] = NES_NIC_SQ_WQE_DISABLE_CHKSUM | - NES_NIC_SQ_WQE_COMPLETION; + nic_sqe->wqe_words[NES_NIC_SQ_WQE_MISC_IDX] = + cpu_to_le32(NES_NIC_SQ_WQE_DISABLE_CHKSUM | + NES_NIC_SQ_WQE_COMPLETION); nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_0_TAG_IDX] = - (u32)NES_FIRST_FRAG_SIZE << 16; + cpu_to_le32((u32)NES_FIRST_FRAG_SIZE << 16); nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX] = - (u32)nesvnic->nic.frag_paddr[counter]; + cpu_to_le32((u32)nesvnic->nic.frag_paddr[counter]); nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX] = - (u32)((u64)nesvnic->nic.frag_paddr[counter] >> 32); + cpu_to_le32((u32)((u64)nesvnic->nic.frag_paddr[counter] >> 32)); } + nesvnic->get_cqp_request = nes_get_cqp_request; + nesvnic->post_cqp_request = nes_post_cqp_request; + nesvnic->mcrq_mcast_filter = NULL; + spin_lock_init(&nesvnic->nic.sq_lock); spin_lock_init(&nesvnic->nic.rq_lock); @@ -1182,8 +1448,6 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev) vmem += (NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_sq_wqe)); pmem += (NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_sq_wqe)); - dprintk("%s:%u vmem=%p, pmem=%016lX\n", - __FUNCTION__, __LINE__, vmem, (long unsigned int)pmem); nesvnic->nic.rq_vbase = vmem; nesvnic->nic.rq_pbase = pmem; @@ -1195,70 +1459,54 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev) vmem += (NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_rq_wqe)); pmem += (NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_rq_wqe)); - dprintk("%s:%u vmem=%p, pmem=%016lX\n", - __FUNCTION__, __LINE__, vmem, (long unsigned int)pmem); + if (nesdev->nesadapter->netdev_count > 2) + nesvnic->mcrq_qp_id = nesvnic->nic_index + 32; + else + nesvnic->mcrq_qp_id = nesvnic->nic.qp_id + 4; nesvnic->nic_cq.cq_vbase = vmem; nesvnic->nic_cq.cq_pbase = pmem; nesvnic->nic_cq.cq_head = 0; nesvnic->nic_cq.cq_size = NES_NIC_WQ_SIZE * 2; -#ifdef NES_NAPI + nesvnic->nic_cq.ce_handler = nes_nic_napi_ce_handler; -#else - nesvnic->nic_cq.ce_handler = nes_nic_ce_handler; -#endif /* Send CreateCQ request to CQP */ spin_lock_irqsave(&nesdev->cqp.lock, flags); cqp_head = nesdev->cqp.sq_head; - dprintk("%s:%u Before filling out cqp_wqe, cqp=%p, sq_head=%u, sq_tail=%u, cqp_head=%u\n", - __FUNCTION__, __LINE__, &nesdev->cqp, nesdev->cqp.sq_head, - nesdev->cqp.sq_tail, cqp_head); cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head]; + nes_fill_init_cqp_wqe(cqp_wqe, nesdev); - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = - NES_CQP_CREATE_CQ | NES_CQP_CQ_CEQ_VALID | (nesvnic->nic_cq.cq_size << 16); - cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = - nesvnic->nic_cq.cq_number | ((u32)nesdev->nic_ceq_index << 16); - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX] = 0; - *((struct nes_hw_cqp **)&cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_LOW_IDX]) = - &nesdev->cqp; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] = 0; + cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32( + NES_CQP_CREATE_CQ | NES_CQP_CQ_CEQ_VALID | + ((u32)nesvnic->nic_cq.cq_size << 16)); + cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32( + nesvnic->nic_cq.cq_number | ((u32)nesdev->nic_ceq_index << 16)); u64temp = (u64)nesvnic->nic_cq.cq_pbase; - cqp_wqe->wqe_words[NES_CQP_CQ_WQE_PBL_LOW_IDX] = cpu_to_le32((u32)u64temp); - cqp_wqe->wqe_words[NES_CQP_CQ_WQE_PBL_HIGH_IDX] = cpu_to_le32((u32)(u64temp >> 32)); + set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp); cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] = 0; - /* the following two lines likely have endian issues */ - *((struct nes_hw_nic_cq **)&cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_LOW_IDX]) = - &nesvnic->nic_cq; - *((u64 *)&cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_LOW_IDX]) >>= 1; - dprintk("%s: CQ%u context = 0x%08X:0x%08X.\n", __FUNCTION__, nesvnic->nic_cq.cq_number, - cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX], - cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_LOW_IDX]); + u64temp = (unsigned long)&nesvnic->nic_cq; + cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_LOW_IDX] = cpu_to_le32((u32)(u64temp >> 1)); + cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] = + cpu_to_le32(((u32)((u64temp) >> 33)) & 0x7FFFFFFF); cqp_wqe->wqe_words[NES_CQP_CQ_WQE_DOORBELL_INDEX_HIGH_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = - cpu_to_le32(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX]); if (++cqp_head >= nesdev->cqp.sq_size) cqp_head = 0; cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head]; + nes_fill_init_cqp_wqe(cqp_wqe, nesdev); /* Send CreateQP request to CQP */ nic_context = (void *)(&nesvnic->nic_cq.cq_vbase[nesvnic->nic_cq.cq_size]); nic_context->context_words[NES_NIC_CTX_MISC_IDX] = cpu_to_le32((u32)NES_NIC_CTX_SIZE | ((u32)PCI_FUNC(nesdev->pcidev->devfn) << 12)); - dprintk("%s: RX_WINDOW_BUFFER_PAGE_TABLE_SIZE = 0x%08X, RX_WINDOW_BUFFER_SIZE = 0x%08X\n", - __FUNCTION__, + nes_debug(NES_DBG_INIT, "RX_WINDOW_BUFFER_PAGE_TABLE_SIZE = 0x%08X, RX_WINDOW_BUFFER_SIZE = 0x%08X\n", nes_read_indexed(nesdev, NES_IDX_RX_WINDOW_BUFFER_PAGE_TABLE_SIZE), nes_read_indexed(nesdev, NES_IDX_RX_WINDOW_BUFFER_SIZE)); - if (0!= nes_read_indexed(nesdev, NES_IDX_RX_WINDOW_BUFFER_SIZE)) { - dprintk("%s: Enabling NIC Backing Store.\n", __FUNCTION__); + if (nes_read_indexed(nesdev, NES_IDX_RX_WINDOW_BUFFER_SIZE) != 0) { nic_context->context_words[NES_NIC_CTX_MISC_IDX] |= cpu_to_le32(NES_NIC_BACK_STORE); } - dprintk("NES_NIC_CTX_SIZE = %0x, word0 = %u.\n", - NES_NIC_CTX_SIZE, nic_context->context_words[NES_NIC_CTX_MISC_IDX]); u64temp = (u64)nesvnic->nic.sq_pbase; nic_context->context_words[NES_NIC_CTX_SQ_LOW_IDX] = cpu_to_le32((u32)u64temp); @@ -1270,52 +1518,42 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev) cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_CREATE_QP | NES_CQP_QP_TYPE_NIC); cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(nesvnic->nic.qp_id); - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX] = 0; - *((struct nes_hw_cqp **)&cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_LOW_IDX]) = &nesdev->cqp; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] = 0; u64temp = (u64)nesvnic->nic_cq.cq_pbase + (nesvnic->nic_cq.cq_size * sizeof(struct nes_hw_nic_cqe)); - cqp_wqe->wqe_words[NES_CQP_QP_WQE_CONTEXT_LOW_IDX] = cpu_to_le32((u32)u64temp); - cqp_wqe->wqe_words[NES_CQP_QP_WQE_CONTEXT_HIGH_IDX] = cpu_to_le32((u32)(u64temp >> 32)); + set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, u64temp); if (++cqp_head >= nesdev->cqp.sq_size) cqp_head = 0; nesdev->cqp.sq_head = cqp_head; barrier(); - dprintk("%s:%u Before cqp wqe alloc, sq_head=%u, sq_tail=%u, cqp_head=%u\n", - __FUNCTION__, __LINE__, nesdev->cqp.sq_head, nesdev->cqp.sq_tail, cqp_head); /* Ring doorbell (2 WQEs) */ nes_write32(nesdev->regs+NES_WQE_ALLOC, 0x02800000 | nesdev->cqp.qp_id); spin_unlock_irqrestore(&nesdev->cqp.lock, flags); - dprintk("Waiting for create NIC QP%u to complete.\n", nesvnic->nic.qp_id); - /* cqp_head = (cqp_head+1) & (nesdev->cqp.sq_size-1); */ - - dprintk("%s:%u Before wait_event_timeout, sq_head=%u, sq_tail=%u, cqp_head=%u\n", - __FUNCTION__, __LINE__, nesdev->cqp.sq_head, nesdev->cqp.sq_tail, cqp_head); + nes_debug(NES_DBG_INIT, "Waiting for create NIC QP%u to complete.\n", + nesvnic->nic.qp_id); ret = wait_event_timeout(nesdev->cqp.waitq, (nesdev->cqp.sq_tail == cqp_head), NES_EVENT_TIMEOUT); - dprintk("Create NIC QP%u completed, wait_event_timeout ret = %u.\n", + nes_debug(NES_DBG_INIT, "Create NIC QP%u completed, wait_event_timeout ret = %u.\n", nesvnic->nic.qp_id, ret); if (!ret) { - dprintk("NIC QP%u create timeout expired\n", nesvnic->nic.qp_id); + nes_debug(NES_DBG_INIT, "NIC QP%u create timeout expired\n", nesvnic->nic.qp_id); pci_free_consistent(nesdev->pcidev, nesvnic->nic_mem_size, nesvnic->nic_vbase, - nesvnic->nic_pbase); - return(-EIO); + nesvnic->nic_pbase); + return -EIO; } /* Populate the RQ */ for (counter = 0; counter < (NES_NIC_WQ_SIZE - 1); counter++) { skb = dev_alloc_skb(nesvnic->max_frame_size); if (!skb) { - dprintk(KERN_ERR PFX "%s: out of memory for receive skb\n", netdev->name); + nes_debug(NES_DBG_INIT, "%s: out of memory for receive skb\n", netdev->name); nes_destroy_nic_qp(nesvnic); - return(-ENOMEM); + return -ENOMEM; } skb->dev = netdev; @@ -1332,7 +1570,7 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev) } wqe_count = NES_NIC_WQ_SIZE - 1; - nesvnic->nic.rq_head = wqe_count - 1; + nesvnic->nic.rq_head = wqe_count; barrier(); do { counter = min(wqe_count, ((u32)255)); @@ -1342,14 +1580,17 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev) init_timer(&nesvnic->rq_wqes_timer); nesvnic->rq_wqes_timer.function = nes_rq_wqes_timeout; nesvnic->rq_wqes_timer.data = (unsigned long)nesvnic; -#ifdef NES_INT_MODERATE - dprintk("%s: Default Interrupt Moderation Enabled\n", __FUNCTION__); -#endif -#ifdef NES_NAPI - dprintk("%s: NAPI support Enabled\n", __FUNCTION__); -#endif + nes_debug(NES_DBG_INIT, "NAPI support Enabled\n"); + + if (nesdev->nesadapter->et_use_adaptive_rx_coalesce) + { + nes_nic_init_timer(nesdev); + if (netdev->mtu > 1500) + jumbomode = 1; + nes_nic_init_timer_defaults(nesdev, jumbomode); + } - return (0); + return 0; } @@ -1366,44 +1607,40 @@ void nes_destroy_nic_qp(struct nes_vnic *nesvnic) unsigned long flags; int ret; - dprintk("%s:%u\n", __FUNCTION__, __LINE__); - /* Free remaining NIC receive buffers */ while (nesvnic->nic.rq_head != nesvnic->nic.rq_tail) { nic_rqe = &nesvnic->nic.rq_vbase[nesvnic->nic.rq_tail]; - wqe_frag = nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]; - wqe_frag += ((u64)nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX]) << 32; + wqe_frag = (u64)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]); + wqe_frag |= ((u64)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX])) << 32; pci_unmap_single(nesdev->pcidev, (dma_addr_t)wqe_frag, nesvnic->max_frame_size, PCI_DMA_FROMDEVICE); dev_kfree_skb(nesvnic->nic.rx_skb[nesvnic->nic.rq_tail++]); nesvnic->nic.rq_tail &= (nesvnic->nic.rq_size - 1); } - /* Destroy NIC QP */ spin_lock_irqsave(&nesdev->cqp.lock, flags); + + /* Destroy NIC QP */ cqp_head = nesdev->cqp.sq_head; cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head]; + nes_fill_init_cqp_wqe(cqp_wqe, nesdev); - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_DESTROY_QP | NES_CQP_QP_TYPE_NIC); - cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(nesvnic->nic_cq.cq_number); - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX] = 0; - *((struct nes_hw_cqp **)&cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_LOW_IDX]) = &nesdev->cqp; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] = 0; + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, + (NES_CQP_DESTROY_QP | NES_CQP_QP_TYPE_NIC)); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX, + nesvnic->nic.qp_id); if (++cqp_head >= nesdev->cqp.sq_size) cqp_head = 0; + cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head]; /* Destroy NIC CQ */ - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_DESTROY_CQ | - ((u32)nesvnic->nic_cq.cq_size << 16)); - cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(nesvnic->nic_cq.cq_number | - ((u32)nesdev->nic_ceq_index << 16)); - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX] = 0; - *((struct nes_hw_cqp **)&cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_LOW_IDX]) = &nesdev->cqp; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] = 0; + nes_fill_init_cqp_wqe(cqp_wqe, nesdev); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, + (NES_CQP_DESTROY_CQ | ((u32)nesvnic->nic_cq.cq_size << 16))); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX, + (nesvnic->nic_cq.cq_number | ((u32)nesdev->nic_ceq_index << 16))); if (++cqp_head >= nesdev->cqp.sq_size) cqp_head = 0; @@ -1415,52 +1652,47 @@ void nes_destroy_nic_qp(struct nes_vnic *nesvnic) nes_write32(nesdev->regs+NES_WQE_ALLOC, 0x02800000 | nesdev->cqp.qp_id); spin_unlock_irqrestore(&nesdev->cqp.lock, flags); - dprintk("Waiting for destroy NIC QP to complete.\n"); - /* cqp_head = (cqp_head + 1) & (nesdev->cqp.sq_size - 1); */ - - dprintk("%s[%u] Waiting for CQP, cqp_head=%u, cqp.sq_head=%u," + nes_debug(NES_DBG_SHUTDOWN, "Waiting for CQP, cqp_head=%u, cqp.sq_head=%u," " cqp.sq_tail=%u, cqp.sq_size=%u\n", - __FUNCTION__, __LINE__, cqp_head, nesdev->cqp.sq_head, + cqp_head, nesdev->cqp.sq_head, nesdev->cqp.sq_tail, nesdev->cqp.sq_size); ret = wait_event_timeout(nesdev->cqp.waitq, (nesdev->cqp.sq_tail == cqp_head), NES_EVENT_TIMEOUT); - dprintk("Destroy NIC QP returned, wait_event_timeout ret = %u, cqp_head=%u," + nes_debug(NES_DBG_SHUTDOWN, "Destroy NIC QP returned, wait_event_timeout ret = %u, cqp_head=%u," " cqp.sq_head=%u, cqp.sq_tail=%u\n", ret, cqp_head, nesdev->cqp.sq_head, nesdev->cqp.sq_tail); if (!ret) { - dprintk("NIC QP%u destroy timeout expired\n", nesvnic->nic.qp_id); + nes_debug(NES_DBG_SHUTDOWN, "NIC QP%u destroy timeout expired\n", + nesvnic->nic.qp_id); } pci_free_consistent(nesdev->pcidev, nesvnic->nic_mem_size, nesvnic->nic_vbase, nesvnic->nic_pbase); } - -#ifdef NES_NAPI /** * nes_napi_isr */ int nes_napi_isr(struct nes_device *nesdev) { + struct nes_adapter *nesadapter = nesdev->nesadapter; u32 int_stat; -#ifdef NES_LEGACY_INT_DETECT - /* interrupt status has already been read in ISR */ - int_stat = nesdev->int_stat; -#else - int_stat = nes_read32(nesdev->regs + NES_INT_STAT); - /* save off the interrupt status so we avoid the extra read */ - nesdev->int_stat = int_stat; - nesdev->napi_isr_ran = 1; - /* int_stat &= (nesdev->int_req | NES_INT_TIMER); */ -#endif + if (nesdev->napi_isr_ran) { + /* interrupt status has already been read in ISR */ + int_stat = nesdev->int_stat; + } else { + int_stat = nes_read32(nesdev->regs + NES_INT_STAT); + nesdev->int_stat = int_stat; + nesdev->napi_isr_ran = 1; + } int_stat &= nesdev->int_req; - /* dprintk("%s: Interrupt Status (postfilter) = 0x%08X\n", __FUNCTION__, int_stat ); */ /* iff NIC, process here, else wait for DPC */ if ((int_stat) && ((int_stat & 0x0000ff00) == int_stat)) { + nesdev->napi_isr_ran = 0; nes_write32(nesdev->regs+NES_INT_STAT, (int_stat & ~(NES_INT_INTF|NES_INT_TIMER|NES_INT_MAC0|NES_INT_MAC1|NES_INT_MAC2|NES_INT_MAC3))); @@ -1468,7 +1700,10 @@ int nes_napi_isr(struct nes_device *nesdev) /* Process the CEQs */ nes_process_ceq(nesdev, &nesdev->nesadapter->ceq[nesdev->nic_ceq_index]); - if (nesdev->et_rx_coalesce_usecs_irq) { + if (unlikely((((nesadapter->et_rx_coalesce_usecs_irq) && + (!nesadapter->et_use_adaptive_rx_coalesce)) || + ((nesadapter->et_use_adaptive_rx_coalesce) && + (nesdev->deepcq_count > nesadapter->et_pkt_rate_low))))) { if ((nesdev->int_req & NES_INT_TIMER) == 0) { /* Enable Periodic timer interrupts */ nesdev->int_req |= NES_INT_TIMER; @@ -1479,6 +1714,11 @@ int nes_napi_isr(struct nes_device *nesdev) nes_write32(nesdev->regs+NES_INTF_INT_MASK, ~(nesdev->intf_int_req | NES_INTF_PERIODIC_TIMER)); } + + if (unlikely(nesadapter->et_use_adaptive_rx_coalesce)) + { + nes_nic_init_timer(nesdev); + } /* Enable interrupts, except CEQs */ nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff | (~nesdev->int_req)); } else { @@ -1487,13 +1727,12 @@ int nes_napi_isr(struct nes_device *nesdev) nes_write32(nesdev->regs+NES_INTF_INT_MASK, ~(nesdev->intf_int_req)); nes_write32(nesdev->regs+NES_INT_MASK, ~nesdev->int_req); } - - return (1); + nesdev->deepcq_count = 0; + return 1; } else { - return (0); + return 0; } } -#endif /** @@ -1512,12 +1751,11 @@ void nes_dpc(unsigned long param) u32 intf_int_stat; u32 debug_error; u32 processed_intf_int = 0; - u32 u32Temp; u16 processed_timer_int = 0; u16 completion_ints = 0; u16 timer_ints = 0; - /* dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); */ + /* nes_debug(NES_DBG_ISR, "\n"); */ do { timer_stat = 0; @@ -1526,12 +1764,11 @@ void nes_dpc(unsigned long param) int_stat = nesdev->int_stat; } else int_stat = nes_read32(nesdev->regs+NES_INT_STAT); - if (0 != processed_intf_int) { + if (processed_intf_int != 0) int_stat &= nesdev->int_req & ~NES_INT_INTF; - } else { + else int_stat &= nesdev->int_req; - } - if (0 == processed_timer_int) { + if (processed_timer_int == 0) { processed_timer_int = 1; if (int_stat & NES_INT_TIMER) { timer_stat = nes_read32(nesdev->regs + NES_TIMER_STAT); @@ -1588,8 +1825,6 @@ void nes_dpc(unsigned long param) if (int_stat & NES_INT_INTF) { processed_intf_int = 1; intf_int_stat = nes_read32(nesdev->regs+NES_INTF_INT_STAT); - printk(KERN_ERR PFX "Interface Interrupt Status (prefilter)=0x%08X\n", - intf_int_stat); intf_int_stat &= nesdev->intf_int_req; if (NES_INTF_INT_CRITERR & intf_int_stat) { debug_error = nes_read_indexed(nesdev, NES_IDX_DEBUG_ERROR_CONTROL_STATUS); @@ -1620,11 +1855,11 @@ void nes_dpc(unsigned long param) NES_INT_MAC1|NES_INT_MAC2|NES_INT_MAC3; } while ((int_stat != 0) && (loop_counter++ < MAX_DPC_ITERATIONS)); - if (1 == timer_ints) { - if (nesdev->et_rx_coalesce_usecs_irq) { - if (0 == completion_ints) { + if (timer_ints == 1) { + if ((nesadapter->et_rx_coalesce_usecs_irq) || (nesadapter->et_use_adaptive_rx_coalesce)) { + if (completion_ints == 0) { nesdev->timer_only_int_count++; - if (nesdev->timer_only_int_count>=NES_TIMER_INT_LIMIT) { + if (nesdev->timer_only_int_count>=nesadapter->timer_int_limit) { nesdev->timer_only_int_count = 0; nesdev->int_req &= ~NES_INT_TIMER; nes_write32(nesdev->regs + NES_INTF_INT_MASK, ~(nesdev->intf_int_req)); @@ -1633,6 +1868,10 @@ void nes_dpc(unsigned long param) nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff|(~nesdev->int_req)); } } else { + if (unlikely(nesadapter->et_use_adaptive_rx_coalesce)) + { + nes_nic_init_timer(nesdev); + } nesdev->timer_only_int_count = 0; nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff|(~nesdev->int_req)); } @@ -1641,16 +1880,20 @@ void nes_dpc(unsigned long param) nesdev->int_req &= ~NES_INT_TIMER; nes_write32(nesdev->regs+NES_INTF_INT_MASK, ~(nesdev->intf_int_req)); nes_write32(nesdev->regs+NES_TIMER_STAT, - nesdev->timer_int_req | ~(nesdev->nesadapter->timer_int_req)); + nesdev->timer_int_req | ~(nesdev->nesadapter->timer_int_req)); nes_write32(nesdev->regs+NES_INT_MASK, ~nesdev->int_req); } } else { - if ((1 == completion_ints) && (nesdev->et_rx_coalesce_usecs_irq)) { - /* dprintk("Enabling periodic timer interrupt.\n" ); */ + if ((completion_ints == 1) && + (((nesadapter->et_rx_coalesce_usecs_irq) && + (!nesadapter->et_use_adaptive_rx_coalesce)) || + ((nesdev->deepcq_count > nesadapter->et_pkt_rate_low) && + (nesadapter->et_use_adaptive_rx_coalesce)))) { + /* nes_debug(NES_DBG_ISR, "Enabling periodic timer interrupt.\n" ); */ nesdev->timer_only_int_count = 0; nesdev->int_req |= NES_INT_TIMER; nes_write32(nesdev->regs+NES_TIMER_STAT, - nesdev->timer_int_req | ~(nesdev->nesadapter->timer_int_req)); + nesdev->timer_int_req | ~(nesdev->nesadapter->timer_int_req)); nes_write32(nesdev->regs+NES_INTF_INT_MASK, ~(nesdev->intf_int_req | NES_INTF_PERIODIC_TIMER)); nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff | (~nesdev->int_req)); @@ -1658,6 +1901,7 @@ void nes_dpc(unsigned long param) nes_write32(nesdev->regs+NES_INT_MASK, ~nesdev->int_req); } } + nesdev->deepcq_count = 0; } @@ -1671,17 +1915,18 @@ void nes_process_ceq(struct nes_device *nesdev, struct nes_hw_ceq *ceq) u32 head; u32 ceq_size; - /* dprintk("%s:%u\n", __FUNCTION__, __LINE__); */ + /* nes_debug(NES_DBG_CQ, "\n"); */ head = ceq->ceq_head; ceq_size = ceq->ceq_size; do { if (le32_to_cpu(ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_HIGH_IDX]) & NES_CEQE_VALID) { - u64temp = *((u64 *)&ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_LOW_IDX]); + u64temp = (((u64)(le32_to_cpu(ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_HIGH_IDX])))<<32) | + ((u64)(le32_to_cpu(ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_LOW_IDX]))); u64temp <<= 1; cq = *((struct nes_hw_cq **)&u64temp); - /* dprintk(KERN_ERR PFX "%s: pCQ = %p\n", __FUNCTION__, cq ); */ + /* nes_debug(NES_DBG_CQ, "pCQ = %p\n", cq); */ barrier(); ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_HIGH_IDX] = 0; @@ -1693,10 +1938,10 @@ void nes_process_ceq(struct nes_device *nesdev, struct nes_hw_ceq *ceq) } else { break; } + } while (1); ceq->ceq_head = head; - /* dprintk("%s:%u\n", __FUNCTION__, __LINE__); */ } @@ -1705,13 +1950,13 @@ void nes_process_ceq(struct nes_device *nesdev, struct nes_hw_ceq *ceq) */ void nes_process_aeq(struct nes_device *nesdev, struct nes_hw_aeq *aeq) { - u64 u64temp; +// u64 u64temp; u32 head; u32 aeq_size; + u32 aeqe_misc; + u32 aeqe_cq_id; struct nes_hw_aeqe volatile *aeqe; - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); - head = aeq->aeq_head; aeq_size = aeq->aeq_size; @@ -1719,24 +1964,19 @@ void nes_process_aeq(struct nes_device *nesdev, struct nes_hw_aeq *aeq) aeqe = &aeq->aeq_vbase[head]; if ((le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]) & NES_AEQE_VALID) == 0) break; - aeqe->aeqe_words[NES_AEQE_MISC_IDX] = - le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]); - aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX] = - le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]); - if (aeqe->aeqe_words[NES_AEQE_MISC_IDX] & (NES_AEQE_QP|NES_AEQE_CQ)) { - if (aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX] >= NES_FIRST_QPN) { + aeqe_misc = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]); + aeqe_cq_id = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]); + if (aeqe_misc & (NES_AEQE_QP|NES_AEQE_CQ)) { + if (aeqe_cq_id >= NES_FIRST_QPN) { /* dealing with an accelerated QP related AE */ - u64temp = *((u64 *)&aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX]); +// u64temp = (((u64)(le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX])))<<32) | +// ((u64)(le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX]))); nes_process_iwarp_aeqe(nesdev, (struct nes_hw_aeqe *)aeqe); } else { /* TODO: dealing with a CQP related AE */ - dprintk("%s: Processing CQP related AE, misc = 0x%04X\n", __FUNCTION__, - (u16)(aeqe->aeqe_words[NES_AEQE_MISC_IDX] >> 16)); + nes_debug(NES_DBG_AEQ, "Processing CQP related AE, misc = 0x%04X\n", + (u16)(aeqe_misc >> 16)); } - } else if (aeqe->aeqe_words[NES_AEQE_MISC_IDX] & NES_AEQE_CQ) { - /* dealing with a CQ related AE */ - dprintk("%s: Processing CQ realated AE, misc = 0x%04X\n", __FUNCTION__, - (u16)(aeqe->aeqe_words[NES_AEQE_MISC_IDX] >> 16)); } aeqe->aeqe_words[NES_AEQE_MISC_IDX] = 0; @@ -1748,6 +1988,75 @@ void nes_process_aeq(struct nes_device *nesdev, struct nes_hw_aeq *aeq) aeq->aeq_head = head; } +static void nes_reset_link(struct nes_device *nesdev, u32 mac_index) +{ + struct nes_adapter *nesadapter = nesdev->nesadapter; + u32 reset_value; + u32 i = 0; + u32 u32temp; + + if (nesadapter->hw_rev == NE020_REV) { + return; + } + mh_detected++; + + reset_value = nes_read32(nesdev->regs + NES_SOFTWARE_RESET); + + if ((mac_index == 0) || ((mac_index == 1) && (nesadapter->OneG_Mode))) + reset_value |= 0x0000001d; + else + reset_value |= 0x0000002d; + + if (4 <= (nesadapter->link_interrupt_count[mac_index] / ((u16)NES_MAX_LINK_INTERRUPTS))) { + if ((!nesadapter->OneG_Mode) && (nesadapter->port_count == 2)) { + nesadapter->link_interrupt_count[0] = 0; + nesadapter->link_interrupt_count[1] = 0; + u32temp = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1); + if (0x00000040 & u32temp) + nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x0000F088); + else + nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x0000F0C8); + reset_value |= 0x0000003d; + } + nesadapter->link_interrupt_count[mac_index] = 0; + } + + nes_write32(nesdev->regs+NES_SOFTWARE_RESET, reset_value); + + while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET) + & 0x00000040) != 0x00000040) && (i++ < 5000)); + + if (0x0000003d == (reset_value & 0x0000003d)) { + u32 pcs_control_status0, pcs_control_status1; + + for (i = 0; i < 10; i++) { + pcs_control_status0 = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0); + pcs_control_status1 = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 + 0x200); + if (((0x0F000000 == (pcs_control_status0 & 0x0F000000)) + && (pcs_control_status0 & 0x00100000)) + || ((0x0F000000 == (pcs_control_status1 & 0x0F000000)) + && (pcs_control_status1 & 0x00100000))) + continue; + else + break; + } + if (10 == i) { + u32temp = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1); + if (0x00000040 & u32temp) + nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x0000F088); + else + nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x0000F0C8); + + nes_write32(nesdev->regs + NES_SOFTWARE_RESET, reset_value); + + while (((nes_read32(nesdev->regs + NES_SOFTWARE_RESET) + & 0x00000040) != 0x00000040) && (i++ < 5000)); + } + } + + + +} /** * nes_process_mac_intr @@ -1777,16 +2086,21 @@ void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number) /* Clear the interrupt */ nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (mac_index * 0x200), mac_status); - dprintk("MAC%u interrupt status = 0x%X.\n", mac_number, mac_status); + nes_debug(NES_DBG_PHY, "MAC%u interrupt status = 0x%X.\n", mac_number, mac_status); if (mac_status & (NES_MAC_INT_LINK_STAT_CHG | NES_MAC_INT_XGMII_EXT)) { nesdev->link_status_interrupts++; + if (0 == (++nesadapter->link_interrupt_count[mac_index] % ((u16)NES_MAX_LINK_INTERRUPTS))) { + spin_lock_irqsave(&nesadapter->phy_lock, flags); + nes_reset_link(nesdev, mac_index); + spin_unlock_irqrestore(&nesadapter->phy_lock, flags); + } /* read the PHY interrupt status register */ if (nesadapter->OneG_Mode) { do { nes_read_1G_phy_reg(nesdev, 0x1a, nesadapter->phy_index[mac_index], &phy_data); - dprintk("Phy%d data from register 0x1a = 0x%X.\n", + nes_debug(NES_DBG_PHY, "Phy%d data from register 0x1a = 0x%X.\n", nesadapter->phy_index[mac_index], phy_data); } while (phy_data&0x8000); @@ -1794,7 +2108,7 @@ void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number) do { nes_read_1G_phy_reg(nesdev, 0x11, nesadapter->phy_index[mac_index], &phy_data); - dprintk("Phy%d data from register 0x11 = 0x%X.\n", + nes_debug(NES_DBG_PHY, "Phy%d data from register 0x11 = 0x%X.\n", nesadapter->phy_index[mac_index], phy_data); if (temp_phy_data == phy_data) break; @@ -1803,29 +2117,29 @@ void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number) nes_read_1G_phy_reg(nesdev, 0x1e, nesadapter->phy_index[mac_index], &phy_data); - dprintk("Phy%d data from register 0x1e = 0x%X.\n", + nes_debug(NES_DBG_PHY, "Phy%d data from register 0x1e = 0x%X.\n", nesadapter->phy_index[mac_index], phy_data); nes_read_1G_phy_reg(nesdev, 1, nesadapter->phy_index[mac_index], &phy_data); - dprintk("1G phy%u data from register 1 = 0x%X\n", + nes_debug(NES_DBG_PHY, "1G phy%u data from register 1 = 0x%X\n", nesadapter->phy_index[mac_index], phy_data); if (temp_phy_data & 0x1000) { - dprintk("The Link is up according to the PHY\n"); + nes_debug(NES_DBG_PHY, "The Link is up according to the PHY\n"); phy_data = 4; } else { - dprintk("The Link is down according to the PHY\n"); + nes_debug(NES_DBG_PHY, "The Link is down according to the PHY\n"); } } - dprintk("%s: Eth SERDES Common Status: 0=0x%08X, 1=0x%08X\n", __FUNCTION__, + nes_debug(NES_DBG_PHY, "Eth SERDES Common Status: 0=0x%08X, 1=0x%08X\n", nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS0), nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS0+0x200)); pcs_control_status = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 + ((mac_index&1)*0x200)); pcs_control_status = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 + ((mac_index&1)*0x200)); - dprintk("%s: PCS PHY Control/Status%u: 0x%08X\n", __FUNCTION__, + nes_debug(NES_DBG_PHY, "PCS PHY Control/Status%u: 0x%08X\n", mac_index, pcs_control_status); if (nesadapter->OneG_Mode) { u32temp = 0x01010000; @@ -1834,8 +2148,24 @@ void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number) } if ((pcs_control_status & u32temp)!= u32temp) { phy_data = 0; - dprintk("PCS says the link is down\n"); + nes_debug(NES_DBG_PHY, "PCS says the link is down\n"); } + } else if (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_IRIS) { + nes_read_10G_phy_reg(nesdev, 1, nesadapter->phy_index[mac_index]); + temp_phy_data = (u16)nes_read_indexed(nesdev, + NES_IDX_MAC_MDIO_CONTROL); + u32temp = 20; + do { + nes_read_10G_phy_reg(nesdev, 1, nesadapter->phy_index[mac_index]); + phy_data = (u16)nes_read_indexed(nesdev, + NES_IDX_MAC_MDIO_CONTROL); + if ((phy_data == temp_phy_data) || (!(--u32temp))) + break; + temp_phy_data = phy_data; + } while (1); + nes_debug(NES_DBG_PHY, "%s: Phy data = 0x%04X, link was %s.\n", + __FUNCTION__, phy_data, nesadapter->mac_link_down ? "DOWN" : "UP"); + } else { phy_data = (0x0f0f0000 == (pcs_control_status & 0x0f1f0000)) ? 4 : 0; } @@ -1843,7 +2173,8 @@ void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number) if (phy_data & 0x0004) { nesadapter->mac_link_down[mac_index] = 0; list_for_each_entry(nesvnic, &nesadapter->nesvnic_list[mac_index], list) { - dprintk("The Link is UP!!. linkup was %d\n", nesvnic->linkup); + nes_debug(NES_DBG_PHY, "The Link is UP!!. linkup was %d\n", + nesvnic->linkup); if (nesvnic->linkup == 0) { printk(PFX "The Link is now up for port %u, netdev %p.\n", mac_index, nesvnic->netdev); @@ -1856,7 +2187,8 @@ void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number) } else { nesadapter->mac_link_down[mac_index] = 1; list_for_each_entry(nesvnic, &nesadapter->nesvnic_list[mac_index], list) { - dprintk("The Link is Down!!. linkup was %d\n", nesvnic->linkup); + nes_debug(NES_DBG_PHY, "The Link is Down!!. linkup was %d\n", + nesvnic->linkup); if (nesvnic->linkup == 1) { printk(PFX "The Link is now down for port %u, netdev %p.\n", mac_index, nesvnic->netdev); @@ -1873,81 +2205,81 @@ void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number) } -#ifdef NES_NAPI -/** - * nes_nic_napi_ce_handler - */ + void nes_nic_napi_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq) -{ +{ struct nes_vnic *nesvnic = container_of(cq, struct nes_vnic, nic_cq); - + netif_rx_schedule(nesdev->netdev[nesvnic->netdev_index]); -} -#endif +} +/* The MAX_RQES_TO_PROCESS defines how many max read requests to complete before +* getting out of nic_ce_handler +*/ +#define MAX_RQES_TO_PROCESS 384 + /** * nes_nic_ce_handler */ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq) { + u64 u64temp; dma_addr_t bus_address; struct nes_hw_nic *nesnic; struct nes_vnic *nesvnic = container_of(cq, struct nes_vnic, nic_cq); + struct nes_adapter *nesadapter = nesdev->nesadapter; struct nes_hw_nic_rq_wqe *nic_rqe; struct nes_hw_nic_sq_wqe *nic_sqe; struct sk_buff *skb; struct sk_buff *rx_skb; - u16 *wqe_fragment_length; - u64 *wqe_fragment_address; - unsigned long flags; + __le16 *wqe_fragment_length; u32 head; u32 cq_size; u32 rx_pkt_size; u32 cqe_count=0; u32 cqe_errv; u32 cqe_misc; - u16 wqe_fragment_index = 1; /* first fragment (0) is used by copy buffer */ + u16 wqe_fragment_index = 1; /* first fragment (0) is used by copy buffer */ u16 vlan_tag; u16 pkt_type; - - /* dprintk("%s:%u:\n", __FUNCTION__, __LINE__); */ + u16 rqes_processed = 0; + u8 sq_cqes = 0; head = cq->cq_head; cq_size = cq->cq_size; -#ifdef NES_NAPI - nesvnic->cqes_pending = 1; -#endif + cq->cqes_pending = 1; do { if (le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_NIC_CQE_MISC_IDX]) & NES_NIC_CQE_VALID) { nesnic = &nesvnic->nic; cqe_misc = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_NIC_CQE_MISC_IDX]); if (cqe_misc & NES_NIC_CQE_SQ) { - + sq_cqes++; wqe_fragment_index = 1; - /* dprintk("%s: Processing SQ completion for QP%u. SQ Tail = %u.\n", __FUNCTION__, - nesvnic->nic.qp_id, nesnic->sq_tail); */ nic_sqe = &nesnic->sq_vbase[nesnic->sq_tail]; skb = nesnic->tx_skb[nesnic->sq_tail]; - wqe_fragment_length = (u16 *)&nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_0_TAG_IDX]; + wqe_fragment_length = (__le16 *)&nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_0_TAG_IDX]; /* bump past the vlan tag */ wqe_fragment_length++; - if (wqe_fragment_length[wqe_fragment_index] != 0) { - wqe_fragment_address = (u64 *)&nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX]; - bus_address = (dma_addr_t)le64_to_cpu(wqe_fragment_address[wqe_fragment_index]); - if ((skb) && (skb_headlen(skb) > NES_FIRST_FRAG_SIZE)) { + if (le16_to_cpu(wqe_fragment_length[wqe_fragment_index]) != 0) { + u64temp = (u64) le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX+wqe_fragment_index*2]); + u64temp += ((u64)le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX+wqe_fragment_index*2]))<<32; + bus_address = (dma_addr_t)u64temp; + if (test_and_clear_bit(nesnic->sq_tail, nesnic->first_frag_overflow)) { pci_unmap_single(nesdev->pcidev, bus_address, - le32_to_cpu(wqe_fragment_length[wqe_fragment_index++]), + le16_to_cpu(wqe_fragment_length[wqe_fragment_index++]), PCI_DMA_TODEVICE); } for (; wqe_fragment_index < 5; wqe_fragment_index++) { if (wqe_fragment_length[wqe_fragment_index]) { - bus_address = (dma_addr_t)le64_to_cpu(wqe_fragment_address[wqe_fragment_index]); + u64temp = le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX+wqe_fragment_index*2]); + u64temp += ((u64)le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX+wqe_fragment_index*2]))<<32; + bus_address = (dma_addr_t)u64temp; pci_unmap_page(nesdev->pcidev, bus_address, - le32_to_cpu(wqe_fragment_length[wqe_fragment_index]), + le16_to_cpu(wqe_fragment_length[wqe_fragment_index]), PCI_DMA_TODEVICE); } else break; @@ -1955,31 +2287,31 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq) if (skb) dev_kfree_skb_any(skb); } - spin_lock_irqsave(&nesnic->sq_lock, flags); nesnic->sq_tail++; nesnic->sq_tail &= nesnic->sq_size-1; - /* restart the queue if it had been stopped */ - if (netif_queue_stopped(nesvnic->netdev)) - netif_wake_queue(nesvnic->netdev); - spin_unlock_irqrestore(&nesnic->sq_lock, flags); + if (sq_cqes > 128) { + barrier(); + /* restart the queue if it had been stopped */ + if (netif_queue_stopped(nesvnic->netdev)) + netif_wake_queue(nesvnic->netdev); + sq_cqes = 0; + } } else { + rqes_processed++; -#ifdef NES_NAPI - nesvnic->rx_cqes_completed++; -#endif + cq->rx_cqes_completed++; + cq->rx_pkts_indicated++; rx_pkt_size = cqe_misc & 0x0000ffff; - /* dprintk("%s: Processing RQ completion for QP%u. RQ Tail = %u, size = %u.\n", - __FUNCTION__, nesvnic->nic.qp_id, nesnic->rq_tail, rx_pkt_size); */ nic_rqe = &nesnic->rq_vbase[nesnic->rq_tail]; /* Get the skb */ rx_skb = nesnic->rx_skb[nesnic->rq_tail]; nic_rqe = &nesnic->rq_vbase[nesvnic->nic.rq_tail]; - bus_address = le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]); + bus_address = (dma_addr_t)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]); bus_address += ((u64)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX])) << 32; pci_unmap_single(nesdev->pcidev, bus_address, nesvnic->max_frame_size, PCI_DMA_FROMDEVICE); -// rx_skb->tail = rx_skb->data + rx_pkt_size; -// rx_skb->len = rx_pkt_size; + /* rx_skb->tail = rx_skb->data + rx_pkt_size; */ + /* rx_skb->len = rx_pkt_size; */ rx_skb->len = 0; /* TODO: see if this is necessary */ skb_put(rx_skb, rx_pkt_size); rx_skb->protocol = eth_type_trans(rx_skb, nesvnic->netdev); @@ -1988,6 +2320,11 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq) atomic_inc(&nesvnic->rx_skbs_needed); if (atomic_read(&nesvnic->rx_skbs_needed) > (nesvnic->nic.rq_size>>1)) { + nes_write32(nesdev->regs+NES_CQE_ALLOC, + cq->cq_number | (cqe_count << 16)); +// nesadapter->tune_timer.cq_count += cqe_count; + nesdev->currcq_count += cqe_count; + cqe_count = 0; nes_replenish_nic_rq(nesvnic); } pkt_type = (u16)(le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_NIC_CQE_TAG_PKT_TYPE_IDX])); @@ -1996,63 +2333,46 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq) if ((NES_PKT_TYPE_TCPV4_BITS == (pkt_type & NES_PKT_TYPE_TCPV4_MASK)) || (NES_PKT_TYPE_UDPV4_BITS == (pkt_type & NES_PKT_TYPE_UDPV4_MASK))) { - if (0 == (cqe_errv & - (NES_NIC_ERRV_BITS_IPV4_CSUM_ERR | - NES_NIC_ERRV_BITS_TCPUDP_CSUM_ERR | - NES_NIC_ERRV_BITS_IPH_ERR | - NES_NIC_ERRV_BITS_WQE_OVERRUN))) { - if (0 == nesvnic->rx_checksum_disabled) { + if ((cqe_errv & + (NES_NIC_ERRV_BITS_IPV4_CSUM_ERR | NES_NIC_ERRV_BITS_TCPUDP_CSUM_ERR | + NES_NIC_ERRV_BITS_IPH_ERR | NES_NIC_ERRV_BITS_WQE_OVERRUN)) == 0) { + if (nesvnic->rx_checksum_disabled == 0) { rx_skb->ip_summed = CHECKSUM_UNNECESSARY; - /* dprintk("%s: Reporting successfully checksummed TCP or UDP packet.\n", - nesvnic->netdev->name); */ } - } else { - dprintk("%s: unsuccessfully checksummed TCP or UDP packet." + } else + nes_debug(NES_DBG_CQ, "%s: unsuccessfully checksummed TCP or UDP packet." " errv = 0x%X, pkt_type = 0x%X.\n", nesvnic->netdev->name, cqe_errv, pkt_type); - } - } else if (NES_PKT_TYPE_IPV4_BITS == (pkt_type & NES_PKT_TYPE_IPV4_MASK)) { - if (0 == (cqe_errv & - (NES_NIC_ERRV_BITS_IPV4_CSUM_ERR | - NES_NIC_ERRV_BITS_IPH_ERR | - NES_NIC_ERRV_BITS_WQE_OVERRUN))) { - if (0 == nesvnic->rx_checksum_disabled) { + + } else if ((pkt_type & NES_PKT_TYPE_IPV4_MASK) == NES_PKT_TYPE_IPV4_BITS) { + if ((cqe_errv & + (NES_NIC_ERRV_BITS_IPV4_CSUM_ERR | NES_NIC_ERRV_BITS_IPH_ERR | + NES_NIC_ERRV_BITS_WQE_OVERRUN)) == 0) { + if (nesvnic->rx_checksum_disabled == 0) { rx_skb->ip_summed = CHECKSUM_UNNECESSARY; - /* dprintk("%s: Reporting successfully checksummed IPv4 packet.\n", + /* nes_debug(NES_DBG_CQ, "%s: Reporting successfully checksummed IPv4 packet.\n", nesvnic->netdev->name); */ } - } else { - dprintk("%s: unsuccessfully checksummed TCP or UDP packet." + } else + nes_debug(NES_DBG_CQ, "%s: unsuccessfully checksummed TCP or UDP packet." " errv = 0x%X, pkt_type = 0x%X.\n", nesvnic->netdev->name, cqe_errv, pkt_type); } - } - /* dprintk("%s:%u: pkt_type=%x, APBVT_MASK=%x\n", __FUNCTION__, __LINE__, + /* nes_debug(NES_DBG_CQ, "pkt_type=%x, APBVT_MASK=%x\n", pkt_type, (pkt_type & NES_PKT_TYPE_APBVT_MASK)); */ - if (NES_PKT_TYPE_APBVT_BITS == (pkt_type & NES_PKT_TYPE_APBVT_MASK)) { - /* dprintk("%s:%u: APBVT bit set; Send up NES; nesif_rx\n", - __FUNCTION__, __LINE__); */ + if ((pkt_type & NES_PKT_TYPE_APBVT_MASK) == NES_PKT_TYPE_APBVT_BITS) { nes_cm_recv(rx_skb, nesvnic->netdev); } else { - if (cqe_misc & NES_NIC_CQE_TAG_VALID) { + if ((cqe_misc & NES_NIC_CQE_TAG_VALID) && (nesvnic->vlan_grp != NULL)) { vlan_tag = (u16)(le32_to_cpu( cq->cq_vbase[head].cqe_words[NES_NIC_CQE_TAG_PKT_TYPE_IDX]) >> 16); - dprintk("%s: Reporting stripped VLAN packet. Tag = 0x%04X\n", + nes_debug(NES_DBG_CQ, "%s: Reporting stripped VLAN packet. Tag = 0x%04X\n", nesvnic->netdev->name, vlan_tag); - -#ifdef NES_NAPI - vlan_hwaccel_receive_skb(rx_skb, nesvnic->vlan_grp, vlan_tag); -#else - vlan_hwaccel_rx(rx_skb, nesvnic->vlan_grp, vlan_tag); -#endif + nes_vlan_rx(rx_skb, nesvnic->vlan_grp, vlan_tag); } else { -#ifdef NES_NAPI - netif_receive_skb(rx_skb); -#else - netif_rx(rx_skb); -#endif + nes_netif_rx(rx_skb); } } @@ -2067,119 +2387,143 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq) if (++head >= cq_size) head = 0; if (cqe_count == 255) { - /* Arm the Nic CQ */ + /* Replenish Nic CQ */ nes_write32(nesdev->regs+NES_CQE_ALLOC, cq->cq_number | (cqe_count << 16)); - nes_read32(nesdev->regs+NES_CQE_ALLOC); +// nesdev->nesadapter->tune_timer.cq_count += cqe_count; + nesdev->currcq_count += cqe_count; cqe_count = 0; } - if (atomic_read(&nesvnic->rx_skbs_needed)) { - nes_replenish_nic_rq(nesvnic); - } -#ifdef NES_NAPI - if (nesvnic->rx_cqes_completed >= nesvnic->budget) + + if (cq->rx_cqes_completed >= nesvnic->budget) break; -#endif } else { - nesvnic->cqes_pending = 0; + cq->cqes_pending = 0; break; } + } while (1); + if (sq_cqes) { + barrier(); + /* restart the queue if it had been stopped */ + if (netif_queue_stopped(nesvnic->netdev)) + netif_wake_queue(nesvnic->netdev); + } + cq->cq_head = head; - /* dprintk("CQ%u Processed = %u cqes, new head = %u.\n", + /* nes_debug(NES_DBG_CQ, "CQ%u Processed = %u cqes, new head = %u.\n", cq->cq_number, cqe_count, cq->cq_head); */ -#ifdef NES_NAPI - nesvnic->cqe_allocs_pending = cqe_count; -#else - /* Arm the CCQ */ - nes_write32(nesdev->regs+NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT | - cq->cq_number | (cqe_count << 16)); - nes_read32(nesdev->regs+NES_CQE_ALLOC); -#endif + cq->cqe_allocs_pending = cqe_count; + if (unlikely(nesadapter->et_use_adaptive_rx_coalesce)) + { +// nesdev->nesadapter->tune_timer.cq_count += cqe_count; + nesdev->currcq_count += cqe_count; + nes_nic_tune_timer(nesdev); + } + if (atomic_read(&nesvnic->rx_skbs_needed)) + nes_replenish_nic_rq(nesvnic); } + /** * nes_cqp_ce_handler */ void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq) { + u64 u64temp; + unsigned long flags; struct nes_hw_cqp *cqp = NULL; struct nes_cqp_request *cqp_request; struct nes_hw_cqp_wqe *cqp_wqe; u32 head; u32 cq_size; u32 cqe_count=0; - unsigned long flags; + u32 error_code; /* u32 counter; */ - /* dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); */ head = cq->cq_head; cq_size = cq->cq_size; - /* dprintk("%s:%u head=%u, cq_size=%u\n", - __FUNCTION__, __LINE__, head, cq_size); */ do { /* process the CQE */ - /* dprintk("%s:%u head=%u cqe_words=%08X\n", __FUNCTION__, __LINE__, head, - cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]); */ + /* nes_debug(NES_DBG_CQP, "head=%u cqe_words=%08X\n", head, + le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX])); */ if (le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]) & NES_CQE_VALID) { - cqp = *((struct nes_hw_cqp **)&cq->cq_vbase[head].cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX]); - - /* dprintk("%s:%u cqp=%p, cqp->sq_head=%u, cqp->sq_tail=%u\n", __FUNCTION__, __LINE__, - cqp, cqp->sq_head, cqp->sq_tail); */ - if (cq->cq_vbase[head].cqe_words[NES_CQE_ERROR_CODE_IDX]) { - cq->cq_vbase[head].cqe_words[NES_CQE_ERROR_CODE_IDX] = - le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_ERROR_CODE_IDX]); - dprintk("%s[%u] Bad Completion code for opcode 0x%02X from CQP," + u64temp = (((u64)(le32_to_cpu(cq->cq_vbase[head]. + cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX])))<<32) | + ((u64)(le32_to_cpu(cq->cq_vbase[head]. + cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX]))); + cqp = *((struct nes_hw_cqp **)&u64temp); + + error_code = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_ERROR_CODE_IDX]); + if (error_code) { + nes_debug(NES_DBG_CQP, "Bad Completion code for opcode 0x%02X from CQP," " Major/Minor codes = 0x%04X:%04X.\n", - __FUNCTION__, __LINE__, le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX])&0x3f, - (u16)(cq->cq_vbase[head].cqe_words[NES_CQE_ERROR_CODE_IDX] >> 16), - (u16)cq->cq_vbase[head].cqe_words[NES_CQE_ERROR_CODE_IDX]); - dprintk("%s[%u] cqp: qp_id=%u, sq_head=%u, sq_tail=%u\n", - __FUNCTION__, __LINE__, + (u16)(error_code >> 16), + (u16)error_code); + nes_debug(NES_DBG_CQP, "cqp: qp_id=%u, sq_head=%u, sq_tail=%u\n", cqp->qp_id, cqp->sq_head, cqp->sq_tail); } - cqp_request = *((struct nes_cqp_request **) - &nesdev->cqp.sq_vbase[cqp->sq_tail].wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX]); - if (++cqp->sq_tail >= cqp->sq_size) - cqp->sq_tail = 0; - - nes_write32(nesdev->regs+NES_CQE_ALLOC, cq->cq_number | (1 << 16)); - + u64temp = (((u64)(le32_to_cpu(nesdev->cqp.sq_vbase[cqp->sq_tail]. + wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX]))) << 32) | + ((u64)(le32_to_cpu(nesdev->cqp.sq_vbase[cqp->sq_tail]. + wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX]))); + cqp_request = *((struct nes_cqp_request **)&u64temp); if (cqp_request) { if (cqp_request->waiting) { - /* dprintk("%s: Waking up requestor\n", __FUNCTION__); */ - cqp_request->major_code = - le16_to_cpu((u16)(cq->cq_vbase[head].cqe_words[NES_CQE_ERROR_CODE_IDX] >> 16)); - cqp_request->minor_code = - le16_to_cpu((u16)cq->cq_vbase[head].cqe_words[NES_CQE_ERROR_CODE_IDX]); + /* nes_debug(NES_DBG_CQP, "%s: Waking up requestor\n"); */ + cqp_request->major_code = (u16)(error_code >> 16); + cqp_request->minor_code = (u16)error_code; barrier(); cqp_request->request_done = 1; wake_up(&cqp_request->waitq); if (atomic_dec_and_test(&cqp_request->refcount)) { + nes_debug(NES_DBG_CQP, "CQP request %p (opcode 0x%02X) freed.\n", + cqp_request, + le32_to_cpu(cqp_request->cqp_wqe.wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f); + if (cqp_request->dynamic) { + kfree(cqp_request); + } else { + spin_lock_irqsave(&nesdev->cqp.lock, flags); + list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); + spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + } + } + } else if (cqp_request->callback) { + /* Envoke the callback routine */ + cqp_request->cqp_callback(nesdev, cqp_request); + if (cqp_request->dynamic) { + kfree(cqp_request); + } else { spin_lock_irqsave(&nesdev->cqp.lock, flags); list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); - dprintk("%s: CQP request %p (opcode 0x%02X) freed.\n", __FUNCTION__, - cqp_request, cqp_request->cqp_wqe.wqe_words[NES_CQP_WQE_OPCODE_IDX]&0x3f); spin_unlock_irqrestore(&nesdev->cqp.lock, flags); } } else { - /* printk("%s: cqp requestor not waiting\n", __FUNCTION__); */ - spin_lock_irqsave(&nesdev->cqp.lock, flags); - list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); - dprintk("%s: CQP request %p (opcode 0x%02X) freed.\n", __FUNCTION__, - cqp_request, cqp_request->cqp_wqe.wqe_words[NES_CQP_WQE_OPCODE_IDX]&0x3f); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + nes_debug(NES_DBG_CQP, "CQP request %p (opcode 0x%02X) freed.\n", + cqp_request, + le32_to_cpu(cqp_request->cqp_wqe.wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f); + if (cqp_request->dynamic) { + kfree(cqp_request); + } else { + spin_lock_irqsave(&nesdev->cqp.lock, flags); + list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); + spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + } } } else { wake_up(&nesdev->cqp.waitq); } cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX] = 0; + nes_write32(nesdev->regs+NES_CQE_ALLOC, cq->cq_number | (1 << 16)); + if (++cqp->sq_tail >= cqp->sq_size) + cqp->sq_tail = 0; + /* Accounting... */ cqe_count++; if (++head >= cq_size) @@ -2193,7 +2537,7 @@ void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq) spin_lock_irqsave(&nesdev->cqp.lock, flags); while ((!list_empty(&nesdev->cqp_pending_reqs)) && ((((nesdev->cqp.sq_tail+nesdev->cqp.sq_size)-nesdev->cqp.sq_head) & - (nesdev->cqp.sq_size - 1)) != 1) ) { + (nesdev->cqp.sq_size - 1)) != 1)) { cqp_request = list_entry(nesdev->cqp_pending_reqs.next, struct nes_cqp_request, list); list_del_init(&cqp_request->list); @@ -2202,10 +2546,12 @@ void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq) cqp_wqe = &nesdev->cqp.sq_vbase[head]; memcpy(cqp_wqe, &cqp_request->cqp_wqe, sizeof(*cqp_wqe)); barrier(); - *((struct nes_cqp_request **)&cqp_wqe->wqe_words - [NES_CQP_WQE_COMP_SCRATCH_LOW_IDX]) = cqp_request; - dprintk("%s: CQP request %p (opcode 0x%02X) put on CQPs SQ wqe%u.\n", __FUNCTION__, - cqp_request, cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX]&0x3f, head); + cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] = + cpu_to_le32((u32)((unsigned long)cqp_request)); + cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] = + cpu_to_le32((u32)(upper_32_bits((unsigned long)cqp_request))); + nes_debug(NES_DBG_CQP, "CQP request %p (opcode 0x%02X) put on CQPs SQ wqe%u.\n", + cqp_request, le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f, head); /* Ring doorbell (1 WQEs) */ barrier(); nes_write32(nesdev->regs+NES_WQE_ALLOC, 0x01800000 | nesdev->cqp.qp_id); @@ -2225,7 +2571,10 @@ void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq) void nes_process_iwarp_aeqe(struct nes_device *nesdev, struct nes_hw_aeqe *aeqe) { u64 context; + u64 aeqe_context = 0; + unsigned long flags; struct nes_qp *nesqp; + int resource_allocated; /* struct iw_cm_id *cm_id; */ struct nes_adapter *nesadapter = nesdev->nesadapter; struct ib_event ibevent; @@ -2235,32 +2584,50 @@ void nes_process_iwarp_aeqe(struct nes_device *nesdev, struct nes_hw_aeqe *aeqe) u16 async_event_id; u8 tcp_state; u8 iwarp_state; - unsigned long flags; - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); - context = aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX]; - context += ((u64)aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX]) << 32; + nes_debug(NES_DBG_AEQ, "\n"); aeq_info = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]); + if ((NES_AEQE_INBOUND_RDMA&aeq_info) || (!(NES_AEQE_QP&aeq_info))) { + context = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX]); + context += ((u64)le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX])) << 32; + } else { + aeqe_context = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX]); + aeqe_context += ((u64)le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX])) << 32; + context = (unsigned long)nesadapter->qp_table[le32_to_cpu( + aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]) - NES_FIRST_QPN]; + BUG_ON(!context); + } + async_event_id = (u16)aeq_info; tcp_state = (aeq_info & NES_AEQE_TCP_STATE_MASK) >> NES_AEQE_TCP_STATE_SHIFT; iwarp_state = (aeq_info & NES_AEQE_IWARP_STATE_MASK) >> NES_AEQE_IWARP_STATE_SHIFT; - dprintk("%s: aeid = 0x%04X, qp-cq id = %d, aeqe = %p, Tcp state = %s, iWARP state = %s\n", - __FUNCTION__, async_event_id, + nes_debug(NES_DBG_AEQ, "aeid = 0x%04X, qp-cq id = %d, aeqe = %p," + " Tcp state = %s, iWARP state = %s\n", + async_event_id, le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]), aeqe, - nes_tcp_state_str[tcp_state], - nes_iwarp_state_str[iwarp_state]); + nes_tcp_state_str[tcp_state], nes_iwarp_state_str[iwarp_state]); switch (async_event_id) { case NES_AEQE_AEID_LLP_FIN_RECEIVED: nesqp = *((struct nes_qp **)&context); + if (atomic_inc_return(&nesqp->close_timer_started) == 1) { + nesqp->cm_id->add_ref(nesqp->cm_id); + nes_add_ref(&nesqp->ibqp); + schedule_nes_timer(nesqp->cm_node, (struct sk_buff *)nesqp, + NES_TIMER_TYPE_CLOSE, 1, 0); + nes_debug(NES_DBG_AEQ, "QP%u Not decrementing QP refcount (%d)," + " need ae to finish up, original_last_aeq = 0x%04X." + " last_aeq = 0x%04X, scheduling timer. TCP state = %d\n", + nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount), + async_event_id, nesqp->last_aeq, tcp_state); + } if ((tcp_state != NES_AEQE_TCP_STATE_CLOSE_WAIT) || (nesqp->ibqp_state != IB_QPS_RTS)) { /* FIN Received but tcp state or IB state moved on, should expect a close complete */ return; } - /* TODO: start timer to make sure close complete occurs */ case NES_AEQE_AEID_LLP_CLOSE_COMPLETE: case NES_AEQE_AEID_LLP_CONNECTION_RESET: case NES_AEQE_AEID_TERMINATE_SENT: @@ -2280,16 +2647,16 @@ void nes_process_iwarp_aeqe(struct nes_device *nesdev, struct nes_hw_aeqe *aeqe) (tcp_state == NES_AEQE_TCP_STATE_TIME_WAIT)) { nesqp->hte_added = 0; spin_unlock_irqrestore(&nesqp->lock, flags); - dprintk(PFX "%s: issuing hw modifyqp for QP%u to remove hte\n", - __FUNCTION__, nesqp->hwqp.qp_id); + nes_debug(NES_DBG_AEQ, "issuing hw modifyqp for QP%u to remove hte\n", + nesqp->hwqp.qp_id); nes_hw_modify_qp(nesdev, nesqp, NES_CQP_QP_IWARP_STATE_ERROR | NES_CQP_QP_DEL_HTE, 0); spin_lock_irqsave(&nesqp->lock, flags); } if ((nesqp->ibqp_state == IB_QPS_RTS) && - ((tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) || - (async_event_id==NES_AEQE_AEID_LLP_CONNECTION_RESET))) { + ((tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) || + (async_event_id == NES_AEQE_AEID_LLP_CONNECTION_RESET))) { switch (nesqp->hw_iwarp_state) { case NES_AEQE_IWARP_STATE_RTS: next_iwarp_state = NES_CQP_QP_IWARP_STATE_CLOSING; @@ -2309,9 +2676,9 @@ void nes_process_iwarp_aeqe(struct nes_device *nesdev, struct nes_hw_aeqe *aeqe) spin_unlock_irqrestore(&nesqp->lock, flags); if (next_iwarp_state) { nes_add_ref(&nesqp->ibqp); - dprintk(PFX "%s: issuing hw modifyqp for QP%u. next state = 0x%08X," + nes_debug(NES_DBG_AEQ, "issuing hw modifyqp for QP%u. next state = 0x%08X," " also added another reference\n", - __FUNCTION__, nesqp->hwqp.qp_id, next_iwarp_state); + nesqp->hwqp.qp_id, next_iwarp_state); nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0); } nes_cm_disconn(nesqp); @@ -2324,12 +2691,12 @@ void nes_process_iwarp_aeqe(struct nes_device *nesdev, struct nes_hw_aeqe *aeqe) return; } spin_unlock_irqrestore(&nesqp->lock, flags); - if (async_event_id==NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE) { + if (async_event_id == NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE) { next_iwarp_state = NES_CQP_QP_IWARP_STATE_TERMINATE | 0x02000000; nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED; - dprintk(PFX "%s: issuing hw modifyqp for QP%u. next state = 0x%08X," + nes_debug(NES_DBG_AEQ, "issuing hw modifyqp for QP%u. next state = 0x%08X," " also added another reference\n", - __FUNCTION__, nesqp->hwqp.qp_id, next_iwarp_state); + nesqp->hwqp.qp_id, next_iwarp_state); nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0); } nes_cm_disconn(nesqp); @@ -2342,9 +2709,9 @@ void nes_process_iwarp_aeqe(struct nes_device *nesdev, struct nes_hw_aeqe *aeqe) nesqp->hw_tcp_state = tcp_state; nesqp->last_aeq = async_event_id; spin_unlock_irqrestore(&nesqp->lock, flags); - dprintk("%s: Processing an NES_AEQE_AEID_LLP_TERMINATE_RECEIVED" + nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_LLP_TERMINATE_RECEIVED" " event on QP%u \n Q2 Data:\n", - __FUNCTION__, nesqp->hwqp.qp_id); + nesqp->hwqp.qp_id); if (nesqp->ibqp.event_handler) { ibevent.device = nesqp->ibqp.device; ibevent.element.qp = &nesqp->ibqp; @@ -2352,8 +2719,8 @@ void nes_process_iwarp_aeqe(struct nes_device *nesdev, struct nes_hw_aeqe *aeqe) nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context); } if ((tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) || - ((nesqp->ibqp_state == IB_QPS_RTS)&& - (async_event_id==NES_AEQE_AEID_LLP_CONNECTION_RESET))) { + ((nesqp->ibqp_state == IB_QPS_RTS)&& + (async_event_id == NES_AEQE_AEID_LLP_CONNECTION_RESET))) { nes_add_ref(&nesqp->ibqp); nes_cm_disconn(nesqp); } else { @@ -2361,10 +2728,37 @@ void nes_process_iwarp_aeqe(struct nes_device *nesdev, struct nes_hw_aeqe *aeqe) wake_up(&nesqp->kick_waitq); } break; + case NES_AEQE_AEID_LLP_TOO_MANY_RETRIES: + nesqp = *((struct nes_qp **)&context); + nes_add_ref(&nesqp->ibqp); + spin_lock_irqsave(&nesqp->lock, flags); + nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_ERROR; + nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED; + nesqp->last_aeq = async_event_id; + if (nesqp->cm_id) { + nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_LLP_TOO_MANY_RETRIES" + " event on QP%u, remote IP = 0x%08X \n", + nesqp->hwqp.qp_id, + ntohl(nesqp->cm_id->remote_addr.sin_addr.s_addr)); + } else { + nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_LLP_TOO_MANY_RETRIES" + " event on QP%u \n", + nesqp->hwqp.qp_id); + } + spin_unlock_irqrestore(&nesqp->lock, flags); + next_iwarp_state = NES_CQP_QP_IWARP_STATE_ERROR | NES_CQP_QP_RESET; + nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0); + if (nesqp->ibqp.event_handler) { + ibevent.device = nesqp->ibqp.device; + ibevent.element.qp = &nesqp->ibqp; + ibevent.event = IB_EVENT_QP_FATAL; + nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context); + } + break; case NES_AEQE_AEID_AMP_BAD_STAG_INDEX: if (NES_AEQE_INBOUND_RDMA&aeq_info) { nesqp = nesadapter->qp_table[le32_to_cpu( - aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX])-NES_FIRST_QPN]; + aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]) - NES_FIRST_QPN]; } else { /* TODO: get the actual WQE and mask off wqe index */ context &= ~((u64)511); @@ -2375,8 +2769,8 @@ void nes_process_iwarp_aeqe(struct nes_device *nesdev, struct nes_hw_aeqe *aeqe) nesqp->hw_tcp_state = tcp_state; nesqp->last_aeq = async_event_id; spin_unlock_irqrestore(&nesqp->lock, flags); - dprintk("%s: Processing an NES_AEQE_AEID_AMP_BAD_STAG_INDEX event on QP%u\n", - __FUNCTION__, nesqp->hwqp.qp_id); + nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_AMP_BAD_STAG_INDEX event on QP%u\n", + nesqp->hwqp.qp_id); if (nesqp->ibqp.event_handler) { ibevent.device = nesqp->ibqp.device; ibevent.element.qp = &nesqp->ibqp; @@ -2391,8 +2785,8 @@ void nes_process_iwarp_aeqe(struct nes_device *nesdev, struct nes_hw_aeqe *aeqe) nesqp->hw_tcp_state = tcp_state; nesqp->last_aeq = async_event_id; spin_unlock_irqrestore(&nesqp->lock, flags); - dprintk("%s: Processing an NES_AEQE_AEID_AMP_UNALLOCATED_STAG event on QP%u\n", - __FUNCTION__, nesqp->hwqp.qp_id); + nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_AMP_UNALLOCATED_STAG event on QP%u\n", + nesqp->hwqp.qp_id); if (nesqp->ibqp.event_handler) { ibevent.device = nesqp->ibqp.device; ibevent.element.qp = &nesqp->ibqp; @@ -2402,15 +2796,15 @@ void nes_process_iwarp_aeqe(struct nes_device *nesdev, struct nes_hw_aeqe *aeqe) break; case NES_AEQE_AEID_PRIV_OPERATION_DENIED: nesqp = nesadapter->qp_table[le32_to_cpu(aeqe->aeqe_words - [NES_AEQE_COMP_QP_CQ_ID_IDX])-NES_FIRST_QPN]; + [NES_AEQE_COMP_QP_CQ_ID_IDX]) - NES_FIRST_QPN]; spin_lock_irqsave(&nesqp->lock, flags); nesqp->hw_iwarp_state = iwarp_state; nesqp->hw_tcp_state = tcp_state; nesqp->last_aeq = async_event_id; spin_unlock_irqrestore(&nesqp->lock, flags); - dprintk("%s: Processing an NES_AEQE_AEID_PRIV_OPERATION_DENIED event on QP%u," + nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_PRIV_OPERATION_DENIED event on QP%u," " nesqp = %p, AE reported %p\n", - __FUNCTION__, nesqp->hwqp.qp_id, nesqp, *((struct nes_qp **)&context)); + nesqp->hwqp.qp_id, nesqp, *((struct nes_qp **)&context)); if (nesqp->ibqp.event_handler) { ibevent.device = nesqp->ibqp.device; ibevent.element.qp = &nesqp->ibqp; @@ -2420,20 +2814,26 @@ void nes_process_iwarp_aeqe(struct nes_device *nesdev, struct nes_hw_aeqe *aeqe) break; case NES_AEQE_AEID_CQ_OPERATION_ERROR: context <<= 1; - dprintk("%s: Processing an NES_AEQE_AEID_CQ_OPERATION_ERROR event on CQ%u, %p\n", - __FUNCTION__, le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]), (void *)context); + nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_CQ_OPERATION_ERROR event on CQ%u, %p\n", + le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]), (void *)(unsigned long)context); + resource_allocated = nes_is_resource_allocated(nesadapter, nesadapter->allocated_cqs, + le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX])); + if (resource_allocated) { + printk(KERN_ERR PFX "%s: Processing an NES_AEQE_AEID_CQ_OPERATION_ERROR event on CQ%u\n", + __FUNCTION__, le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX])); + } break; case NES_AEQE_AEID_DDP_UBE_DDP_MESSAGE_TOO_LONG_FOR_AVAILABLE_BUFFER: nesqp = nesadapter->qp_table[le32_to_cpu( - aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX])-NES_FIRST_QPN]; + aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]) - NES_FIRST_QPN]; spin_lock_irqsave(&nesqp->lock, flags); nesqp->hw_iwarp_state = iwarp_state; nesqp->hw_tcp_state = tcp_state; nesqp->last_aeq = async_event_id; spin_unlock_irqrestore(&nesqp->lock, flags); - dprintk("%s: Processing an NES_AEQE_AEID_DDP_UBE_DDP_MESSAGE_TOO_LONG" + nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_DDP_UBE_DDP_MESSAGE_TOO_LONG" "_FOR_AVAILABLE_BUFFER event on QP%u\n", - __FUNCTION__, nesqp->hwqp.qp_id); + nesqp->hwqp.qp_id); if (nesqp->ibqp.event_handler) { ibevent.device = nesqp->ibqp.device; ibevent.element.qp = &nesqp->ibqp; @@ -2451,9 +2851,9 @@ void nes_process_iwarp_aeqe(struct nes_device *nesdev, struct nes_hw_aeqe *aeqe) nesqp->hw_tcp_state = tcp_state; nesqp->last_aeq = async_event_id; spin_unlock_irqrestore(&nesqp->lock, flags); - dprintk("%s: Processing an NES_AEQE_AEID_DDP_UBE_INVALID_MSN" + nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_DDP_UBE_INVALID_MSN" "_NO_BUFFER_AVAILABLE event on QP%u\n", - __FUNCTION__, nesqp->hwqp.qp_id); + nesqp->hwqp.qp_id); if (nesqp->ibqp.event_handler) { ibevent.device = nesqp->ibqp.device; ibevent.element.qp = &nesqp->ibqp; @@ -2471,9 +2871,9 @@ void nes_process_iwarp_aeqe(struct nes_device *nesdev, struct nes_hw_aeqe *aeqe) nesqp->hw_tcp_state = tcp_state; nesqp->last_aeq = async_event_id; spin_unlock_irqrestore(&nesqp->lock, flags); - dprintk("%s: Processing an NES_AEQE_AEID_LLP_RECEIVED_MPA_CRC_ERROR" + nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_LLP_RECEIVED_MPA_CRC_ERROR" " event on QP%u \n Q2 Data:\n", - __FUNCTION__, nesqp->hwqp.qp_id); + nesqp->hwqp.qp_id); if (nesqp->ibqp.event_handler) { ibevent.device = nesqp->ibqp.device; ibevent.element.qp = &nesqp->ibqp; @@ -2486,12 +2886,11 @@ void nes_process_iwarp_aeqe(struct nes_device *nesdev, struct nes_hw_aeqe *aeqe) break; /* TODO: additional AEs need to be here */ default: - dprintk("%s: Processing an iWARP related AE for QP, misc = 0x%04X\n", - __FUNCTION__, async_event_id); + nes_debug(NES_DBG_AEQ, "Processing an iWARP related AE for QP, misc = 0x%04X\n", + async_event_id); break; } - dprintk("%s:%u: Leaving\n", __FUNCTION__, __LINE__); } @@ -2502,8 +2901,8 @@ void nes_iwarp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *hw_cq) { struct nes_cq *nescq = container_of(hw_cq, struct nes_cq, hw_cq); - /* dprintk("%s: Processing completion event for iWARP CQ%u.\n", - __FUNCTION__, nescq->hw_cq.cq_number); */ + /* nes_debug(NES_DBG_CQ, "Processing completion event for iWARP CQ%u.\n", + nescq->hw_cq.cq_number); */ nes_write32(nesdev->regs+NES_CQ_ACK, nescq->hw_cq.cq_number); if (nescq->ibcq.comp_handler) @@ -2512,6 +2911,7 @@ void nes_iwarp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *hw_cq) return; } + /** * nes_manage_apbvt() */ @@ -2526,55 +2926,50 @@ int nes_manage_apbvt(struct nes_vnic *nesvnic, u32 accel_local_port, u16 major_code; /* Send manage APBVT request to CQP */ - spin_lock_irqsave(&nesdev->cqp.lock, flags); - cqp_request = nes_get_cqp_request(nesdev, NES_CQP_REQUEST_HOLDING_LOCK); - if (NULL == cqp_request) { - dprintk("%s: Failed to get a cqp_request.\n", __FUNCTION__); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); - return (-ENOMEM); + cqp_request = nes_get_cqp_request(nesdev); + if (cqp_request == NULL) { + nes_debug(NES_DBG_QP, "Failed to get a cqp_request.\n"); + return -ENOMEM; } cqp_request->waiting = 1; cqp_wqe = &cqp_request->cqp_wqe; - dprintk("%s:%u: %s APBV for local port=%u(0x%04x), nic_index=%u\n", - __FUNCTION__, __LINE__, + nes_debug(NES_DBG_QP, "%s APBV for local port=%u(0x%04x), nic_index=%u\n", (add_port == NES_MANAGE_APBVT_ADD) ? "ADD" : "DEL", accel_local_port, accel_local_port, nic_index); - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_MANAGE_APBVT | - ((add_port==NES_MANAGE_APBVT_ADD) ? NES_CQP_APBVT_ADD : 0)); - cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = - cpu_to_le32((nic_index << NES_CQP_APBVT_NIC_SHIFT) | accel_local_port); - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX] = 0; - *((struct nes_hw_cqp **)&cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_LOW_IDX]) = - &nesdev->cqp; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] = 0; + nes_fill_init_cqp_wqe(cqp_wqe, nesdev); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, (NES_CQP_MANAGE_APBVT | + ((add_port == NES_MANAGE_APBVT_ADD) ? NES_CQP_APBVT_ADD : 0))); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX, + ((nic_index << NES_CQP_APBVT_NIC_SHIFT) | accel_local_port)); - dprintk("%s: Waiting for CQP completion for APBVT.\n", __FUNCTION__); + nes_debug(NES_DBG_QP, "Waiting for CQP completion for APBVT.\n"); atomic_set(&cqp_request->refcount, 2); - nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_HOLDING_LOCK, - NES_CQP_REQUEST_RING_DOORBELL); + nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_RING_DOORBELL); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); - if(add_port==NES_MANAGE_APBVT_ADD) - ret = wait_event_timeout(cqp_request->waitq, (0 != cqp_request->request_done), - NES_EVENT_TIMEOUT); - dprintk("%s: Completed, ret=%u, CQP Major:Minor codes = 0x%04X:0x%04X\n", - __FUNCTION__, ret, cqp_request->major_code, cqp_request->minor_code); + if (add_port == NES_MANAGE_APBVT_ADD) + ret = wait_event_timeout(cqp_request->waitq, (cqp_request->request_done != 0), + NES_EVENT_TIMEOUT); + nes_debug(NES_DBG_QP, "Completed, ret=%u, CQP Major:Minor codes = 0x%04X:0x%04X\n", + ret, cqp_request->major_code, cqp_request->minor_code); major_code = cqp_request->major_code; if (atomic_dec_and_test(&cqp_request->refcount)) { - spin_lock_irqsave(&nesdev->cqp.lock, flags); - list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + if (cqp_request->dynamic) { + kfree(cqp_request); + } else { + spin_lock_irqsave(&nesdev->cqp.lock, flags); + list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); + spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + } } if (!ret) - return(-ETIME); + return -ETIME; else if (major_code) - return(-EIO); + return -EIO; else - return(0); + return 0; } @@ -2587,70 +2982,48 @@ void nes_manage_arp_cache(struct net_device *netdev, unsigned char *mac_addr, struct nes_hw_cqp_wqe *cqp_wqe; struct nes_vnic *nesvnic = netdev_priv(netdev); struct nes_device *nesdev; - unsigned long flags; struct nes_cqp_request *cqp_request; int arp_index; nesdev = nesvnic->nesdev; arp_index = nes_arp_table(nesdev, ip_addr, mac_addr, action); if (arp_index == -1) { - /* dprintk("%s:%u nes_arp_table call returned -1\n", __FUNCTION__, __LINE__); */ return; } - /* dprintk("%s: Update the ARP entry, arp_index=%d\n", __FUNCTION__, arp_index); */ - /* update the ARP entry */ - spin_lock_irqsave(&nesdev->cqp.lock, flags); - cqp_request = nes_get_cqp_request(nesdev, NES_CQP_REQUEST_HOLDING_LOCK); - if (NULL == cqp_request) { - dprintk("%s: Failed to get a cqp_request.\n", __FUNCTION__); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + cqp_request = nes_get_cqp_request(nesdev); + if (cqp_request == NULL) { + nes_debug(NES_DBG_NETDEV, "Failed to get a cqp_request.\n"); return; } cqp_request->waiting = 0; cqp_wqe = &cqp_request->cqp_wqe; + nes_fill_init_cqp_wqe(cqp_wqe, nesdev); - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = - NES_CQP_MANAGE_ARP_CACHE | NES_CQP_ARP_PERM; - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= - (u32)PCI_FUNC(nesdev->pcidev->devfn) << NES_CQP_ARP_AEQ_INDEX_SHIFT; - cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = arp_index; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX] = 0; - *((struct nes_hw_cqp **)&cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_LOW_IDX]) = - &nesdev->cqp; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] = 0; + cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32( + NES_CQP_MANAGE_ARP_CACHE | NES_CQP_ARP_PERM); + cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= cpu_to_le32( + (u32)PCI_FUNC(nesdev->pcidev->devfn) << NES_CQP_ARP_AEQ_INDEX_SHIFT); + cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(arp_index); if (action == NES_ARP_ADD) { - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= NES_CQP_ARP_VALID; - cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_ADDR_LOW_IDX] = + cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= cpu_to_le32(NES_CQP_ARP_VALID); + cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_ADDR_LOW_IDX] = cpu_to_le32( (((u32)mac_addr[2]) << 24) | (((u32)mac_addr[3]) << 16) | - (((u32)mac_addr[4]) << 8) | (u32)mac_addr[5]; - cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_HIGH_IDX] = - (((u32)mac_addr[0]) << 16) | (u32)mac_addr[1]; + (((u32)mac_addr[4]) << 8) | (u32)mac_addr[5]); + cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_HIGH_IDX] = cpu_to_le32( + (((u32)mac_addr[0]) << 16) | (u32)mac_addr[1]); } else { cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_ADDR_LOW_IDX] = 0; cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_HIGH_IDX] = 0; } - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = - cpu_to_le32(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX]); - cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = - cpu_to_le32(cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX]); - cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_HIGH_IDX] = - cpu_to_le32(cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_HIGH_IDX]); - cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_ADDR_LOW_IDX] = - cpu_to_le32(cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_ADDR_LOW_IDX]); - - dprintk("%s[%u] Not waiting for CQP, cqp.sq_head=%u, cqp.sq_tail=%u\n", - __FUNCTION__, __LINE__, nesdev->cqp.sq_head, nesdev->cqp.sq_tail); + nes_debug(NES_DBG_NETDEV, "Not waiting for CQP, cqp.sq_head=%u, cqp.sq_tail=%u\n", + nesdev->cqp.sq_head, nesdev->cqp.sq_tail); atomic_set(&cqp_request->refcount, 1); - nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_HOLDING_LOCK, - NES_CQP_REQUEST_RING_DOORBELL); - - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_RING_DOORBELL); } @@ -2665,12 +3038,9 @@ void flush_wqes(struct nes_device *nesdev, struct nes_qp *nesqp, struct nes_hw_cqp_wqe *cqp_wqe; int ret; - spin_lock_irqsave(&nesdev->cqp.lock, flags); - - cqp_request = nes_get_cqp_request(nesdev, NES_CQP_REQUEST_HOLDING_LOCK); - if (NULL == cqp_request) { - dprintk("%s: Failed to get a cqp_request.\n", __FUNCTION__); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + cqp_request = nes_get_cqp_request(nesdev); + if (cqp_request == NULL) { + nes_debug(NES_DBG_QP, "Failed to get a cqp_request.\n"); return; } if (wait_completion) { @@ -2680,32 +3050,29 @@ void flush_wqes(struct nes_device *nesdev, struct nes_qp *nesqp, cqp_request->waiting = 0; } cqp_wqe = &cqp_request->cqp_wqe; + nes_fill_init_cqp_wqe(cqp_wqe, nesdev); cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_FLUSH_WQES | which_wq); cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(nesqp->hwqp.qp_id); - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX] = 0; - *((struct nes_hw_cqp **)&cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_LOW_IDX]) = - &nesdev->cqp; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] = 0; - nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_HOLDING_LOCK, - NES_CQP_REQUEST_RING_DOORBELL); - - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_RING_DOORBELL); if (wait_completion) { /* Wait for CQP */ - ret = wait_event_timeout(cqp_request->waitq, (0 != cqp_request->request_done), + ret = wait_event_timeout(cqp_request->waitq, (cqp_request->request_done != 0), NES_EVENT_TIMEOUT); - dprintk("Flush SQ QP WQEs completed, ret=%u, CQP Major:Minor codes = 0x%04X:0x%04X\n", + nes_debug(NES_DBG_QP, "Flush SQ QP WQEs completed, ret=%u," + " CQP Major:Minor codes = 0x%04X:0x%04X\n", ret, cqp_request->major_code, cqp_request->minor_code); if (atomic_dec_and_test(&cqp_request->refcount)) { - spin_lock_irqsave(&nesdev->cqp.lock, flags); - list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + if (cqp_request->dynamic) { + kfree(cqp_request); + } else { + spin_lock_irqsave(&nesdev->cqp.lock, flags); + list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); + spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + } } } } - diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h index c930700..8f784bc 100644 --- a/drivers/infiniband/hw/nes/nes_hw.h +++ b/drivers/infiniband/hw/nes/nes_hw.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2006 - 2007 NetEffect, Inc. All rights reserved. +* Copyright (c) 2006 - 2008 NetEffect, Inc. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -33,6 +33,12 @@ #ifndef __NES_HW_H #define __NES_HW_H +#define NES_PHY_TYPE_1G 2 +#define NES_PHY_TYPE_IRIS 3 +#define NES_PHY_TYPE_PUMA_10G 6 + +#define NES_MULTICAST_PF_MAX 8 + enum pci_regs { NES_INT_STAT = 0x0000, NES_INT_MASK = 0x0004, @@ -44,6 +50,8 @@ enum pci_regs { NES_ONE_SHOT_CONTROL = 0x001C, NES_EEPROM_COMMAND = 0x0020, NES_EEPROM_DATA = 0x0024, + NES_FLASH_COMMAND = 0x0028, + NES_FLASH_DATA = 0x002C, NES_SOFTWARE_RESET = 0x0030, NES_CQ_ACK = 0x0034, NES_WQE_ALLOC = 0x0040, @@ -75,6 +83,8 @@ enum indexed_regs { NES_IDX_DST_IP_ADDR = 0x0400, NES_IDX_PCIX_DIAG = 0x08e8, NES_IDX_MPP_DEBUG = 0x0a00, + NES_IDX_PORT_RX_DISCARDS = 0x0a30, + NES_IDX_PORT_TX_DISCARDS = 0x0a34, NES_IDX_MPP_LB_DEBUG = 0x0b00, NES_IDX_DENALI_CTL_22 = 0x1058, NES_IDX_MAC_TX_CONTROL = 0x2000, @@ -131,6 +141,8 @@ enum indexed_regs { NES_IDX_ETH_SERDES_CDR_RESET1 = 0x2a30, NES_IDX_ETH_SERDES_CDR_CONTROL0 = 0x2834, NES_IDX_ETH_SERDES_CDR_CONTROL1 = 0x2a34, + NES_IDX_ETH_SERDES_TX_HIGHZ_LANE_MODE0 = 0x2838, + NES_IDX_ETH_SERDES_TX_HIGHZ_LANE_MODE1 = 0x2a38, NES_IDX_ENDNODE0_NSTAT_RX_DISCARD = 0x3080, NES_IDX_ENDNODE0_NSTAT_RX_OCTETS_LO = 0x3000, NES_IDX_ENDNODE0_NSTAT_RX_OCTETS_HI = 0x3004, @@ -163,7 +175,7 @@ enum indexed_regs { NES_IDX_DEBUG_ERROR_MASKS5 = 0x9154, }; -#define NES_IDX_MAC_TX_CONFIG_ENABLE_PAUSE 1 +#define NES_IDX_MAC_TX_CONFIG_ENABLE_PAUSE 1 #define NES_IDX_MPP_DEBUG_PORT_DISABLE_PAUSE (1 << 17) enum nes_cqp_opcodes { @@ -352,6 +364,7 @@ enum nes_cqe_opcode_bits { NES_CQE_VALID = (1<<31), }; + enum nes_cqe_word_idx { NES_CQE_PAYLOAD_LENGTH_IDX = 0, NES_CQE_COMP_COMP_CTX_LOW_IDX = 2, @@ -564,14 +577,17 @@ enum nes_nic_cqe_word_idx { #define NES_PKT_TYPE_APBVT_BITS 0xC112 #define NES_PKT_TYPE_APBVT_MASK 0xff3e +#define NES_PKT_TYPE_PVALID_BITS 0x10000000 +#define NES_PKT_TYPE_PVALID_MASK 0x30000000 + #define NES_PKT_TYPE_TCPV4_BITS 0x0110 #define NES_PKT_TYPE_TCPV4_MASK 0x3f30 #define NES_PKT_TYPE_UDPV4_BITS 0x0210 #define NES_PKT_TYPE_UDPV4_MASK 0x3f30 -#define NES_PKT_TYPE_IPV4_BITS 0x0010 -#define NES_PKT_TYPE_IPV4_MASK 0x3f30 +#define NES_PKT_TYPE_IPV4_BITS 0x0010 +#define NES_PKT_TYPE_IPV4_MASK 0x3f30 #define NES_PKT_TYPE_OTHER_BITS 0x0000 #define NES_PKT_TYPE_OTHER_MASK 0x0030 @@ -611,8 +627,8 @@ enum nes_aeqe_bits { NES_AEQE_VALID = (1<<31), }; -#define NES_AEQE_IWARP_STATE_SHIFT 20 -#define NES_AEQE_TCP_STATE_SHIFT 24 +#define NES_AEQE_IWARP_STATE_SHIFT 20 +#define NES_AEQE_TCP_STATE_SHIFT 24 enum nes_aeqe_iwarp_state { NES_AEQE_IWARP_STATE_NON_EXISTANT = 0, @@ -638,8 +654,6 @@ enum nes_aeqe_tcp_state { NES_AEQE_TCP_STATE_TIME_WAIT = 11 }; -#define NES_TIMER_INT_LIMIT 2 - enum nes_aeqe_aeid { NES_AEQE_AEID_AMP_UNALLOCATED_STAG = 0x0102, NES_AEQE_AEID_AMP_INVALID_STAG = 0x0103, @@ -729,7 +743,7 @@ enum nes_iwarp_sq_wqe_bits { }; #define NES_EEPROM_READ_REQUEST (1<<16) -#define NES_MAC_ADDR_VALID (1<<20) +#define NES_MAC_ADDR_VALID (1<<20) /* * NES index registers init values. @@ -737,7 +751,7 @@ enum nes_iwarp_sq_wqe_bits { struct nes_init_values { u32 index; u32 data; - u8 wrt; + u8 wrt; }; /* @@ -752,10 +766,10 @@ struct nes_pci_regs { u32 other_regs[59]; /* pad out to 256 bytes for now */ }; -#define NES_CQP_SQ_SIZE 128 -#define NES_CCQ_SIZE 128 -#define NES_NIC_WQ_SIZE 512 -#define NES_NIC_CTX_SIZE ((NES_NIC_CTX_RQ_SIZE_512) | (NES_NIC_CTX_SQ_SIZE_512)) +#define NES_CQP_SQ_SIZE 128 +#define NES_CCQ_SIZE 128 +#define NES_NIC_WQ_SIZE 512 +#define NES_NIC_CTX_SIZE ((NES_NIC_CTX_RQ_SIZE_512) | (NES_NIC_CTX_SQ_SIZE_512)) #define NES_NIC_BACK_STORE 0x00038000 struct nes_device; @@ -801,26 +815,32 @@ struct nes_hw_aeqe { }; struct nes_cqp_request { - wait_queue_head_t waitq; + union { + u64 cqp_callback_context; + void *cqp_callback_pointer; + }; + wait_queue_head_t waitq; struct nes_hw_cqp_wqe cqp_wqe; - struct list_head list; - atomic_t refcount; - u16 major_code; - u16 minor_code; - u8 waiting; - u8 request_done; - u8 padding[2]; + struct list_head list; + atomic_t refcount; + void (*cqp_callback)(struct nes_device *nesdev, struct nes_cqp_request *cqp_request); + u16 major_code; + u16 minor_code; + u8 waiting; + u8 request_done; + u8 dynamic; + u8 callback; }; struct nes_hw_cqp { struct nes_hw_cqp_wqe *sq_vbase; - dma_addr_t sq_pbase; - spinlock_t lock; - wait_queue_head_t waitq; - u16 qp_id; - u16 sq_head; - u16 sq_tail; - u16 sq_size; + dma_addr_t sq_pbase; + spinlock_t lock; + wait_queue_head_t waitq; + u16 qp_id; + u16 sq_head; + u16 sq_tail; + u16 sq_size; }; #define NES_FIRST_FRAG_SIZE 128 @@ -829,12 +849,13 @@ struct nes_first_frag { }; struct nes_hw_nic { - struct nes_first_frag *first_frag_vbase; /* virtual address of first frags */ - struct nes_hw_nic_sq_wqe *sq_vbase; /* virtual address of sq */ - struct nes_hw_nic_rq_wqe *rq_vbase; /* virtual address of rq */ - struct sk_buff *tx_skb[NES_NIC_WQ_SIZE]; - struct sk_buff *rx_skb[NES_NIC_WQ_SIZE]; + struct nes_first_frag *first_frag_vbase; /* virtual address of first frags */ + struct nes_hw_nic_sq_wqe *sq_vbase; /* virtual address of sq */ + struct nes_hw_nic_rq_wqe *rq_vbase; /* virtual address of rq */ + struct sk_buff *tx_skb[NES_NIC_WQ_SIZE]; + struct sk_buff *rx_skb[NES_NIC_WQ_SIZE]; dma_addr_t frag_paddr[NES_NIC_WQ_SIZE]; + unsigned long first_frag_overflow[BITS_TO_LONGS(NES_NIC_WQ_SIZE)]; dma_addr_t sq_pbase; /* PCI memory for host rings */ dma_addr_t rq_pbase; /* PCI memory for host rings */ @@ -845,6 +866,8 @@ struct nes_hw_nic { u16 rq_head; u16 rq_tail; u16 rq_size; + u8 replenishing_rq; + u8 reserved; spinlock_t sq_lock; spinlock_t rq_lock; @@ -854,15 +877,19 @@ struct nes_hw_nic_cq { struct nes_hw_nic_cqe volatile *cq_vbase; /* PCI memory for host rings */ void (*ce_handler)(struct nes_device *nesdev, struct nes_hw_nic_cq *cq); dma_addr_t cq_pbase; /* PCI memory for host rings */ + int rx_cqes_completed; + int cqe_allocs_pending; + int rx_pkts_indicated; u16 cq_head; u16 cq_size; u16 cq_number; + u8 cqes_pending; }; struct nes_hw_qp { struct nes_hw_qp_wqe *sq_vbase; /* PCI memory for host rings */ struct nes_hw_qp_wqe *rq_vbase; /* PCI memory for host rings */ - void *q2_vbase; /* PCI memory for host rings */ + void *q2_vbase; /* PCI memory for host rings */ dma_addr_t sq_pbase; /* PCI memory for host rings */ dma_addr_t rq_pbase; /* PCI memory for host rings */ dma_addr_t q2_pbase; /* PCI memory for host rings */ @@ -873,8 +900,8 @@ struct nes_hw_qp { u16 rq_head; u16 rq_tail; u16 rq_size; - u8 rq_encoded_size; - u8 sq_encoded_size; + u8 rq_encoded_size; + u8 sq_encoded_size; }; struct nes_hw_cq { @@ -907,55 +934,99 @@ struct nic_qp_map { u8 is_hnic; }; -#define NES_CQP_ARP_AEQ_INDEX_MASK 0x000f0000 +#define NES_CQP_ARP_AEQ_INDEX_MASK 0x000f0000 #define NES_CQP_ARP_AEQ_INDEX_SHIFT 16 #define NES_CQP_APBVT_ADD 0x00008000 #define NES_CQP_APBVT_NIC_SHIFT 16 -#define NES_ARP_ADD 1 -#define NES_ARP_DELETE 2 +#define NES_ARP_ADD 1 +#define NES_ARP_DELETE 2 #define NES_ARP_RESOLVE 3 -#define NES_MAC_SW_IDLE 0 +#define NES_MAC_SW_IDLE 0 #define NES_MAC_SW_INTERRUPT 1 -#define NES_MAC_SW_MH 2 +#define NES_MAC_SW_MH 2 struct nes_arp_entry { u32 ip_addr; u8 mac_addr[ETH_ALEN]; }; +#define NES_NIC_FAST_TIMER 96 +#define NES_NIC_FAST_TIMER_LOW 40 +#define NES_NIC_FAST_TIMER_HIGH 1000 +#define DEFAULT_NES_QL_HIGH 256 +#define DEFAULT_NES_QL_LOW 16 +#define DEFAULT_NES_QL_TARGET 64 +#define DEFAULT_JUMBO_NES_QL_LOW 12 +#define DEFAULT_JUMBO_NES_QL_TARGET 40 +#define DEFAULT_JUMBO_NES_QL_HIGH 128 +#define NES_NIC_CQ_DOWNWARD_TREND 16 + +struct nes_hw_tune_timer { + //u16 cq_count; + u16 threshold_low; + u16 threshold_target; + u16 threshold_high; + u16 timer_in_use; + u16 timer_in_use_old; + u16 timer_in_use_min; + u16 timer_in_use_max; + u8 timer_direction_upward; + u8 timer_direction_downward; + u16 cq_count_old; + u8 cq_direction_downward; +}; + +#define NES_TIMER_INT_LIMIT 2 +#define NES_TIMER_INT_LIMIT_DYNAMIC 10 +#define NES_TIMER_ENABLE_LIMIT 4 +#define NES_MAX_LINK_INTERRUPTS 128 +#define NES_MAX_LINK_CHECK 200 + struct nes_adapter { - u32 hw_rev; - u64 fw_ver; + u64 fw_ver; + unsigned long *allocated_qps; + unsigned long *allocated_cqs; + unsigned long *allocated_mrs; + unsigned long *allocated_pds; + unsigned long *allocated_arps; + struct nes_qp **qp_table; + struct workqueue_struct *work_q; + struct list_head list; + struct list_head active_listeners; + /* list of the netdev's associated with each logical port */ + struct list_head nesvnic_list[4]; + + struct timer_list mh_timer; + struct timer_list lc_timer; + struct work_struct work; + spinlock_t resource_lock; + spinlock_t phy_lock; + spinlock_t pbl_lock; + spinlock_t periodic_timer_lock; + + struct nes_arp_entry arp_table[NES_MAX_ARP_TABLE_SIZE]; + + /* Adapter CEQ and AEQs */ + struct nes_hw_ceq ceq[16]; + struct nes_hw_aeq aeq[8]; + + struct nes_hw_tune_timer tune_timer; + + unsigned long doorbell_start; + + u32 hw_rev; u32 vendor_id; u32 vendor_part_id; - struct nes_qp **qp_table; u32 device_cap_flags; u32 tick_delta; u32 timer_int_req; - /* RNIC Resource Lists */ - unsigned long *allocated_qps; - unsigned long *allocated_cqs; - unsigned long *allocated_mrs; - unsigned long *allocated_pds; - struct list_head active_listeners; - spinlock_t resource_lock; - spinlock_t phy_lock; - - /* arp table */ - unsigned long *allocated_arps; - struct nes_arp_entry arp_table[NES_MAX_ARP_TABLE_SIZE]; - u32 arp_table_size; - u32 next_arp_index; + u32 arp_table_size; + u32 next_arp_index; - /* Adapter CEQ and AEQs */ - struct nes_hw_ceq ceq[16]; - struct nes_hw_aeq aeq[8]; - - /* RNIC Limits */ u32 max_mr; u32 max_256pbl; u32 max_4kpbl; @@ -990,62 +1061,72 @@ struct nes_adapter { u32 nic_rx_eth_route_err; + u32 et_rx_coalesce_usecs; + u32 et_rx_max_coalesced_frames; + u32 et_rx_coalesce_usecs_irq; + u32 et_rx_max_coalesced_frames_irq; + u32 et_pkt_rate_low; + u32 et_rx_coalesce_usecs_low; + u32 et_rx_max_coalesced_frames_low; + u32 et_pkt_rate_high; + u32 et_rx_coalesce_usecs_high; + u32 et_rx_max_coalesced_frames_high; + u32 et_rate_sample_interval; + u32 timer_int_limit; + /* Adapter base MAC address */ - u16 mac_addr_high; u32 mac_addr_low; + u16 mac_addr_high; u16 firmware_eeprom_offset; u16 software_eeprom_offset; u16 max_irrq_wr; - /* PCI information */ - unsigned int devfn; - unsigned char bus_number; - unsigned char OneG_Mode; + /* pd config for each port */ + u16 pd_config_size[4]; + u16 pd_config_base[4]; - struct list_head list; - /* list of the netdev's associated with each logical port */ - struct list_head nesvnic_list[4]; - - unsigned char ref_count; - u8 netdev_count; - u8 netdev_max; /* from host nic address count in EEPROM */ - u8 port_count; + u16 link_interrupt_count[4]; /* the phy index for each port */ - u8 phy_index[4]; - u8 mac_sw_state[4]; - u8 mac_link_down[4]; - u8 ports[4]; + u8 phy_index[4]; + u8 mac_sw_state[4]; + u8 mac_link_down[4]; + u8 phy_type[4]; - struct timer_list mh_timer; - /* wait_queue_head_t wait_q; */ - struct work_struct work; - struct workqueue_struct *work_q; - /* u32 worker_quit; */ + /* PCI information */ + unsigned int devfn; + unsigned char bus_number; + unsigned char OneG_Mode; - void *cm_context; + unsigned char ref_count; + u8 netdev_count; + u8 netdev_max; /* from host nic address count in EEPROM */ + u8 port_count; + u8 virtwq; + u8 et_use_adaptive_rx_coalesce; + u8 adapter_fcn_count; }; struct nes_pbl { - u64 *pbl_vbase; - dma_addr_t pbl_pbase; - unsigned long user_base; - u32 pbl_size; + u64 *pbl_vbase; + dma_addr_t pbl_pbase; + struct page *page; + unsigned long user_base; + u32 pbl_size; struct list_head list; /* TODO: need to add list for two level tables */ }; struct nes_listener { - struct work_struct work; + struct work_struct work; struct workqueue_struct *wq; - struct nes_vnic *nesvnic; - struct iw_cm_id *cm_id; - struct list_head list; - unsigned long socket; - struct socket *ksock; - u8 accept_failed; + struct nes_vnic *nesvnic; + struct iw_cm_id *cm_id; + struct list_head list; + unsigned long socket; + u8 accept_failed; }; struct nes_ib_device; @@ -1068,39 +1149,39 @@ struct nes_vnic { struct nes_device *nesdev; struct net_device *netdev; struct vlan_group *vlan_grp; - atomic_t rx_skbs_needed; - atomic_t rx_skb_timer_running; - int budget; - int rx_cqes_completed; - int cqe_allocs_pending; - u32 msg_enable; + atomic_t rx_skbs_needed; + atomic_t rx_skb_timer_running; + int budget; + u32 msg_enable; /* u32 tx_avail; */ - __be32 local_ipaddr; - - spinlock_t tx_lock; /* could use netdev tx lock? */ - struct timer_list rq_wqes_timer; - u32 nic_mem_size; - void *nic_vbase; - dma_addr_t nic_pbase; - struct nes_hw_nic nic; + __be32 local_ipaddr; + spinlock_t tx_lock; /* could use netdev tx lock? */ + struct timer_list rq_wqes_timer; + u32 nic_mem_size; + void *nic_vbase; + dma_addr_t nic_pbase; + struct nes_hw_nic nic; struct nes_hw_nic_cq nic_cq; - + u32 mcrq_qp_id; + struct nes_ucontext *mcrq_ucontext; + struct nes_cqp_request* (*get_cqp_request)(struct nes_device *nesdev); + void (*post_cqp_request)(struct nes_device*, struct nes_cqp_request *, int); + int (*mcrq_mcast_filter)( struct nes_vnic* nesvnic, __u8* dmi_addr ); struct net_device_stats netstats; /* used to put the netdev on the adapters logical port list */ struct list_head list; u16 max_frame_size; - u8 netdev_open; - u8 linkup; - u8 logical_port; - u8 netdev_index; /* might not be needed, indexes nesdev->netdev */ - u8 perfect_filter_index; - u8 nic_index; - u8 qp_nic_index[4]; - u8 next_qp_nic_index; - u8 of_device_registered; - u8 rdma_enabled; - u8 cqes_pending; - u8 rx_checksum_disabled; + u8 netdev_open; + u8 linkup; + u8 logical_port; + u8 netdev_index; /* might not be needed, indexes nesdev->netdev */ + u8 perfect_filter_index; + u8 nic_index; + u8 qp_nic_index[4]; + u8 next_qp_nic_index; + u8 of_device_registered; + u8 rdma_enabled; + u8 rx_checksum_disabled; }; struct nes_ib_device { @@ -1118,5 +1199,7 @@ struct nes_ib_device { u32 num_pd; }; -#endif /* __NES_HW_H */ +#define nes_vlan_rx vlan_hwaccel_receive_skb +#define nes_netif_rx netif_receive_skb +#endif /* __NES_HW_H */ diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c index bc6542e..d78cc76 100644 --- a/drivers/infiniband/hw/nes/nes_nic.c +++ b/drivers/infiniband/hw/nes/nes_nic.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2007 NetEffect, Inc. All rights reserved. + * Copyright (c) 2006 - 2008 NetEffect, Inc. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -47,76 +47,51 @@ #include "nes.h" -struct nic_qp_map nic_qp_mapping_0[] = { +static struct nic_qp_map nic_qp_mapping_0[] = { {16,0,0,1},{24,4,0,0},{28,8,0,0},{32,12,0,0}, {20,2,2,1},{26,6,2,0},{30,10,2,0},{34,14,2,0}, {18,1,1,1},{25,5,1,0},{29,9,1,0},{33,13,1,0}, {22,3,3,1},{27,7,3,0},{31,11,3,0},{35,15,3,0} }; -struct nic_qp_map nic_qp_mapping_1[] = { +static struct nic_qp_map nic_qp_mapping_1[] = { {18,1,1,1},{25,5,1,0},{29,9,1,0},{33,13,1,0}, {22,3,3,1},{27,7,3,0},{31,11,3,0},{35,15,3,0} }; -struct nic_qp_map nic_qp_mapping_2[] = { +static struct nic_qp_map nic_qp_mapping_2[] = { {20,2,2,1},{26,6,2,0},{30,10,2,0},{34,14,2,0} }; -struct nic_qp_map nic_qp_mapping_3[] = { +static struct nic_qp_map nic_qp_mapping_3[] = { {22,3,3,1},{27,7,3,0},{31,11,3,0},{35,15,3,0} }; -struct nic_qp_map nic_qp_mapping_4[] = { +static struct nic_qp_map nic_qp_mapping_4[] = { {28,8,0,0},{32,12,0,0} }; -struct nic_qp_map nic_qp_mapping_5[] = { +static struct nic_qp_map nic_qp_mapping_5[] = { {29,9,1,0},{33,13,1,0} }; -struct nic_qp_map nic_qp_mapping_6[] = { +static struct nic_qp_map nic_qp_mapping_6[] = { {30,10,2,0},{34,14,2,0} }; -struct nic_qp_map nic_qp_mapping_7[] = { +static struct nic_qp_map nic_qp_mapping_7[] = { {31,11,3,0},{35,15,3,0} }; -struct nic_qp_map *nic_qp_mapping_per_function[] = { +static struct nic_qp_map *nic_qp_mapping_per_function[] = { nic_qp_mapping_0, nic_qp_mapping_1, nic_qp_mapping_2, nic_qp_mapping_3, nic_qp_mapping_4, nic_qp_mapping_5, nic_qp_mapping_6, nic_qp_mapping_7 }; -extern int nics_per_function; - static const u32 default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN; static int debug = -1; -static int rdma_enabled = 0; -extern atomic_t cm_connects; -extern atomic_t cm_accepts; -extern atomic_t cm_disconnects; -extern atomic_t cm_closes; -extern atomic_t cm_connecteds; -extern atomic_t cm_connect_reqs; -extern atomic_t cm_rejects; -extern atomic_t mod_qp_timouts; -extern atomic_t qps_created; -extern atomic_t qps_destroyed; -extern atomic_t sw_qps_destroyed; -extern u32 mh_detected; -extern u32 mh_pauses_sent; -extern u32 cm_packets_sent; -extern u32 cm_packets_bounced; -extern u32 cm_packets_created; -extern u32 cm_packets_received; -extern u32 cm_packets_dropped; -extern u32 cm_packets_retrans; -extern u32 cm_listens_created; -extern u32 cm_listens_destroyed; -extern u32 cm_backlog_drops; static int nes_netdev_open(struct net_device *); static int nes_netdev_stop(struct net_device *); @@ -126,43 +101,39 @@ static void nes_netdev_tx_timeout(struct net_device *); static int nes_netdev_set_mac_address(struct net_device *, void *); static int nes_netdev_change_mtu(struct net_device *, int); -#ifdef NES_NAPI /** * nes_netdev_poll */ -static int nes_netdev_poll(struct net_device* netdev, int* budget) +static int nes_netdev_poll(struct net_device *netdev, int *budget_ptr) { struct nes_vnic *nesvnic = netdev_priv(netdev); struct nes_device *nesdev = nesvnic->nesdev; struct nes_hw_nic_cq *nescq = &nesvnic->nic_cq; - - nesvnic->budget = *budget; - nesvnic->cqes_pending = 0; - nesvnic->rx_cqes_completed = 0; - nesvnic->cqe_allocs_pending = 0; + nesvnic->budget = min(netdev->quota, *budget_ptr); + nescq->cqes_pending = 0; + nescq->rx_cqes_completed = 0; + nescq->cqe_allocs_pending = 0; + nescq->rx_pkts_indicated = 0; nes_nic_ce_handler(nesdev, nescq); + netdev->quota -= nescq->rx_pkts_indicated; + *budget_ptr -= nescq->rx_pkts_indicated; - netdev->quota -= nesvnic->rx_cqes_completed; - *budget -= nesvnic->rx_cqes_completed; - - if (0 == nesvnic->cqes_pending) { + if (nescq->cqes_pending == 0) { netif_rx_complete(netdev); /* clear out completed cqes and arm */ nes_write32(nesdev->regs+NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT | - nescq->cq_number | (nesvnic->cqe_allocs_pending << 16)); + nescq->cq_number | (nescq->cqe_allocs_pending << 16)); nes_read32(nesdev->regs+NES_CQE_ALLOC); } else { /* clear out completed cqes but don't arm */ nes_write32(nesdev->regs+NES_CQE_ALLOC, - nescq->cq_number | (nesvnic->cqe_allocs_pending << 16)); - dprintk("%s: %s: exiting with work pending\n", - nesvnic->netdev->name, __FUNCTION__); + nescq->cq_number | (nescq->cqe_allocs_pending << 16)); + nes_debug(NES_DBG_NETDEV, "%s: exiting with work pending\n", + nesvnic->netdev->name); } - - return(0 == nesvnic->cqes_pending) ? 0 : 1; + return (nescq->cqes_pending == 0) ? 0 : 1; } -#endif /** @@ -177,27 +148,25 @@ static int nes_netdev_open(struct net_device *netdev) struct nes_device *nesdev = nesvnic->nesdev; int ret; int i; - struct nes_vnic *first_nesvnic; + struct nes_vnic *first_nesvnic = NULL; u32 nic_active_bit; u32 nic_active; - - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); - dprintk("%s: netdev->destructor = %p, netdev->uninit = %p, netdev->neigh_setup = %p\n", - __FUNCTION__, netdev->destructor, netdev->uninit, netdev->neigh_setup); + struct list_head *list_pos, *list_temp; assert(nesdev != NULL); - first_nesvnic = list_entry(nesdev->nesadapter->nesvnic_list[nesdev->mac_index].next, - struct nes_vnic, list); + if (nesvnic->netdev_open == 1) + return 0; if (netif_msg_ifup(nesvnic)) printk(KERN_INFO PFX "%s: enabling interface\n", netdev->name); ret = nes_init_nic_qp(nesdev, netdev); if (ret) { - return(ret); + return ret; } + netif_carrier_off(netdev); netif_stop_queue(netdev); if ((!nesvnic->of_device_registered) && (nesvnic->rdma_enabled)) { @@ -218,9 +187,9 @@ static int nes_netdev_open(struct net_device *netdev) nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_ACTIVE); nic_active |= nic_active_bit; nes_write_indexed(nesdev, NES_IDX_NIC_ACTIVE, nic_active); - nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL); + nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ENABLE); nic_active |= nic_active_bit; - nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL, nic_active); + nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ENABLE, nic_active); nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_BROADCAST_ON); nic_active |= nic_active_bit; nes_write_indexed(nesdev, NES_IDX_NIC_BROADCAST_ON, nic_active); @@ -232,15 +201,13 @@ static int nes_netdev_open(struct net_device *netdev) macaddr_low += ((u32)netdev->dev_addr[4]) << 8; macaddr_low += (u32)netdev->dev_addr[5]; -#define NES_MAX_PORT_COUNT 4 /* Program the various MAC regs */ for (i = 0; i < NES_MAX_PORT_COUNT; i++) { if (nesvnic->qp_nic_index[i] == 0xf) { break; } - dprintk("%s: i=%d, perfect filter table index= %d, PERF FILTER LOW" + nes_debug(NES_DBG_NETDEV, "i=%d, perfect filter table index= %d, PERF FILTER LOW" " (Addr:%08X) = %08X, HIGH = %08X.\n", - __FUNCTION__, i, nesvnic->qp_nic_index[i], NES_IDX_PERFECT_FILTER_LOW+((nesvnic->perfect_filter_index + i) * 8), macaddr_low, @@ -255,30 +222,31 @@ static int nes_netdev_open(struct net_device *netdev) ((((u32)nesvnic->nic_index) << 16))); } - - if(netdev->ip_ptr) { - struct in_device *ip = netdev->ip_ptr; - struct in_ifaddr *in = NULL; - if(ip && ip->ifa_list) { - in = ip->ifa_list; - nes_manage_arp_cache(nesvnic->netdev, netdev->dev_addr, ntohl(in->ifa_address), NES_ARP_ADD); - } - } nes_write32(nesdev->regs+NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT | nesvnic->nic_cq.cq_number); nes_read32(nesdev->regs+NES_CQE_ALLOC); - + list_for_each_safe(list_pos, list_temp, &nesdev->nesadapter->nesvnic_list[nesdev->mac_index]) { + first_nesvnic = container_of(list_pos, struct nes_vnic, list); + if (first_nesvnic->netdev_open == 1) + break; + } + if (first_nesvnic->netdev_open == 0) { + nes_debug(NES_DBG_INIT, "Setting up MAC interrupt mask.\n"); + nes_write_indexed(nesdev, NES_IDX_MAC_INT_MASK + (0x200 * nesdev->mac_index), + ~(NES_MAC_INT_LINK_STAT_CHG | NES_MAC_INT_XGMII_EXT | + NES_MAC_INT_TX_UNDERFLOW | NES_MAC_INT_TX_ERROR)); + first_nesvnic = nesvnic; + } if (first_nesvnic->linkup) { /* Enable network packets */ nesvnic->linkup = 1; netif_start_queue(netdev); - } else { - netif_carrier_off(netdev); + netif_carrier_on(netdev); } nesvnic->netdev_open = 1; - return (0); + return 0; } @@ -291,19 +259,33 @@ static int nes_netdev_stop(struct net_device *netdev) struct nes_device *nesdev = nesvnic->nesdev; u32 nic_active_mask; u32 nic_active; + struct nes_vnic *first_nesvnic = NULL; + struct list_head *list_pos, *list_temp; - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); - if (0 == nesvnic->netdev_open) - return (0); + nes_debug(NES_DBG_SHUTDOWN, "nesvnic=%p, nesdev=%p, netdev=%p %s\n", + nesvnic, nesdev, netdev, netdev->name); + if (nesvnic->netdev_open == 0) + return 0; if (netif_msg_ifdown(nesvnic)) printk(KERN_INFO PFX "%s: disabling interface\n", netdev->name); /* Disable network packets */ netif_stop_queue(netdev); - if ((nesdev->netdev[0] == netdev)&(nesvnic->logical_port == nesdev->mac_index)) { - nes_write_indexed(nesdev, - NES_IDX_MAC_INT_MASK+(0x200*nesdev->mac_index), 0xffffffff); + list_for_each_safe(list_pos, list_temp, &nesdev->nesadapter->nesvnic_list[nesdev->mac_index]) { + first_nesvnic = container_of(list_pos, struct nes_vnic, list); + if ((first_nesvnic->netdev_open == 1) && (first_nesvnic != nesvnic)) + break; + } + + if (first_nesvnic->netdev_open == 0) + nes_write_indexed(nesdev, NES_IDX_MAC_INT_MASK+(0x200*nesdev->mac_index), 0xffffffff); + else if ((first_nesvnic != nesvnic) && + (PCI_FUNC(first_nesvnic->nesdev->pcidev->devfn) != PCI_FUNC(nesvnic->nesdev->pcidev->devfn))) { + nes_write_indexed(nesdev, NES_IDX_MAC_INT_MASK + (0x200 * nesdev->mac_index), 0xffffffff); + nes_write_indexed(first_nesvnic->nesdev, NES_IDX_MAC_INT_MASK + (0x200 * first_nesvnic->nesdev->mac_index), + ~(NES_MAC_INT_LINK_STAT_CHG | NES_MAC_INT_XGMII_EXT | + NES_MAC_INT_TX_UNDERFLOW | NES_MAC_INT_TX_ERROR)); } nic_active_mask = ~((u32)(1 << nesvnic->nic_index)); @@ -315,6 +297,12 @@ static int nes_netdev_stop(struct net_device *netdev) nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL); nic_active &= nic_active_mask; nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL, nic_active); + nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ENABLE); + nic_active &= nic_active_mask; + nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ENABLE, nic_active); + nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL); + nic_active &= nic_active_mask; + nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active); nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_BROADCAST_ON); nic_active &= nic_active_mask; nes_write_indexed(nesdev, NES_IDX_NIC_BROADCAST_ON, nic_active); @@ -324,14 +312,12 @@ static int nes_netdev_stop(struct net_device *netdev) nes_destroy_ofa_device(nesvnic->nesibdev); nesvnic->nesibdev = NULL; nesvnic->of_device_registered = 0; - rdma_enabled = 0; } nes_destroy_nic_qp(nesvnic); nesvnic->netdev_open = 0; - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); - return (0); + return 0; } @@ -344,64 +330,50 @@ static int nes_nic_send(struct sk_buff *skb, struct net_device *netdev) struct nes_device *nesdev = nesvnic->nesdev; struct nes_hw_nic *nesnic = &nesvnic->nic; struct nes_hw_nic_sq_wqe *nic_sqe; -#ifdef NETIF_F_TSO - struct tcphdr *pTCPHeader; - /* struct udphdr *pUDPHeader; */ -#endif - u16 *wqe_fragment_length; - u64 *wqe_fragment_address; + struct tcphdr *tcph; + __le16 *wqe_fragment_length; + u32 wqe_misc; u16 wqe_fragment_index = 1; /* first fragment (0) is used by copy buffer */ u16 skb_fragment_index; dma_addr_t bus_address; nic_sqe = &nesnic->sq_vbase[nesnic->sq_head]; - wqe_fragment_length = (u16 *)&nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_0_TAG_IDX]; + wqe_fragment_length = (__le16 *)&nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_0_TAG_IDX]; /* setup the VLAN tag if present */ if (vlan_tx_tag_present(skb)) { - dprintk("%s:%s: VLAN packet to send... VLAN = %08X\n", netdev->name, - __FUNCTION__, vlan_tx_tag_get(skb)); - nic_sqe->wqe_words[NES_NIC_SQ_WQE_MISC_IDX] = - cpu_to_le32(NES_NIC_SQ_WQE_TAGVALUE_ENABLE); - wqe_fragment_length[0] = vlan_tx_tag_get(skb); + nes_debug(NES_DBG_NIC_TX, "%s: VLAN packet to send... VLAN = %08X\n", + netdev->name, vlan_tx_tag_get(skb)); + wqe_misc = NES_NIC_SQ_WQE_TAGVALUE_ENABLE; + wqe_fragment_length[0] = (__force __le16) vlan_tx_tag_get(skb); } else - nic_sqe->wqe_words[NES_NIC_SQ_WQE_MISC_IDX] = 0; + wqe_misc = 0; /* bump past the vlan tag */ wqe_fragment_length++; - wqe_fragment_address = (u64 *)&nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX]; + /* wqe_fragment_address = (u64 *)&nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX]; */ if (skb->ip_summed == CHECKSUM_PARTIAL) { -#ifdef OFED_1_2 - pTCPHeader = skb->h.th; -#else - pTCPHeader = tcp_hdr(skb); -#endif + tcph = tcp_hdr(skb); if (1) { -#ifdef NETIF_F_TSO - if (nes_skb_lso_size(skb)) { - /* dprintk("%s:%s: TSO request... seg size = %u\n", netdev->name, - __FUNCTION__, nes_skb_lso_size(skb)); */ - nic_sqe->wqe_words[NES_NIC_SQ_WQE_MISC_IDX] |= - cpu_to_le32(NES_NIC_SQ_WQE_LSO_ENABLE | - NES_NIC_SQ_WQE_COMPLETION | (u16)nes_skb_lso_size(skb)); - nic_sqe->wqe_words[NES_NIC_SQ_WQE_LSO_INFO_IDX] = - cpu_to_le32(((u32)pTCPHeader->doff) | - (((u32)(((unsigned char *)pTCPHeader) - skb->data)) << 4)); + if (skb_is_gso(skb)) { + /* nes_debug(NES_DBG_NIC_TX, "%s: TSO request... seg size = %u\n", + netdev->name, skb_is_gso(skb)); */ + wqe_misc |= NES_NIC_SQ_WQE_LSO_ENABLE | + NES_NIC_SQ_WQE_COMPLETION | (u16)skb_is_gso(skb); + set_wqe_32bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_LSO_INFO_IDX, + ((u32)tcph->doff) | + (((u32)(((unsigned char *)tcph) - skb->data)) << 4)); } else { -#endif - nic_sqe->wqe_words[NES_NIC_SQ_WQE_MISC_IDX] |= - cpu_to_le32(NES_NIC_SQ_WQE_COMPLETION); -#ifdef NETIF_F_TSO + wqe_misc |= NES_NIC_SQ_WQE_COMPLETION; } -#endif } } else { /* CHECKSUM_HW */ - nic_sqe->wqe_words[NES_NIC_SQ_WQE_MISC_IDX] |= - cpu_to_le32(NES_NIC_SQ_WQE_DISABLE_CHKSUM | NES_NIC_SQ_WQE_COMPLETION); + wqe_misc |= NES_NIC_SQ_WQE_DISABLE_CHKSUM | NES_NIC_SQ_WQE_COMPLETION; } - nic_sqe->wqe_words[NES_NIC_SQ_WQE_TOTAL_LENGTH_IDX] = cpu_to_le32(skb->len); + set_wqe_32bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_TOTAL_LENGTH_IDX, + skb->len); memcpy(&nesnic->first_frag_vbase[nesnic->sq_head].buffer, skb->data, min(((unsigned int)NES_FIRST_FRAG_SIZE), skb_headlen(skb))); wqe_fragment_length[0] = cpu_to_le16(min(((unsigned int)NES_FIRST_FRAG_SIZE), @@ -409,18 +381,20 @@ static int nes_nic_send(struct sk_buff *skb, struct net_device *netdev) wqe_fragment_length[1] = 0; if (skb_headlen(skb) > NES_FIRST_FRAG_SIZE) { if ((skb_shinfo(skb)->nr_frags + 1) > 4) { - dprintk("%s: Packet with %u fragments not sent, skb_headlen=%u\n", + nes_debug(NES_DBG_NIC_TX, "%s: Packet with %u fragments not sent, skb_headlen=%u\n", netdev->name, skb_shinfo(skb)->nr_frags + 2, skb_headlen(skb)); kfree_skb(skb); nesvnic->tx_sw_dropped++; - return(NETDEV_TX_LOCKED); + return NETDEV_TX_LOCKED; } + set_bit(nesnic->sq_head, nesnic->first_frag_overflow); bus_address = pci_map_single(nesdev->pcidev, skb->data + NES_FIRST_FRAG_SIZE, skb_headlen(skb) - NES_FIRST_FRAG_SIZE, PCI_DMA_TODEVICE); - wqe_fragment_length[wqe_fragment_index] = + wqe_fragment_length[wqe_fragment_index++] = cpu_to_le16(skb_headlen(skb) - NES_FIRST_FRAG_SIZE); - wqe_fragment_length[wqe_fragment_index + 1] = 0; - wqe_fragment_address[wqe_fragment_index++] = cpu_to_le64(bus_address); + wqe_fragment_length[wqe_fragment_index] = 0; + set_wqe_64bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_FRAG1_LOW_IDX, + ((u64)(bus_address))); nesnic->tx_skb[nesnic->sq_head] = skb; } @@ -442,16 +416,19 @@ static int nes_nic_send(struct sk_buff *skb, struct net_device *netdev) PCI_DMA_TODEVICE); wqe_fragment_length[wqe_fragment_index] = cpu_to_le16(skb_shinfo(skb)->frags[skb_fragment_index].size); - wqe_fragment_address[wqe_fragment_index++] = cpu_to_le64(bus_address); + set_wqe_64bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_LOW_IDX+(2*wqe_fragment_index), + bus_address); + wqe_fragment_index++; if (wqe_fragment_index < 5) wqe_fragment_length[wqe_fragment_index] = 0; } } + set_wqe_32bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_MISC_IDX, wqe_misc); nesnic->sq_head++; nesnic->sq_head &= nesnic->sq_size - 1; - return(NETDEV_TX_OK); + return NETDEV_TX_OK; } @@ -464,75 +441,102 @@ static int nes_netdev_start_xmit(struct sk_buff *skb, struct net_device *netdev) struct nes_device *nesdev = nesvnic->nesdev; struct nes_hw_nic *nesnic = &nesvnic->nic; struct nes_hw_nic_sq_wqe *nic_sqe; -#ifdef NETIF_F_TSO - struct tcphdr *pTCPHeader; - /* struct udphdr *pUDPHeader; */ + struct tcphdr *tcph; + /* struct udphdr *udph; */ #define NES_MAX_TSO_FRAGS 18 /* 64K segment plus overflow on each side */ dma_addr_t tso_bus_address[NES_MAX_TSO_FRAGS]; + dma_addr_t bus_address; u32 tso_frag_index; u32 tso_frag_count; u32 tso_wqe_length; u32 curr_tcp_seq; -#endif u32 wqe_count=1; u32 send_rc; - struct iphdr *pIPHeader; + struct iphdr *iph; unsigned long flags; - u16 *wqe_fragment_length; - u64 *wqe_fragment_address; + __le16 *wqe_fragment_length; + u32 nr_frags; + u32 original_first_length; +// u64 *wqe_fragment_address; /* first fragment (0) is used by copy buffer */ u16 wqe_fragment_index=1; u16 hoffset; u16 nhoffset; -#ifdef NETIF_F_TSO u16 wqes_needed; u16 wqes_available; -#endif u32 old_head; + u32 wqe_misc; + + /* nes_debug(NES_DBG_NIC_TX, "%s Request to tx NIC packet length %u, headlen %u," + " (%u frags), tso_size=%u\n", + netdev->name, skb->len, skb_headlen(skb), + skb_shinfo(skb)->nr_frags, skb_is_gso(skb)); + */ + + if (!netif_carrier_ok(netdev)) + return NETDEV_TX_OK; + + if (netif_queue_stopped(netdev)) + return NETDEV_TX_BUSY; - if (nes_debug_level & NES_DBG_TX) { - dprintk("%s: %s Request to tx NIC packet length %u, headlen %u," - " (%u frags), tso_size=%u\n", - __FUNCTION__, netdev->name, skb->len, skb_headlen(skb), - skb_shinfo(skb)->nr_frags, nes_skb_lso_size(skb)); - } local_irq_save(flags); if (!spin_trylock(&nesnic->sq_lock)) { local_irq_restore(flags); nesvnic->sq_locked++; - return (NETDEV_TX_LOCKED); + return NETDEV_TX_LOCKED; } /* Check if SQ is full */ if ((((nesnic->sq_tail+(nesnic->sq_size*2))-nesnic->sq_head) & (nesnic->sq_size - 1)) == 1) { - netif_stop_queue(netdev); - spin_unlock_irqrestore(&nesnic->sq_lock, flags); + if (!netif_queue_stopped(netdev)) { + netif_stop_queue(netdev); + barrier(); + if ((((((volatile u16)nesnic->sq_tail)+(nesnic->sq_size*2))-nesnic->sq_head) & (nesnic->sq_size - 1)) != 1) { + netif_start_queue(netdev); + goto sq_no_longer_full; + } + } nesvnic->sq_full++; - return (NETDEV_TX_BUSY); + spin_unlock_irqrestore(&nesnic->sq_lock, flags); + return NETDEV_TX_BUSY; } +sq_no_longer_full: + nr_frags = skb_shinfo(skb)->nr_frags; + if (skb_headlen(skb) > NES_FIRST_FRAG_SIZE) { + nr_frags++; + } /* Check if too many fragments */ - if (unlikely((skb_shinfo(skb)->nr_frags) > 4)) { -#ifdef NETIF_F_TSO - if (nes_skb_lso_size(skb) && (skb_headlen(skb) <= NES_FIRST_FRAG_SIZE)) { + if (unlikely((nr_frags > 4))) { + if (skb_is_gso(skb)) { nesvnic->segmented_tso_requests++; nesvnic->tso_requests++; old_head = nesnic->sq_head; /* Basically 4 fragments available per WQE with extended fragments */ - wqes_needed = skb_shinfo(skb)->nr_frags >> 2; - wqes_needed += (skb_shinfo(skb)->nr_frags&3)?1:0; + wqes_needed = nr_frags >> 2; + wqes_needed += (nr_frags&3)?1:0; wqes_available = (((nesnic->sq_tail+nesnic->sq_size)-nesnic->sq_head) - 1) & (nesnic->sq_size - 1); if (unlikely(wqes_needed > wqes_available)) { - netif_stop_queue(netdev); + if (!netif_queue_stopped(netdev)) { + netif_stop_queue(netdev); + barrier(); + wqes_available = (((((volatile u16)nesnic->sq_tail)+nesnic->sq_size)-nesnic->sq_head) - 1) & + (nesnic->sq_size - 1); + if (wqes_needed <= wqes_available) { + netif_start_queue(netdev); + goto tso_sq_no_longer_full; + } + } + nesvnic->sq_full++; spin_unlock_irqrestore(&nesnic->sq_lock, flags); - dprintk("%s: HNIC SQ full- TSO request has too many frags!\n", + nes_debug(NES_DBG_NIC_TX, "%s: HNIC SQ full- TSO request has too many frags!\n", netdev->name); - nesvnic->sq_full++; - return (NETDEV_TX_BUSY); + return NETDEV_TX_BUSY; } +tso_sq_no_longer_full: /* Map all the buffers */ for (tso_frag_count=0; tso_frag_count < skb_shinfo(skb)->nr_frags; tso_frag_count++) { @@ -544,74 +548,75 @@ static int nes_netdev_start_xmit(struct sk_buff *skb, struct net_device *netdev) } tso_frag_index = 0; -#ifdef OFED_1_2 - curr_tcp_seq = ntohl(skb->h.th->seq); -#else curr_tcp_seq = ntohl(tcp_hdr(skb)->seq); -#endif -#ifdef OFED_1_2 - hoffset = skb->h.raw - skb->data; - nhoffset = skb->nh.raw - skb->data; -#else hoffset = skb_transport_header(skb) - skb->data; nhoffset = skb_network_header(skb) - skb->data; -#endif + original_first_length = hoffset + ((((struct tcphdr *)skb_transport_header(skb))->doff)<<2); for (wqe_count=0; wqe_count<((u32)wqes_needed); wqe_count++) { tso_wqe_length = 0; nic_sqe = &nesnic->sq_vbase[nesnic->sq_head]; wqe_fragment_length = - (u16 *)&nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_0_TAG_IDX]; + (__le16 *)&nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_0_TAG_IDX]; /* setup the VLAN tag if present */ if (vlan_tx_tag_present(skb)) { - dprintk("%s:%s: VLAN packet to send... VLAN = %08X\n", - netdev->name, __FUNCTION__, vlan_tx_tag_get(skb) ); - nic_sqe->wqe_words[NES_NIC_SQ_WQE_MISC_IDX] = - cpu_to_le32(NES_NIC_SQ_WQE_TAGVALUE_ENABLE); - wqe_fragment_length[0] = vlan_tx_tag_get(skb); + nes_debug(NES_DBG_NIC_TX, "%s: VLAN packet to send... VLAN = %08X\n", + netdev->name, vlan_tx_tag_get(skb) ); + wqe_misc = NES_NIC_SQ_WQE_TAGVALUE_ENABLE; + wqe_fragment_length[0] = (__force __le16) vlan_tx_tag_get(skb); } else - nic_sqe->wqe_words[NES_NIC_SQ_WQE_MISC_IDX] = 0; + wqe_misc = 0; /* bump past the vlan tag */ wqe_fragment_length++; - wqe_fragment_address = - (u64 *)&nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX]; /* Assumes header totally fits in allocated buffer and is in first fragment */ - if (skb_headlen(skb) > NES_FIRST_FRAG_SIZE) { - dprintk("ERROR: SKB header too big, skb_headlen=%u, FIRST_FRAG_SIZE=%u\n", - skb_headlen(skb), NES_FIRST_FRAG_SIZE); - dprintk("%s: %s Request to tx NIC packet length %u, headlen %u," + if (original_first_length > NES_FIRST_FRAG_SIZE) { + nes_debug(NES_DBG_NIC_TX, "ERROR: SKB header too big, headlen=%u, FIRST_FRAG_SIZE=%u\n", + original_first_length, NES_FIRST_FRAG_SIZE); + nes_debug(NES_DBG_NIC_TX, "%s Request to tx NIC packet length %u, headlen %u," " (%u frags), tso_size=%u\n", - __FUNCTION__, netdev->name, + netdev->name, skb->len, skb_headlen(skb), - skb_shinfo(skb)->nr_frags, nes_skb_lso_size(skb)); + skb_shinfo(skb)->nr_frags, skb_is_gso(skb)); } memcpy(&nesnic->first_frag_vbase[nesnic->sq_head].buffer, skb->data, min(((unsigned int)NES_FIRST_FRAG_SIZE), - skb_headlen(skb))); - pIPHeader = (struct iphdr *) - (&nesnic->first_frag_vbase[nesnic->sq_head].buffer[nhoffset]); - pTCPHeader = (struct tcphdr *) - (&nesnic->first_frag_vbase[nesnic->sq_head].buffer[hoffset]); + original_first_length)); + iph = (struct iphdr *) + (&nesnic->first_frag_vbase[nesnic->sq_head].buffer[nhoffset]); + tcph = (struct tcphdr *) + (&nesnic->first_frag_vbase[nesnic->sq_head].buffer[hoffset]); if ((wqe_count+1)!=(u32)wqes_needed) { - pTCPHeader->fin = 0; - pTCPHeader->psh = 0; - pTCPHeader->rst = 0; - pTCPHeader->urg = 0; + tcph->fin = 0; + tcph->psh = 0; + tcph->rst = 0; + tcph->urg = 0; } if (wqe_count) { - pTCPHeader->syn = 0; + tcph->syn = 0; } - pTCPHeader->seq = htonl(curr_tcp_seq); + tcph->seq = htonl(curr_tcp_seq); wqe_fragment_length[0] = cpu_to_le16(min(((unsigned int)NES_FIRST_FRAG_SIZE), - skb_headlen(skb))); - - for (wqe_fragment_index = 1; wqe_fragment_index < 5;) { + original_first_length)); + + wqe_fragment_index = 1; + if ((wqe_count==0) && (skb_headlen(skb) > original_first_length)) { + set_bit(nesnic->sq_head, nesnic->first_frag_overflow); + bus_address = pci_map_single(nesdev->pcidev, skb->data + original_first_length, + skb_headlen(skb) - original_first_length, PCI_DMA_TODEVICE); + wqe_fragment_length[wqe_fragment_index++] = + cpu_to_le16(skb_headlen(skb) - original_first_length); + wqe_fragment_length[wqe_fragment_index] = 0; + set_wqe_64bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_FRAG1_LOW_IDX, + bus_address); + } + while (wqe_fragment_index < 5) { wqe_fragment_length[wqe_fragment_index] = cpu_to_le16(skb_shinfo(skb)->frags[tso_frag_index].size); - wqe_fragment_address[wqe_fragment_index++] = - cpu_to_le64(tso_bus_address[tso_frag_index]); + set_wqe_64bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_LOW_IDX+(2*wqe_fragment_index), + (u64)tso_bus_address[tso_frag_index]); + wqe_fragment_index++; tso_wqe_length += skb_shinfo(skb)->frags[tso_frag_index++].size; if (wqe_fragment_index < 5) wqe_fragment_length[wqe_fragment_index] = 0; @@ -623,54 +628,42 @@ static int nes_netdev_start_xmit(struct sk_buff *skb, struct net_device *netdev) } else { nesnic->tx_skb[nesnic->sq_head] = NULL; } - nic_sqe->wqe_words[NES_NIC_SQ_WQE_MISC_IDX] |= - cpu_to_le32(NES_NIC_SQ_WQE_COMPLETION | (u16)nes_skb_lso_size(skb)); - if ((tso_wqe_length + skb_headlen(skb)) > nes_skb_lso_size(skb)) { - nic_sqe->wqe_words[NES_NIC_SQ_WQE_MISC_IDX] |= cpu_to_le32(NES_NIC_SQ_WQE_LSO_ENABLE); + wqe_misc |= NES_NIC_SQ_WQE_COMPLETION | (u16)skb_is_gso(skb); + if ((tso_wqe_length + original_first_length) > skb_is_gso(skb)) { + wqe_misc |= NES_NIC_SQ_WQE_LSO_ENABLE; } else { - pIPHeader->tot_len = htons(tso_wqe_length + skb_headlen(skb) - nhoffset); + iph->tot_len = htons(tso_wqe_length + original_first_length - nhoffset); } - nic_sqe->wqe_words[NES_NIC_SQ_WQE_LSO_INFO_IDX] = - cpu_to_le32(((u32)pTCPHeader->doff) | (((u32)hoffset) << 4)); + set_wqe_32bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_MISC_IDX, + wqe_misc); + set_wqe_32bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_LSO_INFO_IDX, + ((u32)tcph->doff) | (((u32)hoffset) << 4)); - nic_sqe->wqe_words[NES_NIC_SQ_WQE_TOTAL_LENGTH_IDX] = - cpu_to_le32(tso_wqe_length+skb_headlen(skb)); + set_wqe_32bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_TOTAL_LENGTH_IDX, + tso_wqe_length + original_first_length); curr_tcp_seq += tso_wqe_length; nesnic->sq_head++; nesnic->sq_head &= nesnic->sq_size-1; } } else { -#endif nesvnic->linearized_skbs++; -#ifdef OFED_1_2 - hoffset = skb->h.raw - skb->data; - nhoffset = skb->nh.raw - skb->data; -#else hoffset = skb_transport_header(skb) - skb->data; nhoffset = skb_network_header(skb) - skb->data; -#endif - nes_skb_linearize(skb, GFP_ATOMIC); -#ifdef OFED_1_2 - skb->h.raw = skb->data + hoffset; - skb->nh.raw = skb->data + nhoffset; -#else + skb_linearize(skb); skb_set_transport_header(skb, hoffset); skb_set_network_header(skb, nhoffset); -#endif send_rc = nes_nic_send(skb, netdev); if (send_rc != NETDEV_TX_OK) { spin_unlock_irqrestore(&nesnic->sq_lock, flags); - return (NETDEV_TX_OK); + return NETDEV_TX_OK; } -#ifdef NETIF_F_TSO } -#endif } else { send_rc = nes_nic_send(skb, netdev); if (send_rc != NETDEV_TX_OK) { spin_unlock_irqrestore(&nesnic->sq_lock, flags); - return (NETDEV_TX_OK); + return NETDEV_TX_OK; } } @@ -683,7 +676,7 @@ static int nes_netdev_start_xmit(struct sk_buff *skb, struct net_device *netdev) netdev->trans_start = jiffies; spin_unlock_irqrestore(&nesnic->sq_lock, flags); - return(NETDEV_TX_OK); + return NETDEV_TX_OK; } @@ -774,7 +767,7 @@ static struct net_device_stats *nes_netdev_get_stats(struct net_device *netdev) nesvnic->nesdev->mac_tx_errors += u32temp; nesvnic->netstats.tx_errors += u32temp; - return(&nesvnic->netstats); + return &nesvnic->netstats; } @@ -786,7 +779,7 @@ static void nes_netdev_tx_timeout(struct net_device *netdev) struct nes_vnic *nesvnic = netdev_priv(netdev); if (netif_msg_timer(nesvnic)) - dprintk(KERN_DEBUG PFX "%s: tx timeout\n", netdev->name); + nes_debug(NES_DBG_NIC_TX, "%s: tx timeout\n", netdev->name); } @@ -795,30 +788,161 @@ static void nes_netdev_tx_timeout(struct net_device *netdev) */ static int nes_netdev_set_mac_address(struct net_device *netdev, void *p) { - return (-1); + struct nes_vnic *nesvnic = netdev_priv(netdev); + struct nes_device *nesdev = nesvnic->nesdev; + struct sockaddr *mac_addr = p; + int i; + u32 macaddr_low; + u16 macaddr_high; + + if (!is_valid_ether_addr(mac_addr->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(netdev->dev_addr, mac_addr->sa_data, netdev->addr_len); + printk(PFX "%s: Address length = %d, Address = %02X%02X%02X%02X%02X%02X..\n", + __FUNCTION__, netdev->addr_len, + mac_addr->sa_data[0], mac_addr->sa_data[1], + mac_addr->sa_data[2], mac_addr->sa_data[3], + mac_addr->sa_data[4], mac_addr->sa_data[5]); + macaddr_high = ((u16)netdev->dev_addr[0]) << 8; + macaddr_high += (u16)netdev->dev_addr[1]; + macaddr_low = ((u32)netdev->dev_addr[2]) << 24; + macaddr_low += ((u32)netdev->dev_addr[3]) << 16; + macaddr_low += ((u32)netdev->dev_addr[4]) << 8; + macaddr_low += (u32)netdev->dev_addr[5]; + + for (i = 0; i < NES_MAX_PORT_COUNT; i++) { + if (nesvnic->qp_nic_index[i] == 0xf) { + break; + } + nes_write_indexed(nesdev, + NES_IDX_PERFECT_FILTER_LOW + (nesvnic->qp_nic_index[i] * 8), + macaddr_low); + nes_write_indexed(nesdev, + NES_IDX_PERFECT_FILTER_HIGH + (nesvnic->qp_nic_index[i] * 8), + (u32)macaddr_high | NES_MAC_ADDR_VALID | + ((((u32)nesvnic->nic_index) << 16))); + } + return 0; } /** - * nes_netdev_change_mtu + * nes_netdev_set_multicast_list */ -static int nes_netdev_change_mtu(struct net_device *netdev, int new_mtu) +void nes_netdev_set_multicast_list(struct net_device *netdev) { struct nes_vnic *nesvnic = netdev_priv(netdev); - int ret = 0; + struct nes_device *nesdev = nesvnic->nesdev; + struct dev_mc_list *multicast_addr; + u32 nic_active_bit; + u32 nic_active; + u32 perfect_filter_register_address; + u32 macaddr_low; + u16 macaddr_high; + u8 mc_all_on = 0; + u8 mc_index; + int mc_nic_index = -1; + + nic_active_bit = 1 << nesvnic->nic_index; + + if (netdev->flags & IFF_PROMISC) { + nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL); + nic_active |= nic_active_bit; + nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL, nic_active); + nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL); + nic_active |= nic_active_bit; + nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active); + mc_all_on = 1; + } else if ((netdev->flags & IFF_ALLMULTI) || (netdev->mc_count > NES_MULTICAST_PF_MAX) || + (nesvnic->nic_index > 3)) { + nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL); + nic_active |= nic_active_bit; + nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL, nic_active); + nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL); + nic_active &= ~nic_active_bit; + nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active); + mc_all_on = 1; + } else { + nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL); + nic_active &= ~nic_active_bit; + nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL, nic_active); + nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL); + nic_active &= ~nic_active_bit; + nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active); + } - if ((new_mtu < ETH_ZLEN) || (new_mtu > max_mtu)) - return (-EINVAL); + nes_debug(NES_DBG_NIC_RX, "Number of MC entries = %d, Promiscous = %d, All Multicast = %d.\n", + netdev->mc_count, (netdev->flags & IFF_PROMISC)?1:0, + (netdev->flags & IFF_ALLMULTI)?1:0); + if (!mc_all_on) { + multicast_addr = netdev->mc_list; + perfect_filter_register_address = NES_IDX_PERFECT_FILTER_LOW + 0x80; + perfect_filter_register_address += nesvnic->nic_index*0x40; + for (mc_index=0; mc_index < NES_MULTICAST_PF_MAX; mc_index++) { + while (multicast_addr && nesvnic->mcrq_mcast_filter && ((mc_nic_index = nesvnic->mcrq_mcast_filter(nesvnic, multicast_addr->dmi_addr)) == 0)) + multicast_addr = multicast_addr->next; + if (mc_nic_index < 0) + mc_nic_index = nesvnic->nic_index; + if (multicast_addr) { + nes_debug(NES_DBG_NIC_RX, "Assigning MC Address = %02X%02X%02X%02X%02X%02X to register 0x%04X nic_idx=%d\n", + multicast_addr->dmi_addr[0], multicast_addr->dmi_addr[1], + multicast_addr->dmi_addr[2], multicast_addr->dmi_addr[3], + multicast_addr->dmi_addr[4], multicast_addr->dmi_addr[5], + perfect_filter_register_address+(mc_index * 8), mc_nic_index); + macaddr_high = ((u16)multicast_addr->dmi_addr[0]) << 8; + macaddr_high += (u16)multicast_addr->dmi_addr[1]; + macaddr_low = ((u32)multicast_addr->dmi_addr[2]) << 24; + macaddr_low += ((u32)multicast_addr->dmi_addr[3]) << 16; + macaddr_low += ((u32)multicast_addr->dmi_addr[4]) << 8; + macaddr_low += (u32)multicast_addr->dmi_addr[5]; + nes_write_indexed(nesdev, + perfect_filter_register_address+(mc_index * 8), + macaddr_low); + nes_write_indexed(nesdev, + perfect_filter_register_address+4+(mc_index * 8), + (u32)macaddr_high | NES_MAC_ADDR_VALID | + ((((u32)(1<<mc_nic_index)) << 16))); + multicast_addr = multicast_addr->next; + } else { + nes_debug(NES_DBG_NIC_RX, "Clearing MC Address at register 0x%04X\n", + perfect_filter_register_address+(mc_index * 8)); + nes_write_indexed(nesdev, + perfect_filter_register_address+4+(mc_index * 8), + 0); + } + } + } +} + + +/** + * nes_netdev_change_mtu + */ +static int nes_netdev_change_mtu(struct net_device *netdev, int new_mtu) +{ + struct nes_vnic *nesvnic = netdev_priv(netdev); + struct nes_device *nesdev = nesvnic->nesdev; + int ret = 0; + u8 jumbomode=0; + + if ((new_mtu < ETH_ZLEN) || (new_mtu > max_mtu)) + return -EINVAL; - netdev->mtu = new_mtu; - nesvnic->max_frame_size = new_mtu+ETH_HLEN; + netdev->mtu = new_mtu; + nesvnic->max_frame_size = new_mtu + VLAN_ETH_HLEN; + + if (netdev->mtu > 1500) { + jumbomode=1; + } + nes_nic_init_timer_defaults(nesdev, jumbomode); if (netif_running(netdev)) { nes_netdev_stop(netdev); nes_netdev_open(netdev); } - return (ret); + return ret; } @@ -829,21 +953,21 @@ void nes_netdev_exit(struct nes_vnic *nesvnic) { struct net_device *netdev = nesvnic->netdev; struct nes_ib_device *nesibdev = nesvnic->nesibdev; - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); + + nes_debug(NES_DBG_SHUTDOWN, "\n"); // destroy the ibdevice if RDMA enabled if ((nesvnic->rdma_enabled)&&(nesvnic->of_device_registered)) { nes_destroy_ofa_device( nesibdev ); nesvnic->of_device_registered = 0; - rdma_enabled = 0; nesvnic->nesibdev = NULL; } unregister_netdev(netdev); - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); + nes_debug(NES_DBG_SHUTDOWN, "\n"); } -#define NES_ETHTOOL_STAT_COUNT 42 +#define NES_ETHTOOL_STAT_COUNT 55 static const char nes_ethtool_stringset[NES_ETHTOOL_STAT_COUNT][ETH_GSTRING_LEN] = { "Link Change Interrupts", "Linearized SKBs", @@ -887,6 +1011,19 @@ static const char nes_ethtool_stringset[NES_ETHTOOL_STAT_COUNT][ETH_GSTRING_LEN] "CM Listens Created", "CM Listens Destroyed", "CM Backlog Drops", + "CM Loopbacks", + "CM Nodes Created", + "CM Nodes Destroyed", + "CM Accel Drops", + "CM Resets Received", + "Timer Inits", + "CQ Depth 1", + "CQ Depth 4", + "CQ Depth 16", + "CQ Depth 24", + "CQ Depth 32", + "CQ Depth 128", + "CQ Depth 256", }; @@ -898,9 +1035,9 @@ static u32 nes_netdev_get_rx_csum (struct net_device *netdev) struct nes_vnic *nesvnic = netdev_priv(netdev); if (nesvnic->rx_checksum_disabled) - return (0); + return 0; else - return (1); + return 1; } @@ -915,7 +1052,7 @@ static int nes_netdev_set_rx_csum(struct net_device *netdev, u32 enable) nesvnic->rx_checksum_disabled = 0; else nesvnic->rx_checksum_disabled = 1; - return (0); + return 0; } @@ -924,7 +1061,7 @@ static int nes_netdev_set_rx_csum(struct net_device *netdev, u32 enable) */ static int nes_netdev_get_stats_count(struct net_device *netdev) { - return (NES_ETHTOOL_STAT_COUNT); + return NES_ETHTOOL_STAT_COUNT; } @@ -936,8 +1073,8 @@ static void nes_netdev_get_strings(struct net_device *netdev, u32 stringset, { if (stringset == ETH_SS_STATS) memcpy(ethtool_strings, - &nes_ethtool_stringset, - sizeof(nes_ethtool_stringset)); + &nes_ethtool_stringset, + sizeof(nes_ethtool_stringset)); } @@ -967,6 +1104,16 @@ static void nes_netdev_get_ethtool_stats(struct net_device *netdev, NES_IDX_MAC_RX_PAUSE_FRAMES + (nesvnic->nesdev->mac_index*0x200)); nesvnic->nesdev->mac_pause_frames_received += u32temp; + u32temp = nes_read_indexed(nesdev, + NES_IDX_PORT_RX_DISCARDS + (nesvnic->nesdev->mac_index*0x40)); + nesvnic->nesdev->port_rx_discards += u32temp; + nesvnic->netstats.rx_dropped += u32temp; + + u32temp = nes_read_indexed(nesdev, + NES_IDX_PORT_TX_DISCARDS + (nesvnic->nesdev->mac_index*0x40)); + nesvnic->nesdev->port_tx_discards += u32temp; + nesvnic->netstats.tx_dropped += u32temp; + for (nic_count = 0; nic_count < NES_MAX_PORT_COUNT; nic_count++) { if (nesvnic->qp_nic_index[nic_count] == 0xf) break; @@ -1060,6 +1207,19 @@ static void nes_netdev_get_ethtool_stats(struct net_device *netdev, target_stat_values[39] = cm_listens_created; target_stat_values[40] = cm_listens_destroyed; target_stat_values[41] = cm_backlog_drops; + target_stat_values[42] = atomic_read(&cm_loopbacks); + target_stat_values[43] = atomic_read(&cm_nodes_created); + target_stat_values[44] = atomic_read(&cm_nodes_destroyed); + target_stat_values[45] = atomic_read(&cm_accel_dropped_pkts); + target_stat_values[46] = atomic_read(&cm_resets_recvd); + target_stat_values[47] = int_mod_timer_init; + target_stat_values[48] = int_mod_cq_depth_1; + target_stat_values[49] = int_mod_cq_depth_4; + target_stat_values[50] = int_mod_cq_depth_16; + target_stat_values[51] = int_mod_cq_depth_24; + target_stat_values[52] = int_mod_cq_depth_32; + target_stat_values[53] = int_mod_cq_depth_128; + target_stat_values[54] = int_mod_cq_depth_256; } @@ -1067,7 +1227,7 @@ static void nes_netdev_get_ethtool_stats(struct net_device *netdev, /** * nes_netdev_get_drvinfo */ -void nes_netdev_get_drvinfo(struct net_device *netdev, +static void nes_netdev_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) { struct nes_vnic *nesvnic = netdev_priv(netdev); @@ -1087,18 +1247,50 @@ void nes_netdev_get_drvinfo(struct net_device *netdev, * nes_netdev_set_coalesce */ static int nes_netdev_set_coalesce(struct net_device *netdev, - struct ethtool_coalesce *et_coalesce) + struct ethtool_coalesce *et_coalesce) { - struct nes_vnic *nesvnic = netdev_priv(netdev); - struct nes_device *nesdev = nesvnic->nesdev; + struct nes_vnic *nesvnic = netdev_priv(netdev); + struct nes_device *nesdev = nesvnic->nesdev; + struct nes_adapter *nesadapter = nesdev->nesadapter; + struct nes_hw_tune_timer *shared_timer = &nesadapter->tune_timer; + unsigned long flags; + + spin_lock_irqsave(&nesadapter->periodic_timer_lock, flags); + if (et_coalesce->rx_max_coalesced_frames_low) { + shared_timer->threshold_low = et_coalesce->rx_max_coalesced_frames_low; + } + if (et_coalesce->rx_max_coalesced_frames_irq) { + shared_timer->threshold_target = et_coalesce->rx_max_coalesced_frames_irq; + } + if (et_coalesce->rx_max_coalesced_frames_high) { + shared_timer->threshold_high = et_coalesce->rx_max_coalesced_frames_high; + } + if (et_coalesce->rx_coalesce_usecs_low) { + shared_timer->timer_in_use_min = et_coalesce->rx_coalesce_usecs_low; + } + if (et_coalesce->rx_coalesce_usecs_high) { + shared_timer->timer_in_use_max = et_coalesce->rx_coalesce_usecs_high; + } + spin_unlock_irqrestore(&nesadapter->periodic_timer_lock, flags); /* using this to drive total interrupt moderation */ - nesvnic->nesdev->et_rx_coalesce_usecs_irq = et_coalesce->rx_coalesce_usecs_irq; - if (nesdev->et_rx_coalesce_usecs_irq) { - nes_write32(nesdev->regs+NES_PERIODIC_CONTROL, - 0x80000000 | ((u32)(nesdev->et_rx_coalesce_usecs_irq*8))); + nesadapter->et_rx_coalesce_usecs_irq = et_coalesce->rx_coalesce_usecs_irq; + if (et_coalesce->use_adaptive_rx_coalesce) { + nesadapter->et_use_adaptive_rx_coalesce = 1; + nesadapter->timer_int_limit = NES_TIMER_INT_LIMIT_DYNAMIC; + nesadapter->et_rx_coalesce_usecs_irq = 0; + if (et_coalesce->pkt_rate_low) { + nesadapter->et_pkt_rate_low = et_coalesce->pkt_rate_low; + } + } else { + nesadapter->et_use_adaptive_rx_coalesce = 0; + nesadapter->timer_int_limit = NES_TIMER_INT_LIMIT; + if (nesadapter->et_rx_coalesce_usecs_irq) { + nes_write32(nesdev->regs+NES_PERIODIC_CONTROL, + 0x80000000 | ((u32)(nesadapter->et_rx_coalesce_usecs_irq*8))); + } } - return (0); + return 0; } @@ -1106,36 +1298,53 @@ static int nes_netdev_set_coalesce(struct net_device *netdev, * nes_netdev_get_coalesce */ static int nes_netdev_get_coalesce(struct net_device *netdev, - struct ethtool_coalesce *et_coalesce) + struct ethtool_coalesce *et_coalesce) { - struct nes_vnic *nesvnic = netdev_priv(netdev); - struct ethtool_coalesce temp_et_coalesce; + struct nes_vnic *nesvnic = netdev_priv(netdev); + struct nes_device *nesdev = nesvnic->nesdev; + struct nes_adapter *nesadapter = nesdev->nesadapter; + struct ethtool_coalesce temp_et_coalesce; + struct nes_hw_tune_timer *shared_timer = &nesadapter->tune_timer; + unsigned long flags; memset(&temp_et_coalesce, 0, sizeof(temp_et_coalesce)); - temp_et_coalesce.rx_coalesce_usecs_irq = nesvnic->nesdev->et_rx_coalesce_usecs_irq; - memcpy(et_coalesce, &temp_et_coalesce, sizeof(*et_coalesce)); - return (0); + temp_et_coalesce.rx_coalesce_usecs_irq = nesadapter->et_rx_coalesce_usecs_irq; + temp_et_coalesce.use_adaptive_rx_coalesce = nesadapter->et_use_adaptive_rx_coalesce; + temp_et_coalesce.rate_sample_interval = nesadapter->et_rate_sample_interval; + temp_et_coalesce.pkt_rate_low = nesadapter->et_pkt_rate_low; + spin_lock_irqsave(&nesadapter->periodic_timer_lock, flags); + temp_et_coalesce.rx_max_coalesced_frames_low = shared_timer->threshold_low; + temp_et_coalesce.rx_max_coalesced_frames_irq = shared_timer->threshold_target; + temp_et_coalesce.rx_max_coalesced_frames_high = shared_timer->threshold_high; + temp_et_coalesce.rx_coalesce_usecs_low = shared_timer->timer_in_use_min; + temp_et_coalesce.rx_coalesce_usecs_high = shared_timer->timer_in_use_max; + if (nesadapter->et_use_adaptive_rx_coalesce) { + temp_et_coalesce.rx_coalesce_usecs_irq = shared_timer->timer_in_use; + } + spin_unlock_irqrestore(&nesadapter->periodic_timer_lock, flags); + memcpy(et_coalesce, &temp_et_coalesce, sizeof(*et_coalesce)); + return 0; } /** * nes_netdev_get_pauseparam */ -void nes_netdev_get_pauseparam(struct net_device *netdev, +static void nes_netdev_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *et_pauseparam) { struct nes_vnic *nesvnic = netdev_priv(netdev); et_pauseparam->autoneg = 0; - et_pauseparam->rx_pause = (nesvnic->nesdev->disable_rx_flow_control==0)?1:0; - et_pauseparam->tx_pause = (nesvnic->nesdev->disable_tx_flow_control==0)?1:0; + et_pauseparam->rx_pause = (nesvnic->nesdev->disable_rx_flow_control == 0) ? 1:0; + et_pauseparam->tx_pause = (nesvnic->nesdev->disable_tx_flow_control == 0) ? 1:0; } /** * nes_netdev_set_pauseparam */ -int nes_netdev_set_pauseparam(struct net_device *netdev, +static int nes_netdev_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *et_pauseparam) { struct nes_vnic *nesvnic = netdev_priv(netdev); @@ -1144,16 +1353,16 @@ int nes_netdev_set_pauseparam(struct net_device *netdev, if (et_pauseparam->autoneg) { /* TODO: should return unsupported */ - return (0); + return 0; } - if ((et_pauseparam->tx_pause==1) && (nesdev->disable_tx_flow_control==1)) { + if ((et_pauseparam->tx_pause == 1) && (nesdev->disable_tx_flow_control == 1)) { u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONFIG + (nesdev->mac_index*0x200)); u32temp |= NES_IDX_MAC_TX_CONFIG_ENABLE_PAUSE; nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG_ENABLE_PAUSE + (nesdev->mac_index*0x200), u32temp); nesdev->disable_tx_flow_control = 0; - } else if ((et_pauseparam->tx_pause==0) && (nesdev->disable_tx_flow_control==0)) { + } else if ((et_pauseparam->tx_pause == 0) && (nesdev->disable_tx_flow_control == 0)) { u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONFIG + (nesdev->mac_index*0x200)); u32temp &= ~NES_IDX_MAC_TX_CONFIG_ENABLE_PAUSE; @@ -1161,14 +1370,14 @@ int nes_netdev_set_pauseparam(struct net_device *netdev, NES_IDX_MAC_TX_CONFIG_ENABLE_PAUSE + (nesdev->mac_index*0x200), u32temp); nesdev->disable_tx_flow_control = 1; } - if ((et_pauseparam->rx_pause==1) && (nesdev->disable_rx_flow_control==1)) { + if ((et_pauseparam->rx_pause == 1) && (nesdev->disable_rx_flow_control == 1)) { u32temp = nes_read_indexed(nesdev, NES_IDX_MPP_DEBUG + (nesdev->mac_index*0x40)); u32temp &= ~NES_IDX_MPP_DEBUG_PORT_DISABLE_PAUSE; nes_write_indexed(nesdev, NES_IDX_MPP_DEBUG + (nesdev->mac_index*0x40), u32temp); nesdev->disable_rx_flow_control = 0; - } else if ((et_pauseparam->rx_pause==0) && (nesdev->disable_rx_flow_control==0)) { + } else if ((et_pauseparam->rx_pause == 0) && (nesdev->disable_rx_flow_control == 0)) { u32temp = nes_read_indexed(nesdev, NES_IDX_MPP_DEBUG + (nesdev->mac_index*0x40)); u32temp |= NES_IDX_MPP_DEBUG_PORT_DISABLE_PAUSE; @@ -1177,14 +1386,14 @@ int nes_netdev_set_pauseparam(struct net_device *netdev, nesdev->disable_rx_flow_control = 1; } - return (0); + return 0; } /** * nes_netdev_get_settings */ -int nes_netdev_get_settings(struct net_device *netdev, struct ethtool_cmd *et_cmd) +static int nes_netdev_get_settings(struct net_device *netdev, struct ethtool_cmd *et_cmd) { struct nes_vnic *nesvnic = netdev_priv(netdev); struct nes_device *nesdev = nesvnic->nesdev; @@ -1192,6 +1401,7 @@ int nes_netdev_get_settings(struct net_device *netdev, struct ethtool_cmd *et_cm u16 phy_data; et_cmd->duplex = DUPLEX_FULL; + et_cmd->port = PORT_MII; if (nesadapter->OneG_Mode) { et_cmd->supported = SUPPORTED_1000baseT_Full|SUPPORTED_Autoneg; et_cmd->advertising = ADVERTISED_1000baseT_Full|ADVERTISED_Autoneg; @@ -1206,14 +1416,21 @@ int nes_netdev_get_settings(struct net_device *netdev, struct ethtool_cmd *et_cm et_cmd->transceiver = XCVR_EXTERNAL; et_cmd->phy_address = nesadapter->phy_index[nesdev->mac_index]; } else { - et_cmd->supported = SUPPORTED_10000baseT_Full; - et_cmd->advertising = ADVERTISED_10000baseT_Full; + if (nesadapter->phy_type[nesvnic->logical_port] == NES_PHY_TYPE_IRIS) { + et_cmd->transceiver = XCVR_EXTERNAL; + et_cmd->port = PORT_FIBRE; + et_cmd->supported = SUPPORTED_FIBRE; + et_cmd->advertising = ADVERTISED_FIBRE; + et_cmd->phy_address = nesadapter->phy_index[nesdev->mac_index]; + } else { + et_cmd->transceiver = XCVR_INTERNAL; + et_cmd->supported = SUPPORTED_10000baseT_Full; + et_cmd->advertising = ADVERTISED_10000baseT_Full; + et_cmd->phy_address = nesdev->mac_index; + } et_cmd->speed = SPEED_10000; et_cmd->autoneg = AUTONEG_DISABLE; - et_cmd->transceiver = XCVR_INTERNAL; - et_cmd->phy_address = nesdev->mac_index; } - et_cmd->port = PORT_MII; et_cmd->maxtxpkt = 511; et_cmd->maxrxpkt = 511; return 0; @@ -1223,7 +1440,7 @@ int nes_netdev_get_settings(struct net_device *netdev, struct ethtool_cmd *et_cm /** * nes_netdev_set_settings */ -int nes_netdev_set_settings(struct net_device *netdev, struct ethtool_cmd *et_cmd) +static int nes_netdev_set_settings(struct net_device *netdev, struct ethtool_cmd *et_cmd) { struct nes_vnic *nesvnic = netdev_priv(netdev); struct nes_device *nesdev = nesvnic->nesdev; @@ -1248,25 +1465,6 @@ int nes_netdev_set_settings(struct net_device *netdev, struct ethtool_cmd *et_cm } -/** - * nes_netdev_get_msglevel - */ -u32 nes_netdev_get_msglevel(struct net_device *netdev) -{ - return nes_debug_level; -} - - -/** - * nes_netdev_set_msglevel - */ -void nes_netdev_set_msglevel(struct net_device *netdev, u32 level) -{ - dprintk("%s[%u] Setting message level to: %u\n", __FUNCTION__, __LINE__, level); - nes_debug_level = level; -} - - static struct ethtool_ops nes_ethtool_ops = { .get_link = ethtool_op_get_link, .get_settings = nes_netdev_get_settings, @@ -1282,27 +1480,27 @@ static struct ethtool_ops nes_ethtool_ops = { .set_coalesce = nes_netdev_set_coalesce, .get_pauseparam = nes_netdev_get_pauseparam, .set_pauseparam = nes_netdev_set_pauseparam, - .get_msglevel = nes_netdev_get_msglevel, - .set_msglevel = nes_netdev_set_msglevel, .set_tx_csum = ethtool_op_set_tx_csum, .set_rx_csum = nes_netdev_set_rx_csum, .set_sg = ethtool_op_set_sg, -#ifdef NETIF_F_TSO .get_tso = ethtool_op_get_tso, .set_tso = ethtool_op_set_tso, -#endif }; -#ifdef NETIF_F_HW_VLAN_TX static void nes_netdev_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) { struct nes_vnic *nesvnic = netdev_priv(netdev); struct nes_device *nesdev = nesvnic->nesdev; + struct nes_adapter *nesadapter = nesdev->nesadapter; u32 u32temp; + unsigned long flags; + spin_lock_irqsave(&nesadapter->phy_lock, flags); nesvnic->vlan_grp = grp; + nes_debug(NES_DBG_NETDEV, "%s: %s\n", __func__, netdev->name); + /* Enable/Disable VLAN Stripping */ u32temp = nes_read_indexed(nesdev, NES_IDX_PCIX_DIAG); if (grp) @@ -1311,38 +1509,44 @@ static void nes_netdev_vlan_rx_register(struct net_device *netdev, struct vlan_g u32temp |= 0x02000000; nes_write_indexed(nesdev, NES_IDX_PCIX_DIAG, u32temp); + spin_unlock_irqrestore(&nesadapter->phy_lock, flags); } -#endif /** * nes_netdev_init - initialize network device */ struct net_device *nes_netdev_init(struct nes_device *nesdev, - void __iomem *mmio_addr) + void __iomem *mmio_addr) { u64 u64temp; struct nes_vnic *nesvnic = NULL; struct net_device *netdev; struct nic_qp_map *curr_qp_map; u32 u32temp; + u16 phy_data; + u16 temp_phy_data; netdev = alloc_etherdev(sizeof(struct nes_vnic)); if (!netdev) { printk(KERN_ERR PFX "nesvnic etherdev alloc failed"); - return(NULL); + return NULL; } - dprintk("%s: netdev = %p.\n", __FUNCTION__, netdev); + nes_debug(NES_DBG_INIT, "netdev = %p, %s\n", netdev, netdev->name); SET_NETDEV_DEV(netdev, &nesdev->pcidev->dev); + nesvnic = netdev_priv(netdev); + memset(nesvnic, 0, sizeof(*nesvnic)); + netdev->open = nes_netdev_open; netdev->stop = nes_netdev_stop; netdev->hard_start_xmit = nes_netdev_start_xmit; netdev->get_stats = nes_netdev_get_stats; netdev->tx_timeout = nes_netdev_tx_timeout; netdev->set_mac_address = nes_netdev_set_mac_address; + netdev->set_multicast_list = nes_netdev_set_multicast_list; netdev->change_mtu = nes_netdev_change_mtu; netdev->watchdog_timeo = NES_TX_TIMEOUT; netdev->irq = nesdev->pcidev->irq; @@ -1352,29 +1556,20 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, netdev->type = ARPHRD_ETHER; netdev->features = NETIF_F_HIGHDMA; netdev->ethtool_ops = &nes_ethtool_ops; -#ifdef NES_NAPI netdev->poll = nes_netdev_poll; netdev->weight = 128; -#endif -#ifdef NETIF_F_HW_VLAN_TX - dprintk("%s: Enabling VLAN Insert/Delete.\n", __FUNCTION__); + nes_debug(NES_DBG_INIT, "Enabling VLAN Insert/Delete.\n"); netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; netdev->vlan_rx_register = nes_netdev_vlan_rx_register; -#endif -#ifdef NETIF_F_LLTX netdev->features |= NETIF_F_LLTX; -#endif /* Fill in the port structure */ - nesvnic = netdev_priv(netdev); - - memset(nesvnic, 0, sizeof(*nesvnic)); nesvnic->netdev = netdev; nesvnic->nesdev = nesdev; nesvnic->msg_enable = netif_msg_init(debug, default_msg); nesvnic->netdev_index = nesdev->netdev_count; nesvnic->perfect_filter_index = nesdev->nesadapter->netdev_count; - nesvnic->max_frame_size = netdev->mtu+netdev->hard_header_len; + nesvnic->max_frame_size = netdev->mtu + netdev->hard_header_len + VLAN_HLEN; curr_qp_map = nic_qp_mapping_per_function[PCI_FUNC(nesdev->pcidev->devfn)]; nesvnic->nic.qp_id = curr_qp_map[nesdev->netdev_count].qpid; @@ -1391,23 +1586,17 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, netdev->dev_addr[3] = (u8)(u64temp>>16); netdev->dev_addr[4] = (u8)(u64temp>>8); netdev->dev_addr[5] = (u8)u64temp; + memcpy(netdev->perm_addr, netdev->dev_addr, 6); - if (nesvnic->logical_port < 2) { -#ifdef NETIF_F_TSO - dprintk("%s: Enabling TSO \n", __FUNCTION__); - netdev->features |= NETIF_F_TSO | NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_IP_CSUM; -#endif -#ifdef NETIF_F_GSO - dprintk("%s: Enabling GSO \n", __FUNCTION__); - netdev->features |= NETIF_F_GSO | NETIF_F_TSO | NETIF_F_SG | NETIF_F_IP_CSUM; -#endif + if ((nesvnic->logical_port < 2) || (nesdev->nesadapter->hw_rev != NE020_REV)) { + netdev->features |= NETIF_F_TSO | NETIF_F_SG | NETIF_F_IP_CSUM; } else { - netdev->features |= NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_IP_CSUM; + netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; } - dprintk("%s: nesvnic = %p, reported features = 0x%lX, QPid = %d," + nes_debug(NES_DBG_INIT, "nesvnic = %p, reported features = 0x%lX, QPid = %d," " nic_index = %d, logical_port = %d, mac_index = %d.\n", - __FUNCTION__, nesvnic, (unsigned long)netdev->features, nesvnic->nic.qp_id, + nesvnic, (unsigned long)netdev->features, nesvnic->nic.qp_id, nesvnic->nic_index, nesvnic->logical_port, nesdev->mac_index); if (nesvnic->nesdev->nesadapter->port_count == 1) { @@ -1435,11 +1624,8 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, } nesvnic->next_qp_nic_index = 0; - if (0 == nesdev->netdev_count) { - if (rdma_enabled == 0) { - rdma_enabled = 1; - nesvnic->rdma_enabled = 1; - } + if (nesdev->netdev_count == 0) { + nesvnic->rdma_enabled = 1; } else { nesvnic->rdma_enabled = 0; } @@ -1447,14 +1633,13 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, spin_lock_init(&nesvnic->tx_lock); nesdev->netdev[nesdev->netdev_count] = netdev; - dprintk("%s: Adding nesvnic (%p) to the adapters nesvnic_list for MAC%d.\n", - __FUNCTION__, nesvnic, nesdev->mac_index); + nes_debug(NES_DBG_INIT, "Adding nesvnic (%p) to the adapters nesvnic_list for MAC%d.\n", + nesvnic, nesdev->mac_index); list_add_tail(&nesvnic->list, &nesdev->nesadapter->nesvnic_list[nesdev->mac_index]); - if ((0 == nesdev->netdev_count) && - (PCI_FUNC(nesdev->pcidev->devfn) == nesdev->mac_index)) { - dprintk("%s: Setting up PHY interrupt mask. Using register index 0x%04X\n", - __FUNCTION__, + if ((nesdev->netdev_count == 0) && + (PCI_FUNC(nesdev->pcidev->devfn) == nesdev->mac_index)) { + nes_debug(NES_DBG_INIT, "Setting up PHY interrupt mask. Using register index 0x%04X\n", NES_IDX_PHY_PCS_CONTROL_STATUS0+(0x200*(nesvnic->logical_port&1))); u32temp = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 + (0x200*(nesvnic->logical_port&1))); @@ -1463,23 +1648,45 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, (0x200*(nesvnic->logical_port&1)), u32temp); u32temp = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 + (0x200*(nesvnic->logical_port&1)) ); - if (0x0f0f0000 == (u32temp&0x0f1f0000)) { - dprintk("%s: The Link is UP!!.\n", __FUNCTION__); - nesvnic->linkup = 1; + if ((u32temp&0x0f1f0000) == 0x0f0f0000) { + if (nesdev->nesadapter->phy_type[nesvnic->logical_port] == NES_PHY_TYPE_IRIS) { + nes_init_phy(nesdev); + nes_read_10G_phy_reg(nesdev, 1, + nesdev->nesadapter->phy_index[nesvnic->logical_port]); + temp_phy_data = (u16)nes_read_indexed(nesdev, + NES_IDX_MAC_MDIO_CONTROL); + u32temp = 20; + do { + nes_read_10G_phy_reg(nesdev, 1, + nesdev->nesadapter->phy_index[nesvnic->logical_port]); + phy_data = (u16)nes_read_indexed(nesdev, + NES_IDX_MAC_MDIO_CONTROL); + if ((phy_data == temp_phy_data) || (!(--u32temp))) + break; + temp_phy_data = phy_data; + } while (1); + if (phy_data & 4) { + nes_debug(NES_DBG_INIT, "The Link is UP!!.\n"); + nesvnic->linkup = 1; + } else { + nes_debug(NES_DBG_INIT, "The Link is DOWN!!.\n"); + } + } else { + nes_debug(NES_DBG_INIT, "The Link is UP!!.\n"); + nesvnic->linkup = 1; + } } - dprintk("%s: Setting up MAC interrupt mask.\n", __FUNCTION__); /* clear the MAC interrupt status, assumes direct logical to physical mapping */ - u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS+(0x200*nesvnic->logical_port)); - dprintk("Phy interrupt status = 0x%X.\n", u32temp); - nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS+(0x200*nesvnic->logical_port), u32temp); + u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (0x200 * nesdev->mac_index)); + nes_debug(NES_DBG_INIT, "Phy interrupt status = 0x%X.\n", u32temp); + nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (0x200 * nesdev->mac_index), u32temp); + + if (nesdev->nesadapter->phy_type[nesdev->mac_index] != NES_PHY_TYPE_IRIS) + nes_init_phy(nesdev); - nes_init_phy(nesdev); - nes_write_indexed(nesdev, NES_IDX_MAC_INT_MASK+(0x200*nesvnic->logical_port), - ~(NES_MAC_INT_LINK_STAT_CHG | NES_MAC_INT_XGMII_EXT | - NES_MAC_INT_TX_UNDERFLOW | NES_MAC_INT_TX_ERROR)); } - return(netdev); + return netdev; } @@ -1490,8 +1697,6 @@ void nes_netdev_destroy(struct net_device *netdev) { struct nes_vnic *nesvnic = netdev_priv(netdev); - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); - /* make sure 'stop' method is called by Linux stack */ /* nes_netdev_stop(netdev); */ @@ -1501,11 +1706,7 @@ void nes_netdev_destroy(struct net_device *netdev) nes_destroy_ofa_device(nesvnic->nesibdev); } - dprintk("%s:%u\n", __FUNCTION__, __LINE__); - free_netdev(netdev); - - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); } @@ -1516,12 +1717,11 @@ int nes_nic_cm_xmit(struct sk_buff *skb, struct net_device *netdev) { int ret; - ret = nes_netdev_start_xmit(skb, netdev); - + skb->dev = netdev; + ret = dev_queue_xmit(skb); if (ret) { - dprintk("%s:%s:%u Bad return code from nes_netdev_start_xmit %d\n", - __FILE__, __FUNCTION__, __LINE__, ret); + nes_debug(NES_DBG_CM, "Bad return code from dev_queue_xmit %d\n", ret); } - return(ret); + return ret; } diff --git a/drivers/infiniband/hw/nes/nes_user.h b/drivers/infiniband/hw/nes/nes_user.h index 2aceb2c..e64306b 100644 --- a/drivers/infiniband/hw/nes/nes_user.h +++ b/drivers/infiniband/hw/nes/nes_user.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2007 NetEffect. All rights reserved. + * Copyright (c) 2006 - 2008 NetEffect. All rights reserved. * Copyright (c) 2005 Topspin Communications. All rights reserved. * Copyright (c) 2005 Cisco Systems. All rights reserved. * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. @@ -39,6 +39,9 @@ #include <linux/types.h> +#define NES_ABI_USERSPACE_VER 1 +#define NES_ABI_KERNEL_VER 1 + /* * Make sure that all structs defined in this file remain laid out so * that they pack the same way on 32-bit and 64-bit architectures (to @@ -47,11 +50,19 @@ * instead. */ +struct nes_alloc_ucontext_req { + __u32 reserved32; + __u8 userspace_ver; + __u8 reserved8[3]; +}; + struct nes_alloc_ucontext_resp { __u32 max_pds; /* maximum pds allowed for this user process */ __u32 max_qps; /* maximum qps allowed for this user process */ __u32 wq_size; /* size of the WQs (sq+rq) allocated to the mmaped area */ - __u32 reserved; + __u8 virtwq; /* flag to indicate if virtual WQ are to be used or not */ + __u8 kernel_ver; + __u8 reserved[2]; }; struct nes_alloc_pd_resp { @@ -61,6 +72,12 @@ struct nes_alloc_pd_resp { struct nes_create_cq_req { __u64 user_cq_buffer; + __u32 mcrqf; + __u8 reserved[4]; +}; + +struct nes_create_qp_req { + __u64 user_wqe_buffers; }; enum iwnes_memreg_type { @@ -89,7 +106,7 @@ struct nes_create_qp_resp { __u32 actual_rq_size; __u32 mmap_sq_db_index; __u32 mmap_rq_db_index; - __u32 reserved; + __u32 nes_drv_opt; }; #endif /* NES_USER_H */ diff --git a/drivers/infiniband/hw/nes/nes_utils.c b/drivers/infiniband/hw/nes/nes_utils.c index 01a7238..c4ec6ac 100644 --- a/drivers/infiniband/hw/nes/nes_utils.c +++ b/drivers/infiniband/hw/nes/nes_utils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2007 NetEffect, Inc. All rights reserved. + * Copyright (c) 2006 - 2008 NetEffect, Inc. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -50,18 +50,9 @@ #include "nes.h" -#define BITMASK(X) (1L << (X)) -#define NES_CRC_WID 32 -static u16 nes_read16_eeprom(void __iomem *addr, u16 offset); - -static u32 nesCRCTable[256]; -static u32 nesCRCInitialized = 0; -static u32 nesCRCWidMask(u32); -static u32 nes_crc_table_gen(u32 *, u32, u32, u32); -static u32 reflect(u32, u32); -static u32 byte_swap(u32, u32); +static u16 nes_read16_eeprom(void __iomem *addr, u16 offset); u32 mh_detected; u32 mh_pauses_sent; @@ -75,36 +66,127 @@ int nes_read_eeprom_values(struct nes_device *nesdev, struct nes_adapter *nesada u16 mac_addr_high; u16 eeprom_data; u16 eeprom_offset; - u32 index; + u16 next_section_address; + u16 sw_section_ver; + u8 major_ver = 0; + u8 minor_ver = 0; /* TODO: deal with EEPROM endian issues */ if (nesadapter->firmware_eeprom_offset == 0) { /* Read the EEPROM Parameters */ eeprom_data = nes_read16_eeprom(nesdev->regs, 0); - dprintk("EEPROM Offset 0 = 0x%04X\n", eeprom_data); + nes_debug(NES_DBG_HW, "EEPROM Offset 0 = 0x%04X\n", eeprom_data); eeprom_offset = 2 + (((eeprom_data & 0x007f) << 3) << ((eeprom_data & 0x0080) >> 7)); - dprintk("Firmware Offset = 0x%04X\n", eeprom_offset); + nes_debug(NES_DBG_HW, "Firmware Offset = 0x%04X\n", eeprom_offset); nesadapter->firmware_eeprom_offset = eeprom_offset; eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset + 4); if (eeprom_data != 0x5746) { - dprintk("Not a valid Firmware Image = 0x%04X\n", eeprom_data); - return(-1); + nes_debug(NES_DBG_HW, "Not a valid Firmware Image = 0x%04X\n", eeprom_data); + return -1; } eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset + 2); - dprintk("EEPROM Offset %u = 0x%04X\n", eeprom_offset + 2, eeprom_data); + nes_debug(NES_DBG_HW, "EEPROM Offset %u = 0x%04X\n", + eeprom_offset + 2, eeprom_data); eeprom_offset += ((eeprom_data & 0x00ff) << 3) << ((eeprom_data & 0x0100) >> 8); - dprintk("Software Offset = 0x%04X\n", eeprom_offset); + nes_debug(NES_DBG_HW, "Software Offset = 0x%04X\n", eeprom_offset); nesadapter->software_eeprom_offset = eeprom_offset; - eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset); - dprintk("EEPROM Offset %u = 0x%04X\n", eeprom_offset, eeprom_data); eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset + 4); if (eeprom_data != 0x5753) { - dprintk("Not a valid Software Image = 0x%04X\n", eeprom_data); - return(-1); + printk("Not a valid Software Image = 0x%04X\n", eeprom_data); + return -1; + } + sw_section_ver = nes_read16_eeprom(nesdev->regs, nesadapter->software_eeprom_offset + 6); + nes_debug(NES_DBG_HW, "Software section version number = 0x%04X\n", + sw_section_ver); + + eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset + 2); + nes_debug(NES_DBG_HW, "EEPROM Offset %u (next section) = 0x%04X\n", + eeprom_offset + 2, eeprom_data); + next_section_address = eeprom_offset + (((eeprom_data & 0x00ff) << 3) << + ((eeprom_data & 0x0100) >> 8)); + eeprom_data = nes_read16_eeprom(nesdev->regs, next_section_address + 4); + if (eeprom_data != 0x414d) { + nes_debug(NES_DBG_HW, "EEPROM Changed offset should be 0x414d but was 0x%04X\n", + eeprom_data); + goto no_fw_rev; + } + eeprom_offset = next_section_address; + + eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset + 2); + nes_debug(NES_DBG_HW, "EEPROM Offset %u (next section) = 0x%04X\n", + eeprom_offset + 2, eeprom_data); + next_section_address = eeprom_offset + (((eeprom_data & 0x00ff) << 3) << + ((eeprom_data & 0x0100) >> 8)); + eeprom_data = nes_read16_eeprom(nesdev->regs, next_section_address + 4); + if (eeprom_data != 0x4f52) { + nes_debug(NES_DBG_HW, "EEPROM Changed offset should be 0x4f52 but was 0x%04X\n", + eeprom_data); + goto no_fw_rev; + } + eeprom_offset = next_section_address; + + eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset + 2); + nes_debug(NES_DBG_HW, "EEPROM Offset %u (next section) = 0x%04X\n", + eeprom_offset + 2, eeprom_data); + next_section_address = eeprom_offset + ((eeprom_data & 0x00ff) << 3); + eeprom_data = nes_read16_eeprom(nesdev->regs, next_section_address + 4); + if (eeprom_data != 0x5746) { + nes_debug(NES_DBG_HW, "EEPROM Changed offset should be 0x5746 but was 0x%04X\n", + eeprom_data); + goto no_fw_rev; + } + eeprom_offset = next_section_address; + + eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset + 2); + nes_debug(NES_DBG_HW, "EEPROM Offset %u (next section) = 0x%04X\n", + eeprom_offset + 2, eeprom_data); + next_section_address = eeprom_offset + ((eeprom_data & 0x00ff) << 3); + eeprom_data = nes_read16_eeprom(nesdev->regs, next_section_address + 4); + if (eeprom_data != 0x5753) { + nes_debug(NES_DBG_HW, "EEPROM Changed offset should be 0x5753 but was 0x%04X\n", + eeprom_data); + goto no_fw_rev; + } + eeprom_offset = next_section_address; + + eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset + 2); + nes_debug(NES_DBG_HW, "EEPROM Offset %u (next section) = 0x%04X\n", + eeprom_offset + 2, eeprom_data); + next_section_address = eeprom_offset + ((eeprom_data & 0x00ff) << 3); + eeprom_data = nes_read16_eeprom(nesdev->regs, next_section_address + 4); + if (eeprom_data != 0x414d) { + nes_debug(NES_DBG_HW, "EEPROM Changed offset should be 0x414d but was 0x%04X\n", + eeprom_data); + goto no_fw_rev; } + eeprom_offset = next_section_address; + eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset + 2); + nes_debug(NES_DBG_HW, "EEPROM Offset %u (next section) = 0x%04X\n", + eeprom_offset + 2, eeprom_data); + next_section_address = eeprom_offset + ((eeprom_data & 0x00ff) << 3); + eeprom_data = nes_read16_eeprom(nesdev->regs, next_section_address + 4); + if (eeprom_data != 0x464e) { + nes_debug(NES_DBG_HW, "EEPROM Changed offset should be 0x464e but was 0x%04X\n", + eeprom_data); + goto no_fw_rev; + } + eeprom_data = nes_read16_eeprom(nesdev->regs, next_section_address + 8); + printk(PFX "Firmware version %u.%u\n", (u8)(eeprom_data>>8), (u8)eeprom_data); + major_ver = (u8)(eeprom_data >> 8); + minor_ver = (u8)(eeprom_data); + + if (nes_drv_opt & NES_DRV_OPT_DISABLE_VIRT_WQ) { + nes_debug(NES_DBG_HW, "Virtual WQs have been disabled\n"); + } else if (((major_ver == 2) && (minor_ver > 21)) || ((major_ver > 2) && (major_ver != 255))) { + nesadapter->virtwq = 1; + } + nesadapter->firmware_version = (((u32)(u8)(eeprom_data>>8)) << 16) + + (u32)((u8)eeprom_data); + +no_fw_rev: /* eeprom is valid */ eeprom_offset = nesadapter->software_eeprom_offset; eeprom_offset += 8; @@ -116,8 +198,9 @@ int nes_read_eeprom_values(struct nes_device *nesdev, struct nes_adapter *nesada eeprom_offset += 2; mac_addr_low <<= 16; mac_addr_low += (u32)nes_read16_eeprom(nesdev->regs, eeprom_offset); - dprintk("Base MAC Address = 0x%04X%08X\n", mac_addr_high, mac_addr_low); - dprintk("MAC Address count = %u\n", nesadapter->netdev_max); + nes_debug(NES_DBG_HW, "Base MAC Address = 0x%04X%08X\n", + mac_addr_high, mac_addr_low); + nes_debug(NES_DBG_HW, "MAC Address count = %u\n", nesadapter->netdev_max); nesadapter->mac_addr_low = mac_addr_low; nesadapter->mac_addr_high = mac_addr_high; @@ -125,109 +208,151 @@ int nes_read_eeprom_values(struct nes_device *nesdev, struct nes_adapter *nesada /* Read the Phy Type array */ eeprom_offset += 10; eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset); - dprintk("PhyType: 0x%04x\n", eeprom_data); + nesadapter->phy_type[0] = (u8)(eeprom_data >> 8); + nesadapter->phy_type[1] = (u8)eeprom_data; /* Read the port array */ eeprom_offset += 2; eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset); + nesadapter->phy_type[2] = (u8)(eeprom_data >> 8); + nesadapter->phy_type[3] = (u8)eeprom_data; /* port_count is set by soft reset reg */ - for (index = 0; index < 4; index++) { - nesadapter->ports[index] = eeprom_data & 0x000f; - eeprom_data >>= 4; - } - dprintk("port_count = %u, port 0 -> %u, port 1 -> %u, port 2 -> %u, port 3 -> %u\n", + nes_debug(NES_DBG_HW, "port_count = %u, port 0 -> %u, port 1 -> %u," + " port 2 -> %u, port 3 -> %u\n", nesadapter->port_count, - nesadapter->ports[0], nesadapter->ports[1], - nesadapter->ports[2], nesadapter->ports[3]); + nesadapter->phy_type[0], nesadapter->phy_type[1], + nesadapter->phy_type[2], nesadapter->phy_type[3]); - eeprom_offset += 46; + /* Read PD config array */ + eeprom_offset += 10; + eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset); + nesadapter->pd_config_size[0] = eeprom_data; + eeprom_offset += 2; + eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset); + nesadapter->pd_config_base[0] = eeprom_data; + nes_debug(NES_DBG_HW, "PD0 config, size=0x%04x, base=0x%04x\n", + nesadapter->pd_config_size[0], nesadapter->pd_config_base[0]); + + eeprom_offset += 2; + eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset); + nesadapter->pd_config_size[1] = eeprom_data; + eeprom_offset += 2; + eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset); + nesadapter->pd_config_base[1] = eeprom_data; + nes_debug(NES_DBG_HW, "PD1 config, size=0x%04x, base=0x%04x\n", + nesadapter->pd_config_size[1], nesadapter->pd_config_base[1]); + + eeprom_offset += 2; + eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset); + nesadapter->pd_config_size[2] = eeprom_data; + eeprom_offset += 2; + eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset); + nesadapter->pd_config_base[2] = eeprom_data; + nes_debug(NES_DBG_HW, "PD2 config, size=0x%04x, base=0x%04x\n", + nesadapter->pd_config_size[2], nesadapter->pd_config_base[2]); + + eeprom_offset += 2; + eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset); + nesadapter->pd_config_size[3] = eeprom_data; + eeprom_offset += 2; + eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset); + nesadapter->pd_config_base[3] = eeprom_data; + nes_debug(NES_DBG_HW, "PD3 config, size=0x%04x, base=0x%04x\n", + nesadapter->pd_config_size[3], nesadapter->pd_config_base[3]); + + /* Read Rx Pool Size */ + eeprom_offset += 22; /* 46 */ eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset); eeprom_offset += 2; nesadapter->rx_pool_size = (((u32)eeprom_data) << 16) + - nes_read16_eeprom(nesdev->regs, eeprom_offset); - dprintk("rx_pool_size = 0x%08X\n", nesadapter->rx_pool_size); + nes_read16_eeprom(nesdev->regs, eeprom_offset); + nes_debug(NES_DBG_HW, "rx_pool_size = 0x%08X\n", nesadapter->rx_pool_size); eeprom_offset += 2; eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset); eeprom_offset += 2; nesadapter->tx_pool_size = (((u32)eeprom_data) << 16) + - nes_read16_eeprom(nesdev->regs, eeprom_offset); - dprintk("tx_pool_size = 0x%08X\n", nesadapter->tx_pool_size); + nes_read16_eeprom(nesdev->regs, eeprom_offset); + nes_debug(NES_DBG_HW, "tx_pool_size = 0x%08X\n", nesadapter->tx_pool_size); eeprom_offset += 2; eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset); eeprom_offset += 2; nesadapter->rx_threshold = (((u32)eeprom_data) << 16) + - nes_read16_eeprom(nesdev->regs, eeprom_offset); - dprintk("rx_threshold = 0x%08X\n", nesadapter->rx_threshold); + nes_read16_eeprom(nesdev->regs, eeprom_offset); + nes_debug(NES_DBG_HW, "rx_threshold = 0x%08X\n", nesadapter->rx_threshold); eeprom_offset += 2; eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset); eeprom_offset += 2; nesadapter->tcp_timer_core_clk_divisor = (((u32)eeprom_data) << 16) + - nes_read16_eeprom(nesdev->regs, eeprom_offset); - dprintk("tcp_timer_core_clk_divisor = 0x%08X\n", + nes_read16_eeprom(nesdev->regs, eeprom_offset); + nes_debug(NES_DBG_HW, "tcp_timer_core_clk_divisor = 0x%08X\n", nesadapter->tcp_timer_core_clk_divisor); eeprom_offset += 2; eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset); eeprom_offset += 2; nesadapter->iwarp_config = (((u32)eeprom_data) << 16) + - nes_read16_eeprom(nesdev->regs, eeprom_offset); - dprintk("iwarp_config = 0x%08X\n", nesadapter->iwarp_config); + nes_read16_eeprom(nesdev->regs, eeprom_offset); + nes_debug(NES_DBG_HW, "iwarp_config = 0x%08X\n", nesadapter->iwarp_config); eeprom_offset += 2; eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset); eeprom_offset += 2; nesadapter->cm_config = (((u32)eeprom_data) << 16) + - nes_read16_eeprom(nesdev->regs, eeprom_offset); - dprintk("cm_config = 0x%08X\n", nesadapter->cm_config); + nes_read16_eeprom(nesdev->regs, eeprom_offset); + nes_debug(NES_DBG_HW, "cm_config = 0x%08X\n", nesadapter->cm_config); eeprom_offset += 2; eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset); eeprom_offset += 2; nesadapter->sws_timer_config = (((u32)eeprom_data) << 16) + - nes_read16_eeprom(nesdev->regs, eeprom_offset); - dprintk("sws_timer_config = 0x%08X\n", nesadapter->sws_timer_config); + nes_read16_eeprom(nesdev->regs, eeprom_offset); + nes_debug(NES_DBG_HW, "sws_timer_config = 0x%08X\n", nesadapter->sws_timer_config); eeprom_offset += 2; eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset); eeprom_offset += 2; nesadapter->tcp_config1 = (((u32)eeprom_data) << 16) + - nes_read16_eeprom(nesdev->regs, eeprom_offset); - dprintk("tcp_config1 = 0x%08X\n", nesadapter->tcp_config1); + nes_read16_eeprom(nesdev->regs, eeprom_offset); + nes_debug(NES_DBG_HW, "tcp_config1 = 0x%08X\n", nesadapter->tcp_config1); eeprom_offset += 2; eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset); eeprom_offset += 2; nesadapter->wqm_wat = (((u32)eeprom_data) << 16) + - nes_read16_eeprom(nesdev->regs, eeprom_offset); - dprintk("wqm_wat = 0x%08X\n", nesadapter->wqm_wat); + nes_read16_eeprom(nesdev->regs, eeprom_offset); + nes_debug(NES_DBG_HW, "wqm_wat = 0x%08X\n", nesadapter->wqm_wat); eeprom_offset += 2; eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset); eeprom_offset += 2; nesadapter->core_clock = (((u32)eeprom_data) << 16) + - nes_read16_eeprom(nesdev->regs, eeprom_offset); - dprintk("core_clock = 0x%08X\n", nesadapter->core_clock); - - eeprom_offset += 2; - eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset); - eeprom_offset += 2; - nesadapter->firmware_version = (((u32)eeprom_data) << 16) + - nes_read16_eeprom(nesdev->regs, eeprom_offset); - dprintk("firmware_version = 0x%08X\n", nesadapter->firmware_version); + nes_read16_eeprom(nesdev->regs, eeprom_offset); + nes_debug(NES_DBG_HW, "core_clock = 0x%08X\n", nesadapter->core_clock); + + if ((sw_section_ver) && (nesadapter->hw_rev != NE020_REV)) { + eeprom_offset += 2; + eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset); + nesadapter->phy_index[0] = (eeprom_data & 0xff00)>>8; + nesadapter->phy_index[1] = eeprom_data & 0x00ff; + eeprom_offset += 2; + eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset); + nesadapter->phy_index[2] = (eeprom_data & 0xff00)>>8; + nesadapter->phy_index[3] = eeprom_data & 0x00ff; + } else { + nesadapter->phy_index[0] = 4; + nesadapter->phy_index[1] = 5; + nesadapter->phy_index[2] = 6; + nesadapter->phy_index[3] = 7; + } + nes_debug(NES_DBG_HW, "Phy address map = 0 > %u, 1 > %u, 2 > %u, 3 > %u\n", + nesadapter->phy_index[0],nesadapter->phy_index[1], + nesadapter->phy_index[2],nesadapter->phy_index[3]); } - nesadapter->phy_index[0] = 4; - nesadapter->phy_index[1] = 5; - nesadapter->phy_index[2] = 6; - nesadapter->phy_index[3] = 7; - - /* TODO: get this from EEPROM */ - nesdev->base_doorbell_index = 1; - - return (0); + return 0; } @@ -236,14 +361,14 @@ int nes_read_eeprom_values(struct nes_device *nesdev, struct nes_adapter *nesada */ static u16 nes_read16_eeprom(void __iomem *addr, u16 offset) { - writel(cpu_to_le32(NES_EEPROM_READ_REQUEST + (offset >> 1)), - (u8 *)addr + NES_EEPROM_COMMAND); + writel(NES_EEPROM_READ_REQUEST + (offset >> 1), + (void __iomem *)addr + NES_EEPROM_COMMAND); do { - } while ((le32_to_cpu(readl((u8 *)addr + NES_EEPROM_COMMAND)) & - NES_EEPROM_READ_REQUEST)); + } while (readl((void __iomem *)addr + NES_EEPROM_COMMAND) & + NES_EEPROM_READ_REQUEST); - return(le16_to_cpu(readw((u8 *)addr + NES_EEPROM_DATA))); + return readw((void __iomem *)addr + NES_EEPROM_DATA); } @@ -265,13 +390,14 @@ void nes_write_1G_phy_reg(struct nes_device *nesdev, u8 phy_reg, u8 phy_addr, u1 udelay(30); u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS); if (u32temp & 1) { - /* dprintk("Phy interrupt status = 0x%X.\n", u32temp); */ + /* nes_debug(NES_DBG_PHY, "Phy interrupt status = 0x%X.\n", u32temp); */ nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS, 1); break; } } if (!(u32temp & 1)) - dprintk("Phy is not responding. interrupt status = 0x%X.\n", u32temp); + nes_debug(NES_DBG_PHY, "Phy is not responding. interrupt status = 0x%X.\n", + u32temp); spin_unlock_irqrestore(&nesadapter->phy_lock, flags); } @@ -289,8 +415,8 @@ void nes_read_1G_phy_reg(struct nes_device *nesdev, u8 phy_reg, u8 phy_addr, u16 u32 counter; unsigned long flags; - /* dprintk("%s: phy addr = %d, mac_index = %d\n", - __FUNCTION__, phy_addr, nesdev->mac_index); */ + /* nes_debug(NES_DBG_PHY, "phy addr = %d, mac_index = %d\n", + phy_addr, nesdev->mac_index); */ spin_lock_irqsave(&nesadapter->phy_lock, flags); nes_write_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL, @@ -299,13 +425,14 @@ void nes_read_1G_phy_reg(struct nes_device *nesdev, u8 phy_reg, u8 phy_addr, u16 udelay(30); u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS); if (u32temp & 1) { - /* dprintk("Phy interrupt status = 0x%X.\n", u32temp); */ + /* nes_debug(NES_DBG_PHY, "Phy interrupt status = 0x%X.\n", u32temp); */ nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS, 1); break; } } if (!(u32temp & 1)) { - dprintk("Phy is not responding. interrupt status = 0x%X.\n", u32temp); + nes_debug(NES_DBG_PHY, "Phy is not responding. interrupt status = 0x%X.\n", + u32temp); *data = 0xffff; } else { *data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); @@ -325,38 +452,38 @@ void nes_write_10G_phy_reg(struct nes_device *nesdev, u16 phy_reg, u32 u32temp; u32 counter; - dev_addr = 5; - port_addr = 0; + dev_addr = 1; + port_addr = phy_addr; /* set address */ nes_write_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL, - 0x00020000 | phy_reg | (dev_addr << 18) | (port_addr << 23)); + 0x00020000 | (u32)phy_reg | (((u32)dev_addr) << 18) | (((u32)port_addr) << 23)); for (counter = 0; counter < 100 ; counter++) { udelay(30); u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS); if (u32temp & 1) { - /* dprintk("Address phase; Phy interrupt status = 0x%X.\n", u32temp); */ nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS, 1); break; } } if (!(u32temp & 1)) - dprintk("Phy is not responding. interrupt status = 0x%X.\n", u32temp); + nes_debug(NES_DBG_PHY, "Phy is not responding. interrupt status = 0x%X.\n", + u32temp); /* set data */ nes_write_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL, - 0x10020000 | data | (dev_addr << 18) | (port_addr << 23)); + 0x10020000 | (u32)data | (((u32)dev_addr) << 18) | (((u32)port_addr) << 23)); for (counter = 0; counter < 100 ; counter++) { udelay(30); u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS); if (u32temp & 1) { - /* dprintk("Write phase; Phy interrupt status = 0x%X.\n", u32temp); */ nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS, 1); break; } } if (!(u32temp & 1)) - dprintk("Phy is not responding. interrupt status = 0x%X.\n", u32temp); + nes_debug(NES_DBG_PHY, "Phy is not responding. interrupt status = 0x%X.\n", + u32temp); } @@ -372,40 +499,129 @@ void nes_read_10G_phy_reg(struct nes_device *nesdev, u16 phy_reg, u8 phy_addr) u32 u32temp; u32 counter; - dev_addr = 5; - port_addr = 0; + dev_addr = 1; + port_addr = phy_addr; /* set address */ nes_write_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL, - 0x00020000 | phy_reg | (dev_addr << 18) | (port_addr << 23)); - /* dprintk("%s: Waiting for MAC Interrupt.\n", __FUNCTION__ ); */ + 0x00020000 | (u32)phy_reg | (((u32)dev_addr) << 18) | (((u32)port_addr) << 23)); for (counter = 0; counter < 100 ; counter++) { udelay(30); u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS); if (u32temp & 1) { - /* dprintk("Address phase; Phy interrupt status = 0x%X.\n", u32temp); */ nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS, 1); break; } } if (!(u32temp & 1)) - dprintk("Phy is not responding. interrupt status = 0x%X.\n", u32temp); + nes_debug(NES_DBG_PHY, "Phy is not responding. interrupt status = 0x%X.\n", + u32temp); /* issue read */ nes_write_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL, - 0x30020000 | (dev_addr << 18) | (port_addr << 23)); - /* dprintk("%s: Waiting for MAC Interrupt...2nd time.\n", __FUNCTION__ ); */ + 0x30020000 | (((u32)dev_addr) << 18) | (((u32)port_addr) << 23)); for (counter = 0; counter < 100 ; counter++) { udelay(30); u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS); if (u32temp & 1) { - /* dprintk("Read phase; Phy interrupt status = 0x%X.\n", u32temp); */ nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS, 1); break; } } if (!(u32temp & 1)) - dprintk("Phy is not responding. interrupt status = 0x%X.\n", u32temp); + nes_debug(NES_DBG_PHY, "Phy is not responding. interrupt status = 0x%X.\n", + u32temp); +} + + +/** + * nes_get_cqp_request + */ +struct nes_cqp_request *nes_get_cqp_request(struct nes_device *nesdev) +{ + unsigned long flags; + struct nes_cqp_request *cqp_request = NULL; + + if (!list_empty(&nesdev->cqp_avail_reqs)) { + spin_lock_irqsave(&nesdev->cqp.lock, flags); + cqp_request = list_entry(nesdev->cqp_avail_reqs.next, + struct nes_cqp_request, list); + list_del_init(&cqp_request->list); + spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + } else { + cqp_request = kzalloc(sizeof(struct nes_cqp_request), GFP_KERNEL); + if (cqp_request) { + cqp_request->dynamic = 1; + INIT_LIST_HEAD(&cqp_request->list); + } + } + + if (cqp_request) { + init_waitqueue_head(&cqp_request->waitq); + cqp_request->waiting = 0; + cqp_request->request_done = 0; + cqp_request->callback = 0; + init_waitqueue_head(&cqp_request->waitq); + nes_debug(NES_DBG_CQP, "Got cqp request %p from the available list \n", + cqp_request); + } else + printk(KERN_ERR PFX "%s: Could not allocated a CQP request.\n", + __FUNCTION__); + + return cqp_request; +} + + +/** + * nes_post_cqp_request + */ +void nes_post_cqp_request(struct nes_device *nesdev, + struct nes_cqp_request *cqp_request, int ring_doorbell) +{ + struct nes_hw_cqp_wqe *cqp_wqe; + unsigned long flags; + u32 cqp_head; + u64 u64temp; + + spin_lock_irqsave(&nesdev->cqp.lock, flags); + + if (((((nesdev->cqp.sq_tail+(nesdev->cqp.sq_size*2))-nesdev->cqp.sq_head) & + (nesdev->cqp.sq_size - 1)) != 1) + && (list_empty(&nesdev->cqp_pending_reqs))) { + cqp_head = nesdev->cqp.sq_head++; + nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1; + cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head]; + memcpy(cqp_wqe, &cqp_request->cqp_wqe, sizeof(*cqp_wqe)); + barrier(); + u64temp = (unsigned long)cqp_request; + set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_COMP_SCRATCH_LOW_IDX, + u64temp); + nes_debug(NES_DBG_CQP, "CQP request (opcode 0x%02X), line 1 = 0x%08X put on CQPs SQ," + " request = %p, cqp_head = %u, cqp_tail = %u, cqp_size = %u," + " waiting = %d, refcount = %d.\n", + le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f, + le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX]), cqp_request, + nesdev->cqp.sq_head, nesdev->cqp.sq_tail, nesdev->cqp.sq_size, + cqp_request->waiting, atomic_read(&cqp_request->refcount)); + barrier(); + if (ring_doorbell) { + /* Ring doorbell (1 WQEs) */ + nes_write32(nesdev->regs+NES_WQE_ALLOC, 0x01800000 | nesdev->cqp.qp_id); + } + + barrier(); + } else { + nes_debug(NES_DBG_CQP, "CQP request %p (opcode 0x%02X), line 1 = 0x%08X" + " put on the pending queue.\n", + cqp_request, + le32_to_cpu(cqp_request->cqp_wqe.wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f, + le32_to_cpu(cqp_request->cqp_wqe.wqe_words[NES_CQP_WQE_ID_IDX])); + list_add_tail(&cqp_request->list, &nesdev->cqp_pending_reqs); + } + + spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + + return; } @@ -418,9 +634,6 @@ int nes_arp_table(struct nes_device *nesdev, u32 ip_addr, u8 *mac_addr, u32 acti int arp_index; int err = 0; - dprintk("%s: nesadapter=%p, ip_addr=%08x, action=%u, next_arp_index=%u\n", - __FUNCTION__, nesadapter, ip_addr, action, nesadapter->next_arp_index); - for (arp_index = 0; (u32) arp_index < nesadapter->arp_table_size; arp_index++) { if (nesadapter->arp_table[arp_index].ip_addr == ip_addr) break; @@ -428,45 +641,43 @@ int nes_arp_table(struct nes_device *nesdev, u32 ip_addr, u8 *mac_addr, u32 acti if (action == NES_ARP_ADD) { if (arp_index != nesadapter->arp_table_size) { - return (-1); + return -1; } arp_index = 0; err = nes_alloc_resource(nesadapter, nesadapter->allocated_arps, - nesadapter->arp_table_size, &arp_index, &nesadapter->next_arp_index); + nesadapter->arp_table_size, (u32 *)&arp_index, &nesadapter->next_arp_index); if (err) { - dprintk("%s: nes_alloc_resource returned error = %u\n", - __FUNCTION__, err); - return (err); + nes_debug(NES_DBG_NETDEV, "nes_alloc_resource returned error = %u\n", err); + return err; } - dprintk("%s: ADD, arp_index=%d\n", __FUNCTION__, arp_index); + nes_debug(NES_DBG_NETDEV, "ADD, arp_index=%d\n", arp_index); nesadapter->arp_table[arp_index].ip_addr = ip_addr; memcpy(nesadapter->arp_table[arp_index].mac_addr, mac_addr, ETH_ALEN); - return (arp_index); + return arp_index; } /* DELETE or RESOLVE */ if (arp_index == nesadapter->arp_table_size) { - dprintk("%s: mac address not in ARP table - cannot delete or resolve\n", - __FUNCTION__); - return (-1); + nes_debug(NES_DBG_NETDEV, "mac address not in ARP table - cannot delete or resolve\n"); + return -1; } if (action == NES_ARP_RESOLVE) { - dprintk("%s: RESOLVE, arp_index=%d\n", __FUNCTION__, arp_index); - return (arp_index); + nes_debug(NES_DBG_NETDEV, "RESOLVE, arp_index=%d\n", arp_index); + return arp_index; } if (action == NES_ARP_DELETE) { - dprintk("%s: DELETE, arp_index=%d\n", __FUNCTION__, arp_index); + nes_debug(NES_DBG_NETDEV, "DELETE, arp_index=%d\n", arp_index); nesadapter->arp_table[arp_index].ip_addr = 0; memset(nesadapter->arp_table[arp_index].mac_addr, 0x00, ETH_ALEN); nes_free_resource(nesadapter, nesadapter->allocated_arps, arp_index); - return (arp_index); + return arp_index; } - return (-1); + return -1; } @@ -478,7 +689,11 @@ void nes_mh_fix(unsigned long parm) unsigned long flags; struct nes_device *nesdev = (struct nes_device *)parm; struct nes_adapter *nesadapter = nesdev->nesadapter; + struct nes_vnic *nesvnic; u32 used_chunks_tx; + u32 temp_used_chunks_tx; + u32 temp_last_used_chunks_tx; + u32 used_chunks_mask; u32 mac_tx_frames_low; u32 mac_tx_frames_high; u32 mac_tx_pauses; @@ -492,12 +707,12 @@ void nes_mh_fix(unsigned long parm) u32 mac_exact_match; u32 mpp_debug; u32 i=0; - + u32 chunks_tx_progress = 0; spin_lock_irqsave(&nesadapter->phy_lock, flags); if ((nesadapter->mac_sw_state[0] != NES_MAC_SW_IDLE) || (nesadapter->mac_link_down[0])) { spin_unlock_irqrestore(&nesadapter->phy_lock, flags); - return; + goto no_mh_work; } nesadapter->mac_sw_state[0] = NES_MAC_SW_MH; spin_unlock_irqrestore(&nesadapter->phy_lock, flags); @@ -507,25 +722,42 @@ void nes_mh_fix(unsigned long parm) mac_tx_pauses = nes_read_indexed(nesdev, NES_IDX_MAC_TX_PAUSE_FRAMES); used_chunks_tx = nes_read_indexed(nesdev, NES_IDX_USED_CHUNKS_TX); nesdev->mac_pause_frames_sent += mac_tx_pauses; - if ((mac_tx_frames_low) || (mac_tx_frames_high) || - (!used_chunks_tx) || (!nesdev->last_used_chunks_tx) || - (used_chunks_tx < nesdev->last_used_chunks_tx) || - ((!mac_tx_pauses) && - (( nesdev->last_mac_tx_pauses == nesdev->mac_pause_frames_sent )))) { - nesdev->last_mac_tx_pauses = nesdev->mac_pause_frames_sent; + used_chunks_mask = 0; + temp_used_chunks_tx = used_chunks_tx; + temp_last_used_chunks_tx = nesdev->last_used_chunks_tx; + + if (nesdev->netdev[0]) { + nesvnic = netdev_priv(nesdev->netdev[0]); + } else { + break; + } + + for (i=0; i<4; i++) { + used_chunks_mask <<= 8; + if (nesvnic->qp_nic_index[i] != 0xff) { + used_chunks_mask |= 0xff; + if ((temp_used_chunks_tx&0xff)<(temp_last_used_chunks_tx&0xff)) { + chunks_tx_progress = 1; + } + } + temp_used_chunks_tx >>= 8; + temp_last_used_chunks_tx >>= 8; + } + if ((mac_tx_frames_low) || (mac_tx_frames_high) || + (!(used_chunks_tx&used_chunks_mask)) || + (!(nesdev->last_used_chunks_tx&used_chunks_mask)) || + (chunks_tx_progress) ) { nesdev->last_used_chunks_tx = used_chunks_tx; break; } - nesdev->last_mac_tx_pauses = nesdev->mac_pause_frames_sent; nesdev->last_used_chunks_tx = used_chunks_tx; barrier(); - + nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONTROL, 0x00000005); mh_pauses_sent++; mac_tx_pauses = nes_read_indexed(nesdev, NES_IDX_MAC_TX_PAUSE_FRAMES); if (mac_tx_pauses) { nesdev->mac_pause_frames_sent += mac_tx_pauses; - nesdev->last_mac_tx_pauses = nesdev->mac_pause_frames_sent; break; } @@ -540,9 +772,8 @@ void nes_mh_fix(unsigned long parm) /* one last ditch effort to avoid a false positive */ mac_tx_pauses = nes_read_indexed(nesdev, NES_IDX_MAC_TX_PAUSE_FRAMES); if (mac_tx_pauses) { - nesdev->mac_pause_frames_sent += mac_tx_pauses; nesdev->last_mac_tx_pauses = nesdev->mac_pause_frames_sent; - dprintk("%s: failsafe caught slow outbound pause\n", __FUNCTION__); + nes_debug(NES_DBG_HW, "failsafe caught slow outbound pause\n"); break; } mh_detected++; @@ -554,8 +785,8 @@ void nes_mh_fix(unsigned long parm) nes_write32(nesdev->regs+NES_SOFTWARE_RESET, reset_value | 0x0000001d); while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET) - & 0x00000040) != 0x00000040) && (i++ < 5000)) { - // mdelay(1); + & 0x00000040) != 0x00000040) && (i++ < 5000)) { + /* mdelay(1); */ } nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0, 0x00000008); @@ -567,11 +798,14 @@ void nes_mh_fix(unsigned long parm) nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_SIGDET0, 0x00000000); nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_BYPASS0, 0x00000000); nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_LOOPBACK_CONTROL0, 0x00000000); - nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_EQ_CONTROL0, 0xf0002222); + if (nesadapter->OneG_Mode) { + nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_EQ_CONTROL0, 0xf0182222); + } else { + nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_EQ_CONTROL0, 0xf0042222); + } serdes_status = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_RX_EQ_STATUS0); nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000000ff); - nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONTROL, tx_control); nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG, tx_config); nes_write_indexed(nesdev, NES_IDX_MAC_TX_PAUSE_QUANTA, tx_pause_quanta); @@ -583,18 +817,39 @@ void nes_mh_fix(unsigned long parm) } while (0); nesadapter->mac_sw_state[0] = NES_MAC_SW_IDLE; +no_mh_work: nesdev->nesadapter->mh_timer.expires = jiffies + (HZ/5); add_timer(&nesdev->nesadapter->mh_timer); } +/** + * nes_clc + */ +void nes_clc(unsigned long parm) +{ + unsigned long flags; + struct nes_device *nesdev = (struct nes_device *)parm; + struct nes_adapter *nesadapter = nesdev->nesadapter; + + spin_lock_irqsave(&nesadapter->phy_lock, flags); + nesadapter->link_interrupt_count[0] = 0; + nesadapter->link_interrupt_count[1] = 0; + nesadapter->link_interrupt_count[2] = 0; + nesadapter->link_interrupt_count[3] = 0; + spin_unlock_irqrestore(&nesadapter->phy_lock, flags); + + nesadapter->lc_timer.expires = jiffies + 3600 * HZ; /* 1 hour */ + add_timer(&nesadapter->lc_timer); +} + /** * nes_dump_mem */ -void nes_dump_mem(void *addr, int length) +void nes_dump_mem(unsigned int dump_debug_level, void *addr, int length) { char xlate[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'a', 'b', 'c', 'd', 'e', 'f'}; + 'a', 'b', 'c', 'd', 'e', 'f'}; char *ptr; char hex_buf[80]; char ascii_buf[20]; @@ -602,12 +857,16 @@ void nes_dump_mem(void *addr, int length) int num_ascii; int num_hex; + if (!(nes_debug_level & dump_debug_level)) { + return; + } + ptr = addr; if (length > 0x100) { - dprintk("Length truncated from %x to %x\n", length, 0x100); + nes_debug(dump_debug_level, "Length truncated from %x to %x\n", length, 0x100); length = 0x100; } - dprintk("Address=0x%p, length=0x%x (%d)\n", ptr, length, length); + nes_debug(dump_debug_level, "Address=0x%p, length=0x%x (%d)\n", ptr, length, length); memset(ascii_buf, 0, 20); memset(hex_buf, 0, 80); @@ -632,7 +891,7 @@ void nes_dump_mem(void *addr, int length) if (num_ascii >= 17) { /* output line and reset */ - dprintk(" %s | %s\n", hex_buf, ascii_buf); + nes_debug(dump_debug_level, " %s | %s\n", hex_buf, ascii_buf); memset(ascii_buf, 0, 20); memset(hex_buf, 0, 80); num_ascii = 0; @@ -653,199 +912,6 @@ void nes_dump_mem(void *addr, int length) num_ascii++; } - dprintk(" %s | %s\n", hex_buf, ascii_buf); + nes_debug(dump_debug_level, " %s | %s\n", hex_buf, ascii_buf); } } - - -/* -"Everything you wanted to know about CRC algorithms, but were afraid to ask - for fear that errors in your understanding might be detected." Version : 3. -Date : 19 August 1993. -Author : Ross N. Williams. -Net : ross@guest.adelaide.edu.au. -FTP : ftp.adelaide.edu.au/pub/rocksoft/crc_v3.txt -Company : Rocksoft™ Pty Ltd. -Snail : 16 Lerwick Avenue, Hazelwood Park 5066, Australia. -Fax : +61 8 373-4911 (c/- Internode Systems Pty Ltd). -Phone : +61 8 379-9217 (10am to 10pm Adelaide Australia time). -Note : "Rocksoft" is a trademark of Rocksoft Pty Ltd, Australia. -Status : Copyright (C) Ross Williams, 1993. However, permission is granted to - make and distribute verbatim copies of this document provided that this information - block and copyright notice is included. Also, the C code modules included in this - document are fully public domain. - -Thanks : Thanks to Jean-loup Gailly (jloup@chorus.fr) and Mark Adler - (me@quest.jpl.nasa.gov) who both proof read this document and picked - out lots of nits as well as some big fat bugs. - -The current web page for this seems to be http://www.ross.net/crc/crcpaper.html. - -*/ - -/****************************************************************************/ -/* Generate width mask */ -/****************************************************************************/ -/* */ -/* Returns a longword whose value is (2^p_cm->cm_width)-1. */ -/* The trick is to do this portably (e.g. without doing <<32). */ -/* */ -/* Author: Tristan Gross */ -/* Source: "A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS" */ -/* Ross N. Williams */ -/* http://www.rocksoft.com */ -/* */ -/****************************************************************************/ - -static u32 nesCRCWidMask (u32 width) -{ - return(((1L<<(((u32)width)-1))-1L)<<1)|1L; -} - - -/****************************************************************************/ -/* Generate CRC table */ -/****************************************************************************/ -/* */ -/* Source: "A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS" */ -/* Ross N. Williams */ -/* http://www.rocksoft.com */ -/* */ -/****************************************************************************/ -static u32 nes_crc_table_gen ( u32 *pCRCTable, - u32 poly, - u32 order, - u32 reflectIn) -{ - u32 i; - u32 reg; - u32 byte; - u32 topbit = BITMASK(NES_CRC_WID-1); - u32 tmp; - - for (byte=0;byte<256;byte++) { - - // If we need to creat a reflected table we must reflect the index (byte) and - // reflect the final reg - tmp = (reflectIn) ? reflect(byte,8): byte; - - reg = tmp << (NES_CRC_WID-8); - - for (i=0; i<8; i++) { - if (reg & topbit) { - reg = (reg << 1) ^ poly; - } else { - reg <<= 1; - } - } - - reg = (reflectIn) ? reflect(reg,order): reg; - pCRCTable[byte] = reg & nesCRCWidMask(NES_CRC_WID); - } - - return(0); -} - - -/****************************************************************************/ -/* Perform 32 bit based CRC calculation */ -/****************************************************************************/ -/* */ -/* Source: "A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS" */ -/* Ross N. Williams */ -/* http://www.rocksoft.com */ -/* */ -/* This performs a standard 32 bit crc on an array of arbitrary length */ -/* with an arbitrary initial value and passed generator polynomial */ -/* in the form of a crc table. */ -/* */ -/****************************************************************************/ -static u32 reflect (u32 data, u32 num) -{ - /* Reflects the lower num bits in 'data' around their center point. */ - u32 i; - u32 j = 1; - u32 result = 0; - - for (i=(u32)1<<(num-1); i; i>>=1) { - if (data & i) result|=j; - j <<= 1; - } - return(result); -} - - -/** - * byte_swap - */ -static u32 byte_swap (u32 data, u32 num) -{ - u32 i; - u32 result = 0; - - if (num%16) { - dprintk("\nbyte_swap: ERROR: num is not an even number of bytes\n"); - /* ASSERT(0); */ - } - - for (i = 0; i < num; i += 8) { - result |= (0xFF & (data >> i)) << (num-8-i); - } - - return(result); -} - - -/** - * nes_crc32 - - * This is a reflected table algorithm. ReflectIn basically - * means to reflect each incomming byte of the data. But to make - * things more complicated, we can instead reflect the initial - * value, the final crc, and shift data to the right using a - * reflected pCRCTable. CRC is FUN!! - */ -u32 nes_crc32 ( u32 reverse, - u32 initialValue, - u32 finalXOR, - u32 messageLength, - u8 *pMessage, - u32 order, - u32 reflectIn, - u32 reflectOut) - -{ - u8 *pBlockAddr = pMessage; - u32 mlen = messageLength; - u32 crc; - - if (0 == nesCRCInitialized) { - nes_crc_table_gen( &nesCRCTable[0], CRC32C_POLY, ORDER, REFIN); - nesCRCInitialized = 1; - } - - crc = (reflectIn) ? reflect(initialValue,order): initialValue; - - while (mlen--) { - /* printf("byte = %x, index = %u, crctable[index] = %x\n", - *pBlockAddr, (crc & 0xffL) ^ *pBlockAddr, - nesCRCTable[(crc & 0xffL) ^ *pBlockAddr]); - */ - if (reflectIn) { - crc = nesCRCTable[(crc & 0xffL ) ^ *pBlockAddr++] ^ (crc >> 8); - } else { - crc = nesCRCTable[((crc>>24) ^ *pBlockAddr++) & 0xFFL] ^ (crc << 8); - } - } - - /* if reflectOut and reflectIn are both set, we don't */ - /* do anything since reflecting twice effectively does nothing. */ - crc = ((reflectIn)^(reflectOut)) ? reflect(crc,order): crc; - - crc = crc^finalXOR; - - /* We don't really use this, but it is here for completeness */ - crc = (reverse) ? byte_swap(crc,32): crc; - - return (crc); -} - diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index 8ecbb23..1b3032f 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2007 NetEffect, Inc. All rights reserved. + * Copyright (c) 2006 - 2008 NetEffect, Inc. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -34,23 +34,21 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/random.h> +#include <linux/highmem.h> #include <asm/byteorder.h> #include <rdma/ib_verbs.h> #include <rdma/iw_cm.h> #include <rdma/ib_user_verbs.h> + #include "nes.h" -#ifndef OFED_1_2 + #include <rdma/ib_umem.h> -#endif atomic_t mod_qp_timouts; atomic_t qps_created; -extern atomic_t cm_closes; atomic_t sw_qps_destroyed; -extern int disable_mpa_crc; - /** * nes_alloc_mw @@ -72,8 +70,6 @@ static struct ib_mw *nes_alloc_mw(struct ib_pd *ibpd) { u32 driver_key = 0; u8 stag_key = 0; - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); - get_random_bytes(&next_stag_index, sizeof(next_stag_index)); stag_key = (u8)next_stag_index; @@ -85,87 +81,77 @@ static struct ib_mw *nes_alloc_mw(struct ib_pd *ibpd) { ret = nes_alloc_resource(nesadapter, nesadapter->allocated_mrs, nesadapter->max_mr, &stag_index, &next_stag_index); if (ret) { - return (ERR_PTR(ret)); + return ERR_PTR(ret); } - nesmr = kmalloc(sizeof(*nesmr), GFP_KERNEL); + nesmr = kzalloc(sizeof(*nesmr), GFP_KERNEL); if (!nesmr) { nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index); - return (ERR_PTR(-ENOMEM)); + return ERR_PTR(-ENOMEM); } stag = stag_index << 8; stag |= driver_key; stag += (u32)stag_key; - dprintk("%s: Registering STag 0x%08X, index = 0x%08X\n", - __FUNCTION__, stag, stag_index); + nes_debug(NES_DBG_MR, "Registering STag 0x%08X, index = 0x%08X\n", + stag, stag_index); /* Register the region with the adapter */ - spin_lock_irqsave(&nesdev->cqp.lock, flags); - - cqp_request = nes_get_cqp_request(nesdev, NES_CQP_REQUEST_HOLDING_LOCK); - if (NULL == cqp_request) { - dprintk("%s: Failed to get a cqp_request.\n", __FUNCTION__); + cqp_request = nes_get_cqp_request(nesdev); + if (cqp_request == NULL) { kfree(nesmr); nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); - return (ERR_PTR(-ENOMEM)); + return ERR_PTR(-ENOMEM); } + cqp_request->waiting = 1; cqp_wqe = &cqp_request->cqp_wqe; cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = - cpu_to_le32( NES_CQP_ALLOCATE_STAG | NES_CQP_STAG_RIGHTS_REMOTE_READ | + cpu_to_le32(NES_CQP_ALLOCATE_STAG | NES_CQP_STAG_RIGHTS_REMOTE_READ | NES_CQP_STAG_RIGHTS_REMOTE_WRITE | NES_CQP_STAG_VA_TO | NES_CQP_STAG_REM_ACC_EN); - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX] = 0; - *((struct nes_hw_cqp **)&cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_LOW_IDX]) = - &nesdev->cqp; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] = 0; - - cqp_wqe->wqe_words[NES_CQP_STAG_WQE_LEN_LOW_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_STAG_WQE_LEN_HIGH_PD_IDX] = - cpu_to_le32(nespd->pd_id&0x00007fff); - cqp_wqe->wqe_words[NES_CQP_STAG_WQE_STAG_IDX] = cpu_to_le32(stag); - - cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PA_LOW_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PA_HIGH_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PBL_BLK_COUNT_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PBL_LEN_IDX] = 0; + nes_fill_init_cqp_wqe(cqp_wqe, nesdev); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_LEN_HIGH_PD_IDX, (nespd->pd_id & 0x00007fff)); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_STAG_IDX, stag); atomic_set(&cqp_request->refcount, 2); - nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_HOLDING_LOCK, - NES_CQP_REQUEST_RING_DOORBELL); + nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_RING_DOORBELL); /* Wait for CQP */ - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); - - ret = wait_event_timeout(cqp_request->waitq, (0 != cqp_request->request_done), + ret = wait_event_timeout(cqp_request->waitq, (cqp_request->request_done != 0), NES_EVENT_TIMEOUT); - dprintk("%s: Register STag 0x%08X completed, wait_event_timeout ret = %u," + nes_debug(NES_DBG_MR, "Register STag 0x%08X completed, wait_event_timeout ret = %u," " CQP Major:Minor codes = 0x%04X:0x%04X.\n", - __FUNCTION__, stag, ret, cqp_request->major_code, cqp_request->minor_code); + stag, ret, cqp_request->major_code, cqp_request->minor_code); if ((!ret) || (cqp_request->major_code)) { if (atomic_dec_and_test(&cqp_request->refcount)) { - spin_lock_irqsave(&nesdev->cqp.lock, flags); - list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + if (cqp_request->dynamic) { + kfree(cqp_request); + } else { + spin_lock_irqsave(&nesdev->cqp.lock, flags); + list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); + spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + } } kfree(nesmr); nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index); if (!ret) { - return (ERR_PTR(-ETIME)); + return ERR_PTR(-ETIME); } else { - return (ERR_PTR(-ENOMEM)); + return ERR_PTR(-ENOMEM); } } else { if (atomic_dec_and_test(&cqp_request->refcount)) { - spin_lock_irqsave(&nesdev->cqp.lock, flags); - list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + if (cqp_request->dynamic) { + kfree(cqp_request); + } else { + spin_lock_irqsave(&nesdev->cqp.lock, flags); + list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); + spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + } } } @@ -175,7 +161,7 @@ static struct ib_mw *nes_alloc_mw(struct ib_pd *ibpd) { nesmr->pbl_4k = 0; nesmr->pbls_used = 0; - return (ibmw); + return ibmw; } @@ -194,47 +180,38 @@ static int nes_dealloc_mw(struct ib_mw *ibmw) unsigned long flags; int ret; - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); - /* Deallocate the window with the adapter */ - spin_lock_irqsave(&nesdev->cqp.lock, flags); - - cqp_request = nes_get_cqp_request(nesdev, NES_CQP_REQUEST_HOLDING_LOCK); - if (NULL == cqp_request) { - dprintk("%s: Failed to get a cqp_request.\n", __FUNCTION__); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); - return (-ENOMEM); + cqp_request = nes_get_cqp_request(nesdev); + if (cqp_request == NULL) { + nes_debug(NES_DBG_MR, "Failed to get a cqp_request.\n"); + return -ENOMEM; } cqp_request->waiting = 1; cqp_wqe = &cqp_request->cqp_wqe; - - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = NES_CQP_DEALLOCATE_STAG; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX] = 0; - *((struct nes_hw_cqp **)&cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_LOW_IDX]) = - &nesdev->cqp; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PBL_BLK_COUNT_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PBL_LEN_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_STAG_WQE_STAG_IDX] = ibmw->rkey; + nes_fill_init_cqp_wqe(cqp_wqe, nesdev); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, NES_CQP_DEALLOCATE_STAG); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_STAG_IDX, ibmw->rkey); atomic_set(&cqp_request->refcount, 2); - nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_HOLDING_LOCK, - NES_CQP_REQUEST_RING_DOORBELL); + nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_RING_DOORBELL); /* Wait for CQP */ - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); - dprintk("Waiting for deallocate STag 0x%08X to complete.\n", ibmw->rkey); + nes_debug(NES_DBG_MR, "Waiting for deallocate STag 0x%08X to complete.\n", + ibmw->rkey); ret = wait_event_timeout(cqp_request->waitq, (0 != cqp_request->request_done), NES_EVENT_TIMEOUT); - dprintk("Deallocate STag completed, wait_event_timeout ret = %u," + nes_debug(NES_DBG_MR, "Deallocate STag completed, wait_event_timeout ret = %u," " CQP Major:Minor codes = 0x%04X:0x%04X.\n", ret, cqp_request->major_code, cqp_request->minor_code); if ((!ret) || (cqp_request->major_code)) { if (atomic_dec_and_test(&cqp_request->refcount)) { - spin_lock_irqsave(&nesdev->cqp.lock, flags); - list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + if (cqp_request->dynamic) { + kfree(cqp_request); + } else { + spin_lock_irqsave(&nesdev->cqp.lock, flags); + list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); + spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + } } if (!ret) { err = -ETIME; @@ -243,17 +220,21 @@ static int nes_dealloc_mw(struct ib_mw *ibmw) } } else { if (atomic_dec_and_test(&cqp_request->refcount)) { - spin_lock_irqsave(&nesdev->cqp.lock, flags); - list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + if (cqp_request->dynamic) { + kfree(cqp_request); + } else { + spin_lock_irqsave(&nesdev->cqp.lock, flags); + list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); + spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + } } } nes_free_resource(nesadapter, nesadapter->allocated_mrs, - (ibmw->rkey&0x0fffff00) >> 8); + (ibmw->rkey & 0x0fffff00) >> 8); kfree(nesmr); - return (err); + return err; } @@ -263,6 +244,7 @@ static int nes_dealloc_mw(struct ib_mw *ibmw) static int nes_bind_mw(struct ib_qp *ibqp, struct ib_mw *ibmw, struct ib_mw_bind *ibmw_bind) { + u64 u64temp; struct nes_vnic *nesvnic = to_nesvnic(ibqp->device); struct nes_device *nesdev = nesvnic->nesdev; /* struct nes_mr *nesmr = to_nesmw(ibmw); */ @@ -273,9 +255,8 @@ static int nes_bind_mw(struct ib_qp *ibqp, struct ib_mw *ibmw, u32 wqe_misc = 0; u32 qsize; - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); if (nesqp->ibqp_state > IB_QPS_RTS) - return (-EINVAL); + return -EINVAL; spin_lock_irqsave(&nesqp->lock, flags); @@ -284,14 +265,15 @@ static int nes_bind_mw(struct ib_qp *ibqp, struct ib_mw *ibmw, /* Check for SQ overflow */ if (((head + (2 * qsize) - nesqp->hwqp.sq_tail) % qsize) == (qsize - 1)) { - return (-EINVAL); + spin_unlock_irqrestore(&nesqp->lock, flags); + return -EINVAL; } wqe = &nesqp->hwqp.sq_vbase[head]; - /* dprintk("%s:processing sq wqe at %p, head = %u.\n", __FUNCTION__, wqe, head); */ - *((u64 *)&wqe->wqe_words[NES_IWARP_SQ_WQE_COMP_SCRATCH_LOW_IDX]) = ibmw_bind->wr_id; - *((struct nes_qp **)&wqe->wqe_words[NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX]) = nesqp; - wqe->wqe_words[NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX] |= head; + /* nes_debug(NES_DBG_MR, "processing sq wqe at %p, head = %u.\n", wqe, head); */ + nes_fill_init_qp_wqe(wqe, nesqp, head); + u64temp = ibmw_bind->wr_id; + set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_SCRATCH_LOW_IDX, u64temp); wqe_misc = NES_IWARP_SQ_OP_BIND; wqe_misc |= NES_IWARP_SQ_WQE_LOCAL_FENCE; @@ -306,14 +288,14 @@ static int nes_bind_mw(struct ib_qp *ibqp, struct ib_mw *ibmw, wqe_misc |= NES_CQP_STAG_RIGHTS_REMOTE_READ; } - wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] = cpu_to_le32(wqe_misc); - wqe->wqe_words[NES_IWARP_SQ_BIND_WQE_MR_IDX] = cpu_to_le32(ibmw_bind->mr->lkey); - wqe->wqe_words[NES_IWARP_SQ_BIND_WQE_MW_IDX] = cpu_to_le32(ibmw->rkey); - wqe->wqe_words[NES_IWARP_SQ_BIND_WQE_LENGTH_LOW_IDX] = - cpu_to_le32(ibmw_bind->length); + set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_MISC_IDX, wqe_misc); + set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_BIND_WQE_MR_IDX, ibmw_bind->mr->lkey); + set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_BIND_WQE_MW_IDX, ibmw->rkey); + set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_BIND_WQE_LENGTH_LOW_IDX, + ibmw_bind->length); wqe->wqe_words[NES_IWARP_SQ_BIND_WQE_LENGTH_HIGH_IDX] = 0; - *((u64 *)&wqe->wqe_words[NES_IWARP_SQ_BIND_WQE_VA_FBO_LOW_IDX]) = - cpu_to_le64(ibmw_bind->addr); + u64temp = (u64)ibmw_bind->addr; + set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_BIND_WQE_VA_FBO_LOW_IDX, u64temp); head++; if (head >= qsize) @@ -322,12 +304,12 @@ static int nes_bind_mw(struct ib_qp *ibqp, struct ib_mw *ibmw, nesqp->hwqp.sq_head = head; barrier(); - nes_write32(nesdev->regs + NES_WQE_ALLOC, + nes_write32(nesdev->regs+NES_WQE_ALLOC, (1 << 24) | 0x00800000 | nesqp->hwqp.qp_id); spin_unlock_irqrestore(&nesqp->lock, flags); - return (0); + return 0; } @@ -335,8 +317,9 @@ static int nes_bind_mw(struct ib_qp *ibqp, struct ib_mw *ibmw, * nes_alloc_fmr */ static struct ib_fmr *nes_alloc_fmr(struct ib_pd *ibpd, - int ibmr_access_flags, - struct ib_fmr_attr *ibfmr_attr) { + int ibmr_access_flags, + struct ib_fmr_attr *ibfmr_attr) +{ unsigned long flags; struct nes_pd *nespd = to_nespd(ibpd); struct nes_vnic *nesvnic = to_nesvnic(ibpd->device); @@ -350,13 +333,11 @@ static struct ib_fmr *nes_alloc_fmr(struct ib_pd *ibpd, u32 stag_index = 0; u32 next_stag_index = 0; u32 driver_key = 0; + u32 opcode = 0; u8 stag_key = 0; int i=0; struct nes_vpbl vpbl; - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); - - get_random_bytes(&next_stag_index, sizeof(next_stag_index)); stag_key = (u8)next_stag_index; @@ -366,15 +347,15 @@ static struct ib_fmr *nes_alloc_fmr(struct ib_pd *ibpd, next_stag_index %= nesadapter->max_mr; ret = nes_alloc_resource(nesadapter, nesadapter->allocated_mrs, - nesadapter->max_mr, &stag_index, &next_stag_index); + nesadapter->max_mr, &stag_index, &next_stag_index); if (ret) { - goto failed_resource_alloc; + goto failed_resource_alloc; } - nesfmr = kmalloc(sizeof(*nesfmr), GFP_KERNEL); + nesfmr = kzalloc(sizeof(*nesfmr), GFP_KERNEL); if (!nesfmr) { - ret = -ENOMEM; - goto failed_fmr_alloc; + ret = -ENOMEM; + goto failed_fmr_alloc; } nesfmr->nesmr.mode = IWNES_MEMREG_TYPE_FMR; @@ -394,17 +375,17 @@ static struct ib_fmr *nes_alloc_fmr(struct ib_pd *ibpd, /* use two level 4K PBLs */ /* add support for two level 256B PBLs */ nesfmr->nesmr.pbl_4k = 1; - nesfmr->nesmr.pbls_used = 1 + (ibfmr_attr->max_pages>>9) + - ((ibfmr_attr->max_pages&511)?1:0); + nesfmr->nesmr.pbls_used = 1 + (ibfmr_attr->max_pages >> 9) + + ((ibfmr_attr->max_pages & 511) ? 1 : 0); } /* Register the region with the adapter */ - spin_lock_irqsave(&nesdev->cqp.lock, flags); + spin_lock_irqsave(&nesadapter->pbl_lock, flags); /* track PBL resources */ if (nesfmr->nesmr.pbls_used != 0) { if (nesfmr->nesmr.pbl_4k) { if (nesfmr->nesmr.pbls_used > nesadapter->free_4kpbl) { - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); ret = -ENOMEM; goto failed_vpbl_alloc; } else { @@ -412,7 +393,7 @@ static struct ib_fmr *nes_alloc_fmr(struct ib_pd *ibpd, } } else { if (nesfmr->nesmr.pbls_used > nesadapter->free_256pbl) { - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); ret = -ENOMEM; goto failed_vpbl_alloc; } else { @@ -421,148 +402,149 @@ static struct ib_fmr *nes_alloc_fmr(struct ib_pd *ibpd, } } - // one level pbl - if ( nesfmr->nesmr.pbls_used == 0 ) { - nesfmr->root_vpbl.pbl_vbase = 0; - dprintk( "%s(%d) zero level pbl \n", __FUNCTION__, __LINE__ ); - } - else if ( nesfmr->nesmr.pbls_used == 1 ) { - // can change it to kmalloc & dma_map_single - nesfmr->root_vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev, 4096, - &nesfmr->root_vpbl.pbl_pbase); - if (!nesfmr->root_vpbl.pbl_vbase) { - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); - ret = -ENOMEM; - goto failed_vpbl_alloc; - } - nesfmr->leaf_pbl_cnt = 0; - dprintk( "%s(%d) one level pbl, root_vpbl.pbl_vbase=%p \n", __FUNCTION__, __LINE__, nesfmr->root_vpbl.pbl_vbase ); - } - // two level pbl + /* one level pbl */ + if (nesfmr->nesmr.pbls_used == 0) { + nesfmr->root_vpbl.pbl_vbase = NULL; + nes_debug(NES_DBG_MR, "zero level pbl \n"); + } else if (nesfmr->nesmr.pbls_used == 1) { + /* can change it to kmalloc & dma_map_single */ + nesfmr->root_vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev, 4096, + &nesfmr->root_vpbl.pbl_pbase); + if (!nesfmr->root_vpbl.pbl_vbase) { + spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); + ret = -ENOMEM; + goto failed_vpbl_alloc; + } + nesfmr->leaf_pbl_cnt = 0; + nes_debug(NES_DBG_MR, "one level pbl, root_vpbl.pbl_vbase=%p \n", + nesfmr->root_vpbl.pbl_vbase); + } + /* two level pbl */ else { - nesfmr->root_vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev, 8192, - &nesfmr->root_vpbl.pbl_pbase); - if (!nesfmr->root_vpbl.pbl_vbase) { - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); - ret = -ENOMEM; - goto failed_vpbl_alloc; - } - - nesfmr->root_vpbl.leaf_vpbl = kmalloc(sizeof(*nesfmr->root_vpbl.leaf_vpbl)*1024, GFP_KERNEL); - if (!nesfmr->root_vpbl.leaf_vpbl) { - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); - ret = -ENOMEM; - goto failed_leaf_vpbl_alloc; - } - - nesfmr->leaf_pbl_cnt = nesfmr->nesmr.pbls_used-1; - dprintk( "%s(%d) two level pbl, root_vpbl.pbl_vbase=%p leaf_pbl_cnt=%d root_vpbl.leaf_vpbl=%p\n", - __FUNCTION__, __LINE__, nesfmr->root_vpbl.pbl_vbase, nesfmr->leaf_pbl_cnt, nesfmr->root_vpbl.leaf_vpbl ); - - for ( i=0; i<nesfmr->leaf_pbl_cnt; i++ ) - nesfmr->root_vpbl.leaf_vpbl[i].pbl_vbase = 0; - - for ( i=0; i<nesfmr->leaf_pbl_cnt; i++ ) { - vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev, 4096, - &vpbl.pbl_pbase); - - if (!vpbl.pbl_vbase) { - ret = -ENOMEM; - goto failed_leaf_vpbl_pages_alloc; - } - - nesfmr->root_vpbl.pbl_vbase[i].pa_low = cpu_to_le32((u32)vpbl.pbl_pbase); - nesfmr->root_vpbl.pbl_vbase[i].pa_high = cpu_to_le32((u32)((((u64)vpbl.pbl_pbase)>>32))); - nesfmr->root_vpbl.leaf_vpbl[i] = vpbl; - - dprintk( "%s(%d) pbase_low=0x%x, pbase_high=0x%x, vpbl=%p\n", - __FUNCTION__, __LINE__, - nesfmr->root_vpbl.pbl_vbase[i].pa_low, - nesfmr->root_vpbl.pbl_vbase[i].pa_high, - nesfmr->root_vpbl.leaf_vpbl[i]); - } - } - nesfmr->ib_qp = 0; + nesfmr->root_vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev, 8192, + &nesfmr->root_vpbl.pbl_pbase); + if (!nesfmr->root_vpbl.pbl_vbase) { + spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); + ret = -ENOMEM; + goto failed_vpbl_alloc; + } + + nesfmr->root_vpbl.leaf_vpbl = kzalloc(sizeof(*nesfmr->root_vpbl.leaf_vpbl)*1024, GFP_KERNEL); + if (!nesfmr->root_vpbl.leaf_vpbl) { + spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); + ret = -ENOMEM; + goto failed_leaf_vpbl_alloc; + } + + nesfmr->leaf_pbl_cnt = nesfmr->nesmr.pbls_used-1; + nes_debug(NES_DBG_MR, "two level pbl, root_vpbl.pbl_vbase=%p" + " leaf_pbl_cnt=%d root_vpbl.leaf_vpbl=%p\n", + nesfmr->root_vpbl.pbl_vbase, nesfmr->leaf_pbl_cnt, nesfmr->root_vpbl.leaf_vpbl); + + for (i = 0; i < nesfmr->leaf_pbl_cnt; i++) + nesfmr->root_vpbl.leaf_vpbl[i].pbl_vbase = NULL; + + for (i = 0; i < nesfmr->leaf_pbl_cnt; i++) { + vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev, 4096, + &vpbl.pbl_pbase); + + if (!vpbl.pbl_vbase) { + ret = -ENOMEM; + spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); + goto failed_leaf_vpbl_pages_alloc; + } + + nesfmr->root_vpbl.pbl_vbase[i].pa_low = cpu_to_le32((u32)vpbl.pbl_pbase); + nesfmr->root_vpbl.pbl_vbase[i].pa_high = cpu_to_le32((u32)((((u64)vpbl.pbl_pbase)>>32))); + nesfmr->root_vpbl.leaf_vpbl[i] = vpbl; + + nes_debug(NES_DBG_MR, "pbase_low=0x%x, pbase_high=0x%x, vpbl=%p\n", + nesfmr->root_vpbl.pbl_vbase[i].pa_low, + nesfmr->root_vpbl.pbl_vbase[i].pa_high, + &nesfmr->root_vpbl.leaf_vpbl[i]); + } + } + nesfmr->ib_qp = NULL; nesfmr->access_rights =0; stag = stag_index << 8; stag |= driver_key; stag += (u32)stag_key; - cqp_request = nes_get_cqp_request(nesdev, NES_CQP_REQUEST_HOLDING_LOCK); - if (NULL == cqp_request) { - dprintk("%s: Failed to get a cqp_request.\n", __FUNCTION__); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); + cqp_request = nes_get_cqp_request(nesdev); + if (cqp_request == NULL) { + nes_debug(NES_DBG_MR, "Failed to get a cqp_request.\n"); ret = -ENOMEM; goto failed_leaf_vpbl_pages_alloc; } cqp_request->waiting = 1; cqp_wqe = &cqp_request->cqp_wqe; - dprintk("%s: Registering STag 0x%08X, index = 0x%08X\n", - __FUNCTION__, stag, stag_index); - - - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = - NES_CQP_ALLOCATE_STAG | - NES_CQP_STAG_VA_TO | - NES_CQP_STAG_MR; + nes_debug(NES_DBG_MR, "Registering STag 0x%08X, index = 0x%08X\n", + stag, stag_index); + opcode = NES_CQP_ALLOCATE_STAG | NES_CQP_STAG_VA_TO | NES_CQP_STAG_MR; if (nesfmr->nesmr.pbl_4k == 1) - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= NES_CQP_STAG_PBL_BLK_SIZE; + opcode |= NES_CQP_STAG_PBL_BLK_SIZE; - if ( ibmr_access_flags & IB_ACCESS_REMOTE_WRITE ) { - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= NES_CQP_STAG_RIGHTS_REMOTE_WRITE | NES_CQP_STAG_RIGHTS_LOCAL_WRITE | NES_CQP_STAG_REM_ACC_EN; - nesfmr->access_rights |= NES_CQP_STAG_RIGHTS_REMOTE_WRITE | NES_CQP_STAG_RIGHTS_LOCAL_WRITE | NES_CQP_STAG_REM_ACC_EN; + if (ibmr_access_flags & IB_ACCESS_REMOTE_WRITE) { + opcode |= NES_CQP_STAG_RIGHTS_REMOTE_WRITE | + NES_CQP_STAG_RIGHTS_LOCAL_WRITE | NES_CQP_STAG_REM_ACC_EN; + nesfmr->access_rights |= + NES_CQP_STAG_RIGHTS_REMOTE_WRITE | NES_CQP_STAG_RIGHTS_LOCAL_WRITE | + NES_CQP_STAG_REM_ACC_EN; } - if ( ibmr_access_flags & IB_ACCESS_REMOTE_READ ) { - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= NES_CQP_STAG_RIGHTS_REMOTE_READ | NES_CQP_STAG_RIGHTS_LOCAL_READ | NES_CQP_STAG_REM_ACC_EN; - nesfmr->access_rights |= NES_CQP_STAG_RIGHTS_REMOTE_READ | NES_CQP_STAG_RIGHTS_LOCAL_READ | NES_CQP_STAG_REM_ACC_EN; + if (ibmr_access_flags & IB_ACCESS_REMOTE_READ) { + opcode |= NES_CQP_STAG_RIGHTS_REMOTE_READ | + NES_CQP_STAG_RIGHTS_LOCAL_READ | NES_CQP_STAG_REM_ACC_EN; + nesfmr->access_rights |= + NES_CQP_STAG_RIGHTS_REMOTE_READ | NES_CQP_STAG_RIGHTS_LOCAL_READ | + NES_CQP_STAG_REM_ACC_EN; } - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX] = 0; - *((struct nes_hw_cqp **)&cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_LOW_IDX]) = &nesdev->cqp; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] = 0; - - cqp_wqe->wqe_words[NES_CQP_STAG_WQE_LEN_LOW_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_STAG_WQE_LEN_HIGH_PD_IDX] = cpu_to_le32(nespd->pd_id&0x00007fff); - cqp_wqe->wqe_words[NES_CQP_STAG_WQE_STAG_IDX] = cpu_to_le32(stag); + nes_fill_init_cqp_wqe(cqp_wqe, nesdev); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, opcode); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_LEN_HIGH_PD_IDX, (nespd->pd_id & 0x00007fff)); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_STAG_IDX, stag); - cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PA_LOW_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PA_HIGH_IDX] = 0; cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PBL_BLK_COUNT_IDX] = - cpu_to_le32((nesfmr->nesmr.pbls_used>1)?(nesfmr->nesmr.pbls_used-1):nesfmr->nesmr.pbls_used); - cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PBL_LEN_IDX] = 0; + cpu_to_le32((nesfmr->nesmr.pbls_used>1) ? + (nesfmr->nesmr.pbls_used-1) : nesfmr->nesmr.pbls_used); atomic_set(&cqp_request->refcount, 2); - nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_HOLDING_LOCK, - NES_CQP_REQUEST_RING_DOORBELL); + nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_RING_DOORBELL); /* Wait for CQP */ - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); - - ret = wait_event_timeout(cqp_request->waitq, (0 != cqp_request->request_done), + ret = wait_event_timeout(cqp_request->waitq, (cqp_request->request_done != 0), NES_EVENT_TIMEOUT); - dprintk("%s: Register STag 0x%08X completed, wait_event_timeout ret = %u," + nes_debug(NES_DBG_MR, "Register STag 0x%08X completed, wait_event_timeout ret = %u," " CQP Major:Minor codes = 0x%04X:0x%04X.\n", - __FUNCTION__, stag, ret, cqp_request->major_code, cqp_request->minor_code); + stag, ret, cqp_request->major_code, cqp_request->minor_code); if ((!ret) || (cqp_request->major_code)) { if (atomic_dec_and_test(&cqp_request->refcount)) { - spin_lock_irqsave(&nesdev->cqp.lock, flags); - list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + if (cqp_request->dynamic) { + kfree(cqp_request); + } else { + spin_lock_irqsave(&nesdev->cqp.lock, flags); + list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); + spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + } } ret = (!ret) ? -ETIME : -EIO; goto failed_leaf_vpbl_pages_alloc; } else { if (atomic_dec_and_test(&cqp_request->refcount)) { - spin_lock_irqsave(&nesdev->cqp.lock, flags); - list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + if (cqp_request->dynamic) { + kfree(cqp_request); + } else { + spin_lock_irqsave(&nesdev->cqp.lock, flags); + list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); + spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + } } } @@ -570,31 +552,35 @@ static struct ib_fmr *nes_alloc_fmr(struct ib_pd *ibpd, nesfmr->nesmr.ibfmr.rkey = stag; nesfmr->attr = *ibfmr_attr; - return (&nesfmr->nesmr.ibfmr); - failed_leaf_vpbl_pages_alloc: - // unroll all allocated pages - for ( i=0; i<nesfmr->leaf_pbl_cnt; i++ ) { - if ( nesfmr->root_vpbl.leaf_vpbl[i].pbl_vbase ) { - pci_free_consistent(nesdev->pcidev, 4096, nesfmr->root_vpbl.leaf_vpbl[i].pbl_vbase, - nesfmr->root_vpbl.leaf_vpbl[i].pbl_pbase); - } + return &nesfmr->nesmr.ibfmr; + + failed_leaf_vpbl_pages_alloc: + /* unroll all allocated pages */ + for (i = 0; i < nesfmr->leaf_pbl_cnt; i++) { + if (nesfmr->root_vpbl.leaf_vpbl[i].pbl_vbase) { + pci_free_consistent(nesdev->pcidev, 4096, nesfmr->root_vpbl.leaf_vpbl[i].pbl_vbase, + nesfmr->root_vpbl.leaf_vpbl[i].pbl_pbase); + } } if (nesfmr->root_vpbl.leaf_vpbl) - kfree( nesfmr->root_vpbl.leaf_vpbl ); - failed_leaf_vpbl_alloc: - if ( nesfmr->leaf_pbl_cnt == 0 ) { - if ( nesfmr->root_vpbl.pbl_vbase ) - pci_free_consistent(nesdev->pcidev, 4096, nesfmr->root_vpbl.pbl_vbase, + kfree(nesfmr->root_vpbl.leaf_vpbl); + + failed_leaf_vpbl_alloc: + if (nesfmr->leaf_pbl_cnt == 0) { + if (nesfmr->root_vpbl.pbl_vbase) + pci_free_consistent(nesdev->pcidev, 4096, nesfmr->root_vpbl.pbl_vbase, + nesfmr->root_vpbl.pbl_pbase); + } else + pci_free_consistent(nesdev->pcidev, 8192, nesfmr->root_vpbl.pbl_vbase, nesfmr->root_vpbl.pbl_pbase); - } - else - pci_free_consistent(nesdev->pcidev, 8192, nesfmr->root_vpbl.pbl_vbase, - nesfmr->root_vpbl.pbl_pbase); - failed_vpbl_alloc: + + failed_vpbl_alloc: kfree(nesfmr); - failed_fmr_alloc: + + failed_fmr_alloc: nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index); - failed_resource_alloc: + + failed_resource_alloc: return ERR_PTR(ret); } @@ -609,8 +595,7 @@ static int nes_dealloc_fmr(struct ib_fmr *ibfmr) struct nes_vnic *nesvnic = to_nesvnic(ibfmr->device); struct nes_device *nesdev = nesvnic->nesdev; struct nes_mr temp_nesmr = *nesmr; - int i=0; - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); + int i = 0; temp_nesmr.ibmw.device = ibfmr->device; temp_nesmr.ibmw.pd = ibfmr->pd; @@ -620,20 +605,20 @@ static int nes_dealloc_fmr(struct ib_fmr *ibfmr) /* free the resources */ if (nesfmr->leaf_pbl_cnt == 0) { /* single PBL case */ - if ( nesfmr->root_vpbl.pbl_vbase ) - pci_free_consistent(nesdev->pcidev, 4096, nesfmr->root_vpbl.pbl_vbase, - nesfmr->root_vpbl.pbl_pbase); + if (nesfmr->root_vpbl.pbl_vbase) + pci_free_consistent(nesdev->pcidev, 4096, nesfmr->root_vpbl.pbl_vbase, + nesfmr->root_vpbl.pbl_pbase); } else { - for (i=0; i<nesfmr->leaf_pbl_cnt; i++) { - pci_free_consistent(nesdev->pcidev, 4096, nesfmr->root_vpbl.leaf_vpbl[i].pbl_vbase, - nesfmr->root_vpbl.leaf_vpbl[i].pbl_pbase); + for (i = 0; i < nesfmr->leaf_pbl_cnt; i++) { + pci_free_consistent(nesdev->pcidev, 4096, nesfmr->root_vpbl.leaf_vpbl[i].pbl_vbase, + nesfmr->root_vpbl.leaf_vpbl[i].pbl_pbase); } kfree(nesfmr->root_vpbl.leaf_vpbl); pci_free_consistent(nesdev->pcidev, 8192, nesfmr->root_vpbl.pbl_vbase, - nesfmr->root_vpbl.pbl_pbase); + nesfmr->root_vpbl.pbl_pbase); } - return (nes_dealloc_mw(&temp_nesmr.ibmw)); + return nes_dealloc_mw(&temp_nesmr.ibmw); } @@ -643,8 +628,7 @@ static int nes_dealloc_fmr(struct ib_fmr *ibfmr) static int nes_map_phys_fmr(struct ib_fmr *ibfmr, u64 *page_list, int list_len, u64 iova) { - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); - return (0); + return 0; } @@ -653,8 +637,7 @@ static int nes_map_phys_fmr(struct ib_fmr *ibfmr, u64 *page_list, */ static int nes_unmap_fmr(struct list_head *ibfmr_list) { - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); - return (0); + return 0; } @@ -668,8 +651,6 @@ static int nes_query_device(struct ib_device *ibdev, struct ib_device_attr *prop struct nes_device *nesdev = nesvnic->nesdev; struct nes_ib_device *nesibdev = nesvnic->nesibdev; - /* dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); */ - memset(props, 0, sizeof(*props)); memcpy(&props->sys_image_guid, nesvnic->netdev->dev_addr, 6); @@ -708,7 +689,7 @@ static int nes_query_device(struct ib_device *ibdev, struct ib_device_attr *prop props->atomic_cap = IB_ATOMIC_NONE; props->max_map_per_fmr = 1; - return (0); + return 0; } @@ -717,8 +698,6 @@ static int nes_query_device(struct ib_device *ibdev, struct ib_device_attr *prop */ static int nes_query_port(struct ib_device *ibdev, u8 port, struct ib_port_attr *props) { - /* dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); */ - memset(props, 0, sizeof(*props)); props->max_mtu = IB_MTU_2048; @@ -738,7 +717,7 @@ static int nes_query_port(struct ib_device *ibdev, u8 port, struct ib_port_attr props->active_speed = 1; props->max_msg_sz = 0x80000000; - return (0); + return 0; } @@ -748,19 +727,17 @@ static int nes_query_port(struct ib_device *ibdev, u8 port, struct ib_port_attr static int nes_modify_port(struct ib_device *ibdev, u8 port, int port_modify_mask, struct ib_port_modify *props) { - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); - return (0); + return 0; } /** * nes_query_pkey */ -static int nes_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 * pkey) +static int nes_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey) { - /* dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); */ *pkey = 0; - return (0); + return 0; } @@ -772,11 +749,10 @@ static int nes_query_gid(struct ib_device *ibdev, u8 port, { struct nes_vnic *nesvnic = to_nesvnic(ibdev); - /* dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); */ memset(&(gid->raw[0]), 0, sizeof(gid->raw)); memcpy(&(gid->raw[0]), nesvnic->netdev->dev_addr, 6); - return (0); + return 0; } @@ -789,36 +765,53 @@ static struct ib_ucontext *nes_alloc_ucontext(struct ib_device *ibdev, { struct nes_vnic *nesvnic = to_nesvnic(ibdev); struct nes_device *nesdev = nesvnic->nesdev; + struct nes_adapter *nesadapter = nesdev->nesadapter; + struct nes_alloc_ucontext_req req; struct nes_alloc_ucontext_resp uresp; struct nes_ucontext *nes_ucontext; struct nes_ib_device *nesibdev = nesvnic->nesibdev; - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); + + if (ib_copy_from_udata(&req, udata, sizeof(struct nes_alloc_ucontext_req))) { + printk(KERN_ERR PFX "Invalid structure size on allocate user context.\n"); + return ERR_PTR(-EINVAL); + } + + if (req.userspace_ver != NES_ABI_USERSPACE_VER) { + printk(KERN_ERR PFX "Invalid userspace driver version detected. Detected version %d, should be %d\n", + req.userspace_ver, NES_ABI_USERSPACE_VER); + return ERR_PTR(-EINVAL); + } + + memset(&uresp, 0, sizeof uresp); uresp.max_qps = nesibdev->max_qp; uresp.max_pds = nesibdev->max_pd; - uresp.wq_size = nesdev->nesadapter->max_qp_wr*2; + uresp.wq_size = nesdev->nesadapter->max_qp_wr * 2; + uresp.virtwq = nesadapter->virtwq; + uresp.kernel_ver = NES_ABI_KERNEL_VER; - nes_ucontext = kmalloc(sizeof *nes_ucontext, GFP_KERNEL); + nes_ucontext = kzalloc(sizeof *nes_ucontext, GFP_KERNEL); if (!nes_ucontext) - return (ERR_PTR(-ENOMEM)); - - memset(nes_ucontext, 0, sizeof(struct nes_ucontext)); + return ERR_PTR(-ENOMEM); nes_ucontext->nesdev = nesdev; - nes_ucontext->mmap_wq_offset = ((uresp.max_pds * 4096) + PAGE_SIZE-1) / PAGE_SIZE; + nes_ucontext->mmap_wq_offset = uresp.max_pds; nes_ucontext->mmap_cq_offset = nes_ucontext->mmap_wq_offset + ((sizeof(struct nes_hw_qp_wqe) * uresp.max_qps * 2) + PAGE_SIZE-1) / PAGE_SIZE; + if (ib_copy_to_udata(udata, &uresp, sizeof uresp)) { kfree(nes_ucontext); - return (ERR_PTR(-EFAULT)); + return ERR_PTR(-EFAULT); } INIT_LIST_HEAD(&nes_ucontext->cq_reg_mem_list); - return(&nes_ucontext->ibucontext); + INIT_LIST_HEAD(&nes_ucontext->qp_reg_mem_list); + atomic_set(&nes_ucontext->usecnt, 1); + return &nes_ucontext->ibucontext; } @@ -830,10 +823,11 @@ static int nes_dealloc_ucontext(struct ib_ucontext *context) /* struct nes_vnic *nesvnic = to_nesvnic(context->device); */ /* struct nes_device *nesdev = nesvnic->nesdev; */ struct nes_ucontext *nes_ucontext = to_nesucontext(context); - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); + if (!atomic_dec_and_test(&nes_ucontext->usecnt)) + return 0; kfree(nes_ucontext); - return (0); + return 0; } @@ -851,46 +845,45 @@ static int nes_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) nes_ucontext = to_nesucontext(context); - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); if (vma->vm_pgoff >= nes_ucontext->mmap_wq_offset) { index = (vma->vm_pgoff - nes_ucontext->mmap_wq_offset) * PAGE_SIZE; index /= ((sizeof(struct nes_hw_qp_wqe) * nesdev->nesadapter->max_qp_wr * 2) + - PAGE_SIZE-1) & (~(PAGE_SIZE-1)); + PAGE_SIZE-1) & (~(PAGE_SIZE-1)); if (!test_bit(index, nes_ucontext->allocated_wqs)) { - dprintk("%s: wq %lu not allocated\n", __FUNCTION__, index); - return (-EFAULT); + nes_debug(NES_DBG_MMAP, "wq %lu not allocated\n", index); + return -EFAULT; } nesqp = nes_ucontext->mmap_nesqp[index]; - if (NULL == nesqp) { - dprintk("%s: wq %lu has a NULL QP base.\n", __FUNCTION__, index); - return (-EFAULT); + if (nesqp == NULL) { + nes_debug(NES_DBG_MMAP, "wq %lu has a NULL QP base.\n", index); + return -EFAULT; } if (remap_pfn_range(vma, vma->vm_start, - nesqp->hwqp.sq_pbase >> PAGE_SHIFT, - vma->vm_end - vma->vm_start, + virt_to_phys(nesqp->hwqp.sq_vbase) >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, vma->vm_page_prot)) { - dprintk("%s: remap_pfn_range failed.\n", __FUNCTION__); - return(-EAGAIN); + nes_debug(NES_DBG_MMAP, "remap_pfn_range failed.\n"); + return -EAGAIN; } vma->vm_private_data = nesqp; - return (0); + return 0; } else { index = vma->vm_pgoff; if (!test_bit(index, nes_ucontext->allocated_doorbells)) - return(-EFAULT); + return -EFAULT; vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); if (io_remap_pfn_range(vma, vma->vm_start, (nesdev->doorbell_start + - ((nes_ucontext->mmap_db_index[index]-nesdev->base_doorbell_index) * 4096)) + ((nes_ucontext->mmap_db_index[index] - nesdev->base_doorbell_index) * 4096)) >> PAGE_SHIFT, PAGE_SIZE, vma->vm_page_prot)) - return(-EAGAIN); + return -EAGAIN; vma->vm_private_data = nes_ucontext; - return (0); + return 0; } - return(-ENOSYS); + return -ENOSYS; } @@ -909,38 +902,38 @@ static struct ib_pd *nes_alloc_pd(struct ib_device *ibdev, u32 pd_num = 0; int err; - dprintk("%s:%u\n", __FUNCTION__, __LINE__); - dprintk("%s: netdev refcnt = %u.\n", __FUNCTION__, + nes_debug(NES_DBG_PD, "nesvnic=%p, netdev=%p %s, ibdev=%p, context=%p, netdev refcnt=%u\n", + nesvnic, nesdev->netdev[0], nesdev->netdev[0]->name, ibdev, context, atomic_read(&nesvnic->netdev->refcnt)); err = nes_alloc_resource(nesadapter, nesadapter->allocated_pds, nesadapter->max_pd, &pd_num, &nesadapter->next_pd); if (err) { - return (ERR_PTR(err)); + return ERR_PTR(err); } - nespd = kmalloc(sizeof (struct nes_pd), GFP_KERNEL); + nespd = kzalloc(sizeof (struct nes_pd), GFP_KERNEL); if (!nespd) { nes_free_resource(nesadapter, nesadapter->allocated_pds, pd_num); - return (ERR_PTR(-ENOMEM)); + return ERR_PTR(-ENOMEM); } - memset(nespd, 0, sizeof(struct nes_pd)); - dprintk("Allocating PD (%p) for ib device %s\n", + + nes_debug(NES_DBG_PD, "Allocating PD (%p) for ib device %s\n", nespd, nesvnic->nesibdev->ibdev.name); - nespd->pd_id = pd_num + nesadapter->base_pd; + nespd->pd_id = (pd_num << (PAGE_SHIFT-12)) + nesadapter->base_pd; if (context) { nesucontext = to_nesucontext(context); nespd->mmap_db_index = find_next_zero_bit(nesucontext->allocated_doorbells, NES_MAX_USER_DB_REGIONS, nesucontext->first_free_db); - dprintk("find_first_zero_biton doorbells returned %u, mapping pd_id %u.\n", + nes_debug(NES_DBG_PD, "find_first_zero_biton doorbells returned %u, mapping pd_id %u.\n", nespd->mmap_db_index, nespd->pd_id); - if (nespd->mmap_db_index > NES_MAX_USER_DB_REGIONS) { - dprintk("%s:%u: mmap_db_index > MAX\n", __FUNCTION__, __LINE__); + if (nespd->mmap_db_index >= NES_MAX_USER_DB_REGIONS) { + nes_debug(NES_DBG_PD, "mmap_db_index > MAX\n"); nes_free_resource(nesadapter, nesadapter->allocated_pds, pd_num); kfree(nespd); - return (ERR_PTR(-ENOMEM)); + return ERR_PTR(-ENOMEM); } uresp.pd_id = nespd->pd_id; @@ -948,7 +941,7 @@ static struct ib_pd *nes_alloc_pd(struct ib_device *ibdev, if (ib_copy_to_udata(udata, &uresp, sizeof (struct nes_alloc_pd_resp))) { nes_free_resource(nesadapter, nesadapter->allocated_pds, pd_num); kfree(nespd); - return (ERR_PTR(-EFAULT)); + return ERR_PTR(-EFAULT); } set_bit(nespd->mmap_db_index, nesucontext->allocated_doorbells); @@ -956,11 +949,8 @@ static struct ib_pd *nes_alloc_pd(struct ib_device *ibdev, nesucontext->first_free_db = nespd->mmap_db_index + 1; } - dprintk("%s: PD%u structure located @%p.\n", - __FUNCTION__, nespd->pd_id, nespd); - dprintk("%s: netdev refcnt = %u.\n", - __FUNCTION__, atomic_read(&nesvnic->netdev->refcnt)); - return(&nespd->ibpd); + nes_debug(NES_DBG_PD, "PD%u structure located @%p.\n", nespd->pd_id, nespd); + return &nespd->ibpd; } @@ -975,12 +965,10 @@ static int nes_dealloc_pd(struct ib_pd *ibpd) struct nes_device *nesdev = nesvnic->nesdev; struct nes_adapter *nesadapter = nesdev->nesadapter; - dprintk("%s:%u\n", __FUNCTION__, __LINE__); - if ((ibpd->uobject) && (ibpd->uobject->context)) { nesucontext = to_nesucontext(ibpd->uobject->context); - dprintk("%s: Clearing bit %u from allocated doorbells\n", - __FUNCTION__, nespd->mmap_db_index); + nes_debug(NES_DBG_PD, "Clearing bit %u from allocated doorbells\n", + nespd->mmap_db_index); clear_bit(nespd->mmap_db_index, nesucontext->allocated_doorbells); nesucontext->mmap_db_index[nespd->mmap_db_index] = 0; if (nesucontext->first_free_db > nespd->mmap_db_index) { @@ -988,16 +976,13 @@ static int nes_dealloc_pd(struct ib_pd *ibpd) } } - dprintk("%s: Deallocating PD%u structure located @%p.\n", - __FUNCTION__, nespd->pd_id, nespd); + nes_debug(NES_DBG_PD, "Deallocating PD%u structure located @%p.\n", + nespd->pd_id, nespd); nes_free_resource(nesadapter, nesadapter->allocated_pds, - nespd->pd_id-nesadapter->base_pd); + (nespd->pd_id-nesadapter->base_pd)>>(PAGE_SHIFT-12)); kfree(nespd); - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); - /* dprintk("%s: netdev refcnt = %u.\n", __FUNCTION__, - atomic_read(&nesvnic->netdev->refcnt)); */ - return (0); + return 0; } @@ -1006,8 +991,7 @@ static int nes_dealloc_pd(struct ib_pd *ibpd) */ static struct ib_ah *nes_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr) { - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); - return (ERR_PTR(-ENOSYS)); + return ERR_PTR(-ENOSYS); } @@ -1016,8 +1000,220 @@ static struct ib_ah *nes_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr) */ static int nes_destroy_ah(struct ib_ah *ah) { - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); - return (-ENOSYS); + return -ENOSYS; +} + + +/** + * nes_get_encoded_size + */ +static inline u8 nes_get_encoded_size(int *size) +{ + u8 encoded_size = 0; + if (*size <= 32) { + *size = 32; + encoded_size = 1; + } else if (*size <= 128) { + *size = 128; + encoded_size = 2; + } else if (*size <= 512) { + *size = 512; + encoded_size = 3; + } + return (encoded_size); +} + + + +/** + * nes_setup_virt_qp + */ +static int nes_setup_virt_qp(struct nes_qp *nesqp, struct nes_pbl *nespbl, + struct nes_vnic *nesvnic, int sq_size, int rq_size) +{ + unsigned long flags; + void *mem; + __le64 *pbl = NULL; + __le64 *tpbl; + __le64 *pblbuffer; + struct nes_device *nesdev = nesvnic->nesdev; + struct nes_adapter *nesadapter = nesdev->nesadapter; + u32 pbl_entries; + u8 rq_pbl_entries; + u8 sq_pbl_entries; + + pbl_entries = nespbl->pbl_size >> 3; + nes_debug(NES_DBG_QP, "Userspace PBL, pbl_size=%u, pbl_entries = %d pbl_vbase=%p, pbl_pbase=%p\n", + nespbl->pbl_size, pbl_entries, + (void *)nespbl->pbl_vbase, + (void *)nespbl->pbl_pbase); + pbl = (__le64 *) nespbl->pbl_vbase; /* points to first pbl entry */ + /* now lets set the sq_vbase as well as rq_vbase addrs we will assign */ + /* the first pbl to be fro the rq_vbase... */ + rq_pbl_entries = (rq_size * sizeof(struct nes_hw_qp_wqe)) >> 12; + sq_pbl_entries = (sq_size * sizeof(struct nes_hw_qp_wqe)) >> 12; + nesqp->hwqp.sq_pbase = (le32_to_cpu(((__le32 *)pbl)[0])) | ((u64)((le32_to_cpu(((__le32 *)pbl)[1]))) << 32); + if (!nespbl->page) { + nes_debug(NES_DBG_QP, "QP nespbl->page is NULL \n"); + kfree(nespbl); + return -ENOMEM; + } + + nesqp->hwqp.sq_vbase = kmap(nespbl->page); + nesqp->page = nespbl->page; + if (!nesqp->hwqp.sq_vbase) { + nes_debug(NES_DBG_QP, "QP sq_vbase kmap failed\n"); + kfree(nespbl); + return -ENOMEM; + } + + /* Now to get to sq.. we need to calculate how many */ + /* PBL entries were used by the rq.. */ + pbl += sq_pbl_entries; + nesqp->hwqp.rq_pbase = (le32_to_cpu(((__le32 *)pbl)[0])) | ((u64)((le32_to_cpu(((__le32 *)pbl)[1]))) << 32); + /* nesqp->hwqp.rq_vbase = bus_to_virt(*pbl); */ + /*nesqp->hwqp.rq_vbase = phys_to_virt(*pbl); */ + + nes_debug(NES_DBG_QP, "QP sq_vbase= %p sq_pbase=%p rq_vbase=%p rq_pbase=%p\n", + nesqp->hwqp.sq_vbase, (void *)nesqp->hwqp.sq_pbase, + nesqp->hwqp.rq_vbase, (void *)nesqp->hwqp.rq_pbase); + spin_lock_irqsave(&nesadapter->pbl_lock, flags); + if (!nesadapter->free_256pbl) { + pci_free_consistent(nesdev->pcidev, nespbl->pbl_size, nespbl->pbl_vbase, + nespbl->pbl_pbase); + spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); + kunmap(nesqp->page); + kfree(nespbl); + return -ENOMEM; + } + nesadapter->free_256pbl--; + spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); + + nesqp->pbl_vbase = pci_alloc_consistent(nesdev->pcidev, 256, &nesqp->pbl_pbase); + pblbuffer = nesqp->pbl_vbase; + if (!nesqp->pbl_vbase) { + /* memory allocated during nes_reg_user_mr() */ + pci_free_consistent(nesdev->pcidev, nespbl->pbl_size, nespbl->pbl_vbase, + nespbl->pbl_pbase); + kfree(nespbl); + spin_lock_irqsave(&nesadapter->pbl_lock, flags); + nesadapter->free_256pbl++; + spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); + kunmap(nesqp->page); + return -ENOMEM; + } + memset(nesqp->pbl_vbase, 0, 256); + /* fill in the page address in the pbl buffer.. */ + tpbl = pblbuffer + 16; + pbl = (__le64 *)nespbl->pbl_vbase; + while (sq_pbl_entries--) + *tpbl++ = *pbl++; + tpbl = pblbuffer; + while (rq_pbl_entries--) + *tpbl++ = *pbl++; + + /* done with memory allocated during nes_reg_user_mr() */ + pci_free_consistent(nesdev->pcidev, nespbl->pbl_size, nespbl->pbl_vbase, + nespbl->pbl_pbase); + kfree(nespbl); + + nesqp->qp_mem_size = + max((u32)sizeof(struct nes_qp_context), ((u32)256)) + 256; /* this is Q2 */ + /* Round up to a multiple of a page */ + nesqp->qp_mem_size += PAGE_SIZE - 1; + nesqp->qp_mem_size &= ~(PAGE_SIZE - 1); + + mem = pci_alloc_consistent(nesdev->pcidev, nesqp->qp_mem_size, + &nesqp->hwqp.q2_pbase); + + if (!mem) { + pci_free_consistent(nesdev->pcidev, 256, nesqp->pbl_vbase, nesqp->pbl_pbase); + nesqp->pbl_vbase = NULL; + spin_lock_irqsave(&nesadapter->pbl_lock, flags); + nesadapter->free_256pbl++; + spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); + kunmap(nesqp->page); + return -ENOMEM; + } + nesqp->hwqp.q2_vbase = mem; + mem += 256; + memset(nesqp->hwqp.q2_vbase, 0, 256); + nesqp->nesqp_context = mem; + memset(nesqp->nesqp_context, 0, sizeof(*nesqp->nesqp_context)); + nesqp->nesqp_context_pbase = nesqp->hwqp.q2_pbase + 256; + + return 0; +} + + +/** + * nes_setup_mmap_qp + */ +static int nes_setup_mmap_qp(struct nes_qp *nesqp, struct nes_vnic *nesvnic, + int sq_size, int rq_size) +{ + void *mem; + struct nes_device *nesdev = nesvnic->nesdev; + + nesqp->qp_mem_size = (sizeof(struct nes_hw_qp_wqe) * sq_size) + + (sizeof(struct nes_hw_qp_wqe) * rq_size) + + max((u32)sizeof(struct nes_qp_context), ((u32)256)) + + 256; /* this is Q2 */ + /* Round up to a multiple of a page */ + nesqp->qp_mem_size += PAGE_SIZE - 1; + nesqp->qp_mem_size &= ~(PAGE_SIZE - 1); + + mem = pci_alloc_consistent(nesdev->pcidev, nesqp->qp_mem_size, + &nesqp->hwqp.sq_pbase); + if (!mem) + return -ENOMEM; + nes_debug(NES_DBG_QP, "PCI consistent memory for " + "host descriptor rings located @ %p (pa = 0x%08lX.) size = %u.\n", + mem, (unsigned long)nesqp->hwqp.sq_pbase, nesqp->qp_mem_size); + + memset(mem, 0, nesqp->qp_mem_size); + + nesqp->hwqp.sq_vbase = mem; + mem += sizeof(struct nes_hw_qp_wqe) * sq_size; + + nesqp->hwqp.rq_vbase = mem; + nesqp->hwqp.rq_pbase = nesqp->hwqp.sq_pbase + + sizeof(struct nes_hw_qp_wqe) * sq_size; + mem += sizeof(struct nes_hw_qp_wqe) * rq_size; + + nesqp->hwqp.q2_vbase = mem; + nesqp->hwqp.q2_pbase = nesqp->hwqp.rq_pbase + + sizeof(struct nes_hw_qp_wqe) * rq_size; + mem += 256; + memset(nesqp->hwqp.q2_vbase, 0, 256); + + nesqp->nesqp_context = mem; + nesqp->nesqp_context_pbase = nesqp->hwqp.q2_pbase + 256; + memset(nesqp->nesqp_context, 0, sizeof(*nesqp->nesqp_context)); + return 0; +} + + +/** + * nes_free_qp_mem() is to free up the qp's pci_alloc_consistent() memory. + */ +static inline void nes_free_qp_mem(struct nes_device *nesdev, + struct nes_qp *nesqp, int virt_wqs) +{ + unsigned long flags; + struct nes_adapter *nesadapter = nesdev->nesadapter; + if (!virt_wqs) { + pci_free_consistent(nesdev->pcidev, nesqp->qp_mem_size, + nesqp->hwqp.sq_vbase, nesqp->hwqp.sq_pbase); + }else { + spin_lock_irqsave(&nesadapter->pbl_lock, flags); + nesadapter->free_256pbl++; + spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); + pci_free_consistent(nesdev->pcidev, nesqp->qp_mem_size, nesqp->hwqp.q2_vbase, nesqp->hwqp.q2_pbase); + pci_free_consistent(nesdev->pcidev, 256, nesqp->pbl_vbase, nesqp->pbl_pbase ); + nesqp->pbl_vbase = NULL; + kunmap(nesqp->page); + } } @@ -1038,101 +1234,120 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd, struct nes_ucontext *nes_ucontext; struct nes_hw_cqp_wqe *cqp_wqe; struct nes_cqp_request *cqp_request; + struct nes_create_qp_req req; struct nes_create_qp_resp uresp; + struct nes_pbl *nespbl = NULL; u32 qp_num = 0; + u32 opcode = 0; /* u32 counter = 0; */ void *mem; unsigned long flags; int ret; + int err; + int virt_wqs = 0; int sq_size; int rq_size; u8 sq_encoded_size; u8 rq_encoded_size; -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)) - u32 mem_size; - void *vmem; -#endif /* int counter; */ - dprintk("%s:%u\n", __FUNCTION__, __LINE__); - dprintk("%s: netdev refcnt = %u.\n", __FUNCTION__, - atomic_read(&nesvnic->netdev->refcnt)); - atomic_inc(&qps_created); switch (init_attr->qp_type) { case IB_QPT_RC: - init_attr->cap.max_inline_data = 0; - - if (init_attr->cap.max_send_wr <= 32) { - sq_size = 32; - sq_encoded_size = 1; - } else if (init_attr->cap.max_send_wr <= 128) { - sq_size = 128; - sq_encoded_size = 2; - } else if (init_attr->cap.max_send_wr <= 512) { - sq_size = 512; - sq_encoded_size = 3; + if (nes_drv_opt & NES_DRV_OPT_NO_INLINE_DATA) { + init_attr->cap.max_inline_data = 0; } else { - printk(KERN_ERR PFX "%s: SQ size (%u) too large.\n", - __FUNCTION__, init_attr->cap.max_send_wr); - return (ERR_PTR(-EINVAL)); + init_attr->cap.max_inline_data = 64; } - init_attr->cap.max_send_wr = sq_size - 2; - if (init_attr->cap.max_recv_wr <= 32) { - rq_size = 32; - rq_encoded_size = 1; - } else if (init_attr->cap.max_recv_wr <= 128) { - rq_size = 128; - rq_encoded_size = 2; - } else if (init_attr->cap.max_recv_wr <= 512) { - rq_size = 512; - rq_encoded_size = 3; - } else { - printk(KERN_ERR PFX "%s: RQ size (%u) too large.\n", - __FUNCTION__, init_attr->cap.max_recv_wr); - return (ERR_PTR(-EINVAL)); + sq_size = init_attr->cap.max_send_wr; + rq_size = init_attr->cap.max_recv_wr; + + // check if the encoded sizes are OK or not... + sq_encoded_size = nes_get_encoded_size(&sq_size); + rq_encoded_size = nes_get_encoded_size(&rq_size); + + if ((!sq_encoded_size) || (!rq_encoded_size)) { + nes_debug(NES_DBG_QP, "ERROR bad rq (%u) or sq (%u) size\n", + rq_size, sq_size); + return ERR_PTR(-EINVAL); } + + init_attr->cap.max_send_wr = sq_size -2; init_attr->cap.max_recv_wr = rq_size -1; - dprintk("%s: RQ size = %u, SQ Size = %u.\n", __FUNCTION__, - rq_size, sq_size); + nes_debug(NES_DBG_QP, "RQ size=%u, SQ Size=%u\n", rq_size, sq_size); ret = nes_alloc_resource(nesadapter, nesadapter->allocated_qps, nesadapter->max_qp, &qp_num, &nesadapter->next_qp); if (ret) { - return (ERR_PTR(ret)); + return ERR_PTR(ret); } /* Need 512 (actually now 1024) byte alignment on this structure */ mem = kzalloc(sizeof(*nesqp)+NES_SW_CONTEXT_ALIGN-1, GFP_KERNEL); if (!mem) { nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num); - dprintk("%s: Unable to allocate QP\n", __FUNCTION__); - return (ERR_PTR(-ENOMEM)); + nes_debug(NES_DBG_QP, "Unable to allocate QP\n"); + return ERR_PTR(-ENOMEM); } - u64nesqp = (u64)mem; /* u64nesqp = (u64)((uint)mem); */ + u64nesqp = (unsigned long)mem; u64nesqp += ((u64)NES_SW_CONTEXT_ALIGN) - 1; u64temp = ((u64)NES_SW_CONTEXT_ALIGN) - 1; u64nesqp &= ~u64temp; - nesqp = (struct nes_qp *)u64nesqp; - dprintk("nesqp = %p, allocated buffer = %p. Rounded to closest %u\n", - nesqp, mem, NES_SW_CONTEXT_ALIGN); + nesqp = (struct nes_qp *)(unsigned long)u64nesqp; + /* nes_debug(NES_DBG_QP, "nesqp=%p, allocated buffer=%p. Rounded to closest %u\n", + nesqp, mem, NES_SW_CONTEXT_ALIGN); */ nesqp->allocated_buffer = mem; if (udata) { + if (ib_copy_from_udata(&req, udata, sizeof(struct nes_create_qp_req))) { + nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num); + kfree(nesqp->allocated_buffer); + nes_debug(NES_DBG_QP, "ib_copy_from_udata() Failed \n"); + return NULL; + } + if (req.user_wqe_buffers) { + virt_wqs = 1; + } if ((ibpd->uobject) && (ibpd->uobject->context)) { nesqp->user_mode = 1; nes_ucontext = to_nesucontext(ibpd->uobject->context); + if (virt_wqs) { + err = 1; + list_for_each_entry(nespbl, &nes_ucontext->qp_reg_mem_list, list) { + if (nespbl->user_base == (unsigned long )req.user_wqe_buffers) { + list_del(&nespbl->list); + err = 0; + nes_debug(NES_DBG_QP, "Found PBL for virtual QP. nespbl=%p. user_base=0x%lx\n", + nespbl, nespbl->user_base); + break; + } + } + if (err) { + nes_debug(NES_DBG_QP, "Didn't Find PBL for virtual QP. address = %llx.\n", + (long long unsigned int)req.user_wqe_buffers); + nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num); + kfree(nesqp->allocated_buffer); + return ERR_PTR(-EFAULT); + } + } + + nes_ucontext = to_nesucontext(ibpd->uobject->context); nesqp->mmap_sq_db_index = - find_next_zero_bit(nes_ucontext->allocated_wqs, - NES_MAX_USER_WQ_REGIONS, nes_ucontext->first_free_wq); - dprintk("find_first_zero_biton wqs returned %u\n", - nespd->mmap_db_index); - if (nesqp->mmap_sq_db_index > NES_MAX_USER_WQ_REGIONS) { - dprintk("%s: db index > max user regions, failing create QP\n", - __FUNCTION__); + find_next_zero_bit(nes_ucontext->allocated_wqs, + NES_MAX_USER_WQ_REGIONS, nes_ucontext->first_free_wq); + /* nes_debug(NES_DBG_QP, "find_first_zero_biton wqs returned %u\n", + nespd->mmap_db_index); */ + if (nesqp->mmap_sq_db_index >= NES_MAX_USER_WQ_REGIONS) { + nes_debug(NES_DBG_QP, + "db index > max user regions, failing create QP\n"); nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num); + if (virt_wqs) { + pci_free_consistent(nesdev->pcidev, nespbl->pbl_size, nespbl->pbl_vbase, + nespbl->pbl_pbase); + kfree(nespbl); + } kfree(nesqp->allocated_buffer); - return (ERR_PTR(-ENOMEM)); + return ERR_PTR(-ENOMEM); } set_bit(nesqp->mmap_sq_db_index, nes_ucontext->allocated_wqs); nes_ucontext->mmap_nesqp[nesqp->mmap_sq_db_index] = nesqp; @@ -1140,72 +1355,27 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd, } else { nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num); kfree(nesqp->allocated_buffer); - return (ERR_PTR(-EFAULT)); + return ERR_PTR(-EFAULT); } } - - nesqp->qp_mem_size = (sizeof(struct nes_hw_qp_wqe) * sq_size) + - (sizeof(struct nes_hw_qp_wqe) * rq_size) + - max((u32)sizeof(struct nes_qp_context), ((u32)256)) + - 256; /* this is Q2 */ - /* Round up to a multiple of a page */ - nesqp->qp_mem_size += PAGE_SIZE - 1; - nesqp->qp_mem_size &= ~(PAGE_SIZE - 1); - - mem = pci_alloc_consistent(nesdev->pcidev, nesqp->qp_mem_size, - &nesqp->hwqp.sq_pbase); - if (!mem) { + err = (!virt_wqs) ? nes_setup_mmap_qp(nesqp, nesvnic, sq_size, rq_size) : + nes_setup_virt_qp(nesqp, nespbl, nesvnic, sq_size, rq_size); + if (err) { + nes_debug(NES_DBG_QP, + "error geting qp mem code = %d\n", err); nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num); - dprintk("%s: Unable to allocate memory for host descriptor rings\n", - __FUNCTION__); kfree(nesqp->allocated_buffer); - return (ERR_PTR(-ENOMEM)); - } - dprintk(PFX "%s: PCI consistent memory for " - "host descriptor rings located @ %p (pa = 0x%08lX.) size = %u.\n", - __FUNCTION__, mem, (unsigned long)nesqp->hwqp.sq_pbase, - nesqp->qp_mem_size); - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)) - mem_size = nesqp->qp_mem_size; - vmem = mem; - while (mem_size > 0) { - dprintk("%s: Setting memory page %p reserved, mem_size=%u\n", - __FUNCTION__, vmem, mem_size); - SetPageReserved(virt_to_page(vmem)); - mem_size -= PAGE_SIZE; - vmem += PAGE_SIZE; + return ERR_PTR(-ENOMEM); } -#endif - memset(mem, 0, nesqp->qp_mem_size); - - nesqp->hwqp.sq_vbase = mem; nesqp->hwqp.sq_size = sq_size; nesqp->hwqp.sq_encoded_size = sq_encoded_size; nesqp->hwqp.sq_head = 1; - mem += sizeof(struct nes_hw_qp_wqe) * sq_size; - - nesqp->hwqp.rq_vbase = mem; nesqp->hwqp.rq_size = rq_size; nesqp->hwqp.rq_encoded_size = rq_encoded_size; - nesqp->hwqp.rq_pbase = nesqp->hwqp.sq_pbase + - sizeof(struct nes_hw_qp_wqe) * sq_size; - mem += sizeof(struct nes_hw_qp_wqe)*rq_size; - - nesqp->hwqp.q2_vbase = mem; - nesqp->hwqp.q2_pbase = nesqp->hwqp.rq_pbase + - sizeof(struct nes_hw_qp_wqe) * rq_size; - mem += 256; - memset(nesqp->hwqp.q2_vbase, 0, 256); - - nesqp->nesqp_context = mem; - nesqp->nesqp_context_pbase = nesqp->hwqp.q2_pbase + 256; - memset(nesqp->nesqp_context, 0, sizeof(*nesqp->nesqp_context)); - - dprintk("%s:%u: nesqp->nesqp_context_pbase = %p\n", - __FUNCTION__, __LINE__, (void *) nesqp->nesqp_context_pbase); - + /* nes_debug(NES_DBG_QP, "nesqp->nesqp_context_pbase = %p\n", + (void *)nesqp->nesqp_context_pbase); + */ nesqp->hwqp.qp_id = qp_num; nesqp->ibqp.qp_num = nesqp->hwqp.qp_id; nesqp->nespd = nespd; @@ -1215,29 +1385,41 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd, nescq = to_nescq(init_attr->recv_cq); nesqp->nesrcq = nescq; - nesqp->nesqp_context->misc |= (u32)PCI_FUNC(nesdev->pcidev->devfn) << - NES_QPCONTEXT_MISC_PCI_FCN_SHIFT; - nesqp->nesqp_context->misc |= (u32)nesqp->hwqp.rq_encoded_size << - NES_QPCONTEXT_MISC_RQ_SIZE_SHIFT; - nesqp->nesqp_context->misc |= (u32)nesqp->hwqp.sq_encoded_size << - NES_QPCONTEXT_MISC_SQ_SIZE_SHIFT; - nesqp->nesqp_context->misc |= NES_QPCONTEXT_MISC_PRIV_EN; - nesqp->nesqp_context->misc |= NES_QPCONTEXT_MISC_FAST_REGISTER_EN; - nesqp->nesqp_context->cqs = nesqp->nesscq->hw_cq.cq_number + - ((u32)nesqp->nesrcq->hw_cq.cq_number << 16); + nesqp->nesqp_context->misc |= cpu_to_le32((u32)PCI_FUNC(nesdev->pcidev->devfn) << + NES_QPCONTEXT_MISC_PCI_FCN_SHIFT); + nesqp->nesqp_context->misc |= cpu_to_le32((u32)nesqp->hwqp.rq_encoded_size << + NES_QPCONTEXT_MISC_RQ_SIZE_SHIFT); + nesqp->nesqp_context->misc |= cpu_to_le32((u32)nesqp->hwqp.sq_encoded_size << + NES_QPCONTEXT_MISC_SQ_SIZE_SHIFT); + nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_PRIV_EN); + nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_FAST_REGISTER_EN); + nesqp->nesqp_context->cqs = cpu_to_le32(nesqp->nesscq->hw_cq.cq_number + + ((u32)nesqp->nesrcq->hw_cq.cq_number << 16)); u64temp = (u64)nesqp->hwqp.sq_pbase; - nesqp->nesqp_context->sq_addr_low = (u32)u64temp; - nesqp->nesqp_context->sq_addr_high = (u32)(u64temp >> 32); - u64temp = (u64)nesqp->hwqp.rq_pbase; - nesqp->nesqp_context->rq_addr_low = (u32)u64temp; - nesqp->nesqp_context->rq_addr_high = (u32)(u64temp >> 32); + nesqp->nesqp_context->sq_addr_low = cpu_to_le32((u32)u64temp); + nesqp->nesqp_context->sq_addr_high = cpu_to_le32((u32)(u64temp >> 32)); + + + if (!virt_wqs) { + u64temp = (u64)nesqp->hwqp.sq_pbase; + nesqp->nesqp_context->sq_addr_low = cpu_to_le32((u32)u64temp); + nesqp->nesqp_context->sq_addr_high = cpu_to_le32((u32)(u64temp >> 32)); + u64temp = (u64)nesqp->hwqp.rq_pbase; + nesqp->nesqp_context->rq_addr_low = cpu_to_le32((u32)u64temp); + nesqp->nesqp_context->rq_addr_high = cpu_to_le32((u32)(u64temp >> 32)); + } else { + u64temp = (u64)nesqp->pbl_pbase; + nesqp->nesqp_context->rq_addr_low = cpu_to_le32((u32)u64temp); + nesqp->nesqp_context->rq_addr_high = cpu_to_le32((u32)(u64temp >> 32)); + } + + /* nes_debug(NES_DBG_QP, "next_qp_nic_index=%u, using nic_index=%d\n", + nesvnic->next_qp_nic_index, + nesvnic->qp_nic_index[nesvnic->next_qp_nic_index]); */ spin_lock_irqsave(&nesdev->cqp.lock, flags); - dprintk("%s: next_qp_nic_index=%u, using nic_index=%d\n", - __FUNCTION__, nesvnic->next_qp_nic_index, - nesvnic->qp_nic_index[nesvnic->next_qp_nic_index]); - nesqp->nesqp_context->misc2 |= + nesqp->nesqp_context->misc2 |= cpu_to_le32( (u32)nesvnic->qp_nic_index[nesvnic->next_qp_nic_index] << - NES_QPCONTEXT_MISC2_NIC_INDEX_SHIFT; + NES_QPCONTEXT_MISC2_NIC_INDEX_SHIFT); nesvnic->next_qp_nic_index++; if ((nesvnic->next_qp_nic_index > 3) || (nesvnic->qp_nic_index[nesvnic->next_qp_nic_index] == 0xf)) { @@ -1245,84 +1427,88 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd, } spin_unlock_irqrestore(&nesdev->cqp.lock, flags); - nesqp->nesqp_context->pd_index_wscale |= (u32)nesqp->nespd->pd_id << 16; + nesqp->nesqp_context->pd_index_wscale |= cpu_to_le32((u32)nesqp->nespd->pd_id << 16); u64temp = (u64)nesqp->hwqp.q2_pbase; - nesqp->nesqp_context->q2_addr_low = (u32)u64temp; - nesqp->nesqp_context->q2_addr_high = (u32)(u64temp>>32); - *((struct nes_qp **)&nesqp->nesqp_context->aeq_token_low) = nesqp; - nesqp->nesqp_context->ird_ord_sizes = NES_QPCONTEXT_ORDIRD_ALSMM | + nesqp->nesqp_context->q2_addr_low = cpu_to_le32((u32)u64temp); + nesqp->nesqp_context->q2_addr_high = cpu_to_le32((u32)(u64temp >> 32)); + nesqp->nesqp_context->aeq_token_low = cpu_to_le32((u32)((unsigned long)(nesqp))); + nesqp->nesqp_context->aeq_token_high = cpu_to_le32((u32)(upper_32_bits((unsigned long)(nesqp)))); + nesqp->nesqp_context->ird_ord_sizes = cpu_to_le32(NES_QPCONTEXT_ORDIRD_ALSMM | ((((u32)nesadapter->max_irrq_wr) << - NES_QPCONTEXT_ORDIRD_IRDSIZE_SHIFT) & NES_QPCONTEXT_ORDIRD_IRDSIZE_MASK); + NES_QPCONTEXT_ORDIRD_IRDSIZE_SHIFT) & NES_QPCONTEXT_ORDIRD_IRDSIZE_MASK)); if (disable_mpa_crc) { - dprintk("%s Disabling MPA crc checking due to module option.\n", __FUNCTION__); - nesqp->nesqp_context->ird_ord_sizes |= NES_QPCONTEXT_ORDIRD_RNMC; + nes_debug(NES_DBG_QP, "Disabling MPA crc checking due to module option.\n"); + nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32(NES_QPCONTEXT_ORDIRD_RNMC); } /* Create the QP */ - spin_lock_irqsave(&nesdev->cqp.lock, flags); - cqp_request = nes_get_cqp_request(nesdev, NES_CQP_REQUEST_HOLDING_LOCK); - if (NULL == cqp_request) { - dprintk("%s: Failed to get a cqp_request.\n", __FUNCTION__); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + cqp_request = nes_get_cqp_request(nesdev); + if (cqp_request == NULL) { + nes_debug(NES_DBG_QP, "Failed to get a cqp_request\n"); nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num); - pci_free_consistent(nesdev->pcidev, nesqp->qp_mem_size, - nesqp->hwqp.sq_vbase, nesqp->hwqp.sq_pbase); + nes_free_qp_mem(nesdev, nesqp,virt_wqs); kfree(nesqp->allocated_buffer); - return (ERR_PTR(-ENOMEM)); + return ERR_PTR(-ENOMEM); } cqp_request->waiting = 1; cqp_wqe = &cqp_request->cqp_wqe; - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = - NES_CQP_CREATE_QP | NES_CQP_QP_TYPE_IWARP | + if (!virt_wqs) { + opcode = NES_CQP_CREATE_QP | NES_CQP_QP_TYPE_IWARP | + NES_CQP_QP_IWARP_STATE_IDLE; + } else { + opcode = NES_CQP_CREATE_QP | NES_CQP_QP_TYPE_IWARP | NES_CQP_QP_VIRT_WQS | NES_CQP_QP_IWARP_STATE_IDLE; - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= NES_CQP_QP_CQS_VALID; - cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = nesqp->hwqp.qp_id; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX] = 0; - *((struct nes_hw_cqp **)&cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_LOW_IDX]) = - &nesdev->cqp; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] = 0; + } + opcode |= NES_CQP_QP_CQS_VALID; + nes_fill_init_cqp_wqe(cqp_wqe, nesdev); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, opcode); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX, nesqp->hwqp.qp_id); + u64temp = (u64)nesqp->nesqp_context_pbase; - cqp_wqe->wqe_words[NES_CQP_QP_WQE_CONTEXT_LOW_IDX] = (u32)u64temp; - cqp_wqe->wqe_words[NES_CQP_QP_WQE_CONTEXT_HIGH_IDX] = (u32)(u64temp >> 32); + set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, u64temp); atomic_set(&cqp_request->refcount, 2); - nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_HOLDING_LOCK, - NES_CQP_REQUEST_RING_DOORBELL); + nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_RING_DOORBELL); /* Wait for CQP */ - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); - /* dprintk("Waiting for create iWARP QP%u to complete.\n", - nesqp->hwqp.qp_id); */ + nes_debug(NES_DBG_QP, "Waiting for create iWARP QP%u to complete.\n", + nesqp->hwqp.qp_id); ret = wait_event_timeout(cqp_request->waitq, - (0 != cqp_request->request_done), NES_EVENT_TIMEOUT); - dprintk("Create iwarp QP completed, wait_event_timeout ret=%u," + (cqp_request->request_done != 0), NES_EVENT_TIMEOUT); + nes_debug(NES_DBG_QP, "Create iwarp QP%u completed, wait_event_timeout ret=%u," " nesdev->cqp_head = %u, nesdev->cqp.sq_tail = %u," " CQP Major:Minor codes = 0x%04X:0x%04X.\n", - ret, nesdev->cqp.sq_head, nesdev->cqp.sq_tail, + nesqp->hwqp.qp_id, ret, nesdev->cqp.sq_head, nesdev->cqp.sq_tail, cqp_request->major_code, cqp_request->minor_code); if ((!ret) || (cqp_request->major_code)) { if (atomic_dec_and_test(&cqp_request->refcount)) { - spin_lock_irqsave(&nesdev->cqp.lock, flags); - list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + if (cqp_request->dynamic) { + kfree(cqp_request); + } else { + spin_lock_irqsave(&nesdev->cqp.lock, flags); + list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); + spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + } } nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num); - pci_free_consistent(nesdev->pcidev, nesqp->qp_mem_size, - nesqp->hwqp.sq_vbase, nesqp->hwqp.sq_pbase); + nes_free_qp_mem(nesdev, nesqp,virt_wqs); kfree(nesqp->allocated_buffer); if (!ret) { - return (ERR_PTR(-ETIME)); + return ERR_PTR(-ETIME); } else { - return (ERR_PTR(-EIO)); + return ERR_PTR(-EIO); } } else { if (atomic_dec_and_test(&cqp_request->refcount)) { - spin_lock_irqsave(&nesdev->cqp.lock, flags); - list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + if (cqp_request->dynamic) { + kfree(cqp_request); + } else { + spin_lock_irqsave(&nesdev->cqp.lock, flags); + list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); + spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + } } } @@ -1331,34 +1517,34 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd, uresp.actual_sq_size = sq_size; uresp.actual_rq_size = rq_size; uresp.qp_id = nesqp->hwqp.qp_id; + uresp.nes_drv_opt = nes_drv_opt; if (ib_copy_to_udata(udata, &uresp, sizeof uresp)) { - pci_free_consistent(nesdev->pcidev, nesqp->qp_mem_size, - nesqp->hwqp.sq_vbase, nesqp->hwqp.sq_pbase); nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num); + nes_free_qp_mem(nesdev, nesqp,virt_wqs); kfree(nesqp->allocated_buffer); - return (ERR_PTR(-EFAULT)); + return ERR_PTR(-EFAULT); } } - dprintk("%s: QP%u structure located @%p.Size = %u.\n", - __FUNCTION__, nesqp->hwqp.qp_id, nesqp, (u32)sizeof(*nesqp)); + nes_debug(NES_DBG_QP, "QP%u structure located @%p.Size = %u.\n", + nesqp->hwqp.qp_id, nesqp, (u32)sizeof(*nesqp)); spin_lock_init(&nesqp->lock); init_waitqueue_head(&nesqp->state_waitq); init_waitqueue_head(&nesqp->kick_waitq); nes_add_ref(&nesqp->ibqp); break; default: - dprintk("%s: Invalid QP type: %d\n", __FUNCTION__, init_attr->qp_type); - return (ERR_PTR(-EINVAL)); + nes_debug(NES_DBG_QP, "Invalid QP type: %d\n", init_attr->qp_type); + return ERR_PTR(-EINVAL); break; } /* update the QP table */ nesdev->nesadapter->qp_table[nesqp->hwqp.qp_id-NES_FIRST_QPN] = nesqp; - dprintk("%s: netdev refcnt = %u.\n", - __FUNCTION__, atomic_read(&nesvnic->netdev->refcnt)); + nes_debug(NES_DBG_QP, "netdev refcnt=%u\n", + atomic_read(&nesvnic->netdev->refcnt)); - return (&nesqp->ibqp); + return &nesqp->ibqp; } @@ -1371,21 +1557,22 @@ static int nes_destroy_qp(struct ib_qp *ibqp) /* struct nes_vnic *nesvnic = to_nesvnic(ibqp->device); */ struct nes_ucontext *nes_ucontext; struct ib_qp_attr attr; -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)) - u32 mem_size; - void *vmem; -#endif struct iw_cm_id *cm_id; struct iw_cm_event cm_event; int ret; - dprintk("%s:%u: Destroying QP%u, qp reference count = %d\n", - __FUNCTION__, __LINE__, nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount)); - atomic_inc(&sw_qps_destroyed); + nesqp->destroyed = 1; + /* Blow away the connection if it exists. */ + if (nesqp->ibqp_state >= IB_QPS_INIT && nesqp->ibqp_state <= IB_QPS_RTS) { + /* if (nesqp->ibqp_state == IB_QPS_RTS) { */ + attr.qp_state = IB_QPS_ERR; + nes_modify_qp(&nesqp->ibqp, &attr, IB_QP_STATE, NULL); + } + if (((nesqp->ibqp_state == IB_QPS_INIT) || - (nesqp->ibqp_state == IB_QPS_RTR)) && (nesqp->cm_id)) { + (nesqp->ibqp_state == IB_QPS_RTR)) && (nesqp->cm_id)) { cm_id = nesqp->cm_id; cm_event.event = IW_CM_EVENT_CONNECT_REPLY; cm_event.status = IW_CM_EVENT_STATUS_TIMEOUT; @@ -1394,22 +1581,16 @@ static int nes_destroy_qp(struct ib_qp *ibqp) cm_event.private_data = NULL; cm_event.private_data_len = 0; - dprintk("%s: Generating a CM Timeout Event for " - " QP%u. cm_id = %p, refcount = %u. \n", - __FUNCTION__, nesqp->hwqp.qp_id, - cm_id, atomic_read(&nesqp->refcount)); + nes_debug(NES_DBG_QP, "Generating a CM Timeout Event for " + "QP%u. cm_id = %p, refcount = %u. \n", + nesqp->hwqp.qp_id, cm_id, atomic_read(&nesqp->refcount)); cm_id->rem_ref(cm_id); ret = cm_id->event_handler(cm_id, &cm_event); if (ret) - dprintk("%s[%u] OFA CM event_handler returned, ret=%d\n", - __FUNCTION__, __LINE__, ret); + nes_debug(NES_DBG_QP, "OFA CM event_handler returned, ret=%d\n", ret); } - if (nesqp->ibqp_state == IB_QPS_RTS) { - attr.qp_state = IB_QPS_ERR; - nes_modify_qp(&nesqp->ibqp, &attr, IB_QP_STATE, NULL); - } if (nesqp->user_mode) { if ((ibqp->uobject)&&(ibqp->uobject->context)) { @@ -1419,26 +1600,13 @@ static int nes_destroy_qp(struct ib_qp *ibqp) if (nes_ucontext->first_free_wq > nesqp->mmap_sq_db_index) { nes_ucontext->first_free_wq = nesqp->mmap_sq_db_index; } - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)) - mem_size = nesqp->qp_mem_size; - vmem = nesqp->hwqp.sq_vbase; - while (mem_size > 0) { - dprintk("%s: Remove reserved memory page %p, mem_size=%u\n", - __FUNCTION__, vmem, mem_size); - ClearPageReserved(virt_to_page(vmem)); - mem_size -= PAGE_SIZE; - vmem += PAGE_SIZE; - } -#endif } + if (nesqp->pbl_pbase) + kunmap(nesqp->page); } nes_rem_ref(&nesqp->ibqp); - /* dprintk("%s: netdev refcnt = %u.\n", - __FUNCTION__, atomic_read(&nesvnic->netdev->refcnt)); */ - dprintk("%s:%u: QP%u, leaving\n", __FUNCTION__, __LINE__, nesqp->hwqp.qp_id); - return (0); + return 0; } @@ -1446,9 +1614,7 @@ static int nes_destroy_qp(struct ib_qp *ibqp) * nes_create_cq */ static struct ib_cq *nes_create_cq(struct ib_device *ibdev, int entries, -#ifndef OFED_1_2 int comp_vector, -#endif struct ib_ucontext *context, struct ib_udata *udata) { u64 u64temp; @@ -1464,83 +1630,88 @@ static struct ib_cq *nes_create_cq(struct ib_device *ibdev, int entries, struct nes_create_cq_req req; struct nes_create_cq_resp resp; u32 cq_num = 0; + u32 opcode = 0; u32 pbl_entries = 1; int err; unsigned long flags; int ret; - dprintk("%s:%u: entries = %u\n", __FUNCTION__, __LINE__, entries); - /* dprintk("%s: netdev refcnt = %u.\n", - __FUNCTION__, atomic_read(&nesvnic->netdev->refcnt)); */ - err = nes_alloc_resource(nesadapter, nesadapter->allocated_cqs, nesadapter->max_cq, &cq_num, &nesadapter->next_cq); if (err) { - return (ERR_PTR(err)); + return ERR_PTR(err); } - nescq = kmalloc(sizeof(struct nes_cq), GFP_KERNEL); + nescq = kzalloc(sizeof(struct nes_cq), GFP_KERNEL); if (!nescq) { nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num); - dprintk("%s: Unable to allocate CQ\n", __FUNCTION__); - return (ERR_PTR(-ENOMEM)); + nes_debug(NES_DBG_CQ, "Unable to allocate nes_cq struct\n"); + return ERR_PTR(-ENOMEM); } - memset(nescq, 0, sizeof (struct nes_cq)); nescq->hw_cq.cq_size = max(entries + 1, 5); nescq->hw_cq.cq_number = cq_num; nescq->ibcq.cqe = nescq->hw_cq.cq_size - 1; + if (context) { nes_ucontext = to_nesucontext(context); if (ib_copy_from_udata(&req, udata, sizeof (struct nes_create_cq_req))) { nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num); kfree(nescq); - return (ERR_PTR(-EFAULT)); + return ERR_PTR(-EFAULT); } - dprintk("%s: CQ Virtual Address = %08lX, size = %u.\n", - __FUNCTION__, (unsigned long)req.user_cq_buffer, entries); + nesvnic->mcrq_ucontext = nes_ucontext; + nes_ucontext->mcrqf = req.mcrqf; + if (nes_ucontext->mcrqf) { + if (nes_ucontext->mcrqf & 0x80000000) + nescq->hw_cq.cq_number = nesvnic->nic.qp_id + 12 + (nes_ucontext->mcrqf & 0xf) - 1; + else if (nes_ucontext->mcrqf & 0x40000000) + nescq->hw_cq.cq_number = nes_ucontext->mcrqf & 0xffff; + else + nescq->hw_cq.cq_number = nesvnic->mcrq_qp_id + nes_ucontext->mcrqf - 1; + nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num); + } + nes_debug(NES_DBG_CQ, "CQ Virtual Address = %08lX, size = %u.\n", + (unsigned long)req.user_cq_buffer, entries); + err = 1; list_for_each_entry(nespbl, &nes_ucontext->cq_reg_mem_list, list) { if (nespbl->user_base == (unsigned long )req.user_cq_buffer) { list_del(&nespbl->list); err = 0; - dprintk("%s: Found PBL for virtual CQ. nespbl=%p.\n", - __FUNCTION__, nespbl); + nes_debug(NES_DBG_CQ, "Found PBL for virtual CQ. nespbl=%p.\n", + nespbl); break; } } if (err) { nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num); kfree(nescq); - return (ERR_PTR(err)); + return ERR_PTR(-EFAULT); } + pbl_entries = nespbl->pbl_size >> 3; nescq->cq_mem_size = 0; - dprintk("%s: Userspace PBL, pbl_size=%u, pbl_vbase=%p, pbl_pbase=%p\n", - __FUNCTION__, nespbl->pbl_size, (void *)nespbl->pbl_vbase, - (void *)nespbl->pbl_pbase); - dprintk("%s: pbl_entries=%u, cq_mem_size=%u\n", - __FUNCTION__, pbl_entries, nescq->cq_mem_size); } else { nescq->cq_mem_size = nescq->hw_cq.cq_size * sizeof(struct nes_hw_cqe); - dprintk("%s: Attempting to allocate pci memory (%u entries, %u bytes) for CQ%u.\n", - __FUNCTION__, entries, nescq->cq_mem_size, nescq->hw_cq.cq_number); + nes_debug(NES_DBG_CQ, "Attempting to allocate pci memory (%u entries, %u bytes) for CQ%u.\n", + entries, nescq->cq_mem_size, nescq->hw_cq.cq_number); /* allocate the physical buffer space */ mem = pci_alloc_consistent(nesdev->pcidev, nescq->cq_mem_size, &nescq->hw_cq.cq_pbase); if (!mem) { - dprintk(KERN_ERR PFX "Unable to allocate pci memory for cq\n"); + printk(KERN_ERR PFX "Unable to allocate pci memory for cq\n"); nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num); kfree(nescq); - return (ERR_PTR(-ENOMEM)); + return ERR_PTR(-ENOMEM); } memset(mem, 0, nescq->cq_mem_size); nescq->hw_cq.cq_vbase = mem; nescq->hw_cq.cq_head = 0; - dprintk("%s: CQ%u virtual address @ %p, phys = 0x%08X\n", - __FUNCTION__, nescq->hw_cq.cq_number, nescq->hw_cq.cq_vbase, + nes_debug(NES_DBG_CQ, "CQ%u virtual address @ %p, phys = 0x%08X\n", + nescq->hw_cq.cq_number, nescq->hw_cq.cq_vbase, (u32)nescq->hw_cq.cq_pbase); } @@ -1548,119 +1719,134 @@ static struct ib_cq *nes_create_cq(struct ib_device *ibdev, int entries, spin_lock_init(&nescq->lock); /* send CreateCQ request to CQP */ - spin_lock_irqsave(&nesdev->cqp.lock, flags); - cqp_request = nes_get_cqp_request(nesdev, NES_CQP_REQUEST_HOLDING_LOCK); - if (NULL == cqp_request) { - dprintk("%s: Failed to get a cqp_request.\n", __FUNCTION__); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + cqp_request = nes_get_cqp_request(nesdev); + if (cqp_request == NULL) { + nes_debug(NES_DBG_CQ, "Failed to get a cqp_request.\n"); if (!context) pci_free_consistent(nesdev->pcidev, nescq->cq_mem_size, mem, nescq->hw_cq.cq_pbase); nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num); kfree(nescq); - return (ERR_PTR(-ENOMEM)); + return ERR_PTR(-ENOMEM); } cqp_request->waiting = 1; cqp_wqe = &cqp_request->cqp_wqe; - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = - NES_CQP_CREATE_CQ | NES_CQP_CQ_CEQ_VALID | + opcode = NES_CQP_CREATE_CQ | NES_CQP_CQ_CEQ_VALID | NES_CQP_CQ_CHK_OVERFLOW | - NES_CQP_CQ_CEQE_MASK |((u32)nescq->hw_cq.cq_size << 16); - if (1 != pbl_entries) { + NES_CQP_CQ_CEQE_MASK | ((u32)nescq->hw_cq.cq_size << 16); + + spin_lock_irqsave(&nesadapter->pbl_lock, flags); + + if (pbl_entries != 1) { if (pbl_entries > 32) { /* use 4k pbl */ - dprintk("%s: pbl_entries=%u, use a 4k PBL\n", __FUNCTION__, pbl_entries); - if (0 == nesadapter->free_4kpbl) { - list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + nes_debug(NES_DBG_CQ, "pbl_entries=%u, use a 4k PBL\n", pbl_entries); + if (nesadapter->free_4kpbl == 0) { + if (cqp_request->dynamic) { + spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); + kfree(cqp_request); + } else { + list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); + spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); + } if (!context) pci_free_consistent(nesdev->pcidev, nescq->cq_mem_size, mem, nescq->hw_cq.cq_pbase); nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num); kfree(nescq); - return (ERR_PTR(-ENOMEM)); + return ERR_PTR(-ENOMEM); } else { - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= - (NES_CQP_CQ_VIRT | NES_CQP_CQ_4KB_CHUNK); + opcode |= (NES_CQP_CQ_VIRT | NES_CQP_CQ_4KB_CHUNK); nescq->virtual_cq = 2; nesadapter->free_4kpbl--; } } else { /* use 256 byte pbl */ - dprintk("%s: pbl_entries=%u, use a 256 byte PBL\n", - __FUNCTION__, pbl_entries); - if (0 == nesadapter->free_256pbl) { - list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + nes_debug(NES_DBG_CQ, "pbl_entries=%u, use a 256 byte PBL\n", pbl_entries); + if (nesadapter->free_256pbl == 0) { + if (cqp_request->dynamic) { + spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); + kfree(cqp_request); + } else { + list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); + spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); + } if (!context) pci_free_consistent(nesdev->pcidev, nescq->cq_mem_size, mem, nescq->hw_cq.cq_pbase); nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num); kfree(nescq); - return (ERR_PTR(-ENOMEM)); + return ERR_PTR(-ENOMEM); } else { - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= NES_CQP_CQ_VIRT; + opcode |= NES_CQP_CQ_VIRT; nescq->virtual_cq = 1; nesadapter->free_256pbl--; } } } - cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = - cpu_to_le32(nescq->hw_cq.cq_number | ((u32)nesdev->ceq_index << 16)); - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX] = 0; - *((struct nes_hw_cqp **)&cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_LOW_IDX]) = - &nesdev->cqp; + spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); + + nes_fill_init_cqp_wqe(cqp_wqe, nesdev); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, opcode); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX, + (nescq->hw_cq.cq_number | ((u32)nesdev->ceq_index << 16))); + if (context) { - if (1 != pbl_entries) + if (pbl_entries != 1) u64temp = (u64)nespbl->pbl_pbase; else - u64temp = nespbl->pbl_vbase[0]; - cqp_wqe->wqe_words[NES_CQP_CQ_WQE_DOORBELL_INDEX_HIGH_IDX] = - cpu_to_le32(nes_ucontext->mmap_db_index[0]); + u64temp = le64_to_cpu(nespbl->pbl_vbase[0]); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_DOORBELL_INDEX_HIGH_IDX, + nes_ucontext->mmap_db_index[0]); } else { u64temp = (u64)nescq->hw_cq.cq_pbase; cqp_wqe->wqe_words[NES_CQP_CQ_WQE_DOORBELL_INDEX_HIGH_IDX] = 0; } - cqp_wqe->wqe_words[NES_CQP_CQ_WQE_PBL_LOW_IDX] = cpu_to_le32((u32)u64temp); - cqp_wqe->wqe_words[NES_CQP_CQ_WQE_PBL_HIGH_IDX] = cpu_to_le32((u32)(u64temp >> 32)); + set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp); cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] = 0; - *((struct nes_hw_cq **)&cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_LOW_IDX]) = - &nescq->hw_cq; - *((u64 *)&cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_LOW_IDX]) >>= 1; + u64temp = (u64)(unsigned long)&nescq->hw_cq; + cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_LOW_IDX] = + cpu_to_le32((u32)(u64temp >> 1)); + cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] = + cpu_to_le32(((u32)((u64temp) >> 33)) & 0x7FFFFFFF); atomic_set(&cqp_request->refcount, 2); - nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_HOLDING_LOCK, - NES_CQP_REQUEST_RING_DOORBELL); + nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_RING_DOORBELL); /* Wait for CQP */ - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); - dprintk("Waiting for create iWARP CQ%u to complete.\n", nescq->hw_cq.cq_number); + nes_debug(NES_DBG_CQ, "Waiting for create iWARP CQ%u to complete.\n", + nescq->hw_cq.cq_number); ret = wait_event_timeout(cqp_request->waitq, (0 != cqp_request->request_done), NES_EVENT_TIMEOUT * 2); - dprintk("Create iWARP CQ%u completed, wait_event_timeout ret = %d.\n", + nes_debug(NES_DBG_CQ, "Create iWARP CQ%u completed, wait_event_timeout ret = %d.\n", nescq->hw_cq.cq_number, ret); if ((!ret) || (cqp_request->major_code)) { if (atomic_dec_and_test(&cqp_request->refcount)) { - spin_lock_irqsave(&nesdev->cqp.lock, flags); - list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + if (cqp_request->dynamic) { + kfree(cqp_request); + } else { + spin_lock_irqsave(&nesdev->cqp.lock, flags); + list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); + spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + } } - dprintk("iWARP CQ%u create timeout expired, major code = 0x%04X," - " minor code = 0x%04X\n", - nescq->hw_cq.cq_number, cqp_request->major_code, cqp_request->minor_code); if (!context) pci_free_consistent(nesdev->pcidev, nescq->cq_mem_size, mem, nescq->hw_cq.cq_pbase); nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num); kfree(nescq); - return (ERR_PTR(-EIO)); + return ERR_PTR(-EIO); } else { if (atomic_dec_and_test(&cqp_request->refcount)) { - spin_lock_irqsave(&nesdev->cqp.lock, flags); - list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + if (cqp_request->dynamic) { + kfree(cqp_request); + } else { + spin_lock_irqsave(&nesdev->cqp.lock, flags); + list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); + spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + } } } @@ -1675,13 +1861,11 @@ static struct ib_cq *nes_create_cq(struct ib_device *ibdev, int entries, if (ib_copy_to_udata(udata, &resp, sizeof resp)) { nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num); kfree(nescq); - return (ERR_PTR(-EFAULT)); + return ERR_PTR(-EFAULT); } } - dprintk("%s: netdev refcnt = %u.\n", __FUNCTION__, - atomic_read(&nesvnic->netdev->refcnt)); - return(&nescq->ibcq); + return &nescq->ibcq; } @@ -1697,38 +1881,29 @@ static int nes_destroy_cq(struct ib_cq *ib_cq) struct nes_hw_cqp_wqe *cqp_wqe; struct nes_cqp_request *cqp_request; unsigned long flags; + u32 opcode = 0; int ret; - dprintk("%s:%u: %p.\n", __FUNCTION__, __LINE__, ib_cq); - if (ib_cq == NULL) - return (0); + return 0; nescq = to_nescq(ib_cq); nesvnic = to_nesvnic(ib_cq->device); nesdev = nesvnic->nesdev; nesadapter = nesdev->nesadapter; - /* dprintk("%s: netdev refcnt = %u.\n", __FUNCTION__, - atomic_read(&nesvnic->netdev->refcnt)); */ - dprintk("%s:%u: Destroy CQ%u\n", - __FUNCTION__, __LINE__, nescq->hw_cq.cq_number); + nes_debug(NES_DBG_CQ, "Destroy CQ%u\n", nescq->hw_cq.cq_number); /* Send DestroyCQ request to CQP */ - spin_lock_irqsave(&nesdev->cqp.lock, flags); - - cqp_request = nes_get_cqp_request(nesdev, NES_CQP_REQUEST_HOLDING_LOCK); - if (NULL == cqp_request) { - dprintk("%s: Failed to get a cqp_request.\n", __FUNCTION__); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); - return (-ENOMEM); + cqp_request = nes_get_cqp_request(nesdev); + if (cqp_request == NULL) { + nes_debug(NES_DBG_CQ, "Failed to get a cqp_request.\n"); + return -ENOMEM; } cqp_request->waiting = 1; cqp_wqe = &cqp_request->cqp_wqe; - - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = - NES_CQP_DESTROY_CQ | (nescq->hw_cq.cq_size << 16); - + opcode = NES_CQP_DESTROY_CQ | (nescq->hw_cq.cq_size << 16); + spin_lock_irqsave(&nesadapter->pbl_lock, flags); if (nescq->virtual_cq == 1) { nesadapter->free_256pbl++; if (nesadapter->free_256pbl > nesadapter->max_256pbl) { @@ -1741,63 +1916,66 @@ static int nes_destroy_cq(struct ib_cq *ib_cq) printk(KERN_ERR PFX "%s: free 4K PBLs(%u) has exceeded the max(%u)\n", __FUNCTION__, nesadapter->free_4kpbl, nesadapter->max_4kpbl); } - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= NES_CQP_CQ_4KB_CHUNK; + opcode |= NES_CQP_CQ_4KB_CHUNK; } - cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = - nescq->hw_cq.cq_number | ((u32)PCI_FUNC(nesdev->pcidev->devfn) << 16); - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX] = 0; - *((struct nes_hw_cqp **)&cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_LOW_IDX]) = - &nesdev->cqp; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] = 0; + spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); + nes_fill_init_cqp_wqe(cqp_wqe, nesdev); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, opcode); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX, + (nescq->hw_cq.cq_number | ((u32)PCI_FUNC(nesdev->pcidev->devfn) << 16))); + nes_free_resource(nesadapter, nesadapter->allocated_cqs, nescq->hw_cq.cq_number); atomic_set(&cqp_request->refcount, 2); - nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_HOLDING_LOCK, - NES_CQP_REQUEST_RING_DOORBELL); + nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_RING_DOORBELL); /* Wait for CQP */ - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); - dprintk("Waiting for destroy iWARP CQ%u to complete.\n", + nes_debug(NES_DBG_CQ, "Waiting for destroy iWARP CQ%u to complete.\n", nescq->hw_cq.cq_number); - /* cqp_head = (cqp_head+1)&(nesdev->cqp.sq_size-1); */ ret = wait_event_timeout(cqp_request->waitq, (0 != cqp_request->request_done), NES_EVENT_TIMEOUT); - dprintk("Destroy iWARP CQ%u completed, wait_event_timeout ret = %u," + nes_debug(NES_DBG_CQ, "Destroy iWARP CQ%u completed, wait_event_timeout ret = %u," " CQP Major:Minor codes = 0x%04X:0x%04X.\n", nescq->hw_cq.cq_number, ret, cqp_request->major_code, cqp_request->minor_code); if ((!ret) || (cqp_request->major_code)) { if (atomic_dec_and_test(&cqp_request->refcount)) { - spin_lock_irqsave(&nesdev->cqp.lock, flags); - list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + if (cqp_request->dynamic) { + kfree(cqp_request); + } else { + spin_lock_irqsave(&nesdev->cqp.lock, flags); + list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); + spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + } } if (!ret) { - dprintk("iWARP CQ%u destroy timeout expired\n", nescq->hw_cq.cq_number); + nes_debug(NES_DBG_CQ, "iWARP CQ%u destroy timeout expired\n", + nescq->hw_cq.cq_number); ret = -ETIME; } else { - dprintk("iWARP CQ%u destroy failed\n", nescq->hw_cq.cq_number); + nes_debug(NES_DBG_CQ, "iWARP CQ%u destroy failed\n", + nescq->hw_cq.cq_number); ret = -EIO; } } else { ret = 0; if (atomic_dec_and_test(&cqp_request->refcount)) { - spin_lock_irqsave(&nesdev->cqp.lock, flags); - list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + if (cqp_request->dynamic) { + kfree(cqp_request); + } else { + spin_lock_irqsave(&nesdev->cqp.lock, flags); + list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); + spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + } } } if (nescq->cq_mem_size) pci_free_consistent(nesdev->pcidev, nescq->cq_mem_size, (void *)nescq->hw_cq.cq_vbase, nescq->hw_cq.cq_pbase); - nes_free_resource(nesadapter, nesadapter->allocated_cqs, nescq->hw_cq.cq_number); kfree(nescq); - /* dprintk("%s: netdev refcnt = %u.\n", __FUNCTION__, - atomic_read(&nesvnic->netdev->refcnt)); */ - return (ret); + return ret; } @@ -1815,137 +1993,131 @@ static int nes_reg_mr(struct nes_device *nesdev, struct nes_pd *nespd, int ret; struct nes_adapter *nesadapter = nesdev->nesadapter; /* int count; */ + u32 opcode = 0; u16 major_code; /* Register the region with the adapter */ - spin_lock_irqsave(&nesdev->cqp.lock, flags); - cqp_request = nes_get_cqp_request(nesdev, NES_CQP_REQUEST_HOLDING_LOCK); - if (NULL == cqp_request) { - dprintk("%s: Failed to get a cqp_request.\n", __FUNCTION__); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); - return (-ENOMEM); + cqp_request = nes_get_cqp_request(nesdev); + if (cqp_request == NULL) { + nes_debug(NES_DBG_MR, "Failed to get a cqp_request.\n"); + return -ENOMEM; } cqp_request->waiting = 1; cqp_wqe = &cqp_request->cqp_wqe; + spin_lock_irqsave(&nesadapter->pbl_lock, flags); /* track PBL resources */ if (pbl_count != 0) { if (pbl_count > 1) { /* Two level PBL */ if ((pbl_count+1) > nesadapter->free_4kpbl) { - dprintk("%s: Out of 4KB Pbls for two level request.\n", - __FUNCTION__); - list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); - return(-ENOMEM); + nes_debug(NES_DBG_MR, "Out of 4KB Pbls for two level request.\n"); + if (cqp_request->dynamic) { + spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); + kfree(cqp_request); + } else { + list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); + spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); + } + return -ENOMEM; } else { nesadapter->free_4kpbl -= pbl_count+1; } } else if (residual_page_count > 32) { if (pbl_count > nesadapter->free_4kpbl) { - dprintk("%s: Out of 4KB Pbls.\n", __FUNCTION__); - list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); - return (-ENOMEM); + nes_debug(NES_DBG_MR, "Out of 4KB Pbls.\n"); + if (cqp_request->dynamic) { + spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); + kfree(cqp_request); + } else { + list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); + spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); + } + return -ENOMEM; } else { nesadapter->free_4kpbl -= pbl_count; } } else { if (pbl_count > nesadapter->free_256pbl) { - dprintk("%s: Out of 256B Pbls.\n", __FUNCTION__); - list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); - return (-ENOMEM); + nes_debug(NES_DBG_MR, "Out of 256B Pbls.\n"); + if (cqp_request->dynamic) { + spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); + kfree(cqp_request); + } else { + list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); + spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); + } + return -ENOMEM; } else { nesadapter->free_256pbl -= pbl_count; } } } - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = - NES_CQP_REGISTER_STAG | NES_CQP_STAG_RIGHTS_LOCAL_READ; - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= - NES_CQP_STAG_VA_TO | NES_CQP_STAG_MR; - if (acc & IB_ACCESS_LOCAL_WRITE) { - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= NES_CQP_STAG_RIGHTS_LOCAL_WRITE; - } - if (acc & IB_ACCESS_REMOTE_WRITE) { - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= - NES_CQP_STAG_RIGHTS_REMOTE_WRITE | NES_CQP_STAG_REM_ACC_EN; - } - if (acc & IB_ACCESS_REMOTE_READ) { - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= - NES_CQP_STAG_RIGHTS_REMOTE_READ | NES_CQP_STAG_REM_ACC_EN; - } - if (acc & IB_ACCESS_MW_BIND) { - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= - NES_CQP_STAG_RIGHTS_WINDOW_BIND | NES_CQP_STAG_REM_ACC_EN; - } - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX] = 0; - *((struct nes_hw_cqp **)&cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_LOW_IDX]) = - &nesdev->cqp; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_STAG_WQE_VA_LOW_IDX] = cpu_to_le32((u32)*iova_start); - cqp_wqe->wqe_words[NES_CQP_STAG_WQE_VA_HIGH_IDX] = - cpu_to_le32((u32)((((u64)*iova_start) >> 32))); - cqp_wqe->wqe_words[NES_CQP_STAG_WQE_LEN_LOW_IDX] = cpu_to_le32((u32)region_length); + spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); + + opcode = NES_CQP_REGISTER_STAG | NES_CQP_STAG_RIGHTS_LOCAL_READ | + NES_CQP_STAG_VA_TO | NES_CQP_STAG_MR; + if (acc & IB_ACCESS_LOCAL_WRITE) + opcode |= NES_CQP_STAG_RIGHTS_LOCAL_WRITE; + if (acc & IB_ACCESS_REMOTE_WRITE) + opcode |= NES_CQP_STAG_RIGHTS_REMOTE_WRITE | NES_CQP_STAG_REM_ACC_EN; + if (acc & IB_ACCESS_REMOTE_READ) + opcode |= NES_CQP_STAG_RIGHTS_REMOTE_READ | NES_CQP_STAG_REM_ACC_EN; + if (acc & IB_ACCESS_MW_BIND) + opcode |= NES_CQP_STAG_RIGHTS_WINDOW_BIND | NES_CQP_STAG_REM_ACC_EN; + + nes_fill_init_cqp_wqe(cqp_wqe, nesdev); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, opcode); + set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_VA_LOW_IDX, *iova_start); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_LEN_LOW_IDX, region_length); + cqp_wqe->wqe_words[NES_CQP_STAG_WQE_LEN_HIGH_PD_IDX] = cpu_to_le32((u32)(region_length >> 8) & 0xff000000); cqp_wqe->wqe_words[NES_CQP_STAG_WQE_LEN_HIGH_PD_IDX] |= cpu_to_le32(nespd->pd_id & 0x00007fff); - cqp_wqe->wqe_words[NES_CQP_STAG_WQE_STAG_IDX] = cpu_to_le32(stag); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_STAG_IDX, stag); if (pbl_count == 0) { - cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PA_LOW_IDX] = - cpu_to_le32((u32)single_buffer); - cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PA_HIGH_IDX] = - cpu_to_le32((u32)((((u64)single_buffer) >> 32))); - cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PBL_BLK_COUNT_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PBL_LEN_IDX] = 0; + set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_PA_LOW_IDX, single_buffer); } else { - cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PA_LOW_IDX] = - cpu_to_le32((u32)root_vpbl->pbl_pbase); - cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PA_HIGH_IDX] = - cpu_to_le32((u32)((((u64)root_vpbl->pbl_pbase) >> 32))); - cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PBL_BLK_COUNT_IDX] = cpu_to_le32(pbl_count); - cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PBL_LEN_IDX] = - cpu_to_le32(((pbl_count-1) * 4096) + (residual_page_count*8)); - if ((pbl_count > 1) || (residual_page_count > 32)) { - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= NES_CQP_STAG_PBL_BLK_SIZE; - } - } - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = - cpu_to_le32(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX]); + set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_PA_LOW_IDX, root_vpbl->pbl_pbase); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_PBL_BLK_COUNT_IDX, pbl_count); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_PBL_LEN_IDX, + (((pbl_count - 1) * 4096) + (residual_page_count*8))); + if ((pbl_count > 1) || (residual_page_count > 32)) + cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= cpu_to_le32(NES_CQP_STAG_PBL_BLK_SIZE); + } barrier(); atomic_set(&cqp_request->refcount, 2); - nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_HOLDING_LOCK, - NES_CQP_REQUEST_RING_DOORBELL); + nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_RING_DOORBELL); /* Wait for CQP */ - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); - ret = wait_event_timeout(cqp_request->waitq, (0 != cqp_request->request_done), NES_EVENT_TIMEOUT); - dprintk("%s: Register STag 0x%08X completed, wait_event_timeout ret = %u," + nes_debug(NES_DBG_MR, "Register STag 0x%08X completed, wait_event_timeout ret = %u," " CQP Major:Minor codes = 0x%04X:0x%04X.\n", - __FUNCTION__, stag, ret, cqp_request->major_code, cqp_request->minor_code); + stag, ret, cqp_request->major_code, cqp_request->minor_code); major_code = cqp_request->major_code; if (atomic_dec_and_test(&cqp_request->refcount)) { - spin_lock_irqsave(&nesdev->cqp.lock, flags); - list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + if (cqp_request->dynamic) { + kfree(cqp_request); + } else { + spin_lock_irqsave(&nesdev->cqp.lock, flags); + list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); + spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + } } if (!ret) - return(-ETIME); + return -ETIME; else if (major_code) - return(-EIO); + return -EIO; else - return (0); + return 0; - return (0); + return 0; } @@ -1978,8 +2150,6 @@ static struct ib_mr *nes_reg_phys_mr(struct ib_pd *ib_pd, u8 single_page = 1; u8 stag_key = 0; - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); - pbl_depth = 0; region_length = 0; vpbl.pbl_vbase = NULL; @@ -1994,39 +2164,38 @@ static struct ib_mr *nes_reg_phys_mr(struct ib_pd *ib_pd, next_stag_index >>= 8; next_stag_index %= nesadapter->max_mr; if (num_phys_buf > (1024*512)) { - return (ERR_PTR(-E2BIG)); + return ERR_PTR(-E2BIG); } err = nes_alloc_resource(nesadapter, nesadapter->allocated_mrs, nesadapter->max_mr, &stag_index, &next_stag_index); if (err) { - return (ERR_PTR(err)); + return ERR_PTR(err); } - nesmr = kmalloc(sizeof(*nesmr), GFP_KERNEL); + nesmr = kzalloc(sizeof(*nesmr), GFP_KERNEL); if (!nesmr) { nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index); - return (ERR_PTR(-ENOMEM)); + return ERR_PTR(-ENOMEM); } for (i = 0; i < num_phys_buf; i++) { if ((i & 0x01FF) == 0) { - if (1 == root_pbl_index) { + if (root_pbl_index == 1) { /* Allocate the root PBL */ root_vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev, 8192, &root_vpbl.pbl_pbase); - dprintk("%s: Allocating root PBL, va = %p, pa = 0x%08X\n", - __FUNCTION__, root_vpbl.pbl_vbase, - (unsigned int)root_vpbl.pbl_pbase); + nes_debug(NES_DBG_MR, "Allocating root PBL, va = %p, pa = 0x%08X\n", + root_vpbl.pbl_vbase, (unsigned int)root_vpbl.pbl_pbase); if (!root_vpbl.pbl_vbase) { pci_free_consistent(nesdev->pcidev, 4096, vpbl.pbl_vbase, vpbl.pbl_pbase); nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index); kfree(nesmr); - return (ERR_PTR(-ENOMEM)); + return ERR_PTR(-ENOMEM); } - root_vpbl.leaf_vpbl = kmalloc(sizeof(*root_vpbl.leaf_vpbl)*1024, GFP_KERNEL); + root_vpbl.leaf_vpbl = kzalloc(sizeof(*root_vpbl.leaf_vpbl)*1024, GFP_KERNEL); if (!root_vpbl.leaf_vpbl) { pci_free_consistent(nesdev->pcidev, 8192, root_vpbl.pbl_vbase, root_vpbl.pbl_pbase); @@ -2034,7 +2203,7 @@ static struct ib_mr *nes_reg_phys_mr(struct ib_pd *ib_pd, vpbl.pbl_pbase); nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index); kfree(nesmr); - return (ERR_PTR(-ENOMEM)); + return ERR_PTR(-ENOMEM); } root_vpbl.pbl_vbase[0].pa_low = cpu_to_le32((u32)vpbl.pbl_pbase); root_vpbl.pbl_vbase[0].pa_high = @@ -2044,8 +2213,8 @@ static struct ib_mr *nes_reg_phys_mr(struct ib_pd *ib_pd, /* Allocate a 4K buffer for the PBL */ vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev, 4096, &vpbl.pbl_pbase); - dprintk("%s: Allocating leaf PBL, va = %p, pa = 0x%016lX\n", - __FUNCTION__, vpbl.pbl_vbase, (unsigned long)vpbl.pbl_pbase); + nes_debug(NES_DBG_MR, "Allocating leaf PBL, va = %p, pa = 0x%016lX\n", + vpbl.pbl_vbase, (unsigned long)vpbl.pbl_pbase); if (!vpbl.pbl_vbase) { nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index); ibmr = ERR_PTR(-ENOMEM); @@ -2066,7 +2235,7 @@ static struct ib_mr *nes_reg_phys_mr(struct ib_pd *ib_pd, if (buffer_list[i].addr & ~PAGE_MASK) { /* TODO: Unwind allocated buffers */ nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index); - dprintk("Unaligned Memory Buffer: 0x%x\n", + nes_debug(NES_DBG_MR, "Unaligned Memory Buffer: 0x%x\n", (unsigned int) buffer_list[i].addr); ibmr = ERR_PTR(-EINVAL); kfree(nesmr); @@ -2075,7 +2244,7 @@ static struct ib_mr *nes_reg_phys_mr(struct ib_pd *ib_pd, if (!buffer_list[i].size) { nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index); - dprintk("Invalid Buffer Size\n"); + nes_debug(NES_DBG_MR, "Invalid Buffer Size\n"); ibmr = ERR_PTR(-EINVAL); kfree(nesmr); goto reg_phys_err; @@ -2095,10 +2264,9 @@ static struct ib_mr *nes_reg_phys_mr(struct ib_pd *ib_pd, stag |= driver_key; stag += (u32)stag_key; - dprintk("%s: Registering STag 0x%08X, VA = 0x%016lX," + nes_debug(NES_DBG_MR, "Registering STag 0x%08X, VA = 0x%016lX," " length = 0x%016lX, index = 0x%08X\n", - __FUNCTION__, stag, (unsigned long)*iova_start, - (unsigned long)region_length, stag_index); + stag, (unsigned long)*iova_start, (unsigned long)region_length, stag_index); region_length -= (*iova_start)&PAGE_MASK; @@ -2145,38 +2313,34 @@ static struct ib_mr *nes_reg_phys_mr(struct ib_pd *ib_pd, root_vpbl.pbl_pbase); } - return (ibmr); + return ibmr; } /** * nes_get_dma_mr */ -static struct ib_mr *nes_get_dma_mr(struct ib_pd *pd, int acc) { +static struct ib_mr *nes_get_dma_mr(struct ib_pd *pd, int acc) +{ struct ib_phys_buf bl; u64 kva = 0; - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); + nes_debug(NES_DBG_MR, "\n"); bl.size = (u64)0xffffffffffULL; bl.addr = 0; - return (nes_reg_phys_mr(pd, &bl, 1, acc, &kva)); + return nes_reg_phys_mr(pd, &bl, 1, acc, &kva); } /** * nes_reg_user_mr */ -#ifdef OFED_1_2 -static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, struct ib_umem *region, - int acc, struct ib_udata *udata) -#else static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, - u64 virt, int acc, struct ib_udata *udata) -#endif + u64 virt, int acc, struct ib_udata *udata) { u64 iova_start; - u64 *pbl; + __le64 *pbl; u64 region_length; dma_addr_t last_dma_addr = 0; dma_addr_t first_dma_addr = 0; @@ -2184,20 +2348,19 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, struct nes_vnic *nesvnic = to_nesvnic(pd->device); struct nes_device *nesdev = nesvnic->nesdev; struct nes_adapter *nesadapter = nesdev->nesadapter; - struct ib_mr *ibmr; + struct ib_mr *ibmr = ERR_PTR(-EINVAL); struct ib_umem_chunk *chunk; struct nes_ucontext *nes_ucontext; struct nes_pbl *nespbl; struct nes_mr *nesmr; -#ifndef OFED_1_2 struct ib_umem *region; -#endif struct nes_mem_reg_req req; struct nes_vpbl vpbl; struct nes_root_vpbl root_vpbl; - int j; + int nmap_index, page_index; int page_count = 0; int err, pbl_depth = 0; + int chunk_pages; int ret; u32 stag; u32 stag_index = 0; @@ -2205,31 +2368,26 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, u32 driver_key; u32 root_pbl_index = 0; u32 cur_pbl_index = 0; + u32 skip_pages; u16 pbl_count; u8 single_page = 1; u8 stag_key; - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); - -#ifdef OFED_1_2 - dprintk("%s: User base = 0x%lX, Virt base = 0x%lX, length = %u," - " offset = %u, page size = %u.\n", - __FUNCTION__, region->user_base, region->virt_base, (u32)region->length, - region->offset, region->page_size); -#else region = ib_umem_get(pd->uobject->context, start, length, acc); if (IS_ERR(region)) { - return ((struct ib_mr *)region); + return (struct ib_mr *)region; } - dprintk("%s: User base = 0x%lX, Virt base = 0x%lX, length = %u\n", - __FUNCTION__, (unsigned long int)start, - (unsigned long int)virt, (u32)length); -#endif + nes_debug(NES_DBG_MR, "User base = 0x%lX, Virt base = 0x%lX, length = %u," + " offset = %u, page size = %u.\n", + (unsigned long int)start, (unsigned long int)virt, (u32)length, + region->offset, region->page_size); + + skip_pages = ((u32)region->offset) >> 12; if (ib_copy_from_udata(&req, udata, sizeof(req))) - return (ERR_PTR(-EFAULT)); - dprintk("%s: Memory Registration type = %08X.\n", __FUNCTION__, req.reg_type); + return ERR_PTR(-EFAULT); + nes_debug(NES_DBG_MR, "Memory Registration type = %08X.\n", req.reg_type); switch (req.reg_type) { case IWNES_MEMREG_TYPE_MEM: @@ -2242,7 +2400,7 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, get_random_bytes(&next_stag_index, sizeof(next_stag_index)); stag_key = (u8)next_stag_index; - driver_key = 0; + driver_key = next_stag_index & 0x70000000; next_stag_index >>= 8; next_stag_index %= nesadapter->max_mr; @@ -2250,149 +2408,145 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, err = nes_alloc_resource(nesadapter, nesadapter->allocated_mrs, nesadapter->max_mr, &stag_index, &next_stag_index); if (err) { -#ifndef OFED_1_2 ib_umem_release(region); -#endif - return (ERR_PTR(err)); + return ERR_PTR(err); } - nesmr = kmalloc(sizeof(*nesmr), GFP_KERNEL); + nesmr = kzalloc(sizeof(*nesmr), GFP_KERNEL); if (!nesmr) { -#ifndef OFED_1_2 ib_umem_release(region); -#endif nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index); - return (ERR_PTR(-ENOMEM)); + return ERR_PTR(-ENOMEM); } -#ifndef OFED_1_2 nesmr->region = region; -#endif list_for_each_entry(chunk, ®ion->chunk_list, list) { - dprintk("%s: Chunk: nents = %u, nmap = %u .\n", - __FUNCTION__, chunk->nents, chunk->nmap); - for (j = 0; j < chunk->nmap; ++j) { - if ((page_count&0x01FF) == 0) { - if (page_count>(1024*512)) { -#ifndef OFED_1_2 - ib_umem_release(region); -#endif - pci_free_consistent(nesdev->pcidev, 4096, vpbl.pbl_vbase, - vpbl.pbl_pbase); - nes_free_resource(nesadapter, - nesadapter->allocated_mrs, stag_index); - kfree(nesmr); - return (ERR_PTR(-E2BIG)); - } - if (1 == root_pbl_index) { - root_vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev, - 8192, &root_vpbl.pbl_pbase); - dprintk("%s: Allocating root PBL, va = %p, pa = 0x%08X\n", - __FUNCTION__, root_vpbl.pbl_vbase, - (unsigned int)root_vpbl.pbl_pbase); - if (!root_vpbl.pbl_vbase) { -#ifndef OFED_1_2 - ib_umem_release(region); -#endif - pci_free_consistent(nesdev->pcidev, 4096, vpbl.pbl_vbase, - vpbl.pbl_pbase); - nes_free_resource(nesadapter, nesadapter->allocated_mrs, - stag_index); - kfree(nesmr); - return (ERR_PTR(-ENOMEM)); - } - root_vpbl.leaf_vpbl = kmalloc(sizeof(*root_vpbl.leaf_vpbl)*1024, - GFP_KERNEL); - if (!root_vpbl.leaf_vpbl) { -#ifndef OFED_1_2 - ib_umem_release(region); -#endif - pci_free_consistent(nesdev->pcidev, 8192, root_vpbl.pbl_vbase, - root_vpbl.pbl_pbase); - pci_free_consistent(nesdev->pcidev, 4096, vpbl.pbl_vbase, - vpbl.pbl_pbase); - nes_free_resource(nesadapter, nesadapter->allocated_mrs, - stag_index); - kfree(nesmr); - return (ERR_PTR(-ENOMEM)); - } - root_vpbl.pbl_vbase[0].pa_low = - cpu_to_le32((u32)vpbl.pbl_pbase); - root_vpbl.pbl_vbase[0].pa_high = - cpu_to_le32((u32)((((u64)vpbl.pbl_pbase) >> 32))); - root_vpbl.leaf_vpbl[0] = vpbl; - } - vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev, 4096, - &vpbl.pbl_pbase); - dprintk("%s: Allocating leaf PBL, va = %p, pa = 0x%08X\n", - __FUNCTION__, vpbl.pbl_vbase, (unsigned int)vpbl.pbl_pbase); - if (!vpbl.pbl_vbase) { -#ifndef OFED_1_2 - ib_umem_release(region); -#endif - nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index); - ibmr = ERR_PTR(-ENOMEM); - kfree(nesmr); - goto reg_user_mr_err; - } - if (1 <= root_pbl_index) { - root_vpbl.pbl_vbase[root_pbl_index].pa_low = - cpu_to_le32((u32)vpbl.pbl_pbase); - root_vpbl.pbl_vbase[root_pbl_index].pa_high = - cpu_to_le32((u32)((((u64)vpbl.pbl_pbase)>>32))); - root_vpbl.leaf_vpbl[root_pbl_index] = vpbl; - } - root_pbl_index++; - cur_pbl_index = 0; - } - if (sg_dma_address(&chunk->page_list[j]) & ~PAGE_MASK) { -#ifndef OFED_1_2 + nes_debug(NES_DBG_MR, "Chunk: nents = %u, nmap = %u .\n", + chunk->nents, chunk->nmap); + for (nmap_index = 0; nmap_index < chunk->nmap; ++nmap_index) { + if (sg_dma_address(&chunk->page_list[nmap_index]) & ~PAGE_MASK) { ib_umem_release(region); -#endif nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index); - dprintk("%s: Unaligned Memory Buffer: 0x%x\n", __FUNCTION__, - (unsigned int) sg_dma_address(&chunk->page_list[j])); + nes_debug(NES_DBG_MR, "Unaligned Memory Buffer: 0x%x\n", + (unsigned int) sg_dma_address(&chunk->page_list[nmap_index])); ibmr = ERR_PTR(-EINVAL); kfree(nesmr); goto reg_user_mr_err; } - if (!sg_dma_len(&chunk->page_list[j])) { -#ifndef OFED_1_2 + if (!sg_dma_len(&chunk->page_list[nmap_index])) { ib_umem_release(region); -#endif nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index); - dprintk("%s: Invalid Buffer Size\n", __FUNCTION__); + nes_debug(NES_DBG_MR, "Invalid Buffer Size\n"); ibmr = ERR_PTR(-EINVAL); kfree(nesmr); goto reg_user_mr_err; } - region_length += sg_dma_len(&chunk->page_list[j]); - if (single_page) { - if (page_count != 0) { - if ((last_dma_addr+PAGE_SIZE) != - sg_dma_address(&chunk->page_list[j])) - single_page = 0; - last_dma_addr = sg_dma_address(&chunk->page_list[j]); - } else { - first_dma_addr = sg_dma_address(&chunk->page_list[j]); - last_dma_addr = first_dma_addr; + region_length += sg_dma_len(&chunk->page_list[nmap_index]); + chunk_pages = sg_dma_len(&chunk->page_list[nmap_index]) >> 12; + region_length -= skip_pages << 12; + for (page_index = skip_pages; page_index < chunk_pages; page_index++) { + skip_pages = 0; + if ((page_count!=0)&&(page_count<<12)-(region->offset&(4096-1))>=region->length) + goto enough_pages; + if ((page_count&0x01FF) == 0) { + if (page_count>(1024*512)) { + ib_umem_release(region); + pci_free_consistent(nesdev->pcidev, 4096, vpbl.pbl_vbase, + vpbl.pbl_pbase); + nes_free_resource(nesadapter, + nesadapter->allocated_mrs, stag_index); + kfree(nesmr); + ibmr = ERR_PTR(-E2BIG); + goto reg_user_mr_err; + } + if (root_pbl_index == 1) { + root_vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev, + 8192, &root_vpbl.pbl_pbase); + nes_debug(NES_DBG_MR, "Allocating root PBL, va = %p, pa = 0x%08X\n", + root_vpbl.pbl_vbase, (unsigned int)root_vpbl.pbl_pbase); + if (!root_vpbl.pbl_vbase) { + ib_umem_release(region); + pci_free_consistent(nesdev->pcidev, 4096, vpbl.pbl_vbase, + vpbl.pbl_pbase); + nes_free_resource(nesadapter, nesadapter->allocated_mrs, + stag_index); + kfree(nesmr); + ibmr = ERR_PTR(-ENOMEM); + goto reg_user_mr_err; + } + root_vpbl.leaf_vpbl = kzalloc(sizeof(*root_vpbl.leaf_vpbl)*1024, + GFP_KERNEL); + if (!root_vpbl.leaf_vpbl) { + ib_umem_release(region); + pci_free_consistent(nesdev->pcidev, 8192, root_vpbl.pbl_vbase, + root_vpbl.pbl_pbase); + pci_free_consistent(nesdev->pcidev, 4096, vpbl.pbl_vbase, + vpbl.pbl_pbase); + nes_free_resource(nesadapter, nesadapter->allocated_mrs, + stag_index); + kfree(nesmr); + ibmr = ERR_PTR(-ENOMEM); + goto reg_user_mr_err; + } + root_vpbl.pbl_vbase[0].pa_low = + cpu_to_le32((u32)vpbl.pbl_pbase); + root_vpbl.pbl_vbase[0].pa_high = + cpu_to_le32((u32)((((u64)vpbl.pbl_pbase) >> 32))); + root_vpbl.leaf_vpbl[0] = vpbl; + } + vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev, 4096, + &vpbl.pbl_pbase); + nes_debug(NES_DBG_MR, "Allocating leaf PBL, va = %p, pa = 0x%08X\n", + vpbl.pbl_vbase, (unsigned int)vpbl.pbl_pbase); + if (!vpbl.pbl_vbase) { + ib_umem_release(region); + nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index); + ibmr = ERR_PTR(-ENOMEM); + kfree(nesmr); + goto reg_user_mr_err; + } + if (1 <= root_pbl_index) { + root_vpbl.pbl_vbase[root_pbl_index].pa_low = + cpu_to_le32((u32)vpbl.pbl_pbase); + root_vpbl.pbl_vbase[root_pbl_index].pa_high = + cpu_to_le32((u32)((((u64)vpbl.pbl_pbase)>>32))); + root_vpbl.leaf_vpbl[root_pbl_index] = vpbl; + } + root_pbl_index++; + cur_pbl_index = 0; + } + if (single_page) { + if (page_count != 0) { + if ((last_dma_addr+4096) != + (sg_dma_address(&chunk->page_list[nmap_index])+ + (page_index * 4096))) + single_page = 0; + last_dma_addr = sg_dma_address(&chunk->page_list[nmap_index])+ + (page_index * 4096); + } else { + first_dma_addr = sg_dma_address(&chunk->page_list[nmap_index])+ + (page_index * 4096); + last_dma_addr = first_dma_addr; + } } - } - vpbl.pbl_vbase[cur_pbl_index].pa_low = - cpu_to_le32((u32)sg_dma_address(&chunk->page_list[j])); - vpbl.pbl_vbase[cur_pbl_index].pa_high = - cpu_to_le32((u32)((((u64)sg_dma_address(&chunk->page_list[j]))>>32))); - cur_pbl_index++; - page_count++; + vpbl.pbl_vbase[cur_pbl_index].pa_low = + cpu_to_le32((u32)(sg_dma_address(&chunk->page_list[nmap_index])+ + (page_index * 4096))); + vpbl.pbl_vbase[cur_pbl_index].pa_high = + cpu_to_le32((u32)((((u64)(sg_dma_address(&chunk->page_list[nmap_index])+ + (page_index * 4096))) >> 32))); + cur_pbl_index++; + page_count++; + } } } - - dprintk("%s[%u] calculating stag, stag_index=0x%08x, driver_key=0x%08x," - " stag_key=0x%08x\n", __FUNCTION__, __LINE__, + enough_pages: + nes_debug(NES_DBG_MR, "calculating stag, stag_index=0x%08x, driver_key=0x%08x," + " stag_key=0x%08x\n", stag_index, driver_key, stag_key); stag = stag_index << 8; stag |= driver_key; @@ -2401,17 +2555,7 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, stag = 1; } -#ifdef OFED_1_2 - iova_start = (u64)region->virt_base; -#else iova_start = virt; -#endif - dprintk("%s: Registering STag 0x%08X, VA = 0x%08X, length = 0x%08X," - " index = 0x%08X, region->length=0x%08llx\n", - __FUNCTION__, stag, (unsigned int)iova_start, - (unsigned int)region_length, stag_index, - (unsigned long long)region->length); - /* Make the leaf PBL the root if only one PBL */ if (root_pbl_index == 1) { root_vpbl.pbl_pbase = vpbl.pbl_pbase; @@ -2423,9 +2567,16 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, pbl_count = root_pbl_index; first_dma_addr = 0; } + nes_debug(NES_DBG_MR, "Registering STag 0x%08X, VA = 0x%08X, length = 0x%08X," + " index = 0x%08X, region->length=0x%08llx, pbl_count = %u\n", + stag, (unsigned int)iova_start, + (unsigned int)region_length, stag_index, + (unsigned long long)region->length, pbl_count); ret = nes_reg_mr( nesdev, nespd, stag, region->length, &root_vpbl, first_dma_addr, pbl_count, (u16)cur_pbl_index, acc, &iova_start); + nes_debug(NES_DBG_MR, "ret=%d\n", ret); + if (ret == 0) { nesmr->ibmr.rkey = stag; nesmr->ibmr.lkey = stag; @@ -2437,9 +2588,7 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, nesmr->pbls_used++; } } else { -#ifndef OFED_1_2 ib_umem_release(region); -#endif kfree(nesmr); ibmr = ERR_PTR(-ENOMEM); } @@ -2450,92 +2599,97 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, pci_free_consistent(nesdev->pcidev, 4096, vpbl.pbl_vbase, vpbl.pbl_pbase); } else { - for (j=0; j<root_pbl_index; j++) { + for (page_index = 0; page_index < root_pbl_index; page_index++) { pci_free_consistent(nesdev->pcidev, 4096, - root_vpbl.leaf_vpbl[j].pbl_vbase, - root_vpbl.leaf_vpbl[j].pbl_pbase); + root_vpbl.leaf_vpbl[page_index].pbl_vbase, + root_vpbl.leaf_vpbl[page_index].pbl_pbase); } kfree(root_vpbl.leaf_vpbl); pci_free_consistent(nesdev->pcidev, 8192, root_vpbl.pbl_vbase, root_vpbl.pbl_pbase); } - return (ibmr); + nes_debug(NES_DBG_MR, "Leaving, ibmr=%p", ibmr); + + return ibmr; break; case IWNES_MEMREG_TYPE_QP: -#ifndef OFED_1_2 - ib_umem_release(region); -#endif - return (ERR_PTR(-ENOSYS)); - break; case IWNES_MEMREG_TYPE_CQ: - nespbl = kmalloc(sizeof(*nespbl), GFP_KERNEL); + nespbl = kzalloc(sizeof(*nespbl), GFP_KERNEL); if (!nespbl) { - dprintk("%s: Unable to allocate PBL\n", __FUNCTION__); -#ifndef OFED_1_2 + nes_debug(NES_DBG_MR, "Unable to allocate PBL\n"); ib_umem_release(region); -#endif - return (ERR_PTR(-ENOMEM)); + return ERR_PTR(-ENOMEM); } - memset(nespbl, 0, sizeof(*nespbl)); - nesmr = kmalloc(sizeof(*nesmr), GFP_KERNEL); + nesmr = kzalloc(sizeof(*nesmr), GFP_KERNEL); if (!nesmr) { -#ifndef OFED_1_2 ib_umem_release(region); -#endif kfree(nespbl); - dprintk("%s: Unable to allocate nesmr\n", __FUNCTION__); - return (ERR_PTR(-ENOMEM)); + nes_debug(NES_DBG_MR, "Unable to allocate nesmr\n"); + return ERR_PTR(-ENOMEM); } - memset(nesmr, 0, sizeof(*nesmr)); -#ifndef OFED_1_2 nesmr->region = region; -#endif nes_ucontext = to_nesucontext(pd->uobject->context); - pbl_depth = region->length >> PAGE_SHIFT; - pbl_depth += (region->length & ~PAGE_MASK) ? 1 : 0; + pbl_depth = region->length >> 12; + pbl_depth += (region->length & (4096-1)) ? 1 : 0; nespbl->pbl_size = pbl_depth*sizeof(u64); - dprintk("%s: Attempting to allocate CQ PBL memory, %u bytes, %u entries.\n", - __FUNCTION__, nespbl->pbl_size, pbl_depth); + if (req.reg_type == IWNES_MEMREG_TYPE_QP) { + nes_debug(NES_DBG_MR, "Attempting to allocate QP PBL memory"); + } else { + nes_debug(NES_DBG_MR, "Attempting to allocate CP PBL memory"); + } + + nes_debug(NES_DBG_MR, " %u bytes, %u entries.\n", + nespbl->pbl_size, pbl_depth); pbl = pci_alloc_consistent(nesdev->pcidev, nespbl->pbl_size, &nespbl->pbl_pbase); if (!pbl) { -#ifndef OFED_1_2 ib_umem_release(region); -#endif kfree(nesmr); kfree(nespbl); - dprintk("%s: Unable to allocate cq PBL memory\n", __FUNCTION__); - return (ERR_PTR(-ENOMEM)); + nes_debug(NES_DBG_MR, "Unable to allocate PBL memory\n"); + return ERR_PTR(-ENOMEM); } - nespbl->pbl_vbase = pbl; -#ifdef OFED_1_2 - nespbl->user_base = region->user_base; -#else + nespbl->pbl_vbase = (u64 *)pbl; nespbl->user_base = start; -#endif - dprintk("%s: Allocated CQ PBL memory, %u bytes, pbl_pbase=%p," + nes_debug(NES_DBG_MR, "Allocated PBL memory, %u bytes, pbl_pbase=%p," " pbl_vbase=%p user_base=0x%lx\n", - __FUNCTION__, nespbl->pbl_size, (void *)nespbl->pbl_pbase, + nespbl->pbl_size, (void *)nespbl->pbl_pbase, (void*)nespbl->pbl_vbase, nespbl->user_base); list_for_each_entry(chunk, ®ion->chunk_list, list) { - for (j = 0; j < chunk->nmap; ++j) { - *pbl = cpu_to_le64((u64)sg_dma_address(&chunk->page_list[j])); - /* dprintk("%s: pbl=%p, *pbl=0x%016llx\n", __FUNCTION__, pbl, *pbl); */ - pbl++; + for (nmap_index = 0; nmap_index < chunk->nmap; ++nmap_index) { + chunk_pages = sg_dma_len(&chunk->page_list[nmap_index]) >> 12; + chunk_pages += (sg_dma_len(&chunk->page_list[nmap_index]) & (4096 - 1)) ? 1 : 0; + nespbl->page = sg_page(&chunk->page_list[0]); + for (page_index = 0; page_index < chunk_pages; page_index++) { + ((__le32 *)pbl)[0] = cpu_to_le32((u32) + (sg_dma_address(&chunk->page_list[nmap_index]) + + (page_index * 4096))); + ((__le32 *)pbl)[1] = cpu_to_le32(((u64) + (sg_dma_address(&chunk->page_list[nmap_index]) + + (page_index * 4096))) >> 32); + nes_debug(NES_DBG_MR, "pbl=%p, *pbl=0x%016llx, 0x%08x%08x\n", pbl, + (unsigned long long)*pbl, + le32_to_cpu(((__le32 *)pbl)[1]), le32_to_cpu(((__le32 *)pbl)[0])); + pbl++; + } } } - list_add_tail(&nespbl->list, &nes_ucontext->cq_reg_mem_list); + if (req.reg_type == IWNES_MEMREG_TYPE_QP) { + list_add_tail(&nespbl->list, &nes_ucontext->qp_reg_mem_list); + } else { + list_add_tail(&nespbl->list, &nes_ucontext->cq_reg_mem_list); + } nesmr->ibmr.rkey = -1; nesmr->ibmr.lkey = -1; - nesmr->mode = IWNES_MEMREG_TYPE_CQ; - return (&nesmr->ibmr); + nesmr->mode = req.reg_type; + return &nesmr->ibmr; break; } - return (ERR_PTR(-ENOSYS)); + return ERR_PTR(-ENOSYS); } @@ -2555,72 +2709,58 @@ static int nes_dereg_mr(struct ib_mr *ib_mr) u16 major_code; u16 minor_code; - dprintk("%s:%u ib_mr=%p, rkey = 0x%08X, lkey = 0x%08X, mode = %u\n", - __FUNCTION__, __LINE__, ib_mr, ib_mr->rkey, ib_mr->lkey, nesmr->mode); - -#ifndef OFED_1_2 if (nesmr->region) { ib_umem_release(nesmr->region); } -#endif if (nesmr->mode != IWNES_MEMREG_TYPE_MEM) { kfree(nesmr); - return (0); + return 0; } /* Deallocate the region with the adapter */ - spin_lock_irqsave(&nesdev->cqp.lock, flags); - cqp_request = nes_get_cqp_request(nesdev, NES_CQP_REQUEST_HOLDING_LOCK); - if (NULL == cqp_request) { - dprintk("%s: Failed to get a cqp_request.\n", __FUNCTION__); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); - return (-ENOMEM); + cqp_request = nes_get_cqp_request(nesdev); + if (cqp_request == NULL) { + nes_debug(NES_DBG_MR, "Failed to get a cqp_request.\n"); + return -ENOMEM; } cqp_request->waiting = 1; cqp_wqe = &cqp_request->cqp_wqe; - if (0 != nesmr->pbls_used) { + spin_lock_irqsave(&nesadapter->pbl_lock, flags); + if (nesmr->pbls_used != 0) { if (nesmr->pbl_4k) { nesadapter->free_4kpbl += nesmr->pbls_used; if (nesadapter->free_4kpbl > nesadapter->max_4kpbl) { printk(KERN_ERR PFX "free 4KB PBLs(%u) has exceeded the max(%u)\n", - nesadapter->free_4kpbl, nesadapter->max_4kpbl); + nesadapter->free_4kpbl, nesadapter->max_4kpbl); } } else { nesadapter->free_256pbl += nesmr->pbls_used; if (nesadapter->free_256pbl > nesadapter->max_256pbl) { printk(KERN_ERR PFX "free 256B PBLs(%u) has exceeded the max(%u)\n", - nesadapter->free_256pbl, nesadapter->max_256pbl); + nesadapter->free_256pbl, nesadapter->max_256pbl); } } } - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = + spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); + nes_fill_init_cqp_wqe(cqp_wqe, nesdev); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, NES_CQP_DEALLOCATE_STAG | NES_CQP_STAG_VA_TO | - NES_CQP_STAG_DEALLOC_PBLS | NES_CQP_STAG_MR; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX] = 0; - *((struct nes_hw_cqp **)&cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_LOW_IDX]) = - &nesdev->cqp; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PBL_BLK_COUNT_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PBL_LEN_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_STAG_WQE_STAG_IDX] = ib_mr->rkey; + NES_CQP_STAG_DEALLOC_PBLS | NES_CQP_STAG_MR); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_STAG_IDX, ib_mr->rkey); atomic_set(&cqp_request->refcount, 2); - nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_HOLDING_LOCK, - NES_CQP_REQUEST_RING_DOORBELL); + nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_RING_DOORBELL); /* Wait for CQP */ - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); - dprintk("%s: Waiting for deallocate STag 0x%08X completed\n", - __FUNCTION__, ib_mr->rkey); - ret = wait_event_timeout(cqp_request->waitq, (0 != cqp_request->request_done), + nes_debug(NES_DBG_MR, "Waiting for deallocate STag 0x%08X completed\n", ib_mr->rkey); + ret = wait_event_timeout(cqp_request->waitq, (cqp_request->request_done != 0), NES_EVENT_TIMEOUT); - dprintk("%s: Deallocate STag 0x%08X completed, wait_event_timeout ret = %u," + nes_debug(NES_DBG_MR, "Deallocate STag 0x%08X completed, wait_event_timeout ret = %u," " CQP Major:Minor codes = 0x%04X:0x%04X\n", - __FUNCTION__, ib_mr->rkey, ret, cqp_request->major_code, cqp_request->minor_code); + ib_mr->rkey, ret, cqp_request->major_code, cqp_request->minor_code); nes_free_resource(nesadapter, nesadapter->allocated_mrs, (ib_mr->rkey & 0x0fffff00) >> 8); @@ -2630,23 +2770,26 @@ static int nes_dereg_mr(struct ib_mr *ib_mr) major_code = cqp_request->major_code; minor_code = cqp_request->minor_code; if (atomic_dec_and_test(&cqp_request->refcount)) { - spin_lock_irqsave(&nesdev->cqp.lock, flags); - list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + if (cqp_request->dynamic) { + kfree(cqp_request); + } else { + spin_lock_irqsave(&nesdev->cqp.lock, flags); + list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); + spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + } } if (!ret) { - dprintk(KERN_ERR PFX "%s:%u Timeout waiting to destroy STag," + nes_debug(NES_DBG_MR, "Timeout waiting to destroy STag," " ib_mr=%p, rkey = 0x%08X\n", - __FUNCTION__, __LINE__, ib_mr, ib_mr->rkey); - return(-ETIME); + ib_mr, ib_mr->rkey); + return -ETIME; } else if (major_code) { - dprintk(KERN_ERR PFX "%s:%u Error (0x%04X:0x%04X) while attempting" + nes_debug(NES_DBG_MR, "Error (0x%04X:0x%04X) while attempting" " to destroy STag, ib_mr=%p, rkey = 0x%08X\n", - __FUNCTION__, __LINE__, major_code, minor_code, - ib_mr, ib_mr->rkey); - return(-EIO); + major_code, minor_code, ib_mr, ib_mr->rkey); + return -EIO; } else - return (0); + return 0; } @@ -2659,8 +2802,8 @@ static ssize_t show_rev(struct class_device *cdev, char *buf) container_of(cdev, struct nes_ib_device, ibdev.class_dev); struct nes_vnic *nesvnic = nesibdev->nesvnic; - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); - return (sprintf(buf, "%x\n", nesvnic->nesdev->nesadapter->hw_rev)); + nes_debug(NES_DBG_INIT, "\n"); + return sprintf(buf, "%x\n", nesvnic->nesdev->nesadapter->hw_rev); } @@ -2673,11 +2816,11 @@ static ssize_t show_fw_ver(struct class_device *cdev, char *buf) container_of(cdev, struct nes_ib_device, ibdev.class_dev); struct nes_vnic *nesvnic = nesibdev->nesvnic; - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); - return (sprintf(buf, "%x.%x.%x\n", + nes_debug(NES_DBG_INIT, "\n"); + return sprintf(buf, "%x.%x.%x\n", (int)(nesvnic->nesdev->nesadapter->fw_ver >> 32), (int)(nesvnic->nesdev->nesadapter->fw_ver >> 16) & 0xffff, - (int)(nesvnic->nesdev->nesadapter->fw_ver & 0xffff))); + (int)(nesvnic->nesdev->nesadapter->fw_ver & 0xffff)); } @@ -2686,8 +2829,8 @@ static ssize_t show_fw_ver(struct class_device *cdev, char *buf) */ static ssize_t show_hca(struct class_device *cdev, char *buf) { - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); - return (sprintf(buf, "NES020\n")); + nes_debug(NES_DBG_INIT, "\n"); + return sprintf(buf, "NES020\n"); } @@ -2696,8 +2839,8 @@ static ssize_t show_hca(struct class_device *cdev, char *buf) */ static ssize_t show_board(struct class_device *cdev, char *buf) { - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); - return (sprintf(buf, "%.*s\n", 32, "NES020 Board ID")); + nes_debug(NES_DBG_INIT, "\n"); + return sprintf(buf, "%.*s\n", 32, "NES020 Board ID"); } @@ -2722,13 +2865,17 @@ static int nes_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, { struct nes_qp *nesqp = to_nesqp(ibqp); - dprintk("%s:%u\n", __FUNCTION__, __LINE__); + nes_debug(NES_DBG_QP, "\n"); attr->qp_access_flags = 0; attr->cap.max_send_wr = nesqp->hwqp.sq_size; attr->cap.max_recv_wr = nesqp->hwqp.rq_size; attr->cap.max_recv_sge = 1; - attr->cap.max_inline_data = 0; /* 64?*/ + if (nes_drv_opt & NES_DRV_OPT_NO_INLINE_DATA) { + init_attr->cap.max_inline_data = 0; + } else { + init_attr->cap.max_inline_data = 64; + } init_attr->event_handler = nesqp->ibqp.event_handler; init_attr->qp_context = nesqp->ibqp.qp_context; @@ -2737,18 +2884,16 @@ static int nes_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, init_attr->srq = nesqp->ibqp.srq = nesqp->ibqp.srq; init_attr->cap = attr->cap; - dprintk("%s:%u Leaving\n", __FUNCTION__, __LINE__); - - return (0); + return 0; } /** * nes_hw_modify_qp */ -int nes_hw_modify_qp(struct nes_device *nesdev, struct nes_qp *nesqp, u32 next_iwarp_state, u32 wait_completion) +int nes_hw_modify_qp(struct nes_device *nesdev, struct nes_qp *nesqp, + u32 next_iwarp_state, u32 wait_completion) { - u64 u64temp; struct nes_hw_cqp_wqe *cqp_wqe; /* struct iw_cm_id *cm_id = nesqp->cm_id; */ /* struct iw_cm_event cm_event; */ @@ -2757,16 +2902,13 @@ int nes_hw_modify_qp(struct nes_device *nesdev, struct nes_qp *nesqp, u32 next_i int ret; u16 major_code; - spin_lock_irqsave(&nesdev->cqp.lock, flags); - - dprintk("%s:%u: QP%u, refcount = %d\n", - __FUNCTION__, __LINE__, nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount)); + nes_debug(NES_DBG_MOD_QP, "QP%u, refcount=%d\n", + nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount)); - cqp_request = nes_get_cqp_request(nesdev, NES_CQP_REQUEST_HOLDING_LOCK); - if (NULL == cqp_request) { - dprintk("%s: Failed to get a cqp_request.\n", __FUNCTION__); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); - return (-ENOMEM); + cqp_request = nes_get_cqp_request(nesdev); + if (cqp_request == NULL) { + nes_debug(NES_DBG_MOD_QP, "Failed to get a cqp_request.\n"); + return -ENOMEM; } if (wait_completion) { cqp_request->waiting = 1; @@ -2775,63 +2917,54 @@ int nes_hw_modify_qp(struct nes_device *nesdev, struct nes_qp *nesqp, u32 next_i } cqp_wqe = &cqp_request->cqp_wqe; - cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = - NES_CQP_MODIFY_QP | NES_CQP_QP_TYPE_IWARP | next_iwarp_state; - dprintk("%s:%u: using next_iwarp_state=%08x, wqe_words=%08x\n", - __FUNCTION__, __LINE__, - next_iwarp_state, cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX]); - - cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = nesqp->hwqp.qp_id; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX] = 0; - *((struct nes_hw_cqp **)&cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_LOW_IDX]) = - &nesdev->cqp; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] = 0; - cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] = 0; - u64temp = (u64)nesqp->nesqp_context_pbase; - cqp_wqe->wqe_words[NES_CQP_QP_WQE_CONTEXT_LOW_IDX] = (u32)u64temp; - cqp_wqe->wqe_words[NES_CQP_QP_WQE_CONTEXT_HIGH_IDX] = (u32)(u64temp >> 32); - - + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, + NES_CQP_MODIFY_QP | NES_CQP_QP_TYPE_IWARP | next_iwarp_state); + nes_debug(NES_DBG_MOD_QP, "using next_iwarp_state=%08x, wqe_words=%08x\n", + next_iwarp_state, le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX])); + nes_fill_init_cqp_wqe(cqp_wqe, nesdev); + set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX, nesqp->hwqp.qp_id); + set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, (u64)nesqp->nesqp_context_pbase); atomic_set(&cqp_request->refcount, 2); - nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_HOLDING_LOCK, - NES_CQP_REQUEST_RING_DOORBELL); + nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_RING_DOORBELL); /* Wait for CQP */ - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); if (wait_completion) { - /* dprintk("Waiting for modify iWARP QP%u to complete.\n", nesqp->hwqp.qp_id); */ - ret = wait_event_timeout(cqp_request->waitq, (0 != cqp_request->request_done), + /* nes_debug(NES_DBG_MOD_QP, "Waiting for modify iWARP QP%u to complete.\n", + nesqp->hwqp.qp_id); */ + ret = wait_event_timeout(cqp_request->waitq, (cqp_request->request_done != 0), NES_EVENT_TIMEOUT); - dprintk("%s:%u: Modify iwarp QP%u completed, wait_event_timeout ret=%u, " + nes_debug(NES_DBG_MOD_QP, "Modify iwarp QP%u completed, wait_event_timeout ret=%u, " "CQP Major:Minor codes = 0x%04X:0x%04X.\n", - __FUNCTION__, __LINE__, nesqp->hwqp.qp_id, ret, cqp_request->major_code, - cqp_request->minor_code); + nesqp->hwqp.qp_id, ret, cqp_request->major_code, cqp_request->minor_code); major_code = cqp_request->major_code; if (major_code) { - dprintk("%s:%u: Modify iwarp QP%u failed" - "CQP Major:Minor codes = 0x%04X:0x%04X, intended next state = 0x%08X.\n", - __FUNCTION__, __LINE__, nesqp->hwqp.qp_id, cqp_request->major_code, - cqp_request->minor_code, next_iwarp_state); + nes_debug(NES_DBG_MOD_QP, "Modify iwarp QP%u failed" + "CQP Major:Minor codes = 0x%04X:0x%04X, intended next state = 0x%08X.\n", + nesqp->hwqp.qp_id, cqp_request->major_code, + cqp_request->minor_code, next_iwarp_state); } if (atomic_dec_and_test(&cqp_request->refcount)) { - spin_lock_irqsave(&nesdev->cqp.lock, flags); - list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); - spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + if (cqp_request->dynamic) { + kfree(cqp_request); + } else { + spin_lock_irqsave(&nesdev->cqp.lock, flags); + list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); + spin_unlock_irqrestore(&nesdev->cqp.lock, flags); + } } if (!ret) - return(-ETIME); + return -ETIME; else if (major_code) - return(-EIO); + return -EIO; else - return (0); + return 0; } else { - return (0); + return 0; } } - /** * nes_modify_qp */ @@ -2852,55 +2985,57 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, u8 issue_disconnect = 0; u8 dont_wait = 0; + nes_debug(NES_DBG_MOD_QP, "QP%u: QP State=%u, cur QP State=%u," + " iwarp_state=0x%X, refcount=%d\n", + nesqp->hwqp.qp_id, attr->qp_state, nesqp->ibqp_state, + nesqp->iwarp_state, atomic_read(&nesqp->refcount)); + nes_add_ref(&nesqp->ibqp); spin_lock_irqsave(&nesqp->lock, qplockflags); - dprintk("%s:QP%u: QP State = %u, cur QP State = %u, iwarp_state = 0x%X, refcount = %d. \n", - __FUNCTION__, nesqp->hwqp.qp_id, attr->qp_state, nesqp->ibqp_state, - nesqp->iwarp_state, atomic_read(&nesqp->refcount)); - dprintk("%s:QP%u: hw_iwarp_state=0x%X, hw_tcp_state=0x%X, QP Access Flags=0x%X," - " attr_mask = 0x%0x. \n", - __FUNCTION__, nesqp->hwqp.qp_id, nesqp->hw_iwarp_state, + nes_debug(NES_DBG_MOD_QP, "QP%u: hw_iwarp_state=0x%X, hw_tcp_state=0x%X," + " QP Access Flags=0x%X, attr_mask = 0x%0x\n", + nesqp->hwqp.qp_id, nesqp->hw_iwarp_state, nesqp->hw_tcp_state, attr->qp_access_flags, attr_mask); if (attr_mask & IB_QP_STATE) { switch (attr->qp_state) { case IB_QPS_INIT: - dprintk("%s:QP%u: new state = init. \n", - __FUNCTION__, nesqp->hwqp.qp_id); + nes_debug(NES_DBG_MOD_QP, "QP%u: new state = init\n", + nesqp->hwqp.qp_id); if (nesqp->iwarp_state > (u32)NES_CQP_QP_IWARP_STATE_IDLE) { spin_unlock_irqrestore(&nesqp->lock, qplockflags); nes_rem_ref(&nesqp->ibqp); - return (-EINVAL); + return -EINVAL; } next_iwarp_state = NES_CQP_QP_IWARP_STATE_IDLE; issue_modify_qp = 1; break; case IB_QPS_RTR: - dprintk("%s:QP%u: new state = rtr. \n", - __FUNCTION__, nesqp->hwqp.qp_id ); + nes_debug(NES_DBG_MOD_QP, "QP%u: new state = rtr\n", + nesqp->hwqp.qp_id); if (nesqp->iwarp_state>(u32)NES_CQP_QP_IWARP_STATE_IDLE) { spin_unlock_irqrestore(&nesqp->lock, qplockflags); nes_rem_ref(&nesqp->ibqp); - return (-EINVAL); + return -EINVAL; } next_iwarp_state = NES_CQP_QP_IWARP_STATE_IDLE; issue_modify_qp = 1; break; case IB_QPS_RTS: - dprintk("%s:QP%u: new state = rts. \n", - __FUNCTION__, nesqp->hwqp.qp_id ); + nes_debug(NES_DBG_MOD_QP, "QP%u: new state = rts\n", + nesqp->hwqp.qp_id); if (nesqp->iwarp_state>(u32)NES_CQP_QP_IWARP_STATE_RTS) { spin_unlock_irqrestore(&nesqp->lock, qplockflags); nes_rem_ref(&nesqp->ibqp); - return (-EINVAL); + return -EINVAL; } if (nesqp->cm_id == NULL) { - dprintk("%s:QP%u: Failing attempt to move QP to RTS without a CM_ID. \n", - __FUNCTION__, nesqp->hwqp.qp_id ); + nes_debug(NES_DBG_MOD_QP, "QP%u: Failing attempt to move QP to RTS without a CM_ID. \n", + nesqp->hwqp.qp_id ); spin_unlock_irqrestore(&nesqp->lock, qplockflags); nes_rem_ref(&nesqp->ibqp); - return (-EINVAL); + return -EINVAL; } next_iwarp_state = NES_CQP_QP_IWARP_STATE_RTS; if (nesqp->iwarp_state != NES_CQP_QP_IWARP_STATE_RTS) @@ -2913,24 +3048,25 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, break; case IB_QPS_SQD: issue_modify_qp = 1; - dprintk("%s:QP%u: new state=closing. SQ head=%u, SQ tail=%u\n", - __FUNCTION__, nesqp->hwqp.qp_id, nesqp->hwqp.sq_head, - nesqp->hwqp.sq_tail); - if (nesqp->iwarp_state==(u32)NES_CQP_QP_IWARP_STATE_CLOSING) { + nes_debug(NES_DBG_MOD_QP, "QP%u: new state=closing. SQ head=%u, SQ tail=%u\n", + nesqp->hwqp.qp_id, nesqp->hwqp.sq_head, nesqp->hwqp.sq_tail); + if (nesqp->iwarp_state == (u32)NES_CQP_QP_IWARP_STATE_CLOSING) { spin_unlock_irqrestore(&nesqp->lock, qplockflags); nes_rem_ref(&nesqp->ibqp); return 0; } else { if (nesqp->iwarp_state > (u32)NES_CQP_QP_IWARP_STATE_CLOSING) { - dprintk("%s:QP%u: State change to closing ignored due to current iWARP state\n", - __FUNCTION__, nesqp->hwqp.qp_id); + nes_debug(NES_DBG_MOD_QP, "QP%u: State change to closing" + " ignored due to current iWARP state\n", + nesqp->hwqp.qp_id); spin_unlock_irqrestore(&nesqp->lock, qplockflags); nes_rem_ref(&nesqp->ibqp); - return (-EINVAL); + return -EINVAL; } if (nesqp->hw_iwarp_state != NES_AEQE_IWARP_STATE_RTS) { - dprintk("%s:QP%u: State change to closing already done based on hw state.\n", - __FUNCTION__, nesqp->hwqp.qp_id); + nes_debug(NES_DBG_MOD_QP, "QP%u: State change to closing" + " already done based on hw state.\n", + nesqp->hwqp.qp_id); issue_modify_qp = 0; nesqp->in_disconnect = 0; } @@ -2952,12 +3088,12 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, } break; case IB_QPS_SQE: - dprintk("%s:QP%u: new state = terminate. \n", - __FUNCTION__, nesqp->hwqp.qp_id ); + nes_debug(NES_DBG_MOD_QP, "QP%u: new state = terminate\n", + nesqp->hwqp.qp_id); if (nesqp->iwarp_state>=(u32)NES_CQP_QP_IWARP_STATE_TERMINATE) { spin_unlock_irqrestore(&nesqp->lock, qplockflags); nes_rem_ref(&nesqp->ibqp); - return (-EINVAL); + return -EINVAL; } /* next_iwarp_state = (NES_CQP_QP_IWARP_STATE_TERMINATE | 0x02000000); */ next_iwarp_state = NES_CQP_QP_IWARP_STATE_TERMINATE; @@ -2967,27 +3103,27 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, break; case IB_QPS_ERR: case IB_QPS_RESET: - if (nesqp->iwarp_state==(u32)NES_CQP_QP_IWARP_STATE_ERROR) { + if (nesqp->iwarp_state == (u32)NES_CQP_QP_IWARP_STATE_ERROR) { spin_unlock_irqrestore(&nesqp->lock, qplockflags); nes_rem_ref(&nesqp->ibqp); - return (-EINVAL); + return -EINVAL; } - dprintk("%s:QP%u: new state = error. \n", - __FUNCTION__, nesqp->hwqp.qp_id ); + nes_debug(NES_DBG_MOD_QP, "QP%u: new state = error\n", + nesqp->hwqp.qp_id); next_iwarp_state = NES_CQP_QP_IWARP_STATE_ERROR; /* next_iwarp_state = (NES_CQP_QP_IWARP_STATE_TERMINATE | 0x02000000); */ - if (nesqp->hte_added) { - dprintk("%s:%u: set CQP_QP_DEL_HTE\n", __FUNCTION__, __LINE__); - next_iwarp_state |= NES_CQP_QP_DEL_HTE; - nesqp->hte_added = 0; - } + if (nesqp->hte_added) { + nes_debug(NES_DBG_MOD_QP, "set CQP_QP_DEL_HTE\n"); + next_iwarp_state |= NES_CQP_QP_DEL_HTE; + nesqp->hte_added = 0; + } if ((nesqp->hw_tcp_state > NES_AEQE_TCP_STATE_CLOSED) && - (nesqp->hw_tcp_state != NES_AEQE_TCP_STATE_TIME_WAIT)) { + (nesqp->hw_tcp_state != NES_AEQE_TCP_STATE_TIME_WAIT)) { next_iwarp_state |= NES_CQP_QP_RESET; nesqp->in_disconnect = 1; } else { - dprintk("%s:%u:QP%u NOT setting NES_CQP_QP_RESET since TCP state = %u\n", - __FUNCTION__, __LINE__, nesqp->hwqp.qp_id, nesqp->hw_tcp_state); + nes_debug(NES_DBG_MOD_QP, "QP%u NOT setting NES_CQP_QP_RESET since TCP state = %u\n", + nesqp->hwqp.qp_id, nesqp->hw_tcp_state); dont_wait = 1; } issue_modify_qp = 1; @@ -2996,7 +3132,7 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, default: spin_unlock_irqrestore(&nesqp->lock, qplockflags); nes_rem_ref(&nesqp->ibqp); - return (-EINVAL); + return -EINVAL; break; } @@ -3006,38 +3142,38 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, ((next_iwarp_state & NES_CQP_QP_IWARP_STATE_MASK) > (u32)NES_CQP_QP_IWARP_STATE_RTS)) { nesqp->iwarp_state = next_iwarp_state & NES_CQP_QP_IWARP_STATE_MASK; - dprintk("%s:%u: Change nesqp->iwarp_state=%08x\n", - __FUNCTION__, __LINE__, nesqp->iwarp_state); + nes_debug(NES_DBG_MOD_QP, "Change nesqp->iwarp_state=%08x\n", + nesqp->iwarp_state); issue_disconnect = 1; } else { nesqp->iwarp_state = next_iwarp_state & NES_CQP_QP_IWARP_STATE_MASK; - dprintk("%s:%u: Change nesqp->iwarp_state=%08x\n", - __FUNCTION__, __LINE__, nesqp->iwarp_state); + nes_debug(NES_DBG_MOD_QP, "Change nesqp->iwarp_state=%08x\n", + nesqp->iwarp_state); } } if (attr_mask & IB_QP_ACCESS_FLAGS) { if (attr->qp_access_flags & IB_ACCESS_LOCAL_WRITE) { - nesqp->nesqp_context->misc |= NES_QPCONTEXT_MISC_RDMA_WRITE_EN | - NES_QPCONTEXT_MISC_RDMA_READ_EN; + nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_RDMA_WRITE_EN | + NES_QPCONTEXT_MISC_RDMA_READ_EN); issue_modify_qp = 1; } if (attr->qp_access_flags & IB_ACCESS_REMOTE_WRITE) { - nesqp->nesqp_context->misc |= NES_QPCONTEXT_MISC_RDMA_WRITE_EN; + nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_RDMA_WRITE_EN); issue_modify_qp = 1; } if (attr->qp_access_flags & IB_ACCESS_REMOTE_READ) { - nesqp->nesqp_context->misc |= NES_QPCONTEXT_MISC_RDMA_READ_EN; + nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_RDMA_READ_EN); issue_modify_qp = 1; } if (attr->qp_access_flags & IB_ACCESS_MW_BIND) { - nesqp->nesqp_context->misc |= NES_QPCONTEXT_MISC_WBIND_EN; + nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_WBIND_EN); issue_modify_qp = 1; } if (nesqp->user_mode) { - nesqp->nesqp_context->misc |= NES_QPCONTEXT_MISC_RDMA_WRITE_EN | - NES_QPCONTEXT_MISC_RDMA_READ_EN; + nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_RDMA_WRITE_EN | + NES_QPCONTEXT_MISC_RDMA_READ_EN); issue_modify_qp = 1; } } @@ -3045,36 +3181,35 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, original_last_aeq = nesqp->last_aeq; spin_unlock_irqrestore(&nesqp->lock, qplockflags); - dprintk("%s[%u]: issue_modify_qp=%u\n", __FUNCTION__, __LINE__, issue_modify_qp); + nes_debug(NES_DBG_MOD_QP, "issue_modify_qp=%u\n", issue_modify_qp); ret = 0; if (issue_modify_qp) { - dprintk("%s[%u]: call nes_hw_modify_qp\n", __FUNCTION__, __LINE__); + nes_debug(NES_DBG_MOD_QP, "call nes_hw_modify_qp\n"); ret = nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 1); if (ret) - dprintk("%s[%u]: nes_hw_modify_qp (next_iwarp_state = 0x%08X)" + nes_debug(NES_DBG_MOD_QP, "nes_hw_modify_qp (next_iwarp_state = 0x%08X)" " failed for QP%u.\n", - __FUNCTION__, __LINE__, next_iwarp_state, nesqp->hwqp.qp_id); + next_iwarp_state, nesqp->hwqp.qp_id); } if ((issue_modify_qp) && (nesqp->ibqp_state > IB_QPS_RTS)) { - dprintk("%s%u: QP%u Issued ModifyQP refcount (%d)," + nes_debug(NES_DBG_MOD_QP, "QP%u Issued ModifyQP refcount (%d)," " original_last_aeq = 0x%04X. last_aeq = 0x%04X.\n", - __FUNCTION__, __LINE__, nesqp->hwqp.qp_id, - atomic_read(&nesqp->refcount), original_last_aeq, nesqp->last_aeq); + nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount), + original_last_aeq, nesqp->last_aeq); if ((!ret) || ((original_last_aeq != NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE) && (ret))) { if (dont_wait) { - if (nesqp->cm_id) { - dprintk("%s%u: QP%u Queuing fake disconnect for QP refcount (%d)," + if (nesqp->cm_id && nesqp->hw_tcp_state != 0) { + nes_debug(NES_DBG_MOD_QP, "QP%u Queuing fake disconnect for QP refcount (%d)," " original_last_aeq = 0x%04X. last_aeq = 0x%04X.\n", - __FUNCTION__, __LINE__, nesqp->hwqp.qp_id, - atomic_read(&nesqp->refcount), original_last_aeq, - nesqp->last_aeq); + nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount), + original_last_aeq, nesqp->last_aeq); /* this one is for the cm_disconnect thread */ nes_add_ref(&nesqp->ibqp); spin_lock_irqsave(&nesqp->lock, qplockflags); @@ -3083,52 +3218,55 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, spin_unlock_irqrestore(&nesqp->lock, qplockflags); nes_cm_disconn(nesqp); } else { + nes_debug(NES_DBG_MOD_QP, "QP%u No fake disconnect, QP refcount=%d\n", + nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount)); nes_rem_ref(&nesqp->ibqp); } } else { spin_lock_irqsave(&nesqp->lock, qplockflags); if (nesqp->cm_id) { /* These two are for the timer thread */ - nes_add_ref(&nesqp->ibqp); - nesqp->cm_id->add_ref(nesqp->cm_id); - dprintk("%s%u: QP%u Not decrementing QP refcount (%d)," - " need ae to finish up, original_last_aeq = 0x%04X." - " last_aeq = 0x%04X, scheduling timer.\n", - __FUNCTION__, __LINE__, nesqp->hwqp.qp_id, - atomic_read(&nesqp->refcount), original_last_aeq, - nesqp->last_aeq); - schedule_nes_timer(nesqp->cm_node_p, (struct sk_buff *) nesqp, NES_TIMER_TYPE_CLOSE, 1, 0); + if (atomic_inc_return(&nesqp->close_timer_started) == 1) { + nes_add_ref(&nesqp->ibqp); + nesqp->cm_id->add_ref(nesqp->cm_id); + nes_debug(NES_DBG_MOD_QP, "QP%u Not decrementing QP refcount (%d)," + " need ae to finish up, original_last_aeq = 0x%04X." + " last_aeq = 0x%04X, scheduling timer.\n", + nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount), + original_last_aeq, nesqp->last_aeq); + schedule_nes_timer(nesqp->cm_node, (struct sk_buff *) nesqp, NES_TIMER_TYPE_CLOSE, 1, 0); + } spin_unlock_irqrestore(&nesqp->lock, qplockflags); } else { spin_unlock_irqrestore(&nesqp->lock, qplockflags); - dprintk("%s%u: QP%u Not decrementing QP refcount (%d)," + nes_debug(NES_DBG_MOD_QP, "QP%u Not decrementing QP refcount (%d)," " need ae to finish up, original_last_aeq = 0x%04X." " last_aeq = 0x%04X.\n", - __FUNCTION__, __LINE__, nesqp->hwqp.qp_id, - atomic_read(&nesqp->refcount), original_last_aeq, - nesqp->last_aeq); + nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount), + original_last_aeq, nesqp->last_aeq); } } } else { - dprintk("%s%u: QP%u Decrementing QP refcount (%d), No ae to finish up," + nes_debug(NES_DBG_MOD_QP, "QP%u Decrementing QP refcount (%d), No ae to finish up," " original_last_aeq = 0x%04X. last_aeq = 0x%04X.\n", - __FUNCTION__, __LINE__, nesqp->hwqp.qp_id, - atomic_read(&nesqp->refcount), original_last_aeq, nesqp->last_aeq); + nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount), + original_last_aeq, nesqp->last_aeq); nes_rem_ref(&nesqp->ibqp); } } else { - dprintk("%s%u: QP%u Decrementing QP refcount (%d), No ae to finish up," + nes_debug(NES_DBG_MOD_QP, "QP%u Decrementing QP refcount (%d), No ae to finish up," " original_last_aeq = 0x%04X. last_aeq = 0x%04X.\n", - __FUNCTION__, __LINE__, nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount), + nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount), original_last_aeq, nesqp->last_aeq); nes_rem_ref(&nesqp->ibqp); } err = 0; - dprintk("%s: QP%u Leaving\n", __FUNCTION__, nesqp->hwqp.qp_id); + nes_debug(NES_DBG_MOD_QP, "QP%u Leaving, refcount=%d\n", + nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount)); - return (err); + return err; } @@ -3137,8 +3275,8 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, */ static int nes_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) { - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); - return (-ENOSYS); + nes_debug(NES_DBG_INIT, "\n"); + return -ENOSYS; } @@ -3147,8 +3285,8 @@ static int nes_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) */ static int nes_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) { - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); - return (-ENOSYS); + nes_debug(NES_DBG_INIT, "\n"); + return -ENOSYS; } @@ -3159,10 +3297,33 @@ static int nes_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, struct ib_wc *in_wc, struct ib_grh *in_grh, struct ib_mad *in_mad, struct ib_mad *out_mad) { - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); - return (-ENOSYS); + nes_debug(NES_DBG_INIT, "\n"); + return -ENOSYS; } +static inline void +fill_wqe_sg_send(struct nes_hw_qp_wqe *wqe, struct ib_send_wr *ib_wr, u32 uselkey) +{ + int sge_index; + int total_payload_length = 0; + for (sge_index = 0; sge_index < ib_wr->num_sge; sge_index++) { + set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_FRAG0_LOW_IDX + (sge_index * 4), + ib_wr->sg_list[sge_index].addr); + set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_LENGTH0_IDX + (sge_index * 4), + ib_wr->sg_list[sge_index].length); + if (uselkey) + set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_STAG0_IDX + (sge_index * 4), + (ib_wr->sg_list[sge_index].lkey)); + else + set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_STAG0_IDX + (sge_index * 4), 0); + + total_payload_length += ib_wr->sg_list[sge_index].length; + } + nes_debug(NES_DBG_IW_TX, "UC UC UC, sending total_payload_length=%u \n", + total_payload_length); + set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX, + total_payload_length); +} /** * nes_post_send @@ -3170,23 +3331,27 @@ static int nes_process_mad(struct ib_device *ibdev, int mad_flags, static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr, struct ib_send_wr **bad_wr) { + u64 u64temp; + unsigned long flags = 0; struct nes_vnic *nesvnic = to_nesvnic(ibqp->device); struct nes_device *nesdev = nesvnic->nesdev; struct nes_qp *nesqp = to_nesqp(ibqp); - u32 qsize = nesqp->hwqp.sq_size; struct nes_hw_qp_wqe *wqe; - unsigned long flags = 0; + int err; + u32 qsize = nesqp->hwqp.sq_size; u32 head; - u32 wqe_misc = 0; - int err = 0; - u32 wqe_count = 0; + u32 wqe_misc; + u32 wqe_count; u32 counter; - int sge_index; - u32 total_payload_length = 0; + u32 total_payload_length; + + err = 0; + wqe_misc = 0; + wqe_count = 0; + total_payload_length = 0; - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); if (nesqp->ibqp_state > IB_QPS_RTS) - return (-EINVAL); + return -EINVAL; spin_lock_irqsave(&nesqp->lock, flags); @@ -3200,133 +3365,98 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr, } wqe = &nesqp->hwqp.sq_vbase[head]; - /* dprintk("%s:processing sq wqe for QP%u at %p, head = %u.\n", - __FUNCTION__, nesqp->hwqp.qp_id, wqe, head); */ - *((u64 *)&wqe->wqe_words[NES_IWARP_SQ_WQE_COMP_SCRATCH_LOW_IDX]) = - ib_wr->wr_id; - *((struct nes_qp **)&wqe->wqe_words[NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX]) = nesqp; - wqe->wqe_words[NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX] |= head; - - switch (ib_wr->opcode) { - case IB_WR_SEND: - if (ib_wr->send_flags & IB_SEND_SOLICITED) { - wqe_misc = NES_IWARP_SQ_OP_SENDSE; - } else { - wqe_misc = NES_IWARP_SQ_OP_SEND; - } - if (ib_wr->num_sge > nesdev->nesadapter->max_sge) { - err = -EINVAL; + /* nes_debug(NES_DBG_IW_TX, "processing sq wqe for QP%u at %p, head = %u.\n", + nesqp->hwqp.qp_id, wqe, head); */ + nes_fill_init_qp_wqe(wqe, nesqp, head); + u64temp = (u64)(ib_wr->wr_id); + set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_SCRATCH_LOW_IDX, + u64temp); + switch (ib_wr->opcode) { + case IB_WR_SEND: + if (ib_wr->send_flags & IB_SEND_SOLICITED) { + wqe_misc = NES_IWARP_SQ_OP_SENDSE; + } else { + wqe_misc = NES_IWARP_SQ_OP_SEND; + } + if (ib_wr->num_sge > nesdev->nesadapter->max_sge) { + err = -EINVAL; + break; + } + if (ib_wr->send_flags & IB_SEND_FENCE) { + wqe_misc |= NES_IWARP_SQ_WQE_LOCAL_FENCE; + } + if ((ib_wr->send_flags & IB_SEND_INLINE) && + ((nes_drv_opt & NES_DRV_OPT_NO_INLINE_DATA) == 0) && + (ib_wr->sg_list[0].length <= 64)) { + memcpy(&wqe->wqe_words[NES_IWARP_SQ_WQE_IMM_DATA_START_IDX], + (void *)(unsigned long)ib_wr->sg_list[0].addr, ib_wr->sg_list[0].length); + set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX, + ib_wr->sg_list[0].length); + wqe_misc |= NES_IWARP_SQ_WQE_IMM_DATA; + } else { + fill_wqe_sg_send(wqe, ib_wr, 1); + } + break; - } - if (ib_wr->send_flags & IB_SEND_FENCE) { - wqe_misc |= NES_IWARP_SQ_WQE_LOCAL_FENCE; - } - if ((ib_wr->send_flags & IB_SEND_INLINE) && - (ib_wr->sg_list[0].length <= 64)) { - memcpy(&wqe->wqe_words[NES_IWARP_SQ_WQE_IMM_DATA_START_IDX], - (void *)ib_wr->sg_list[0].addr, ib_wr->sg_list[0].length); - wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = - ib_wr->sg_list[0].length; - wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] |= - NES_IWARP_SQ_WQE_IMM_DATA; - } else { - total_payload_length = 0; - for (sge_index=0; sge_index < ib_wr->num_sge; sge_index++) { - wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX+(sge_index*4)] = - cpu_to_le32((u32)ib_wr->sg_list[sge_index].addr); - wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX+(sge_index*4)] = - cpu_to_le32((u32)(ib_wr->sg_list[sge_index].addr>>32)); - wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX+(sge_index*4)] = - cpu_to_le32(ib_wr->sg_list[sge_index].length); - wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX+(sge_index*4)] = - cpu_to_le32(ib_wr->sg_list[sge_index].lkey); - total_payload_length += ib_wr->sg_list[sge_index].length; + case IB_WR_RDMA_WRITE: + wqe_misc = NES_IWARP_SQ_OP_RDMAW; + if (ib_wr->num_sge > nesdev->nesadapter->max_sge) { + nes_debug(NES_DBG_IW_TX, "Exceeded max sge, ib_wr=%u, max=%u\n", + ib_wr->num_sge, + nesdev->nesadapter->max_sge); + err = -EINVAL; + break; + } + if (ib_wr->send_flags & IB_SEND_FENCE) { + wqe_misc |= NES_IWARP_SQ_WQE_LOCAL_FENCE; } - wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = - cpu_to_le32(total_payload_length); - } - break; - case IB_WR_RDMA_WRITE: - wqe_misc = NES_IWARP_SQ_OP_RDMAW; - if (ib_wr->num_sge > nesdev->nesadapter->max_sge) { - dprintk("%s:%u: Exceeded max sge, ib_wr=%u, max=%u\n", - __FUNCTION__, __LINE__, ib_wr->num_sge, - nesdev->nesadapter->max_sge); - err = -EINVAL; + set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_STAG_IDX, + ib_wr->wr.rdma.rkey); + set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_TO_LOW_IDX, + ib_wr->wr.rdma.remote_addr); + + if ((ib_wr->send_flags & IB_SEND_INLINE) && + ((nes_drv_opt & NES_DRV_OPT_NO_INLINE_DATA) == 0) && + (ib_wr->sg_list[0].length <= 64)) { + memcpy(&wqe->wqe_words[NES_IWARP_SQ_WQE_IMM_DATA_START_IDX], + (void *)(unsigned long)ib_wr->sg_list[0].addr, ib_wr->sg_list[0].length); + set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX, + ib_wr->sg_list[0].length); + wqe_misc |= NES_IWARP_SQ_WQE_IMM_DATA; + } else { + fill_wqe_sg_send(wqe, ib_wr, 1); + } + wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_LENGTH_IDX] = + wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX]; break; - } - if (ib_wr->send_flags & IB_SEND_FENCE) { - wqe_misc |= NES_IWARP_SQ_WQE_LOCAL_FENCE; - } - wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_STAG_IDX] = - cpu_to_le32(ib_wr->wr.rdma.rkey); - wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_TO_LOW_IDX] = - cpu_to_le32(ib_wr->wr.rdma.remote_addr); - wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_TO_HIGH_IDX] = - cpu_to_le32((u32)(ib_wr->wr.rdma.remote_addr >> 32)); - - if ((ib_wr->send_flags & IB_SEND_INLINE) && - (ib_wr->sg_list[0].length <= 64)) { - memcpy(&wqe->wqe_words[NES_IWARP_SQ_WQE_IMM_DATA_START_IDX], - (void *)ib_wr->sg_list[0].addr, ib_wr->sg_list[0].length); - wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = - ib_wr->sg_list[0].length; - wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] |= - NES_IWARP_SQ_WQE_IMM_DATA; - } else { - total_payload_length = 0; - for (sge_index=0; sge_index < ib_wr->num_sge; sge_index++) { - wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX+(sge_index*4)] = - cpu_to_le32((u32)ib_wr->sg_list[sge_index].addr); - wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX+(sge_index*4)] = - cpu_to_le32((u32)(ib_wr->sg_list[sge_index].addr>>32)); - wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX+(sge_index*4)] = - cpu_to_le32(ib_wr->sg_list[sge_index].length); - wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX+(sge_index*4)] = - cpu_to_le32(ib_wr->sg_list[sge_index].lkey); - total_payload_length += ib_wr->sg_list[sge_index].length; + case IB_WR_RDMA_READ: + /* iWARP only supports 1 sge for RDMA reads */ + if (ib_wr->num_sge > 1) { + nes_debug(NES_DBG_IW_TX, "Exceeded max sge, ib_wr=%u, max=1\n", + ib_wr->num_sge); + err = -EINVAL; + break; } - wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = - cpu_to_le32(total_payload_length); - } - wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_LENGTH_IDX] = - wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX]; - break; - case IB_WR_RDMA_READ: - /* IWarp only supports 1 sge for RDMA reads */ - if (ib_wr->num_sge > 1) { - dprintk("%s:%u: Exceeded max sge, ib_wr=%u, max=1\n", - __FUNCTION__, __LINE__, ib_wr->num_sge); + wqe_misc = NES_IWARP_SQ_OP_RDMAR; + set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_TO_LOW_IDX, + ib_wr->wr.rdma.remote_addr); + set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_STAG_IDX, + ib_wr->wr.rdma.rkey); + set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_LENGTH_IDX, + ib_wr->sg_list->length); + set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_FRAG0_LOW_IDX, + ib_wr->sg_list->addr); + set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_STAG0_IDX, + ib_wr->sg_list->lkey); + break; + default: + /* error */ err = -EINVAL; break; - } - wqe_misc = NES_IWARP_SQ_OP_RDMAR; - - wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_TO_LOW_IDX] = - cpu_to_le32(ib_wr->wr.rdma.remote_addr); - wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_TO_HIGH_IDX] = - cpu_to_le32((u32)(ib_wr->wr.rdma.remote_addr >> 32)); - wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_STAG_IDX] = - cpu_to_le32(ib_wr->wr.rdma.rkey); - wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_LENGTH_IDX] = - cpu_to_le32(ib_wr->sg_list->length); - wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] = - cpu_to_le32(ib_wr->sg_list->addr); - wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] = - cpu_to_le32((u32)(ib_wr->sg_list->addr >> 32)); - wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = - cpu_to_le32(ib_wr->sg_list->lkey); - break; - default: - /* error */ - err = -EINVAL; - break; - } + } if (ib_wr->send_flags & IB_SEND_SIGNALED) { - dprintk("%s:%u: Setting SQ_WQE_SIGNALED_COMPL\n", - __FUNCTION__, __LINE__); wqe_misc |= NES_IWARP_SQ_WQE_SIGNALED_COMPL; } wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] = cpu_to_le32(wqe_misc); @@ -3352,7 +3482,7 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr, if (err) *bad_wr = ib_wr; - return(err); + return err; } @@ -3362,22 +3492,22 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr, static int nes_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *ib_wr, struct ib_recv_wr **bad_wr) { + u64 u64temp; + unsigned long flags = 0; struct nes_vnic *nesvnic = to_nesvnic(ibqp->device); struct nes_device *nesdev = nesvnic->nesdev; struct nes_qp *nesqp = to_nesqp(ibqp); - u32 qsize = nesqp->hwqp.rq_size; struct nes_hw_qp_wqe *wqe; - unsigned long flags = 0; - u32 head; int err = 0; + int sge_index; + u32 qsize = nesqp->hwqp.rq_size; + u32 head; u32 wqe_count = 0; u32 counter; - int sge_index; u32 total_payload_length; - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); if (nesqp->ibqp_state > IB_QPS_RTS) - return (-EINVAL); + return -EINVAL; spin_lock_irqsave(&nesqp->lock, flags); @@ -3394,31 +3524,28 @@ static int nes_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *ib_wr, break; } - dprintk("%s: ibwr sge count = %u.\n", __FUNCTION__, ib_wr->num_sge); + nes_debug(NES_DBG_IW_RX, "ibwr sge count = %u.\n", ib_wr->num_sge); wqe = &nesqp->hwqp.rq_vbase[head]; - /* dprintk("%s:QP%u:processing rq wqe at %p, head = %u.\n", - __FUNCTION__, nesqp->hwqp.qp_id, wqe, head); */ - *((u64 *)&wqe->wqe_words[NES_IWARP_RQ_WQE_COMP_SCRATCH_LOW_IDX]) = - ib_wr->wr_id; - *((struct nes_qp **)&wqe->wqe_words[NES_IWARP_RQ_WQE_COMP_CTX_LOW_IDX]) = - nesqp; - wqe->wqe_words[NES_IWARP_RQ_WQE_COMP_CTX_LOW_IDX] |= head; - + /* nes_debug(NES_DBG_IW_RX, "QP%u:processing rq wqe at %p, head = %u.\n", + nesqp->hwqp.qp_id, wqe, head); */ + nes_fill_init_qp_wqe(wqe, nesqp, head); + u64temp = (u64)(ib_wr->wr_id); + set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_SCRATCH_LOW_IDX, + u64temp); total_payload_length = 0; - for (sge_index=0; sge_index < ib_wr->num_sge; sge_index++) { - wqe->wqe_words[NES_IWARP_RQ_WQE_FRAG0_LOW_IDX+(sge_index*4)] = - cpu_to_le32((u32)ib_wr->sg_list[sge_index].addr); - wqe->wqe_words[NES_IWARP_RQ_WQE_FRAG0_HIGH_IDX+(sge_index*4)] = - cpu_to_le32((u32)(ib_wr->sg_list[sge_index].addr >> 32)); - wqe->wqe_words[NES_IWARP_RQ_WQE_LENGTH0_IDX+(sge_index*4)] = - cpu_to_le32(ib_wr->sg_list[sge_index].length); - wqe->wqe_words[NES_IWARP_RQ_WQE_STAG0_IDX+(sge_index*4)] = - cpu_to_le32(ib_wr->sg_list[sge_index].lkey); + for (sge_index = 0; sge_index < ib_wr->num_sge; sge_index++) { + set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_RQ_WQE_FRAG0_LOW_IDX + (sge_index * 4), + ib_wr->sg_list[sge_index].addr); + set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_RQ_WQE_LENGTH0_IDX + (sge_index * 4), + ib_wr->sg_list[sge_index].length); + set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_RQ_WQE_STAG0_IDX + (sge_index * 4), + ib_wr->sg_list[sge_index].lkey); + total_payload_length += ib_wr->sg_list[sge_index].length; } - wqe->wqe_words[NES_IWARP_RQ_WQE_TOTAL_PAYLOAD_IDX] = - cpu_to_le32(total_payload_length); + set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_RQ_WQE_TOTAL_PAYLOAD_IDX, + total_payload_length); ib_wr = ib_wr->next; head++; @@ -3439,7 +3566,7 @@ static int nes_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *ib_wr, if (err) *bad_wr = ib_wr; - return (err); + return err; } @@ -3448,41 +3575,45 @@ static int nes_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *ib_wr, */ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry) { + u64 u64temp; u64 wrid; /* u64 u64temp; */ + unsigned long flags = 0; struct nes_vnic *nesvnic = to_nesvnic(ibcq->device); struct nes_device *nesdev = nesvnic->nesdev; struct nes_cq *nescq = to_nescq(ibcq); struct nes_qp *nesqp; struct nes_hw_cqe cqe; - unsigned long flags = 0; u32 head; u32 wq_tail; u32 cq_size; - u32 cqe_count=0; + u32 cqe_count = 0; u32 wqe_index; + u32 u32temp; /* u32 counter; */ - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); + nes_debug(NES_DBG_CQ, "\n"); spin_lock_irqsave(&nescq->lock, flags); head = nescq->hw_cq.cq_head; cq_size = nescq->hw_cq.cq_size; - while (cqe_count<num_entries) { + while (cqe_count < num_entries) { if (le32_to_cpu(nescq->hw_cq.cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]) & NES_CQE_VALID) { cqe = nescq->hw_cq.cq_vbase[head]; nescq->hw_cq.cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX] = 0; - wqe_index = cqe.cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX] & + u32temp = le32_to_cpu(cqe.cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX]); + wqe_index = u32temp & (nesdev->nesadapter->max_qp_wr - 1); - cqe.cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX] &= ~(NES_SW_CONTEXT_ALIGN-1); - barrier(); + u32temp &= ~(NES_SW_CONTEXT_ALIGN-1); /* parse CQE, get completion context from WQE (either rq or sq */ - nesqp = *((struct nes_qp **)&cqe.cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX]); + u64temp = (((u64)(le32_to_cpu(cqe.cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX])))<<32) | + ((u64)u32temp); + nesqp = *((struct nes_qp **)&u64temp); memset(entry, 0, sizeof *entry); - if (0 == cqe.cqe_words[NES_CQE_ERROR_CODE_IDX]) { + if (cqe.cqe_words[NES_CQE_ERROR_CODE_IDX] == 0) { entry->status = IB_WC_SUCCESS; } else { entry->status = IB_WC_WR_FLUSH_ERR; @@ -3500,19 +3631,21 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry) /* Working on a SQ Completion*/ wq_tail = wqe_index; nesqp->hwqp.sq_tail = (wqe_index+1)&(nesqp->hwqp.sq_size - 1); - wrid = *((u64 *)&nesqp->hwqp.sq_vbase[wq_tail]. - wqe_words[NES_IWARP_SQ_WQE_COMP_SCRATCH_LOW_IDX]); + wrid = (((u64)(cpu_to_le32((u32)nesqp->hwqp.sq_vbase[wq_tail]. + wqe_words[NES_IWARP_SQ_WQE_COMP_SCRATCH_HIGH_IDX]))) << 32) | + ((u64)(cpu_to_le32((u32)nesqp->hwqp.sq_vbase[wq_tail]. + wqe_words[NES_IWARP_SQ_WQE_COMP_SCRATCH_LOW_IDX]))); entry->byte_len = le32_to_cpu(nesqp->hwqp.sq_vbase[wq_tail]. wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX]); switch (le32_to_cpu(nesqp->hwqp.sq_vbase[wq_tail]. wqe_words[NES_IWARP_SQ_WQE_MISC_IDX]) & 0x3f) { case NES_IWARP_SQ_OP_RDMAW: - dprintk("%s: Operation = RDMA WRITE.\n", __FUNCTION__); + nes_debug(NES_DBG_CQ, "Operation = RDMA WRITE.\n"); entry->opcode = IB_WC_RDMA_WRITE; break; case NES_IWARP_SQ_OP_RDMAR: - dprintk("%s: Operation = RDMA READ.\n", __FUNCTION__); + nes_debug(NES_DBG_CQ, "Operation = RDMA READ.\n"); entry->opcode = IB_WC_RDMA_READ; entry->byte_len = le32_to_cpu(nesqp->hwqp.sq_vbase[wq_tail]. wqe_words[NES_IWARP_SQ_WQE_RDMA_LENGTH_IDX]); @@ -3521,18 +3654,18 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry) case NES_IWARP_SQ_OP_SENDSEINV: case NES_IWARP_SQ_OP_SEND: case NES_IWARP_SQ_OP_SENDSE: - dprintk("%s: Operation = Send.\n", __FUNCTION__); + nes_debug(NES_DBG_CQ, "Operation = Send.\n"); entry->opcode = IB_WC_SEND; break; } } else { /* Working on a RQ Completion*/ wq_tail = wqe_index; - nesqp->hwqp.rq_tail = (wqe_index+1)&(nesqp->hwqp.rq_size - 1); + nesqp->hwqp.rq_tail = (wqe_index+1)&(nesqp->hwqp.rq_size - 1); entry->byte_len = le32_to_cpu(cqe.cqe_words[NES_CQE_PAYLOAD_LENGTH_IDX]); - wrid = *((u64 *)&nesqp->hwqp.rq_vbase[wq_tail]. - wqe_words[NES_IWARP_RQ_WQE_COMP_SCRATCH_LOW_IDX]); - entry->opcode = IB_WC_RECV; + wrid = ((u64)(le32_to_cpu(nesqp->hwqp.rq_vbase[wq_tail].wqe_words[NES_IWARP_RQ_WQE_COMP_SCRATCH_LOW_IDX]))) | + ((u64)(le32_to_cpu(nesqp->hwqp.rq_vbase[wq_tail].wqe_words[NES_IWARP_RQ_WQE_COMP_SCRATCH_HIGH_IDX]))<<32); + entry->opcode = IB_WC_RECV; } entry->wr_id = wrid; @@ -3540,12 +3673,11 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry) head = 0; cqe_count++; nescq->polled_completions++; - if ((nescq->polled_completions > (cq_size/2)) || + if ((nescq->polled_completions > (cq_size / 2)) || (nescq->polled_completions == 255)) { - dprintk("%s: CQ%u Issuing CQE Allocate since more than half of cqes" + nes_debug(NES_DBG_CQ, "CQ%u Issuing CQE Allocate since more than half of cqes" " are pending %u of %u.\n", - __FUNCTION__, nescq->hw_cq.cq_number, - nescq->polled_completions, cq_size); + nescq->hw_cq.cq_number, nescq->polled_completions, cq_size); nes_write32(nesdev->regs+NES_CQE_ALLOC, nescq->hw_cq.cq_number | (nescq->polled_completions << 16)); nescq->polled_completions = 0; @@ -3556,61 +3688,46 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry) } if (nescq->polled_completions) { - /* dprintk("%s: CQ%u Issuing CQE Allocate for %u cqes.\n", - __FUNCTION__, nescq->hw_cq.cq_number, nescq->polled_completions); */ nes_write32(nesdev->regs+NES_CQE_ALLOC, nescq->hw_cq.cq_number | (nescq->polled_completions << 16)); nescq->polled_completions = 0; } nescq->hw_cq.cq_head = head; - dprintk("%s: Reporting %u completions for CQ%u.\n", __FUNCTION__, cqe_count, - nescq->hw_cq.cq_number); + nes_debug(NES_DBG_CQ, "Reporting %u completions for CQ%u.\n", + cqe_count, nescq->hw_cq.cq_number); spin_unlock_irqrestore(&nescq->lock, flags); - return (cqe_count); + return cqe_count; } /** * nes_req_notify_cq */ -#ifdef OFED_1_2 -static int nes_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify notify) -#else static int nes_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags notify_flags) -#endif -{ + { struct nes_vnic *nesvnic = to_nesvnic(ibcq->device); struct nes_device *nesdev = nesvnic->nesdev; struct nes_cq *nescq = to_nescq(ibcq); u32 cq_arm; - dprintk("%s: Requesting notification for CQ%u.\n", - __FUNCTION__, nescq->hw_cq.cq_number); + nes_debug(NES_DBG_CQ, "Requesting notification for CQ%u.\n", + nescq->hw_cq.cq_number); cq_arm = nescq->hw_cq.cq_number; -#ifdef OFED_1_2 - if (notify == IB_CQ_NEXT_COMP) - cq_arm |= NES_CQE_ALLOC_NOTIFY_NEXT; - else if (notify == IB_CQ_SOLICITED) - cq_arm |= NES_CQE_ALLOC_NOTIFY_SE; -#else if ((notify_flags & IB_CQ_SOLICITED_MASK) == IB_CQ_NEXT_COMP) cq_arm |= NES_CQE_ALLOC_NOTIFY_NEXT; else if ((notify_flags & IB_CQ_SOLICITED_MASK) == IB_CQ_SOLICITED) cq_arm |= NES_CQE_ALLOC_NOTIFY_SE; -#endif else - return (-EINVAL); + return -EINVAL; - /* dprintk("%s: Arming CQ%u, command = 0x%08X.\n", - __FUNCTION__, nescq->hw_cq.cq_number, cq_arm); */ nes_write32(nesdev->regs+NES_CQE_ALLOC, cq_arm); nes_read32(nesdev->regs+NES_CQE_ALLOC); - return (0); + return 0; } @@ -3623,11 +3740,9 @@ struct nes_ib_device *nes_init_ofa_device(struct net_device *netdev) struct nes_vnic *nesvnic = netdev_priv(netdev); struct nes_device *nesdev = nesvnic->nesdev; - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); - nesibdev = (struct nes_ib_device *)ib_alloc_device(sizeof(struct nes_ib_device)); if (nesibdev == NULL) { - return(NULL); + return NULL; } strlcpy(nesibdev->ibdev.name, "nes%d", IB_DEVICE_NAME_MAX); nesibdev->ibdev.owner = THIS_MODULE; @@ -3661,9 +3776,7 @@ struct nes_ib_device *nes_init_ofa_device(struct net_device *netdev) (1ull << IB_USER_VERBS_CMD_POST_SEND); nesibdev->ibdev.phys_port_cnt = 1; -#ifndef OFED_1_2 nesibdev->ibdev.num_comp_vectors = 1; -#endif nesibdev->ibdev.dma_device = &nesdev->pcidev->dev; nesibdev->ibdev.class_dev.dev = &nesdev->pcidev->dev; nesibdev->ibdev.query_device = nes_query_device; @@ -3706,10 +3819,10 @@ struct nes_ib_device *nes_init_ofa_device(struct net_device *netdev) nesibdev->ibdev.post_send = nes_post_send; nesibdev->ibdev.post_recv = nes_post_recv; - nesibdev->ibdev.iwcm = kmalloc(sizeof(*nesibdev->ibdev.iwcm), GFP_KERNEL); + nesibdev->ibdev.iwcm = kzalloc(sizeof(*nesibdev->ibdev.iwcm), GFP_KERNEL); if (nesibdev->ibdev.iwcm == NULL) { ib_dealloc_device(&nesibdev->ibdev); - return(NULL); + return NULL; } nesibdev->ibdev.iwcm->add_ref = nes_add_ref; nesibdev->ibdev.iwcm->rem_ref = nes_rem_ref; @@ -3720,8 +3833,7 @@ struct nes_ib_device *nes_init_ofa_device(struct net_device *netdev) nesibdev->ibdev.iwcm->create_listen = nes_create_listen; nesibdev->ibdev.iwcm->destroy_listen = nes_destroy_listen; - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); - return(nesibdev); + return nesibdev; } @@ -3730,16 +3842,13 @@ struct nes_ib_device *nes_init_ofa_device(struct net_device *netdev) */ void nes_destroy_ofa_device(struct nes_ib_device *nesibdev) { - dprintk("%s:%u\n", __FUNCTION__, __LINE__); - if (NULL == nesibdev) + if (nesibdev == NULL) return; nes_unregister_ofa_device(nesibdev); kfree(nesibdev->ibdev.iwcm); ib_dealloc_device(&nesibdev->ibdev); - - dprintk("%s:%u\n", __FUNCTION__, __LINE__); } @@ -3753,17 +3862,11 @@ int nes_register_ofa_device(struct nes_ib_device *nesibdev) struct nes_adapter *nesadapter = nesdev->nesadapter; int i, ret; - dprintk("%s: %u: &nesvnic=0x%p : &ibdev=0x%p\n", __FUNCTION__, __LINE__, - nesvnic, &nesvnic->nesibdev->ibdev); - ret = ib_register_device(&nesvnic->nesibdev->ibdev); if (ret) { - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); - return(ret); + return ret; } - dprintk("%s:%u after ib_register_device\n", __FUNCTION__, __LINE__); - /* Get the resources allocated to this device */ nesibdev->max_cq = (nesadapter->max_cq-NES_FIRST_QPN) / nesadapter->port_count; nesibdev->max_mr = nesadapter->max_mr / nesadapter->port_count; @@ -3771,25 +3874,21 @@ int nes_register_ofa_device(struct nes_ib_device *nesibdev) nesibdev->max_pd = nesadapter->max_pd / nesadapter->port_count; for (i = 0; i < ARRAY_SIZE(nes_class_attributes); ++i) { - dprintk("%s:%u call class_device_create_file\n", __FUNCTION__, __LINE__); ret = class_device_create_file(&nesibdev->ibdev.class_dev, nes_class_attributes[i]); if (ret) { - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); - while (i > 0) { i--; class_device_remove_file(&nesibdev->ibdev.class_dev, nes_class_attributes[i]); } ib_unregister_device(&nesibdev->ibdev); - return(ret); + return ret; } } nesvnic->of_device_registered = 1; - dprintk("%s:%s:%u\n", __FILE__, __FUNCTION__, __LINE__); - return (0); + return 0; } @@ -3801,8 +3900,7 @@ void nes_unregister_ofa_device(struct nes_ib_device *nesibdev) struct nes_vnic *nesvnic = nesibdev->nesvnic; int i; - dprintk("%s:%u\n", __FUNCTION__, __LINE__); - if (NULL == nesibdev) + if (nesibdev == NULL) return; for (i = 0; i < ARRAY_SIZE(nes_class_attributes); ++i) { @@ -3810,12 +3908,8 @@ void nes_unregister_ofa_device(struct nes_ib_device *nesibdev) } if (nesvnic->of_device_registered) { - dprintk("%s:%u call ib_unregister_device()\n", __FUNCTION__, __LINE__); ib_unregister_device(&nesibdev->ibdev); } nesvnic->of_device_registered = 0; - - dprintk("%s:%u\n", __FUNCTION__, __LINE__); } - diff --git a/drivers/infiniband/hw/nes/nes_verbs.h b/drivers/infiniband/hw/nes/nes_verbs.h index 68f7823..6c6b4da 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.h +++ b/drivers/infiniband/hw/nes/nes_verbs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 NetEffect, Inc. All rights reserved. + * Copyright (c) 2006 - 2008 NetEffect, Inc. All rights reserved. * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. * * This software is available to you under a choice of one of two @@ -42,75 +42,76 @@ struct nes_device; struct nes_ucontext { struct ib_ucontext ibucontext; - struct nes_device *nesdev; - unsigned long mmap_wq_offset; - unsigned long mmap_cq_offset; /* to be removed */ - int index; /* rnic index (minor) */ - unsigned long allocated_doorbells[BITS_TO_LONGS(NES_MAX_USER_DB_REGIONS)]; - u16 mmap_db_index[NES_MAX_USER_DB_REGIONS]; - u16 first_free_db; - unsigned long allocated_wqs[BITS_TO_LONGS(NES_MAX_USER_WQ_REGIONS)]; - struct nes_qp * mmap_nesqp[NES_MAX_USER_WQ_REGIONS]; - u16 first_free_wq; - struct list_head cq_reg_mem_list; + struct nes_device *nesdev; + unsigned long mmap_wq_offset; + unsigned long mmap_cq_offset; /* to be removed */ + int index; /* rnic index (minor) */ + unsigned long allocated_doorbells[BITS_TO_LONGS(NES_MAX_USER_DB_REGIONS)]; + u16 mmap_db_index[NES_MAX_USER_DB_REGIONS]; + u16 first_free_db; + unsigned long allocated_wqs[BITS_TO_LONGS(NES_MAX_USER_WQ_REGIONS)]; + struct nes_qp *mmap_nesqp[NES_MAX_USER_WQ_REGIONS]; + u16 first_free_wq; + struct list_head cq_reg_mem_list; + struct list_head qp_reg_mem_list; + u32 mcrqf; + atomic_t usecnt; }; struct nes_pd { struct ib_pd ibpd; - u16 pd_id; - atomic_t sqp_count; - u16 mmap_db_index; + u16 pd_id; + atomic_t sqp_count; + u16 mmap_db_index; }; struct nes_mr { union { - struct ib_mr ibmr; - struct ib_mw ibmw; + struct ib_mr ibmr; + struct ib_mw ibmw; struct ib_fmr ibfmr; }; -#ifndef OFED_1_2 - struct ib_umem *region; -#endif - u16 pbls_used; - u8 mode; - u8 pbl_4k; + struct ib_umem *region; + u16 pbls_used; + u8 mode; + u8 pbl_4k; }; struct nes_hw_pb { - u32 pa_low; - u32 pa_high; + __le32 pa_low; + __le32 pa_high; }; struct nes_vpbl { - dma_addr_t pbl_pbase; + dma_addr_t pbl_pbase; struct nes_hw_pb *pbl_vbase; }; struct nes_root_vpbl { - dma_addr_t pbl_pbase; + dma_addr_t pbl_pbase; struct nes_hw_pb *pbl_vbase; - struct nes_vpbl *leaf_vpbl; + struct nes_vpbl *leaf_vpbl; }; struct nes_fmr { - struct nes_mr nesmr; - u32 leaf_pbl_cnt; - struct nes_root_vpbl root_vpbl; - struct ib_qp* ib_qp; - int access_rights; - struct ib_fmr_attr attr; + struct nes_mr nesmr; + u32 leaf_pbl_cnt; + struct nes_root_vpbl root_vpbl; + struct ib_qp *ib_qp; + int access_rights; + struct ib_fmr_attr attr; }; struct nes_av; struct nes_cq { - struct ib_cq ibcq; + struct ib_cq ibcq; struct nes_hw_cq hw_cq; - u32 polled_completions; - u32 cq_mem_size; - spinlock_t lock; - u8 virtual_cq; - u8 pad[3]; + u32 polled_completions; + u32 cq_mem_size; + spinlock_t lock; + u8 virtual_cq; + u8 pad[3]; }; struct nes_wq { @@ -121,44 +122,48 @@ struct iw_cm_id; struct ietf_mpa_frame; struct nes_qp { - struct ib_qp ibqp; - void * allocated_buffer; - struct iw_cm_id *cm_id; + struct ib_qp ibqp; + void *allocated_buffer; + struct iw_cm_id *cm_id; struct workqueue_struct *wq; - struct work_struct disconn_work; - struct socket *ksock; - struct nes_cq *nesscq; - struct nes_cq *nesrcq; - struct nes_pd *nespd; + struct work_struct disconn_work; + struct nes_cq *nesscq; + struct nes_cq *nesrcq; + struct nes_pd *nespd; + void *cm_node; /* handle of the node this QP is associated with */ struct ietf_mpa_frame *ietf_frame; - dma_addr_t ietf_frame_pbase; - wait_queue_head_t state_waitq; - unsigned long socket; - struct nes_hw_qp hwqp; - struct work_struct work; - struct work_struct ae_work; - enum ib_qp_state ibqp_state; - u32 iwarp_state; - u32 hte_index; - u32 last_aeq; - u32 qp_mem_size; - atomic_t refcount; - u32 mmap_sq_db_index; - u32 mmap_rq_db_index; - spinlock_t lock; + dma_addr_t ietf_frame_pbase; + wait_queue_head_t state_waitq; + unsigned long socket; + struct nes_hw_qp hwqp; + struct work_struct work; + struct work_struct ae_work; + enum ib_qp_state ibqp_state; + u32 iwarp_state; + u32 hte_index; + u32 last_aeq; + u32 qp_mem_size; + atomic_t refcount; + atomic_t close_timer_started; + u32 mmap_sq_db_index; + u32 mmap_rq_db_index; + spinlock_t lock; struct nes_qp_context *nesqp_context; - dma_addr_t nesqp_context_pbase; - wait_queue_head_t kick_waitq; - u16 in_disconnect; - u16 private_data_len; - u8 active_conn; - u8 skip_lsmm; - u8 user_mode; - u8 hte_added; - u8 hw_iwarp_state; - u8 flush_issued; - u8 hw_tcp_state; - u8 disconn_pending; - void *cm_node_p; /* handle of the node this QP is associated with */ + dma_addr_t nesqp_context_pbase; + void *pbl_vbase; + dma_addr_t pbl_pbase; + struct page *page; + wait_queue_head_t kick_waitq; + u16 in_disconnect; + u16 private_data_len; + u8 active_conn; + u8 skip_lsmm; + u8 user_mode; + u8 hte_added; + u8 hw_iwarp_state; + u8 flush_issued; + u8 hw_tcp_state; + u8 disconn_pending; + u8 destroyed; }; #endif /* NES_VERBS_H */ diff --git a/include/linux/kernel.h b/include/linux/kernel.h index ab8250f..69d8ac8 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -39,6 +39,16 @@ extern const char linux_banner[]; #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) +/** + * upper_32_bits - return bits 32-63 of a number + * @n: the number we're accessing + * + * A basic shift-right of a 64- or 32-bit quantity. Use this to suppress + * the "right shift count >= width of type" warning when that quantity is + * 32-bits. + */ +#define upper_32_bits(n) ((u32)(((n) >> 16) >> 16)) + #define KERN_EMERG "<0>" /* system is unusable */ #define KERN_ALERT "<1>" /* action must be taken immediately */ #define KERN_CRIT "<2>" /* critical conditions */