From 6a4ab669ad0b0eadb042383ef7677a84a68a0e0e Mon Sep 17 00:00:00 2001 From: Parav Pandit Date: Mon, 26 Mar 2012 14:27:12 +0000 Subject: be2net: Add function to issue mailbox cmd on MQ - Add generic function to issue mailbox cmd on MQ as export function. - RoCE driver will use this before it setups its own MQ. Signed-off-by: Parav Pandit Acked-by: David S. Miller Signed-off-by: Roland Dreier --- drivers/net/ethernet/emulex/benet/be_cmds.c | 39 +++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 67b030d72df1..1c7c7d06a0b7 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -15,6 +15,7 @@ * Costa Mesa, CA 92626 */ +#include #include "be.h" #include "be_cmds.h" @@ -2556,3 +2557,41 @@ err: pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma); return status; } + +int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload, + int wrb_payload_size, u16 *cmd_status, u16 *ext_status) +{ + struct be_adapter *adapter = netdev_priv(netdev_handle); + struct be_mcc_wrb *wrb; + struct be_cmd_req_hdr *hdr = (struct be_cmd_req_hdr *) wrb_payload; + struct be_cmd_req_hdr *req; + struct be_cmd_resp_hdr *resp; + int status; + + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } + req = embedded_payload(wrb); + resp = embedded_payload(wrb); + + be_wrb_cmd_hdr_prepare(req, hdr->subsystem, + hdr->opcode, wrb_payload_size, wrb, NULL); + memcpy(req, wrb_payload, wrb_payload_size); + be_dws_cpu_to_le(req, wrb_payload_size); + + status = be_mcc_notify_wait(adapter); + if (cmd_status) + *cmd_status = (status & 0xffff); + if (ext_status) + *ext_status = 0; + memcpy(wrb_payload, resp, sizeof(*resp) + resp->response_length); + be_dws_le_to_cpu(wrb_payload, sizeof(*resp) + resp->response_length); +err: + spin_unlock_bh(&adapter->mcc_lock); + return status; +} +EXPORT_SYMBOL(be_roce_mcc_cmd); -- cgit v1.2.3 From 045508a8a36f9a82b63d1f6362bd323085638588 Mon Sep 17 00:00:00 2001 From: Parav Pandit Date: Mon, 26 Mar 2012 14:27:13 +0000 Subject: be2net: Add functionality to support RoCE driver - Increase MSI-X vectors by 5 for RoCE traffic. - Add macro to check roce support on a device. - Add device-specific doorbell and MSI-X vector fields shared with NIC functionality. - Provide RoCE driver registration and deregistration functions. - Add support functions which will be invoked on adapter add/remove and port up/down events. - Traverse through the list of adapters to invoke callback functions. Signed-off-by: Parav Pandit Acked-by: David S. Miller Signed-off-by: Roland Dreier --- drivers/net/ethernet/emulex/benet/Makefile | 2 +- drivers/net/ethernet/emulex/benet/be.h | 38 +++++- drivers/net/ethernet/emulex/benet/be_cmds.h | 1 + drivers/net/ethernet/emulex/benet/be_hw.h | 4 +- drivers/net/ethernet/emulex/benet/be_main.c | 88 ++++++++++++-- drivers/net/ethernet/emulex/benet/be_roce.c | 182 ++++++++++++++++++++++++++++ drivers/net/ethernet/emulex/benet/be_roce.h | 75 ++++++++++++ 7 files changed, 375 insertions(+), 15 deletions(-) create mode 100644 drivers/net/ethernet/emulex/benet/be_roce.c create mode 100644 drivers/net/ethernet/emulex/benet/be_roce.h (limited to 'drivers/net') diff --git a/drivers/net/ethernet/emulex/benet/Makefile b/drivers/net/ethernet/emulex/benet/Makefile index a60cd8051135..1a91b276940d 100644 --- a/drivers/net/ethernet/emulex/benet/Makefile +++ b/drivers/net/ethernet/emulex/benet/Makefile @@ -4,4 +4,4 @@ obj-$(CONFIG_BE2NET) += be2net.o -be2net-y := be_main.o be_cmds.o be_ethtool.o +be2net-y := be_main.o be_cmds.o be_ethtool.o be_roce.o diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index 9576ac002c23..7bb2e97af898 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -32,6 +32,7 @@ #include #include "be_hw.h" +#include "be_roce.h" #define DRV_VER "4.2.116u" #define DRV_NAME "be2net" @@ -102,7 +103,8 @@ static inline char *nic_name(struct pci_dev *pdev) #define MAX_RX_QS (MAX_RSS_QS + 1) /* RSS qs + 1 def Rx */ #define MAX_TX_QS 8 -#define MAX_MSIX_VECTORS MAX_RSS_QS +#define MAX_ROCE_EQS 5 +#define MAX_MSIX_VECTORS (MAX_RSS_QS + MAX_ROCE_EQS) /* RSS qs + RoCE */ #define BE_TX_BUDGET 256 #define BE_NAPI_WEIGHT 64 #define MAX_RX_POST BE_NAPI_WEIGHT /* Frags posted at a time */ @@ -382,6 +384,17 @@ struct be_adapter { u8 transceiver; u8 autoneg; u8 generation; /* BladeEngine ASIC generation */ + u32 if_type; + struct { + u8 __iomem *base; /* Door Bell */ + u32 size; + u32 total_size; + u64 io_addr; + } roce_db; + u32 num_msix_roce_vec; + struct ocrdma_dev *ocrdma_dev; + struct list_head entry; + u32 flash_status; struct completion flash_compl; @@ -413,6 +426,10 @@ struct be_adapter { #define lancer_chip(adapter) ((adapter->pdev->device == OC_DEVICE_ID3) || \ (adapter->pdev->device == OC_DEVICE_ID4)) +#define be_roce_supported(adapter) ((adapter->if_type == SLI_INTF_TYPE_3 || \ + adapter->sli_family == SKYHAWK_SLI_FAMILY) && \ + (adapter->function_mode & RDMA_ENABLED)) + extern const struct ethtool_ops be_ethtool_ops; #define msix_enabled(adapter) (adapter->num_msix_vec > 0) @@ -577,10 +594,29 @@ static inline bool be_is_wol_excluded(struct be_adapter *adapter) } } +static inline bool be_type_2_3(struct be_adapter *adapter) +{ + return (adapter->if_type == SLI_INTF_TYPE_2 || + adapter->if_type == SLI_INTF_TYPE_3) ? true : false; +} + extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, u16 num_popped); extern void be_link_status_update(struct be_adapter *adapter, u8 link_status); extern void be_parse_stats(struct be_adapter *adapter); extern int be_load_fw(struct be_adapter *adapter, u8 *func); extern bool be_is_wol_supported(struct be_adapter *adapter); + +/* + * internal function to initialize-cleanup roce device. + */ +extern void be_roce_dev_add(struct be_adapter *); +extern void be_roce_dev_remove(struct be_adapter *); + +/* + * internal function to open-close roce device during ifup-ifdown. + */ +extern void be_roce_dev_open(struct be_adapter *); +extern void be_roce_dev_close(struct be_adapter *); + #endif /* BE_H */ diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h index d5b680c56af0..54eabd8ff397 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.h +++ b/drivers/net/ethernet/emulex/benet/be_cmds.h @@ -1056,6 +1056,7 @@ struct be_cmd_resp_modify_eq_delay { /* The HW can come up in either of the following multi-channel modes * based on the skew/IPL. */ +#define RDMA_ENABLED 0x4 #define FLEX10_MODE 0x400 #define VNIC_MODE 0x20000 #define UMC_ENABLED 0x1000000 diff --git a/drivers/net/ethernet/emulex/benet/be_hw.h b/drivers/net/ethernet/emulex/benet/be_hw.h index f2c89e3ccabd..23a345486564 100644 --- a/drivers/net/ethernet/emulex/benet/be_hw.h +++ b/drivers/net/ethernet/emulex/benet/be_hw.h @@ -98,11 +98,13 @@ #define SLI_INTF_REV_SHIFT 4 #define SLI_INTF_FT_MASK 0x00000001 +#define SLI_INTF_TYPE_2 2 +#define SLI_INTF_TYPE_3 3 /* SLI family */ #define BE_SLI_FAMILY 0x0 #define LANCER_A0_SLI_FAMILY 0xA - +#define SKYHAWK_SLI_FAMILY 0x2 /********* ISR0 Register offset **********/ #define CEV_ISR0_OFFSET 0xC18 diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 528a886bc2cd..fcc15e755d5c 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -2103,10 +2103,17 @@ static uint be_num_rss_want(struct be_adapter *adapter) static void be_msix_enable(struct be_adapter *adapter) { #define BE_MIN_MSIX_VECTORS 1 - int i, status, num_vec; + int i, status, num_vec, num_roce_vec = 0; /* If RSS queues are not used, need a vec for default RX Q */ num_vec = min(be_num_rss_want(adapter), num_online_cpus()); + if (be_roce_supported(adapter)) { + num_roce_vec = min_t(u32, MAX_ROCE_MSIX_VECTORS, + (num_online_cpus() + 1)); + num_roce_vec = min(num_roce_vec, MAX_ROCE_EQS); + num_vec += num_roce_vec; + num_vec = min(num_vec, MAX_MSIX_VECTORS); + } num_vec = max(num_vec, BE_MIN_MSIX_VECTORS); for (i = 0; i < num_vec; i++) @@ -2123,7 +2130,17 @@ static void be_msix_enable(struct be_adapter *adapter) } return; done: - adapter->num_msix_vec = num_vec; + if (be_roce_supported(adapter)) { + if (num_vec > num_roce_vec) { + adapter->num_msix_vec = num_vec - num_roce_vec; + adapter->num_msix_roce_vec = + num_vec - adapter->num_msix_vec; + } else { + adapter->num_msix_vec = num_vec; + adapter->num_msix_roce_vec = 0; + } + } else + adapter->num_msix_vec = num_vec; return; } @@ -2282,6 +2299,8 @@ static int be_close(struct net_device *netdev) struct be_eq_obj *eqo; int i; + be_roce_dev_close(adapter); + be_async_mcc_disable(adapter); if (!lancer_chip(adapter)) @@ -2390,6 +2409,7 @@ static int be_open(struct net_device *netdev) if (!status) be_link_status_update(adapter, link_status); + be_roce_dev_open(adapter); return 0; err: be_close(adapter->netdev); @@ -3122,6 +3142,24 @@ static void be_unmap_pci_bars(struct be_adapter *adapter) iounmap(adapter->csr); if (adapter->db) iounmap(adapter->db); + if (adapter->roce_db.base) + pci_iounmap(adapter->pdev, adapter->roce_db.base); +} + +static int lancer_roce_map_pci_bars(struct be_adapter *adapter) +{ + struct pci_dev *pdev = adapter->pdev; + u8 __iomem *addr; + + addr = pci_iomap(pdev, 2, 0); + if (addr == NULL) + return -ENOMEM; + + adapter->roce_db.base = addr; + adapter->roce_db.io_addr = pci_resource_start(pdev, 2); + adapter->roce_db.size = 8192; + adapter->roce_db.total_size = pci_resource_len(pdev, 2); + return 0; } static int be_map_pci_bars(struct be_adapter *adapter) @@ -3130,11 +3168,18 @@ static int be_map_pci_bars(struct be_adapter *adapter) int db_reg; if (lancer_chip(adapter)) { - addr = ioremap_nocache(pci_resource_start(adapter->pdev, 0), - pci_resource_len(adapter->pdev, 0)); - if (addr == NULL) - return -ENOMEM; - adapter->db = addr; + if (be_type_2_3(adapter)) { + addr = ioremap_nocache( + pci_resource_start(adapter->pdev, 0), + pci_resource_len(adapter->pdev, 0)); + if (addr == NULL) + return -ENOMEM; + adapter->db = addr; + } + if (adapter->if_type == SLI_INTF_TYPE_3) { + if (lancer_roce_map_pci_bars(adapter)) + goto pci_map_err; + } return 0; } @@ -3159,14 +3204,19 @@ static int be_map_pci_bars(struct be_adapter *adapter) if (addr == NULL) goto pci_map_err; adapter->db = addr; - + if (adapter->sli_family == SKYHAWK_SLI_FAMILY) { + adapter->roce_db.size = 4096; + adapter->roce_db.io_addr = + pci_resource_start(adapter->pdev, db_reg); + adapter->roce_db.total_size = + pci_resource_len(adapter->pdev, db_reg); + } return 0; pci_map_err: be_unmap_pci_bars(adapter); return -ENOMEM; } - static void be_ctrl_cleanup(struct be_adapter *adapter) { struct be_dma_mem *mem = &adapter->mbox_mem_alloced; @@ -3272,6 +3322,8 @@ static void __devexit be_remove(struct pci_dev *pdev) if (!adapter) return; + be_roce_dev_remove(adapter); + unregister_netdev(adapter->netdev); be_clear(adapter); @@ -3350,17 +3402,27 @@ static int be_dev_family_check(struct be_adapter *adapter) break; case BE_DEVICE_ID2: case OC_DEVICE_ID2: - case OC_DEVICE_ID5: adapter->generation = BE_GEN3; break; case OC_DEVICE_ID3: case OC_DEVICE_ID4: pci_read_config_dword(pdev, SLI_INTF_REG_OFFSET, &sli_intf); + adapter->if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >> + SLI_INTF_IF_TYPE_SHIFT; if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >> SLI_INTF_IF_TYPE_SHIFT; - if (((sli_intf & SLI_INTF_VALID_MASK) != SLI_INTF_VALID) || - if_type != 0x02) { + !be_type_2_3(adapter)) { + dev_err(&pdev->dev, "SLI_INTF reg val is not valid\n"); + return -EINVAL; + } + adapter->sli_family = ((sli_intf & SLI_INTF_FAMILY_MASK) >> + SLI_INTF_FAMILY_SHIFT); + adapter->generation = BE_GEN3; + break; + case OC_DEVICE_ID5: + pci_read_config_dword(pdev, SLI_INTF_REG_OFFSET, &sli_intf); + if ((sli_intf & SLI_INTF_VALID_MASK) != SLI_INTF_VALID) { dev_err(&pdev->dev, "SLI_INTF reg val is not valid\n"); return -EINVAL; } @@ -3620,6 +3682,8 @@ static int __devinit be_probe(struct pci_dev *pdev, if (status != 0) goto unsetup; + be_roce_dev_add(adapter); + dev_info(&pdev->dev, "%s: %s port %d\n", netdev->name, nic_name(pdev), adapter->port_num); diff --git a/drivers/net/ethernet/emulex/benet/be_roce.c b/drivers/net/ethernet/emulex/benet/be_roce.c new file mode 100644 index 000000000000..deecc44b3617 --- /dev/null +++ b/drivers/net/ethernet/emulex/benet/be_roce.c @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2005 - 2011 Emulex + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. The full GNU General + * Public License is included in this distribution in the file called COPYING. + * + * Contact Information: + * linux-drivers@emulex.com + * + * Emulex + * 3333 Susan Street + * Costa Mesa, CA 92626 + */ + +#include +#include +#include +#include + +#include "be.h" +#include "be_cmds.h" + +static struct ocrdma_driver *ocrdma_drv; +static LIST_HEAD(be_adapter_list); +static DEFINE_MUTEX(be_adapter_list_lock); + +static void _be_roce_dev_add(struct be_adapter *adapter) +{ + struct be_dev_info dev_info; + int i, num_vec; + struct pci_dev *pdev = adapter->pdev; + + if (!ocrdma_drv) + return; + if (pdev->device == OC_DEVICE_ID5) { + /* only msix is supported on these devices */ + if (!msix_enabled(adapter)) + return; + /* DPP region address and length */ + dev_info.dpp_unmapped_addr = pci_resource_start(pdev, 2); + dev_info.dpp_unmapped_len = pci_resource_len(pdev, 2); + } else { + dev_info.dpp_unmapped_addr = 0; + dev_info.dpp_unmapped_len = 0; + } + dev_info.pdev = adapter->pdev; + if (adapter->sli_family == SKYHAWK_SLI_FAMILY) + dev_info.db = adapter->db; + else + dev_info.db = adapter->roce_db.base; + dev_info.unmapped_db = adapter->roce_db.io_addr; + dev_info.db_page_size = adapter->roce_db.size; + dev_info.db_total_size = adapter->roce_db.total_size; + dev_info.netdev = adapter->netdev; + memcpy(dev_info.mac_addr, adapter->netdev->dev_addr, ETH_ALEN); + dev_info.dev_family = adapter->sli_family; + if (msix_enabled(adapter)) { + /* provide all the vectors, so that EQ creation response + * can decide which one to use. + */ + num_vec = adapter->num_msix_vec + adapter->num_msix_roce_vec; + dev_info.intr_mode = BE_INTERRUPT_MODE_MSIX; + dev_info.msix.num_vectors = min(num_vec, MAX_ROCE_MSIX_VECTORS); + /* provide start index of the vector, + * so in case of linear usage, + * it can use the base as starting point. + */ + dev_info.msix.start_vector = adapter->num_evt_qs; + for (i = 0; i < dev_info.msix.num_vectors; i++) { + dev_info.msix.vector_list[i] = + adapter->msix_entries[i].vector; + } + } else { + dev_info.msix.num_vectors = 0; + dev_info.intr_mode = BE_INTERRUPT_MODE_INTX; + } + adapter->ocrdma_dev = ocrdma_drv->add(&dev_info); +} + +void be_roce_dev_add(struct be_adapter *adapter) +{ + if (be_roce_supported(adapter)) { + INIT_LIST_HEAD(&adapter->entry); + mutex_lock(&be_adapter_list_lock); + list_add_tail(&adapter->entry, &be_adapter_list); + + /* invoke add() routine of roce driver only if + * valid driver registered with add method and add() is not yet + * invoked on a given adapter. + */ + _be_roce_dev_add(adapter); + mutex_unlock(&be_adapter_list_lock); + } +} + +void _be_roce_dev_remove(struct be_adapter *adapter) +{ + if (ocrdma_drv && ocrdma_drv->remove && adapter->ocrdma_dev) + ocrdma_drv->remove(adapter->ocrdma_dev); + adapter->ocrdma_dev = NULL; +} + +void be_roce_dev_remove(struct be_adapter *adapter) +{ + if (be_roce_supported(adapter)) { + mutex_lock(&be_adapter_list_lock); + _be_roce_dev_remove(adapter); + list_del(&adapter->entry); + mutex_unlock(&be_adapter_list_lock); + } +} + +void _be_roce_dev_open(struct be_adapter *adapter) +{ + if (ocrdma_drv && adapter->ocrdma_dev && + ocrdma_drv->state_change_handler) + ocrdma_drv->state_change_handler(adapter->ocrdma_dev, 0); +} + +void be_roce_dev_open(struct be_adapter *adapter) +{ + if (be_roce_supported(adapter)) { + mutex_lock(&be_adapter_list_lock); + _be_roce_dev_open(adapter); + mutex_unlock(&be_adapter_list_lock); + } +} + +void _be_roce_dev_close(struct be_adapter *adapter) +{ + if (ocrdma_drv && adapter->ocrdma_dev && + ocrdma_drv->state_change_handler) + ocrdma_drv->state_change_handler(adapter->ocrdma_dev, 1); +} + +void be_roce_dev_close(struct be_adapter *adapter) +{ + if (be_roce_supported(adapter)) { + mutex_lock(&be_adapter_list_lock); + _be_roce_dev_close(adapter); + mutex_unlock(&be_adapter_list_lock); + } +} + +int be_roce_register_driver(struct ocrdma_driver *drv) +{ + struct be_adapter *dev; + + mutex_lock(&be_adapter_list_lock); + if (ocrdma_drv) { + mutex_unlock(&be_adapter_list_lock); + return -EINVAL; + } + ocrdma_drv = drv; + list_for_each_entry(dev, &be_adapter_list, entry) { + struct net_device *netdev; + _be_roce_dev_add(dev); + netdev = dev->netdev; + if (netif_running(netdev) && netif_oper_up(netdev)) + _be_roce_dev_open(dev); + } + mutex_unlock(&be_adapter_list_lock); + return 0; +} +EXPORT_SYMBOL(be_roce_register_driver); + +void be_roce_unregister_driver(struct ocrdma_driver *drv) +{ + struct be_adapter *dev; + + mutex_lock(&be_adapter_list_lock); + list_for_each_entry(dev, &be_adapter_list, entry) { + if (dev->ocrdma_dev) + _be_roce_dev_remove(dev); + } + ocrdma_drv = NULL; + mutex_unlock(&be_adapter_list_lock); +} +EXPORT_SYMBOL(be_roce_unregister_driver); diff --git a/drivers/net/ethernet/emulex/benet/be_roce.h b/drivers/net/ethernet/emulex/benet/be_roce.h new file mode 100644 index 000000000000..db4ea8081c07 --- /dev/null +++ b/drivers/net/ethernet/emulex/benet/be_roce.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2005 - 2011 Emulex + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. The full GNU General + * Public License is included in this distribution in the file called COPYING. + * + * Contact Information: + * linux-drivers@emulex.com + * + * Emulex + * 3333 Susan Street + * Costa Mesa, CA 92626 + */ + +#ifndef BE_ROCE_H +#define BE_ROCE_H + +#include +#include + +struct ocrdma_dev; + +enum be_interrupt_mode { + BE_INTERRUPT_MODE_MSIX = 0, + BE_INTERRUPT_MODE_INTX = 1, + BE_INTERRUPT_MODE_MSI = 2, +}; + +#define MAX_ROCE_MSIX_VECTORS 16 +struct be_dev_info { + u8 __iomem *db; + u64 unmapped_db; + u32 db_page_size; + u32 db_total_size; + u64 dpp_unmapped_addr; + u32 dpp_unmapped_len; + struct pci_dev *pdev; + struct net_device *netdev; + u8 mac_addr[ETH_ALEN]; + u32 dev_family; + enum be_interrupt_mode intr_mode; + struct { + int num_vectors; + int start_vector; + u32 vector_list[MAX_ROCE_MSIX_VECTORS]; + } msix; +}; + +/* ocrdma driver register's the callback functions with nic driver. */ +struct ocrdma_driver { + unsigned char name[32]; + struct ocrdma_dev *(*add) (struct be_dev_info *dev_info); + void (*remove) (struct ocrdma_dev *); + void (*state_change_handler) (struct ocrdma_dev *, u32 new_state); +}; + +enum { + BE_DEV_UP = 0, + BE_DEV_DOWN = 1 +}; + +/* APIs for RoCE driver to register callback handlers, + * which will be invoked when device is added, removed, ifup, ifdown + */ +int be_roce_register_driver(struct ocrdma_driver *drv); +void be_roce_unregister_driver(struct ocrdma_driver *drv); + +/* API for RoCE driver to issue mailbox commands */ +int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload, + int wrb_payload_size, u16 *cmd_status, u16 *ext_status); + +#endif /* BE_ROCE_H */ -- cgit v1.2.3 From b3416f4476f39f76fd5ca238e8332ba9b8f059d9 Mon Sep 17 00:00:00 2001 From: Shlomo Pongratz Date: Sun, 29 Apr 2012 17:04:25 +0300 Subject: mlx4_core: Add second capabilities flags field This patch adds a 64-bit flags2 features member to struct mlx4_dev to export further features of the hardware. The original flags field tracks features whose support bits are advertised by the firmware in offsets 0x40 and 0x44 of the query device capabilities command. flags2 will track features whose support bits are scattered at various offsets. RSS support is the first feature to be exported through flags2. RSS capabilities are located at offset 0x2e. The size of the RSS indirection table is also given in this offset. Signed-off-by: Shlomo Pongratz Signed-off-by: Roland Dreier --- drivers/net/ethernet/mellanox/mlx4/fw.c | 29 +++++++++++++++++++++++++++++ drivers/net/ethernet/mellanox/mlx4/fw.h | 2 ++ drivers/net/ethernet/mellanox/mlx4/main.c | 2 ++ 3 files changed, 33 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c index 2a02ba522e60..f7488dfef8eb 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.c +++ b/drivers/net/ethernet/mellanox/mlx4/fw.c @@ -118,6 +118,20 @@ static void dump_dev_cap_flags(struct mlx4_dev *dev, u64 flags) mlx4_dbg(dev, " %s\n", fname[i]); } +static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags) +{ + static const char * const fname[] = { + [0] = "RSS support", + [1] = "RSS Toeplitz Hash Function support", + [2] = "RSS XOR Hash Function support" + }; + int i; + + for (i = 0; i < ARRAY_SIZE(fname); ++i) + if (fname[i] && (flags & (1LL << i))) + mlx4_dbg(dev, " %s\n", fname[i]); +} + int mlx4_MOD_STAT_CFG(struct mlx4_dev *dev, struct mlx4_mod_stat_cfg *cfg) { struct mlx4_cmd_mailbox *mailbox; @@ -346,6 +360,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) #define QUERY_DEV_CAP_MAX_REQ_QP_OFFSET 0x29 #define QUERY_DEV_CAP_MAX_RES_QP_OFFSET 0x2b #define QUERY_DEV_CAP_MAX_GSO_OFFSET 0x2d +#define QUERY_DEV_CAP_RSS_OFFSET 0x2e #define QUERY_DEV_CAP_MAX_RDMA_OFFSET 0x2f #define QUERY_DEV_CAP_RSZ_SRQ_OFFSET 0x33 #define QUERY_DEV_CAP_ACK_DELAY_OFFSET 0x35 @@ -390,6 +405,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) #define QUERY_DEV_CAP_RSVD_LKEY_OFFSET 0x98 #define QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET 0xa0 + dev_cap->flags2 = 0; mailbox = mlx4_alloc_cmd_mailbox(dev); if (IS_ERR(mailbox)) return PTR_ERR(mailbox); @@ -439,6 +455,17 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) else dev_cap->max_gso_sz = 1 << field; + MLX4_GET(field, outbox, QUERY_DEV_CAP_RSS_OFFSET); + if (field & 0x20) + dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_RSS_XOR; + if (field & 0x10) + dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_RSS_TOP; + field &= 0xf; + if (field) { + dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_RSS; + dev_cap->max_rss_tbl_sz = 1 << field; + } else + dev_cap->max_rss_tbl_sz = 0; MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_RDMA_OFFSET); dev_cap->max_rdma_global = 1 << (field & 0x3f); MLX4_GET(field, outbox, QUERY_DEV_CAP_ACK_DELAY_OFFSET); @@ -632,8 +659,10 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) dev_cap->max_rq_desc_sz, dev_cap->max_rq_sg); mlx4_dbg(dev, "Max GSO size: %d\n", dev_cap->max_gso_sz); mlx4_dbg(dev, "Max counters: %d\n", dev_cap->max_counters); + mlx4_dbg(dev, "Max RSS Table size: %d\n", dev_cap->max_rss_tbl_sz); dump_dev_cap_flags(dev, dev_cap->flags); + dump_dev_cap_flags2(dev, dev_cap->flags2); out: mlx4_free_cmd_mailbox(dev, mailbox); diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.h b/drivers/net/ethernet/mellanox/mlx4/fw.h index e1a5fa56bcbc..64c0399e4b78 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.h +++ b/drivers/net/ethernet/mellanox/mlx4/fw.h @@ -79,6 +79,7 @@ struct mlx4_dev_cap { u64 trans_code[MLX4_MAX_PORTS + 1]; u16 stat_rate_support; u64 flags; + u64 flags2; int reserved_uars; int uar_size; int min_page_sz; @@ -110,6 +111,7 @@ struct mlx4_dev_cap { u32 reserved_lkey; u64 max_icm_sz; int max_gso_sz; + int max_rss_tbl_sz; u8 supported_port_types[MLX4_MAX_PORTS + 1]; u8 suggested_type[MLX4_MAX_PORTS + 1]; u8 default_sense[MLX4_MAX_PORTS + 1]; diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 8bb05b46db86..bb04a8208780 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -272,10 +272,12 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) dev->caps.max_msg_sz = dev_cap->max_msg_sz; dev->caps.page_size_cap = ~(u32) (dev_cap->min_page_sz - 1); dev->caps.flags = dev_cap->flags; + dev->caps.flags2 = dev_cap->flags2; dev->caps.bmme_flags = dev_cap->bmme_flags; dev->caps.reserved_lkey = dev_cap->reserved_lkey; dev->caps.stat_rate_support = dev_cap->stat_rate_support; dev->caps.max_gso_sz = dev_cap->max_gso_sz; + dev->caps.max_rss_tbl_sz = dev_cap->max_rss_tbl_sz; /* Sense port always allowed on supported devices for ConnectX1 and 2 */ if (dev->pdev->device != 0x1003) -- cgit v1.2.3 From f4ec9e9531ac79ee2521faf7ad3d98978f747e42 Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Thu, 10 May 2012 23:28:04 +0300 Subject: mlx4_core: Change bitmap allocator to work in round-robin fashion Under most circumstances, the bitmap allocator does not allocate the same full 24-bit QP number immediately after a QP is destroyed. This works by using the upper bits of a 24-bit QP number, beyond the number of QPs that are actually available in the low level driver. For example, say that the HCA is willing to allocate a maximum of 64K qps. We use the bits 23..16 as a "counter" which is incremented by 1 at each allocation so that even if the same physical QP is re-allocated, it will not receive the same 24-bit QP number. However, we have seen the following scenario: 1. Allocate, say, 255 QPs in succession. This will cause a wrap of the "counter". 2. Destroy the first QP allocated, then allocate a new QP. The new QP, because of the counter wraparound, will get the same FULL QP number as the QP just destroyed! This is a problem because packets in transit can be erroneously delivered to the new QP when they were meant for the old (destroyed) QP, because the full QP number of the new QP is identical to the destroyed QP. (The "counter" mechanism is meant to prevent this by having the full 24-bit QP numbers differ even if the physical QP on the HCA is the same. As we see above, however, this mechanism does not always work). The best fix for this problem is to allocate QPs in round-robin mode, so that the physical QP numbers are not immediately re-used. Found-by: Matthew Finlay Signed-off-by: Jack Morgenstein Signed-off-by: Roland Dreier --- drivers/net/ethernet/mellanox/mlx4/alloc.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx4/alloc.c b/drivers/net/ethernet/mellanox/mlx4/alloc.c index 8be20e7ea3d1..06fef5b44f77 100644 --- a/drivers/net/ethernet/mellanox/mlx4/alloc.c +++ b/drivers/net/ethernet/mellanox/mlx4/alloc.c @@ -124,9 +124,6 @@ void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt) spin_lock(&bitmap->lock); bitmap_clear(bitmap->table, obj, cnt); - bitmap->last = min(bitmap->last, obj); - bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top) - & bitmap->mask; bitmap->avail += cnt; spin_unlock(&bitmap->lock); } -- cgit v1.2.3 From 881806bc155c0d5d78196c8bfae0ea2e76ae7386 Mon Sep 17 00:00:00 2001 From: Vipul Pandya Date: Fri, 18 May 2012 15:29:24 +0530 Subject: cxgb4: Detect DB FULL events and notify RDMA ULD Signed-off-by: Vipul Pandya Signed-off-by: Steve Wise Signed-off-by: Roland Dreier --- drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 4 ++ drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 77 +++++++++++++++++++++++++ drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h | 7 +++ drivers/net/ethernet/chelsio/cxgb4/sge.c | 6 ++ drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 9 +++ 5 files changed, 103 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index 0fe18850c838..f91b259f19be 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h @@ -504,6 +504,8 @@ struct adapter { void **tid_release_head; spinlock_t tid_release_lock; struct work_struct tid_release_task; + struct work_struct db_full_task; + struct work_struct db_drop_task; bool tid_release_task_busy; struct dentry *debugfs_root; @@ -719,4 +721,6 @@ int t4_ctrl_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf, int t4_ofld_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf, unsigned int vf, unsigned int eqid); int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl); +void t4_db_full(struct adapter *adapter); +void t4_db_dropped(struct adapter *adapter); #endif /* __CXGB4_H__ */ diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index b126b98065a9..c243f932099e 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -2366,6 +2366,16 @@ unsigned int cxgb4_port_chan(const struct net_device *dev) } EXPORT_SYMBOL(cxgb4_port_chan); +unsigned int cxgb4_dbfifo_count(const struct net_device *dev, int lpfifo) +{ + struct adapter *adap = netdev2adap(dev); + u32 v; + + v = t4_read_reg(adap, A_SGE_DBFIFO_STATUS); + return lpfifo ? G_LP_COUNT(v) : G_HP_COUNT(v); +} +EXPORT_SYMBOL(cxgb4_dbfifo_count); + /** * cxgb4_port_viid - get the VI id of a port * @dev: the net device for the port @@ -2446,6 +2456,69 @@ static struct notifier_block cxgb4_netevent_nb = { .notifier_call = netevent_cb }; +static void notify_rdma_uld(struct adapter *adap, enum cxgb4_control cmd) +{ + mutex_lock(&uld_mutex); + if (adap->uld_handle[CXGB4_ULD_RDMA]) + ulds[CXGB4_ULD_RDMA].control(adap->uld_handle[CXGB4_ULD_RDMA], + cmd); + mutex_unlock(&uld_mutex); +} + +static void process_db_full(struct work_struct *work) +{ + struct adapter *adap; + static int delay = 1000; + u32 v; + + adap = container_of(work, struct adapter, db_full_task); + + + /* stop LLD queues */ + + notify_rdma_uld(adap, CXGB4_CONTROL_DB_FULL); + do { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(usecs_to_jiffies(delay)); + v = t4_read_reg(adap, A_SGE_DBFIFO_STATUS); + if (G_LP_COUNT(v) == 0 && G_HP_COUNT(v) == 0) + break; + } while (1); + notify_rdma_uld(adap, CXGB4_CONTROL_DB_EMPTY); + + + /* + * The more we get db full interrupts, the more we'll delay + * in re-enabling db rings on queues, capped off at 200ms. + */ + delay = min(delay << 1, 200000); + + /* resume LLD queues */ +} + +static void process_db_drop(struct work_struct *work) +{ + struct adapter *adap; + adap = container_of(work, struct adapter, db_drop_task); + + + /* + * sync the PIDX values in HW and SW for LLD queues. + */ + + notify_rdma_uld(adap, CXGB4_CONTROL_DB_DROP); +} + +void t4_db_full(struct adapter *adap) +{ + schedule_work(&adap->db_full_task); +} + +void t4_db_dropped(struct adapter *adap) +{ + schedule_work(&adap->db_drop_task); +} + static void uld_attach(struct adapter *adap, unsigned int uld) { void *handle; @@ -2649,6 +2722,8 @@ static void cxgb_down(struct adapter *adapter) { t4_intr_disable(adapter); cancel_work_sync(&adapter->tid_release_task); + cancel_work_sync(&adapter->db_full_task); + cancel_work_sync(&adapter->db_drop_task); adapter->tid_release_task_busy = false; adapter->tid_release_head = NULL; @@ -3601,6 +3676,8 @@ static int __devinit init_one(struct pci_dev *pdev, spin_lock_init(&adapter->tid_release_lock); INIT_WORK(&adapter->tid_release_task, process_tid_release_list); + INIT_WORK(&adapter->db_full_task, process_db_full); + INIT_WORK(&adapter->db_drop_task, process_db_drop); err = t4_prep_adapter(adapter); if (err) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h index b1d39b8d141a..5cc2f27d60c7 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h @@ -163,6 +163,12 @@ enum cxgb4_state { CXGB4_STATE_DETACH }; +enum cxgb4_control { + CXGB4_CONTROL_DB_FULL, + CXGB4_CONTROL_DB_EMPTY, + CXGB4_CONTROL_DB_DROP, +}; + struct pci_dev; struct l2t_data; struct net_device; @@ -225,6 +231,7 @@ struct cxgb4_uld_info { int cxgb4_register_uld(enum cxgb4_uld type, const struct cxgb4_uld_info *p); int cxgb4_unregister_uld(enum cxgb4_uld type); int cxgb4_ofld_send(struct net_device *dev, struct sk_buff *skb); +unsigned int cxgb4_dbfifo_count(const struct net_device *dev, int lpfifo); unsigned int cxgb4_port_chan(const struct net_device *dev); unsigned int cxgb4_port_viid(const struct net_device *dev); unsigned int cxgb4_port_idx(const struct net_device *dev); diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c index 2dae7959f000..234c157a4879 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c @@ -2415,6 +2415,12 @@ void t4_sge_init(struct adapter *adap) RXPKTCPLMODE | (STAT_LEN == 128 ? EGRSTATUSPAGESIZE : 0)); + t4_set_reg_field(adap, A_SGE_DBFIFO_STATUS, + V_HP_INT_THRESH(5) | V_LP_INT_THRESH(5), + V_HP_INT_THRESH(5) | V_LP_INT_THRESH(5)); + t4_set_reg_field(adap, A_SGE_DOORBELL_CONTROL, F_ENABLE_DROP, + F_ENABLE_DROP); + for (i = v = 0; i < 32; i += 4) v |= (PAGE_SHIFT - 10) << i; t4_write_reg(adap, SGE_HOST_PAGE_SIZE, v); diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index d1ec111aebd8..13609bf056b0 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -1013,6 +1013,8 @@ static void sge_intr_handler(struct adapter *adapter) { ERR_INVALID_CIDX_INC, "SGE GTS CIDX increment too large", -1, 0 }, { ERR_CPL_OPCODE_0, "SGE received 0-length CPL", -1, 0 }, + { F_DBFIFO_LP_INT, NULL, -1, 0 }, + { F_DBFIFO_HP_INT, NULL, -1, 0 }, { ERR_DROPPED_DB, "SGE doorbell dropped", -1, 0 }, { ERR_DATA_CPL_ON_HIGH_QID1 | ERR_DATA_CPL_ON_HIGH_QID0, "SGE IQID > 1023 received CPL for FL", -1, 0 }, @@ -1042,6 +1044,12 @@ static void sge_intr_handler(struct adapter *adapter) t4_write_reg(adapter, SGE_INT_CAUSE2, v >> 32); } + err = t4_read_reg(adapter, A_SGE_INT_CAUSE3); + if (err & (F_DBFIFO_HP_INT|F_DBFIFO_LP_INT)) + t4_db_full(adapter); + if (err & F_ERR_DROPPED_DB) + t4_db_dropped(adapter); + if (t4_handle_intr_status(adapter, SGE_INT_CAUSE3, sge_intr_info) || v != 0) t4_fatal_err(adapter); @@ -1513,6 +1521,7 @@ void t4_intr_enable(struct adapter *adapter) ERR_BAD_DB_PIDX2 | ERR_BAD_DB_PIDX1 | ERR_BAD_DB_PIDX0 | ERR_ING_CTXT_PRIO | ERR_EGR_CTXT_PRIO | INGRESS_SIZE_ERR | + F_DBFIFO_HP_INT | F_DBFIFO_LP_INT | EGRESS_SIZE_ERR); t4_write_reg(adapter, MYPF_REG(PL_PF_INT_ENABLE), PF_INTR_MASK); t4_set_reg_field(adapter, PL_INT_MAP0, 0, 1 << pf); -- cgit v1.2.3 From 8caa1e8446948afefdb4dd2050a465f6da777652 Mon Sep 17 00:00:00 2001 From: Vipul Pandya Date: Fri, 18 May 2012 15:29:25 +0530 Subject: cxgb4: Common platform specific changes for DB Drop Recovery Add platform-specific callback functions for interrupts. This is needed to do a single read-clear of the CAUSE register and then call out to platform specific functions for DB threshold interrupts and DB drop interrupts. Add t4_mem_win_read_len() - mem-window reads for arbitrary lengths. This is used to read the CIDX/PIDX values from EC contexts during DB drop recovery. Add t4_fwaddrspace_write() - sends addrspace write cmds to the fw. Needed to flush the sge eq context cache. Signed-off-by: Vipul Pandya Signed-off-by: Steve Wise Signed-off-by: Roland Dreier --- drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 3 ++ drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 69 +++++++++++++++++++++++++----- 2 files changed, 61 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index f91b259f19be..5f3c0a728e18 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h @@ -723,4 +723,7 @@ int t4_ofld_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf, int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl); void t4_db_full(struct adapter *adapter); void t4_db_dropped(struct adapter *adapter); +int t4_mem_win_read_len(struct adapter *adap, u32 addr, __be32 *data, int len); +int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox, + u32 addr, u32 val); #endif /* __CXGB4_H__ */ diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index 13609bf056b0..32e1dd566a14 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -868,11 +868,14 @@ int t4_restart_aneg(struct adapter *adap, unsigned int mbox, unsigned int port) return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); } +typedef void (*int_handler_t)(struct adapter *adap); + struct intr_info { unsigned int mask; /* bits to check in interrupt status */ const char *msg; /* message to print or NULL */ short stat_idx; /* stat counter to increment or -1 */ unsigned short fatal; /* whether the condition reported is fatal */ + int_handler_t int_handler; /* platform-specific int handler */ }; /** @@ -905,6 +908,8 @@ static int t4_handle_intr_status(struct adapter *adapter, unsigned int reg, } else if (acts->msg && printk_ratelimit()) dev_warn(adapter->pdev_dev, "%s (0x%x)\n", acts->msg, status & acts->mask); + if (acts->int_handler) + acts->int_handler(adapter); mask |= acts->mask; } status &= mask; @@ -1013,9 +1018,9 @@ static void sge_intr_handler(struct adapter *adapter) { ERR_INVALID_CIDX_INC, "SGE GTS CIDX increment too large", -1, 0 }, { ERR_CPL_OPCODE_0, "SGE received 0-length CPL", -1, 0 }, - { F_DBFIFO_LP_INT, NULL, -1, 0 }, - { F_DBFIFO_HP_INT, NULL, -1, 0 }, - { ERR_DROPPED_DB, "SGE doorbell dropped", -1, 0 }, + { F_DBFIFO_LP_INT, NULL, -1, 0, t4_db_full }, + { F_DBFIFO_HP_INT, NULL, -1, 0, t4_db_full }, + { F_ERR_DROPPED_DB, NULL, -1, 0, t4_db_dropped }, { ERR_DATA_CPL_ON_HIGH_QID1 | ERR_DATA_CPL_ON_HIGH_QID0, "SGE IQID > 1023 received CPL for FL", -1, 0 }, { ERR_BAD_DB_PIDX3, "SGE DBP 3 pidx increment too large", -1, @@ -1036,20 +1041,14 @@ static void sge_intr_handler(struct adapter *adapter) }; v = (u64)t4_read_reg(adapter, SGE_INT_CAUSE1) | - ((u64)t4_read_reg(adapter, SGE_INT_CAUSE2) << 32); + ((u64)t4_read_reg(adapter, SGE_INT_CAUSE2) << 32); if (v) { dev_alert(adapter->pdev_dev, "SGE parity error (%#llx)\n", - (unsigned long long)v); + (unsigned long long)v); t4_write_reg(adapter, SGE_INT_CAUSE1, v); t4_write_reg(adapter, SGE_INT_CAUSE2, v >> 32); } - err = t4_read_reg(adapter, A_SGE_INT_CAUSE3); - if (err & (F_DBFIFO_HP_INT|F_DBFIFO_LP_INT)) - t4_db_full(adapter); - if (err & F_ERR_DROPPED_DB) - t4_db_dropped(adapter); - if (t4_handle_intr_status(adapter, SGE_INT_CAUSE3, sge_intr_info) || v != 0) t4_fatal_err(adapter); @@ -1995,6 +1994,54 @@ int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map, (var).retval_len16 = htonl(FW_LEN16(var)); \ } while (0) +int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox, + u32 addr, u32 val) +{ + struct fw_ldst_cmd c; + + memset(&c, 0, sizeof(c)); + c.op_to_addrspace = htonl(V_FW_CMD_OP(FW_LDST_CMD) | F_FW_CMD_REQUEST | + F_FW_CMD_WRITE | + V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_FIRMWARE)); + c.cycles_to_len16 = htonl(FW_LEN16(c)); + c.u.addrval.addr = htonl(addr); + c.u.addrval.val = htonl(val); + + return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); +} + +/* + * t4_mem_win_read_len - read memory through PCIE memory window + * @adap: the adapter + * @addr: address of first byte requested aligned on 32b. + * @data: len bytes to hold the data read + * @len: amount of data to read from window. Must be <= + * MEMWIN0_APERATURE after adjusting for 16B alignment + * requirements of the the memory window. + * + * Read len bytes of data from MC starting at @addr. + */ +int t4_mem_win_read_len(struct adapter *adap, u32 addr, __be32 *data, int len) +{ + int i; + int off; + + /* + * Align on a 16B boundary. + */ + off = addr & 15; + if ((addr & 3) || (len + off) > MEMWIN0_APERTURE) + return -EINVAL; + + t4_write_reg(adap, A_PCIE_MEM_ACCESS_OFFSET, addr & ~15); + t4_read_reg(adap, A_PCIE_MEM_ACCESS_OFFSET); + + for (i = 0; i < len; i += 4) + *data++ = t4_read_reg(adap, (MEMWIN0_BASE + off + i)); + + return 0; +} + /** * t4_mdio_rd - read a PHY register through MDIO * @adap: the adapter -- cgit v1.2.3 From 3069ee9bc451d90a2fa8c3c7ef2774744d9d3bb0 Mon Sep 17 00:00:00 2001 From: Vipul Pandya Date: Fri, 18 May 2012 15:29:26 +0530 Subject: cxgb4: DB Drop Recovery for RDMA and LLD queues recover LLD EQs for DB drop interrupts. This includes adding a new db_lock, a spin lock disabling BH too, used by the recovery thread and the ring_tx_db() paths to allow db drop recovery. Clean up initial DB avoidance code. Add read_eq_indices() - this allows the LLD to use the PCIe mw to efficiently read hw eq contexts. Add cxgb4_sync_txq_pidx() - called by iw_cxgb4 to sync up the sw/hw pidx value. Add flush_eq_cache() and cxgb4_flush_eq_cache(). This allows iw_cxgb4 to flush the sge eq context cache before beginning db drop recovery. Add module parameter, dbfoifo_int_thresh, to allow tuning the db interrupt threshold value. Add dbfifo_int_thresh to cxgb4_lld_info so iw_cxgb4 knows the threshold. Add module parameter, dbfoifo_drain_delay, to allow tuning the amount of time delay between DB FULL and EMPTY upcalls to iw_cxgb4. Signed-off-by: Vipul Pandya Signed-off-by: Steve Wise Signed-off-by: Roland Dreier --- drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 16 ++ drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 214 +++++++++++++++++++----- drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h | 4 + drivers/net/ethernet/chelsio/cxgb4/sge.c | 20 ++- drivers/net/ethernet/chelsio/cxgb4/t4_regs.h | 53 ++++++ drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h | 15 ++ 6 files changed, 280 insertions(+), 42 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index 5f3c0a728e18..ec2dafe8ae5b 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h @@ -51,6 +51,8 @@ #define FW_VERSION_MINOR 1 #define FW_VERSION_MICRO 0 +#define CH_WARN(adap, fmt, ...) dev_warn(adap->pdev_dev, fmt, ## __VA_ARGS__) + enum { MAX_NPORTS = 4, /* max # of ports */ SERNUM_LEN = 24, /* Serial # length */ @@ -64,6 +66,15 @@ enum { MEM_MC }; +enum { + MEMWIN0_APERTURE = 65536, + MEMWIN0_BASE = 0x30000, + MEMWIN1_APERTURE = 32768, + MEMWIN1_BASE = 0x28000, + MEMWIN2_APERTURE = 2048, + MEMWIN2_BASE = 0x1b800, +}; + enum dev_master { MASTER_CANT, MASTER_MAY, @@ -403,6 +414,9 @@ struct sge_txq { struct tx_sw_desc *sdesc; /* address of SW Tx descriptor ring */ struct sge_qstat *stat; /* queue status entry */ dma_addr_t phys_addr; /* physical address of the ring */ + spinlock_t db_lock; + int db_disabled; + unsigned short db_pidx; }; struct sge_eth_txq { /* state for an SGE Ethernet Tx queue */ @@ -475,6 +489,7 @@ struct adapter { void __iomem *regs; struct pci_dev *pdev; struct device *pdev_dev; + unsigned int mbox; unsigned int fn; unsigned int flags; @@ -607,6 +622,7 @@ irqreturn_t t4_sge_intr_msix(int irq, void *cookie); void t4_sge_init(struct adapter *adap); void t4_sge_start(struct adapter *adap); void t4_sge_stop(struct adapter *adap); +extern int dbfifo_int_thresh; #define for_each_port(adapter, iter) \ for (iter = 0; iter < (adapter)->params.nports; ++iter) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index c243f932099e..e1f96fbb48c1 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -148,15 +148,6 @@ static unsigned int pfvfres_pmask(struct adapter *adapter, } #endif -enum { - MEMWIN0_APERTURE = 65536, - MEMWIN0_BASE = 0x30000, - MEMWIN1_APERTURE = 32768, - MEMWIN1_BASE = 0x28000, - MEMWIN2_APERTURE = 2048, - MEMWIN2_BASE = 0x1b800, -}; - enum { MAX_TXQ_ENTRIES = 16384, MAX_CTRL_TXQ_ENTRIES = 1024, @@ -371,6 +362,15 @@ static int set_addr_filters(const struct net_device *dev, bool sleep) uhash | mhash, sleep); } +int dbfifo_int_thresh = 10; /* 10 == 640 entry threshold */ +module_param(dbfifo_int_thresh, int, 0644); +MODULE_PARM_DESC(dbfifo_int_thresh, "doorbell fifo interrupt threshold"); + +int dbfifo_drain_delay = 1000; /* usecs to sleep while draining the dbfifo */ +module_param(dbfifo_drain_delay, int, 0644); +MODULE_PARM_DESC(dbfifo_drain_delay, + "usecs to sleep while draining the dbfifo"); + /* * Set Rx properties of a port, such as promiscruity, address filters, and MTU. * If @mtu is -1 it is left unchanged. @@ -389,6 +389,8 @@ static int set_rxmode(struct net_device *dev, int mtu, bool sleep_ok) return ret; } +static struct workqueue_struct *workq; + /** * link_start - enable a port * @dev: the port to enable @@ -2196,7 +2198,7 @@ static void cxgb4_queue_tid_release(struct tid_info *t, unsigned int chan, adap->tid_release_head = (void **)((uintptr_t)p | chan); if (!adap->tid_release_task_busy) { adap->tid_release_task_busy = true; - schedule_work(&adap->tid_release_task); + queue_work(workq, &adap->tid_release_task); } spin_unlock_bh(&adap->tid_release_lock); } @@ -2423,6 +2425,59 @@ void cxgb4_iscsi_init(struct net_device *dev, unsigned int tag_mask, } EXPORT_SYMBOL(cxgb4_iscsi_init); +int cxgb4_flush_eq_cache(struct net_device *dev) +{ + struct adapter *adap = netdev2adap(dev); + int ret; + + ret = t4_fwaddrspace_write(adap, adap->mbox, + 0xe1000000 + A_SGE_CTXT_CMD, 0x20000000); + return ret; +} +EXPORT_SYMBOL(cxgb4_flush_eq_cache); + +static int read_eq_indices(struct adapter *adap, u16 qid, u16 *pidx, u16 *cidx) +{ + u32 addr = t4_read_reg(adap, A_SGE_DBQ_CTXT_BADDR) + 24 * qid + 8; + __be64 indices; + int ret; + + ret = t4_mem_win_read_len(adap, addr, (__be32 *)&indices, 8); + if (!ret) { + indices = be64_to_cpu(indices); + *cidx = (indices >> 25) & 0xffff; + *pidx = (indices >> 9) & 0xffff; + } + return ret; +} + +int cxgb4_sync_txq_pidx(struct net_device *dev, u16 qid, u16 pidx, + u16 size) +{ + struct adapter *adap = netdev2adap(dev); + u16 hw_pidx, hw_cidx; + int ret; + + ret = read_eq_indices(adap, qid, &hw_pidx, &hw_cidx); + if (ret) + goto out; + + if (pidx != hw_pidx) { + u16 delta; + + if (pidx >= hw_pidx) + delta = pidx - hw_pidx; + else + delta = size - hw_pidx + pidx; + wmb(); + t4_write_reg(adap, MYPF_REG(A_SGE_PF_KDOORBELL), + V_QID(qid) | V_PIDX(delta)); + } +out: + return ret; +} +EXPORT_SYMBOL(cxgb4_sync_txq_pidx); + static struct pci_driver cxgb4_driver; static void check_neigh_update(struct neighbour *neigh) @@ -2456,6 +2511,95 @@ static struct notifier_block cxgb4_netevent_nb = { .notifier_call = netevent_cb }; +static void drain_db_fifo(struct adapter *adap, int usecs) +{ + u32 v; + + do { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(usecs_to_jiffies(usecs)); + v = t4_read_reg(adap, A_SGE_DBFIFO_STATUS); + if (G_LP_COUNT(v) == 0 && G_HP_COUNT(v) == 0) + break; + } while (1); +} + +static void disable_txq_db(struct sge_txq *q) +{ + spin_lock_irq(&q->db_lock); + q->db_disabled = 1; + spin_unlock_irq(&q->db_lock); +} + +static void enable_txq_db(struct sge_txq *q) +{ + spin_lock_irq(&q->db_lock); + q->db_disabled = 0; + spin_unlock_irq(&q->db_lock); +} + +static void disable_dbs(struct adapter *adap) +{ + int i; + + for_each_ethrxq(&adap->sge, i) + disable_txq_db(&adap->sge.ethtxq[i].q); + for_each_ofldrxq(&adap->sge, i) + disable_txq_db(&adap->sge.ofldtxq[i].q); + for_each_port(adap, i) + disable_txq_db(&adap->sge.ctrlq[i].q); +} + +static void enable_dbs(struct adapter *adap) +{ + int i; + + for_each_ethrxq(&adap->sge, i) + enable_txq_db(&adap->sge.ethtxq[i].q); + for_each_ofldrxq(&adap->sge, i) + enable_txq_db(&adap->sge.ofldtxq[i].q); + for_each_port(adap, i) + enable_txq_db(&adap->sge.ctrlq[i].q); +} + +static void sync_txq_pidx(struct adapter *adap, struct sge_txq *q) +{ + u16 hw_pidx, hw_cidx; + int ret; + + spin_lock_bh(&q->db_lock); + ret = read_eq_indices(adap, (u16)q->cntxt_id, &hw_pidx, &hw_cidx); + if (ret) + goto out; + if (q->db_pidx != hw_pidx) { + u16 delta; + + if (q->db_pidx >= hw_pidx) + delta = q->db_pidx - hw_pidx; + else + delta = q->size - hw_pidx + q->db_pidx; + wmb(); + t4_write_reg(adap, MYPF_REG(A_SGE_PF_KDOORBELL), + V_QID(q->cntxt_id) | V_PIDX(delta)); + } +out: + q->db_disabled = 0; + spin_unlock_bh(&q->db_lock); + if (ret) + CH_WARN(adap, "DB drop recovery failed.\n"); +} +static void recover_all_queues(struct adapter *adap) +{ + int i; + + for_each_ethrxq(&adap->sge, i) + sync_txq_pidx(adap, &adap->sge.ethtxq[i].q); + for_each_ofldrxq(&adap->sge, i) + sync_txq_pidx(adap, &adap->sge.ofldtxq[i].q); + for_each_port(adap, i) + sync_txq_pidx(adap, &adap->sge.ctrlq[i].q); +} + static void notify_rdma_uld(struct adapter *adap, enum cxgb4_control cmd) { mutex_lock(&uld_mutex); @@ -2468,55 +2612,41 @@ static void notify_rdma_uld(struct adapter *adap, enum cxgb4_control cmd) static void process_db_full(struct work_struct *work) { struct adapter *adap; - static int delay = 1000; - u32 v; adap = container_of(work, struct adapter, db_full_task); - - /* stop LLD queues */ - notify_rdma_uld(adap, CXGB4_CONTROL_DB_FULL); - do { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(usecs_to_jiffies(delay)); - v = t4_read_reg(adap, A_SGE_DBFIFO_STATUS); - if (G_LP_COUNT(v) == 0 && G_HP_COUNT(v) == 0) - break; - } while (1); + drain_db_fifo(adap, dbfifo_drain_delay); + t4_set_reg_field(adap, A_SGE_INT_ENABLE3, + F_DBFIFO_HP_INT | F_DBFIFO_LP_INT, + F_DBFIFO_HP_INT | F_DBFIFO_LP_INT); notify_rdma_uld(adap, CXGB4_CONTROL_DB_EMPTY); - - - /* - * The more we get db full interrupts, the more we'll delay - * in re-enabling db rings on queues, capped off at 200ms. - */ - delay = min(delay << 1, 200000); - - /* resume LLD queues */ } static void process_db_drop(struct work_struct *work) { struct adapter *adap; - adap = container_of(work, struct adapter, db_drop_task); + adap = container_of(work, struct adapter, db_drop_task); - /* - * sync the PIDX values in HW and SW for LLD queues. - */ - + t4_set_reg_field(adap, A_SGE_DOORBELL_CONTROL, F_DROPPED_DB, 0); + disable_dbs(adap); notify_rdma_uld(adap, CXGB4_CONTROL_DB_DROP); + drain_db_fifo(adap, 1); + recover_all_queues(adap); + enable_dbs(adap); } void t4_db_full(struct adapter *adap) { - schedule_work(&adap->db_full_task); + t4_set_reg_field(adap, A_SGE_INT_ENABLE3, + F_DBFIFO_HP_INT | F_DBFIFO_LP_INT, 0); + queue_work(workq, &adap->db_full_task); } void t4_db_dropped(struct adapter *adap) { - schedule_work(&adap->db_drop_task); + queue_work(workq, &adap->db_drop_task); } static void uld_attach(struct adapter *adap, unsigned int uld) @@ -2552,6 +2682,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld) lli.gts_reg = adap->regs + MYPF_REG(SGE_PF_GTS); lli.db_reg = adap->regs + MYPF_REG(SGE_PF_KDOORBELL); lli.fw_vers = adap->params.fw_vers; + lli.dbfifo_int_thresh = dbfifo_int_thresh; handle = ulds[uld].add(&lli); if (IS_ERR(handle)) { @@ -3668,6 +3799,7 @@ static int __devinit init_one(struct pci_dev *pdev, adapter->pdev = pdev; adapter->pdev_dev = &pdev->dev; + adapter->mbox = func; adapter->fn = func; adapter->msg_enable = dflt_msg_enable; memset(adapter->chan_map, 0xff, sizeof(adapter->chan_map)); @@ -3865,6 +3997,10 @@ static int __init cxgb4_init_module(void) { int ret; + workq = create_singlethread_workqueue("cxgb4"); + if (!workq) + return -ENOMEM; + /* Debugfs support is optional, just warn if this fails */ cxgb4_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); if (!cxgb4_debugfs_root) @@ -3880,6 +4016,8 @@ static void __exit cxgb4_cleanup_module(void) { pci_unregister_driver(&cxgb4_driver); debugfs_remove(cxgb4_debugfs_root); /* NULL ok */ + flush_workqueue(workq); + destroy_workqueue(workq); } module_init(cxgb4_init_module); diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h index 5cc2f27d60c7..d79980c5fc63 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h @@ -218,6 +218,7 @@ struct cxgb4_lld_info { unsigned short ucq_density; /* # of user CQs/page */ void __iomem *gts_reg; /* address of GTS register */ void __iomem *db_reg; /* address of kernel doorbell */ + int dbfifo_int_thresh; /* doorbell fifo int threshold */ }; struct cxgb4_uld_info { @@ -226,6 +227,7 @@ struct cxgb4_uld_info { int (*rx_handler)(void *handle, const __be64 *rsp, const struct pkt_gl *gl); int (*state_change)(void *handle, enum cxgb4_state new_state); + int (*control)(void *handle, enum cxgb4_control control, ...); }; int cxgb4_register_uld(enum cxgb4_uld type, const struct cxgb4_uld_info *p); @@ -243,4 +245,6 @@ void cxgb4_iscsi_init(struct net_device *dev, unsigned int tag_mask, const unsigned int *pgsz_order); struct sk_buff *cxgb4_pktgl_to_skb(const struct pkt_gl *gl, unsigned int skb_len, unsigned int pull_len); +int cxgb4_sync_txq_pidx(struct net_device *dev, u16 qid, u16 pidx, u16 size); +int cxgb4_flush_eq_cache(struct net_device *dev); #endif /* !__CXGB4_OFLD_H */ diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c index 234c157a4879..e111d974afd8 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c @@ -767,8 +767,13 @@ static void write_sgl(const struct sk_buff *skb, struct sge_txq *q, static inline void ring_tx_db(struct adapter *adap, struct sge_txq *q, int n) { wmb(); /* write descriptors before telling HW */ - t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL), - QID(q->cntxt_id) | PIDX(n)); + spin_lock(&q->db_lock); + if (!q->db_disabled) { + t4_write_reg(adap, MYPF_REG(A_SGE_PF_KDOORBELL), + V_QID(q->cntxt_id) | V_PIDX(n)); + } + q->db_pidx = q->pidx; + spin_unlock(&q->db_lock); } /** @@ -2081,6 +2086,7 @@ static void init_txq(struct adapter *adap, struct sge_txq *q, unsigned int id) q->stops = q->restarts = 0; q->stat = (void *)&q->desc[q->size]; q->cntxt_id = id; + spin_lock_init(&q->db_lock); adap->sge.egr_map[id - adap->sge.egr_start] = q; } @@ -2415,9 +2421,15 @@ void t4_sge_init(struct adapter *adap) RXPKTCPLMODE | (STAT_LEN == 128 ? EGRSTATUSPAGESIZE : 0)); + /* + * Set up to drop DOORBELL writes when the DOORBELL FIFO overflows + * and generate an interrupt when this occurs so we can recover. + */ t4_set_reg_field(adap, A_SGE_DBFIFO_STATUS, - V_HP_INT_THRESH(5) | V_LP_INT_THRESH(5), - V_HP_INT_THRESH(5) | V_LP_INT_THRESH(5)); + V_HP_INT_THRESH(M_HP_INT_THRESH) | + V_LP_INT_THRESH(M_LP_INT_THRESH), + V_HP_INT_THRESH(dbfifo_int_thresh) | + V_LP_INT_THRESH(dbfifo_int_thresh)); t4_set_reg_field(adap, A_SGE_DOORBELL_CONTROL, F_ENABLE_DROP, F_ENABLE_DROP); diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h index 0adc5bcec7c4..111fc323f155 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h @@ -190,6 +190,59 @@ #define SGE_DEBUG_DATA_LOW 0x10d4 #define SGE_INGRESS_QUEUES_PER_PAGE_PF 0x10f4 +#define S_LP_INT_THRESH 12 +#define V_LP_INT_THRESH(x) ((x) << S_LP_INT_THRESH) +#define S_HP_INT_THRESH 28 +#define V_HP_INT_THRESH(x) ((x) << S_HP_INT_THRESH) +#define A_SGE_DBFIFO_STATUS 0x10a4 + +#define S_ENABLE_DROP 13 +#define V_ENABLE_DROP(x) ((x) << S_ENABLE_DROP) +#define F_ENABLE_DROP V_ENABLE_DROP(1U) +#define A_SGE_DOORBELL_CONTROL 0x10a8 + +#define A_SGE_CTXT_CMD 0x11fc +#define A_SGE_DBQ_CTXT_BADDR 0x1084 + +#define A_SGE_PF_KDOORBELL 0x0 + +#define S_QID 15 +#define V_QID(x) ((x) << S_QID) + +#define S_PIDX 0 +#define V_PIDX(x) ((x) << S_PIDX) + +#define M_LP_COUNT 0x7ffU +#define S_LP_COUNT 0 +#define G_LP_COUNT(x) (((x) >> S_LP_COUNT) & M_LP_COUNT) + +#define M_HP_COUNT 0x7ffU +#define S_HP_COUNT 16 +#define G_HP_COUNT(x) (((x) >> S_HP_COUNT) & M_HP_COUNT) + +#define A_SGE_INT_ENABLE3 0x1040 + +#define S_DBFIFO_HP_INT 8 +#define V_DBFIFO_HP_INT(x) ((x) << S_DBFIFO_HP_INT) +#define F_DBFIFO_HP_INT V_DBFIFO_HP_INT(1U) + +#define S_DBFIFO_LP_INT 7 +#define V_DBFIFO_LP_INT(x) ((x) << S_DBFIFO_LP_INT) +#define F_DBFIFO_LP_INT V_DBFIFO_LP_INT(1U) + +#define S_DROPPED_DB 0 +#define V_DROPPED_DB(x) ((x) << S_DROPPED_DB) +#define F_DROPPED_DB V_DROPPED_DB(1U) + +#define S_ERR_DROPPED_DB 18 +#define V_ERR_DROPPED_DB(x) ((x) << S_ERR_DROPPED_DB) +#define F_ERR_DROPPED_DB V_ERR_DROPPED_DB(1U) + +#define A_PCIE_MEM_ACCESS_OFFSET 0x306c + +#define M_HP_INT_THRESH 0xfU +#define M_LP_INT_THRESH 0xfU + #define PCIE_PF_CLI 0x44 #define PCIE_INT_CAUSE 0x3004 #define UNXSPLCPLERR 0x20000000U diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h index edcfd7ec7802..ad53f796b574 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h @@ -1620,4 +1620,19 @@ struct fw_hdr { #define FW_HDR_FW_VER_MINOR_GET(x) (((x) >> 16) & 0xff) #define FW_HDR_FW_VER_MICRO_GET(x) (((x) >> 8) & 0xff) #define FW_HDR_FW_VER_BUILD_GET(x) (((x) >> 0) & 0xff) + +#define S_FW_CMD_OP 24 +#define V_FW_CMD_OP(x) ((x) << S_FW_CMD_OP) + +#define S_FW_CMD_REQUEST 23 +#define V_FW_CMD_REQUEST(x) ((x) << S_FW_CMD_REQUEST) +#define F_FW_CMD_REQUEST V_FW_CMD_REQUEST(1U) + +#define S_FW_CMD_WRITE 21 +#define V_FW_CMD_WRITE(x) ((x) << S_FW_CMD_WRITE) +#define F_FW_CMD_WRITE V_FW_CMD_WRITE(1U) + +#define S_FW_LDST_CMD_ADDRSPACE 0 +#define V_FW_LDST_CMD_ADDRSPACE(x) ((x) << S_FW_LDST_CMD_ADDRSPACE) + #endif /* _T4FW_INTERFACE_H_ */ -- cgit v1.2.3