Commit 363dc396 authored by David S. Miller's avatar David S. Miller

Merge branch 'cxgb-crypto'

Hariprasad Shenai says:

====================
crypto/chcr: Add support for Chelsio Crypto Driver

This patch series adds support for Chelsio Crypto driver.

The patch series has been created against net-next tree and includes
patches for Chelsio Low Level Driver(cxgb4) and adds the new crypto
Upper Layer Driver(chcr) under a new directory drivers/crypto/chelsio.

Patch 1/4 ("cxgb4: Add support for dynamic allocation of resources for
ULD") adds support for dynamic allocation of resources for ULD. The
objective of this patch is to provide generic interface for upper layer
drivers to allocate and initialize hardware resources.

The present cxgb4 (network driver) apart from network functionality, also
initializes hardware and thus acts as lower layer driver for other drivers
to use hardware resources. Thus it acts as both a Low level driver for
Upper layer driver's like iw_cxgb4, cxgb4i and cxgb4it and a Network Driver.

Right now the allocation of resources for Upper layer driver's is done
statically. Patch 1/4 adds a new infrastructure for dynamic allocation of
resources. cxgb4 will read the hardware capability through firmware and
allocate/free the queues for Upper layer drivers when the respective
driver's are loaded and freed when unloaded.

Patch 2/3, 3/4 and 4/4 adds support for Chelsio Crypto Driver. The Crypto
driver will act as another ULD on top of cxgb4.

In this patch series, the ULD API framework is used only by crypto and other
ULD's will make use of it in the next series.

This patch series is only for review, if this looks ok we will test it
thoroughly and send request for merge.

We have included all the maintainers of respective drivers. Kindly
review the changes and provide feedback on the same.

V3: - Removed crypto queues from cxgb4 and added support for dynamic
      allocation of resources for Upper layer drivers
    - Dependency fix in Kconfig.

V2: - Some residual code cleanup
    - Adds pr_fmt with chcr (KBUILD_MODNAME) added
    - Changes var name to accomodate them <80 columns in the chcr_register_alg
    - Support for printing the crypto queue stats
    - Fix compile warnings reported by kbuild bot for certain architectures
    - Dependency fix in Kconfig.
    - If the request has the MAY_BACKLOG bit set and hardware queue is
      full the request is queued up else -EBUSY is returned to throttle
      the user. The queue when executed and processed returns -EINPROGRESS
      in completion.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents b65b24d4 02038fd6
...@@ -550,4 +550,6 @@ config CRYPTO_DEV_ROCKCHIP ...@@ -550,4 +550,6 @@ config CRYPTO_DEV_ROCKCHIP
This driver interfaces with the hardware crypto accelerator. This driver interfaces with the hardware crypto accelerator.
Supporting cbc/ecb chainmode, and aes/des/des3_ede cipher mode. Supporting cbc/ecb chainmode, and aes/des/des3_ede cipher mode.
source "drivers/crypto/chelsio/Kconfig"
endif # CRYPTO_HW endif # CRYPTO_HW
...@@ -31,3 +31,4 @@ obj-$(CONFIG_CRYPTO_DEV_QCE) += qce/ ...@@ -31,3 +31,4 @@ obj-$(CONFIG_CRYPTO_DEV_QCE) += qce/
obj-$(CONFIG_CRYPTO_DEV_VMX) += vmx/ obj-$(CONFIG_CRYPTO_DEV_VMX) += vmx/
obj-$(CONFIG_CRYPTO_DEV_SUN4I_SS) += sunxi-ss/ obj-$(CONFIG_CRYPTO_DEV_SUN4I_SS) += sunxi-ss/
obj-$(CONFIG_CRYPTO_DEV_ROCKCHIP) += rockchip/ obj-$(CONFIG_CRYPTO_DEV_ROCKCHIP) += rockchip/
obj-$(CONFIG_CRYPTO_DEV_CHELSIO) += chelsio/
config CRYPTO_DEV_CHELSIO
tristate "Chelsio Crypto Co-processor Driver"
depends on CHELSIO_T4
select CRYPTO_SHA1
select CRYPTO_SHA256
select CRYPTO_SHA512
---help---
The Chelsio Crypto Co-processor driver for T6 adapters.
For general information about Chelsio and our products, visit
our website at <http://www.chelsio.com>.
For customer support, please visit our customer support page at
<http://www.chelsio.com/support.html>.
Please send feedback to <linux-bugs@chelsio.com>.
To compile this driver as a module, choose M here: the module
will be called chcr.
ccflags-y := -Idrivers/net/ethernet/chelsio/cxgb4
obj-$(CONFIG_CRYPTO_DEV_CHELSIO) += chcr.o
chcr-objs := chcr_core.o chcr_algo.o
This diff is collapsed.
This diff is collapsed.
/**
* This file is part of the Chelsio T4/T5/T6 Ethernet driver for Linux.
*
* Copyright (C) 2011-2016 Chelsio Communications. 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 as published by
* the Free Software Foundation.
*
* Written and Maintained by:
* Manoj Malviya (manojmalviya@chelsio.com)
* Atul Gupta (atul.gupta@chelsio.com)
* Jitendra Lulla (jlulla@chelsio.com)
* Yeshaswi M R Gowda (yeshaswi@chelsio.com)
* Harsh Jain (harsh@chelsio.com)
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/skbuff.h>
#include <crypto/aes.h>
#include <crypto/hash.h>
#include "t4_msg.h"
#include "chcr_core.h"
#include "cxgb4_uld.h"
static LIST_HEAD(uld_ctx_list);
static DEFINE_MUTEX(dev_mutex);
static atomic_t dev_count;
typedef int (*chcr_handler_func)(struct chcr_dev *dev, unsigned char *input);
static int cpl_fw6_pld_handler(struct chcr_dev *dev, unsigned char *input);
static void *chcr_uld_add(const struct cxgb4_lld_info *lld);
static int chcr_uld_state_change(void *handle, enum cxgb4_state state);
static chcr_handler_func work_handlers[NUM_CPL_CMDS] = {
[CPL_FW6_PLD] = cpl_fw6_pld_handler,
};
static struct cxgb4_pci_uld_info chcr_uld_info = {
.name = DRV_MODULE_NAME,
.nrxq = 4,
.rxq_size = 1024,
.nciq = 0,
.ciq_size = 0,
.add = chcr_uld_add,
.state_change = chcr_uld_state_change,
.rx_handler = chcr_uld_rx_handler,
};
int assign_chcr_device(struct chcr_dev **dev)
{
struct uld_ctx *u_ctx;
/*
* Which device to use if multiple devices are available TODO
* May be select the device based on round robin. One session
* must go to the same device to maintain the ordering.
*/
mutex_lock(&dev_mutex); /* TODO ? */
u_ctx = list_first_entry(&uld_ctx_list, struct uld_ctx, entry);
if (!u_ctx) {
mutex_unlock(&dev_mutex);
return -ENXIO;
}
*dev = u_ctx->dev;
mutex_unlock(&dev_mutex);
return 0;
}
static int chcr_dev_add(struct uld_ctx *u_ctx)
{
struct chcr_dev *dev;
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return -ENXIO;
spin_lock_init(&dev->lock_chcr_dev);
u_ctx->dev = dev;
dev->u_ctx = u_ctx;
atomic_inc(&dev_count);
return 0;
}
static int chcr_dev_remove(struct uld_ctx *u_ctx)
{
kfree(u_ctx->dev);
u_ctx->dev = NULL;
atomic_dec(&dev_count);
return 0;
}
static int cpl_fw6_pld_handler(struct chcr_dev *dev,
unsigned char *input)
{
struct crypto_async_request *req;
struct cpl_fw6_pld *fw6_pld;
u32 ack_err_status = 0;
int error_status = 0;
fw6_pld = (struct cpl_fw6_pld *)input;
req = (struct crypto_async_request *)(uintptr_t)be64_to_cpu(
fw6_pld->data[1]);
ack_err_status =
ntohl(*(__be32 *)((unsigned char *)&fw6_pld->data[0] + 4));
if (ack_err_status) {
if (CHK_MAC_ERR_BIT(ack_err_status) ||
CHK_PAD_ERR_BIT(ack_err_status))
error_status = -EINVAL;
}
/* call completion callback with failure status */
if (req) {
if (!chcr_handle_resp(req, input, error_status))
req->complete(req, error_status);
else
return -EINVAL;
} else {
pr_err("Incorrect request address from the firmware\n");
return -EFAULT;
}
return 0;
}
int chcr_send_wr(struct sk_buff *skb)
{
return cxgb4_ofld_send(skb->dev, skb);
}
static void *chcr_uld_add(const struct cxgb4_lld_info *lld)
{
struct uld_ctx *u_ctx;
/* Create the device and add it in the device list */
u_ctx = kzalloc(sizeof(*u_ctx), GFP_KERNEL);
if (!u_ctx) {
u_ctx = ERR_PTR(-ENOMEM);
goto out;
}
u_ctx->lldi = *lld;
mutex_lock(&dev_mutex);
list_add_tail(&u_ctx->entry, &uld_ctx_list);
mutex_unlock(&dev_mutex);
out:
return u_ctx;
}
int chcr_uld_rx_handler(void *handle, const __be64 *rsp,
const struct pkt_gl *pgl)
{
struct uld_ctx *u_ctx = (struct uld_ctx *)handle;
struct chcr_dev *dev = u_ctx->dev;
const struct cpl_act_establish *rpl = (struct cpl_act_establish
*)rsp;
if (rpl->ot.opcode != CPL_FW6_PLD) {
pr_err("Unsupported opcode\n");
return 0;
}
if (!pgl)
work_handlers[rpl->ot.opcode](dev, (unsigned char *)&rsp[1]);
else
work_handlers[rpl->ot.opcode](dev, pgl->va);
return 0;
}
static int chcr_uld_state_change(void *handle, enum cxgb4_state state)
{
struct uld_ctx *u_ctx = handle;
int ret = 0;
switch (state) {
case CXGB4_STATE_UP:
if (!u_ctx->dev) {
ret = chcr_dev_add(u_ctx);
if (ret != 0)
return ret;
}
if (atomic_read(&dev_count) == 1)
ret = start_crypto();
break;
case CXGB4_STATE_DETACH:
if (u_ctx->dev) {
mutex_lock(&dev_mutex);
chcr_dev_remove(u_ctx);
mutex_unlock(&dev_mutex);
}
if (!atomic_read(&dev_count))
stop_crypto();
break;
case CXGB4_STATE_START_RECOVERY:
case CXGB4_STATE_DOWN:
default:
break;
}
return ret;
}
static int __init chcr_crypto_init(void)
{
if (cxgb4_register_pci_uld(CXGB4_PCI_ULD1, &chcr_uld_info)) {
pr_err("ULD register fail: No chcr crypto support in cxgb4");
return -1;
}
return 0;
}
static void __exit chcr_crypto_exit(void)
{
struct uld_ctx *u_ctx, *tmp;
if (atomic_read(&dev_count))
stop_crypto();
/* Remove all devices from list */
mutex_lock(&dev_mutex);
list_for_each_entry_safe(u_ctx, tmp, &uld_ctx_list, entry) {
if (u_ctx->dev)
chcr_dev_remove(u_ctx);
kfree(u_ctx);
}
mutex_unlock(&dev_mutex);
cxgb4_unregister_pci_uld(CXGB4_PCI_ULD1);
}
module_init(chcr_crypto_init);
module_exit(chcr_crypto_exit);
MODULE_DESCRIPTION("Crypto Co-processor for Chelsio Terminator cards.");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Chelsio Communications");
MODULE_VERSION(DRV_VERSION);
/*
* This file is part of the Chelsio T6 Crypto driver for Linux.
*
* Copyright (c) 2003-2016 Chelsio Communications, 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
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* 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
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
#ifndef __CHCR_CORE_H__
#define __CHCR_CORE_H__
#include <crypto/algapi.h>
#include "t4_hw.h"
#include "cxgb4.h"
#include "cxgb4_uld.h"
#define DRV_MODULE_NAME "chcr"
#define DRV_VERSION "1.0.0.0"
#define MAX_PENDING_REQ_TO_HW 20
#define CHCR_TEST_RESPONSE_TIMEOUT 1000
#define PAD_ERROR_BIT 1
#define CHK_PAD_ERR_BIT(x) (((x) >> PAD_ERROR_BIT) & 1)
#define MAC_ERROR_BIT 0
#define CHK_MAC_ERR_BIT(x) (((x) >> MAC_ERROR_BIT) & 1)
struct uld_ctx;
struct chcr_dev {
/* Request submited to h/w and waiting for response. */
spinlock_t lock_chcr_dev;
struct crypto_queue pending_queue;
struct uld_ctx *u_ctx;
unsigned char tx_channel_id;
};
struct uld_ctx {
struct list_head entry;
struct cxgb4_lld_info lldi;
struct chcr_dev *dev;
};
int assign_chcr_device(struct chcr_dev **dev);
int chcr_send_wr(struct sk_buff *skb);
int start_crypto(void);
int stop_crypto(void);
int chcr_uld_rx_handler(void *handle, const __be64 *rsp,
const struct pkt_gl *pgl);
int chcr_handle_resp(struct crypto_async_request *req, unsigned char *input,
int err);
#endif /* __CHCR_CORE_H__ */
/*
* This file is part of the Chelsio T6 Crypto driver for Linux.
*
* Copyright (c) 2003-2016 Chelsio Communications, 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
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* 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
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
#ifndef __CHCR_CRYPTO_H__
#define __CHCR_CRYPTO_H__
/* Define following if h/w is not dropping the AAD and IV data before
* giving the processed data
*/
#define CHCR_CRA_PRIORITY 300
#define CHCR_AES_MAX_KEY_LEN (2 * (AES_MAX_KEY_SIZE)) /* consider xts */
#define CHCR_MAX_CRYPTO_IV_LEN 16 /* AES IV len */
#define CHCR_MAX_AUTHENC_AES_KEY_LEN 32 /* max aes key length*/
#define CHCR_MAX_AUTHENC_SHA_KEY_LEN 128 /* max sha key length*/
#define CHCR_GIVENCRYPT_OP 2
/* CPL/SCMD parameters */
#define CHCR_ENCRYPT_OP 0
#define CHCR_DECRYPT_OP 1
#define CHCR_SCMD_SEQ_NO_CTRL_32BIT 1
#define CHCR_SCMD_SEQ_NO_CTRL_48BIT 2
#define CHCR_SCMD_SEQ_NO_CTRL_64BIT 3
#define CHCR_SCMD_PROTO_VERSION_GENERIC 4
#define CHCR_SCMD_AUTH_CTRL_AUTH_CIPHER 0
#define CHCR_SCMD_AUTH_CTRL_CIPHER_AUTH 1
#define CHCR_SCMD_CIPHER_MODE_NOP 0
#define CHCR_SCMD_CIPHER_MODE_AES_CBC 1
#define CHCR_SCMD_CIPHER_MODE_GENERIC_AES 4
#define CHCR_SCMD_CIPHER_MODE_AES_XTS 6
#define CHCR_SCMD_AUTH_MODE_NOP 0
#define CHCR_SCMD_AUTH_MODE_SHA1 1
#define CHCR_SCMD_AUTH_MODE_SHA224 2
#define CHCR_SCMD_AUTH_MODE_SHA256 3
#define CHCR_SCMD_AUTH_MODE_SHA512_224 5
#define CHCR_SCMD_AUTH_MODE_SHA512_256 6
#define CHCR_SCMD_AUTH_MODE_SHA512_384 7
#define CHCR_SCMD_AUTH_MODE_SHA512_512 8
#define CHCR_SCMD_HMAC_CTRL_NOP 0
#define CHCR_SCMD_HMAC_CTRL_NO_TRUNC 1
#define CHCR_SCMD_IVGEN_CTRL_HW 0
#define CHCR_SCMD_IVGEN_CTRL_SW 1
/* This are not really mac key size. They are intermediate values
* of sha engine and its size
*/
#define CHCR_KEYCTX_MAC_KEY_SIZE_128 0
#define CHCR_KEYCTX_MAC_KEY_SIZE_160 1
#define CHCR_KEYCTX_MAC_KEY_SIZE_192 2
#define CHCR_KEYCTX_MAC_KEY_SIZE_256 3
#define CHCR_KEYCTX_MAC_KEY_SIZE_512 4
#define CHCR_KEYCTX_CIPHER_KEY_SIZE_128 0
#define CHCR_KEYCTX_CIPHER_KEY_SIZE_192 1
#define CHCR_KEYCTX_CIPHER_KEY_SIZE_256 2
#define CHCR_KEYCTX_NO_KEY 15
#define CHCR_CPL_FW4_PLD_IV_OFFSET (5 * 64) /* bytes. flt #5 and #6 */
#define CHCR_CPL_FW4_PLD_HASH_RESULT_OFFSET (7 * 64) /* bytes. flt #7 */
#define CHCR_CPL_FW4_PLD_DATA_SIZE (4 * 64) /* bytes. flt #4 to #7 */
#define KEY_CONTEXT_HDR_SALT_AND_PAD 16
#define flits_to_bytes(x) (x * 8)
#define IV_NOP 0
#define IV_IMMEDIATE 1
#define IV_DSGL 2
#define CRYPTO_ALG_SUB_TYPE_MASK 0x0f000000
#define CRYPTO_ALG_SUB_TYPE_HASH_HMAC 0x01000000
#define CRYPTO_ALG_TYPE_HMAC (CRYPTO_ALG_TYPE_AHASH |\
CRYPTO_ALG_SUB_TYPE_HASH_HMAC)
#define MAX_SALT 4
#define MAX_SCRATCH_PAD_SIZE 32
#define CHCR_HASH_MAX_BLOCK_SIZE_64 64
#define CHCR_HASH_MAX_BLOCK_SIZE_128 128
/* Aligned to 128 bit boundary */
struct _key_ctx {
__be32 ctx_hdr;
u8 salt[MAX_SALT];
__be64 reserverd;
unsigned char key[0];
};
struct ablk_ctx {
u8 enc;
unsigned int processed_len;
__be32 key_ctx_hdr;
unsigned int enckey_len;
unsigned int dst_nents;
struct scatterlist iv_sg;
u8 key[CHCR_AES_MAX_KEY_LEN];
u8 iv[CHCR_MAX_CRYPTO_IV_LEN];
unsigned char ciph_mode;
};
struct hmac_ctx {
struct shash_desc *desc;
u8 ipad[CHCR_HASH_MAX_BLOCK_SIZE_128];
u8 opad[CHCR_HASH_MAX_BLOCK_SIZE_128];
};
struct __crypto_ctx {
struct hmac_ctx hmacctx[0];
struct ablk_ctx ablkctx[0];
};
struct chcr_context {
struct chcr_dev *dev;
unsigned char tx_channel_id;
struct __crypto_ctx crypto_ctx[0];
};
struct chcr_ahash_req_ctx {
u32 result;
char bfr[CHCR_HASH_MAX_BLOCK_SIZE_128];
u8 bfr_len;
/* DMA the partial hash in it */
u8 partial_hash[CHCR_HASH_MAX_DIGEST_SIZE];
u64 data_len; /* Data len till time */
void *dummy_payload_ptr;
/* SKB which is being sent to the hardware for processing */
struct sk_buff *skb;
};
struct chcr_blkcipher_req_ctx {
struct sk_buff *skb;
};
struct chcr_alg_template {
u32 type;
u32 is_registered;
union {
struct crypto_alg crypto;
struct ahash_alg hash;
} alg;
};
struct chcr_req_ctx {
union {
struct ahash_request *ahash_req;
struct ablkcipher_request *ablk_req;
} req;
union {
struct chcr_ahash_req_ctx *ahash_ctx;
struct chcr_blkcipher_req_ctx *ablk_ctx;
} ctx;
};
struct sge_opaque_hdr {
void *dev;
dma_addr_t addr[MAX_SKB_FRAGS + 1];
};
typedef struct sk_buff *(*create_wr_t)(struct crypto_async_request *req,
struct chcr_context *ctx,
unsigned short qid,
unsigned short op_type);
#endif /* __CHCR_CRYPTO_H__ */
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
obj-$(CONFIG_CHELSIO_T4) += cxgb4.o obj-$(CONFIG_CHELSIO_T4) += cxgb4.o
cxgb4-objs := cxgb4_main.o l2t.o t4_hw.o sge.o clip_tbl.o cxgb4_ethtool.o cxgb4-objs := cxgb4_main.o l2t.o t4_hw.o sge.o clip_tbl.o cxgb4_ethtool.o cxgb4_uld.o
cxgb4-$(CONFIG_CHELSIO_T4_DCB) += cxgb4_dcb.o cxgb4-$(CONFIG_CHELSIO_T4_DCB) += cxgb4_dcb.o
cxgb4-$(CONFIG_CHELSIO_T4_FCOE) += cxgb4_fcoe.o cxgb4-$(CONFIG_CHELSIO_T4_FCOE) += cxgb4_fcoe.o
cxgb4-$(CONFIG_DEBUG_FS) += cxgb4_debugfs.o cxgb4-$(CONFIG_DEBUG_FS) += cxgb4_debugfs.o
...@@ -53,6 +53,8 @@ ...@@ -53,6 +53,8 @@
#include "cxgb4_uld.h" #include "cxgb4_uld.h"
#define CH_WARN(adap, fmt, ...) dev_warn(adap->pdev_dev, fmt, ## __VA_ARGS__) #define CH_WARN(adap, fmt, ...) dev_warn(adap->pdev_dev, fmt, ## __VA_ARGS__)
extern struct list_head adapter_list;
extern struct mutex uld_mutex;
enum { enum {
MAX_NPORTS = 4, /* max # of ports */ MAX_NPORTS = 4, /* max # of ports */
...@@ -338,6 +340,7 @@ struct adapter_params { ...@@ -338,6 +340,7 @@ struct adapter_params {
enum chip_type chip; /* chip code */ enum chip_type chip; /* chip code */
struct arch_specific_params arch; /* chip specific params */ struct arch_specific_params arch; /* chip specific params */
unsigned char offload; unsigned char offload;
unsigned char crypto; /* HW capability for crypto */
unsigned char bypass; unsigned char bypass;
...@@ -403,7 +406,6 @@ struct fw_info { ...@@ -403,7 +406,6 @@ struct fw_info {
struct fw_hdr fw_hdr; struct fw_hdr fw_hdr;
}; };
struct trace_params { struct trace_params {
u32 data[TRACE_LEN / 4]; u32 data[TRACE_LEN / 4];
u32 mask[TRACE_LEN / 4]; u32 mask[TRACE_LEN / 4];
...@@ -510,6 +512,10 @@ enum { /* adapter flags */ ...@@ -510,6 +512,10 @@ enum { /* adapter flags */
FW_OFLD_CONN = (1 << 9), FW_OFLD_CONN = (1 << 9),
}; };
enum {
ULP_CRYPTO_LOOKASIDE = 1 << 0,
};
struct rx_sw_desc; struct rx_sw_desc;
struct sge_fl { /* SGE free-buffer queue state */ struct sge_fl { /* SGE free-buffer queue state */
...@@ -680,6 +686,16 @@ struct sge_ctrl_txq { /* state for an SGE control Tx queue */ ...@@ -680,6 +686,16 @@ struct sge_ctrl_txq { /* state for an SGE control Tx queue */
u8 full; /* the Tx ring is full */ u8 full; /* the Tx ring is full */
} ____cacheline_aligned_in_smp; } ____cacheline_aligned_in_smp;
struct sge_uld_rxq_info {
char name[IFNAMSIZ]; /* name of ULD driver */
struct sge_ofld_rxq *uldrxq; /* Rxq's for ULD */
u16 *msix_tbl; /* msix_tbl for uld */
u16 *rspq_id; /* response queue id's of rxq */
u16 nrxq; /* # of ingress uld queues */
u16 nciq; /* # of completion queues */
u8 uld; /* uld type */
};
struct sge { struct sge {
struct sge_eth_txq ethtxq[MAX_ETH_QSETS]; struct sge_eth_txq ethtxq[MAX_ETH_QSETS];
struct sge_ofld_txq ofldtxq[MAX_OFLD_QSETS]; struct sge_ofld_txq ofldtxq[MAX_OFLD_QSETS];
...@@ -691,6 +707,7 @@ struct sge { ...@@ -691,6 +707,7 @@ struct sge {
struct sge_ofld_rxq rdmarxq[MAX_RDMA_QUEUES]; struct sge_ofld_rxq rdmarxq[MAX_RDMA_QUEUES];
struct sge_ofld_rxq rdmaciq[MAX_RDMA_CIQS]; struct sge_ofld_rxq rdmaciq[MAX_RDMA_CIQS];
struct sge_rspq fw_evtq ____cacheline_aligned_in_smp; struct sge_rspq fw_evtq ____cacheline_aligned_in_smp;
struct sge_uld_rxq_info **uld_rxq_info;
struct sge_rspq intrq ____cacheline_aligned_in_smp; struct sge_rspq intrq ____cacheline_aligned_in_smp;
spinlock_t intrq_lock; spinlock_t intrq_lock;
...@@ -702,6 +719,7 @@ struct sge { ...@@ -702,6 +719,7 @@ struct sge {
u16 niscsitq; /* # of available iSCST Rx queues */ u16 niscsitq; /* # of available iSCST Rx queues */
u16 rdmaqs; /* # of available RDMA Rx queues */ u16 rdmaqs; /* # of available RDMA Rx queues */
u16 rdmaciqs; /* # of available RDMA concentrator IQs */ u16 rdmaciqs; /* # of available RDMA concentrator IQs */
u16 nqs_per_uld; /* # of Rx queues per ULD */
u16 iscsi_rxq[MAX_OFLD_QSETS]; u16 iscsi_rxq[MAX_OFLD_QSETS];
u16 iscsit_rxq[MAX_ISCSIT_QUEUES]; u16 iscsit_rxq[MAX_ISCSIT_QUEUES];
u16 rdma_rxq[MAX_RDMA_QUEUES]; u16 rdma_rxq[MAX_RDMA_QUEUES];
...@@ -757,6 +775,17 @@ struct hash_mac_addr { ...@@ -757,6 +775,17 @@ struct hash_mac_addr {
u8 addr[ETH_ALEN]; u8 addr[ETH_ALEN];
}; };
struct uld_msix_bmap {
unsigned long *msix_bmap;
unsigned int mapsize;
spinlock_t lock; /* lock for acquiring bitmap */
};
struct uld_msix_info {
unsigned short vec;
char desc[IFNAMSIZ + 10];
};
struct adapter { struct adapter {
void __iomem *regs; void __iomem *regs;
void __iomem *bar2; void __iomem *bar2;
...@@ -779,6 +808,9 @@ struct adapter { ...@@ -779,6 +808,9 @@ struct adapter {
unsigned short vec; unsigned short vec;
char desc[IFNAMSIZ + 10]; char desc[IFNAMSIZ + 10];
} msix_info[MAX_INGQ + 1]; } msix_info[MAX_INGQ + 1];
struct uld_msix_info *msix_info_ulds; /* msix info for uld's */
struct uld_msix_bmap msix_bmap_ulds; /* msix bitmap for all uld */
unsigned int msi_idx;
struct doorbell_stats db_stats; struct doorbell_stats db_stats;
struct sge sge; struct sge sge;
...@@ -793,7 +825,9 @@ struct adapter { ...@@ -793,7 +825,9 @@ struct adapter {
unsigned int clipt_start; unsigned int clipt_start;
unsigned int clipt_end; unsigned int clipt_end;
struct clip_tbl *clipt; struct clip_tbl *clipt;
struct cxgb4_pci_uld_info *uld;
void *uld_handle[CXGB4_ULD_MAX]; void *uld_handle[CXGB4_ULD_MAX];
unsigned int num_uld;
struct list_head list_node; struct list_head list_node;
struct list_head rcu_node; struct list_head rcu_node;
struct list_head mac_hlist; /* list of MAC addresses in MPS Hash */ struct list_head mac_hlist; /* list of MAC addresses in MPS Hash */
...@@ -952,6 +986,11 @@ static inline int is_offload(const struct adapter *adap) ...@@ -952,6 +986,11 @@ static inline int is_offload(const struct adapter *adap)
return adap->params.offload; return adap->params.offload;
} }
static inline int is_pci_uld(const struct adapter *adap)
{
return adap->params.crypto;
}
static inline u32 t4_read_reg(struct adapter *adap, u32 reg_addr) static inline u32 t4_read_reg(struct adapter *adap, u32 reg_addr)
{ {
return readl(adap->regs + reg_addr); return readl(adap->regs + reg_addr);
...@@ -1185,8 +1224,6 @@ int t4_sge_init(struct adapter *adap); ...@@ -1185,8 +1224,6 @@ int t4_sge_init(struct adapter *adap);
void t4_sge_start(struct adapter *adap); void t4_sge_start(struct adapter *adap);
void t4_sge_stop(struct adapter *adap); void t4_sge_stop(struct adapter *adap);
int cxgb_busy_poll(struct napi_struct *napi); int cxgb_busy_poll(struct napi_struct *napi);
int cxgb4_set_rspq_intr_params(struct sge_rspq *q, unsigned int us,
unsigned int cnt);
void cxgb4_set_ethtool_ops(struct net_device *netdev); void cxgb4_set_ethtool_ops(struct net_device *netdev);
int cxgb4_write_rss(const struct port_info *pi, const u16 *queues); int cxgb4_write_rss(const struct port_info *pi, const u16 *queues);
extern int dbfifo_int_thresh; extern int dbfifo_int_thresh;
...@@ -1289,6 +1326,18 @@ static inline int hash_mac_addr(const u8 *addr) ...@@ -1289,6 +1326,18 @@ static inline int hash_mac_addr(const u8 *addr)
return a & 0x3f; return a & 0x3f;
} }
int cxgb4_set_rspq_intr_params(struct sge_rspq *q, unsigned int us,
unsigned int cnt);
static inline void init_rspq(struct adapter *adap, struct sge_rspq *q,
unsigned int us, unsigned int cnt,
unsigned int size, unsigned int iqe_size)
{
q->adap = adap;
cxgb4_set_rspq_intr_params(q, us, cnt);
q->iqe_len = iqe_size;
q->size = size;
}
void t4_write_indirect(struct adapter *adap, unsigned int addr_reg, void t4_write_indirect(struct adapter *adap, unsigned int addr_reg,
unsigned int data_reg, const u32 *vals, unsigned int data_reg, const u32 *vals,
unsigned int nregs, unsigned int start_idx); unsigned int nregs, unsigned int start_idx);
...@@ -1523,5 +1572,7 @@ void t4_idma_monitor(struct adapter *adapter, ...@@ -1523,5 +1572,7 @@ void t4_idma_monitor(struct adapter *adapter,
int hz, int ticks); int hz, int ticks);
int t4_set_vf_mac_acl(struct adapter *adapter, unsigned int vf, int t4_set_vf_mac_acl(struct adapter *adapter, unsigned int vf,
unsigned int naddr, u8 *addr); unsigned int naddr, u8 *addr);
void uld_mem_free(struct adapter *adap);
int uld_mem_alloc(struct adapter *adap);
void free_rspq_fl(struct adapter *adap, struct sge_rspq *rq, struct sge_fl *fl);
#endif /* __CXGB4_H__ */ #endif /* __CXGB4_H__ */
...@@ -223,8 +223,8 @@ MODULE_PARM_DESC(select_queue, ...@@ -223,8 +223,8 @@ MODULE_PARM_DESC(select_queue,
static struct dentry *cxgb4_debugfs_root; static struct dentry *cxgb4_debugfs_root;
static LIST_HEAD(adapter_list); LIST_HEAD(adapter_list);
static DEFINE_MUTEX(uld_mutex); DEFINE_MUTEX(uld_mutex);
/* Adapter list to be accessed from atomic context */ /* Adapter list to be accessed from atomic context */
static LIST_HEAD(adap_rcu_list); static LIST_HEAD(adap_rcu_list);
static DEFINE_SPINLOCK(adap_rcu_lock); static DEFINE_SPINLOCK(adap_rcu_lock);
...@@ -1066,20 +1066,20 @@ static int alloc_ofld_rxqs(struct adapter *adap, struct sge_ofld_rxq *q, ...@@ -1066,20 +1066,20 @@ static int alloc_ofld_rxqs(struct adapter *adap, struct sge_ofld_rxq *q,
*/ */
static int setup_sge_queues(struct adapter *adap) static int setup_sge_queues(struct adapter *adap)
{ {
int err, msi_idx, i, j; int err, i, j;
struct sge *s = &adap->sge; struct sge *s = &adap->sge;
bitmap_zero(s->starving_fl, s->egr_sz); bitmap_zero(s->starving_fl, s->egr_sz);
bitmap_zero(s->txq_maperr, s->egr_sz); bitmap_zero(s->txq_maperr, s->egr_sz);
if (adap->flags & USING_MSIX) if (adap->flags & USING_MSIX)
msi_idx = 1; /* vector 0 is for non-queue interrupts */ adap->msi_idx = 1; /* vector 0 is for non-queue interrupts */
else { else {
err = t4_sge_alloc_rxq(adap, &s->intrq, false, adap->port[0], 0, err = t4_sge_alloc_rxq(adap, &s->intrq, false, adap->port[0], 0,
NULL, NULL, NULL, -1); NULL, NULL, NULL, -1);
if (err) if (err)
return err; return err;
msi_idx = -((int)s->intrq.abs_id + 1); adap->msi_idx = -((int)s->intrq.abs_id + 1);
} }
/* NOTE: If you add/delete any Ingress/Egress Queue allocations in here, /* NOTE: If you add/delete any Ingress/Egress Queue allocations in here,
...@@ -1096,7 +1096,7 @@ static int setup_sge_queues(struct adapter *adap) ...@@ -1096,7 +1096,7 @@ static int setup_sge_queues(struct adapter *adap)
* new/deleted queues. * new/deleted queues.
*/ */
err = t4_sge_alloc_rxq(adap, &s->fw_evtq, true, adap->port[0], err = t4_sge_alloc_rxq(adap, &s->fw_evtq, true, adap->port[0],
msi_idx, NULL, fwevtq_handler, NULL, -1); adap->msi_idx, NULL, fwevtq_handler, NULL, -1);
if (err) { if (err) {
freeout: t4_free_sge_resources(adap); freeout: t4_free_sge_resources(adap);
return err; return err;
...@@ -1109,10 +1109,10 @@ freeout: t4_free_sge_resources(adap); ...@@ -1109,10 +1109,10 @@ freeout: t4_free_sge_resources(adap);
struct sge_eth_txq *t = &s->ethtxq[pi->first_qset]; struct sge_eth_txq *t = &s->ethtxq[pi->first_qset];
for (j = 0; j < pi->nqsets; j++, q++) { for (j = 0; j < pi->nqsets; j++, q++) {
if (msi_idx > 0) if (adap->msi_idx > 0)
msi_idx++; adap->msi_idx++;
err = t4_sge_alloc_rxq(adap, &q->rspq, false, dev, err = t4_sge_alloc_rxq(adap, &q->rspq, false, dev,
msi_idx, &q->fl, adap->msi_idx, &q->fl,
t4_ethrx_handler, t4_ethrx_handler,
NULL, NULL,
t4_get_mps_bg_map(adap, t4_get_mps_bg_map(adap,
...@@ -1141,11 +1141,11 @@ freeout: t4_free_sge_resources(adap); ...@@ -1141,11 +1141,11 @@ freeout: t4_free_sge_resources(adap);
} }
#define ALLOC_OFLD_RXQS(firstq, nq, per_chan, ids, lro) do { \ #define ALLOC_OFLD_RXQS(firstq, nq, per_chan, ids, lro) do { \
err = alloc_ofld_rxqs(adap, firstq, nq, per_chan, msi_idx, ids, lro); \ err = alloc_ofld_rxqs(adap, firstq, nq, per_chan, adap->msi_idx, ids, lro); \
if (err) \ if (err) \
goto freeout; \ goto freeout; \
if (msi_idx > 0) \ if (adap->msi_idx > 0) \
msi_idx += nq; \ adap->msi_idx += nq; \
} while (0) } while (0)
ALLOC_OFLD_RXQS(s->iscsirxq, s->iscsiqsets, j, s->iscsi_rxq, false); ALLOC_OFLD_RXQS(s->iscsirxq, s->iscsiqsets, j, s->iscsi_rxq, false);
...@@ -2565,6 +2565,12 @@ static void detach_ulds(struct adapter *adap) ...@@ -2565,6 +2565,12 @@ static void detach_ulds(struct adapter *adap)
CXGB4_STATE_DETACH); CXGB4_STATE_DETACH);
adap->uld_handle[i] = NULL; adap->uld_handle[i] = NULL;
} }
for (i = 0; i < CXGB4_PCI_ULD_MAX; i++)
if (adap->uld && adap->uld[i].handle) {
adap->uld[i].state_change(adap->uld[i].handle,
CXGB4_STATE_DETACH);
adap->uld[i].handle = NULL;
}
if (netevent_registered && list_empty(&adapter_list)) { if (netevent_registered && list_empty(&adapter_list)) {
unregister_netevent_notifier(&cxgb4_netevent_nb); unregister_netevent_notifier(&cxgb4_netevent_nb);
netevent_registered = false; netevent_registered = false;
...@@ -2584,6 +2590,10 @@ static void notify_ulds(struct adapter *adap, enum cxgb4_state new_state) ...@@ -2584,6 +2590,10 @@ static void notify_ulds(struct adapter *adap, enum cxgb4_state new_state)
for (i = 0; i < CXGB4_ULD_MAX; i++) for (i = 0; i < CXGB4_ULD_MAX; i++)
if (adap->uld_handle[i]) if (adap->uld_handle[i])
ulds[i].state_change(adap->uld_handle[i], new_state); ulds[i].state_change(adap->uld_handle[i], new_state);
for (i = 0; i < CXGB4_PCI_ULD_MAX; i++)
if (adap->uld && adap->uld[i].handle)
adap->uld[i].state_change(adap->uld[i].handle,
new_state);
mutex_unlock(&uld_mutex); mutex_unlock(&uld_mutex);
} }
...@@ -4170,6 +4180,11 @@ static int adap_init0(struct adapter *adap) ...@@ -4170,6 +4180,11 @@ static int adap_init0(struct adapter *adap)
adap->vres.iscsi.start = val[0]; adap->vres.iscsi.start = val[0];
adap->vres.iscsi.size = val[1] - val[0] + 1; adap->vres.iscsi.size = val[1] - val[0] + 1;
} }
if (caps_cmd.cryptocaps) {
/* Should query params here...TODO */
adap->params.crypto |= ULP_CRYPTO_LOOKASIDE;
adap->num_uld += 1;
}
#undef FW_PARAM_PFVF #undef FW_PARAM_PFVF
#undef FW_PARAM_DEV #undef FW_PARAM_DEV
...@@ -4351,16 +4366,6 @@ static inline bool is_x_10g_port(const struct link_config *lc) ...@@ -4351,16 +4366,6 @@ static inline bool is_x_10g_port(const struct link_config *lc)
(lc->supported & FW_PORT_CAP_SPEED_40G) != 0; (lc->supported & FW_PORT_CAP_SPEED_40G) != 0;
} }
static inline void init_rspq(struct adapter *adap, struct sge_rspq *q,
unsigned int us, unsigned int cnt,
unsigned int size, unsigned int iqe_size)
{
q->adap = adap;
cxgb4_set_rspq_intr_params(q, us, cnt);
q->iqe_len = iqe_size;
q->size = size;
}
/* /*
* Perform default configuration of DMA queues depending on the number and type * Perform default configuration of DMA queues depending on the number and type
* of ports we found and the number of available CPUs. Most settings can be * of ports we found and the number of available CPUs. Most settings can be
...@@ -4375,6 +4380,15 @@ static void cfg_queues(struct adapter *adap) ...@@ -4375,6 +4380,15 @@ static void cfg_queues(struct adapter *adap)
#endif #endif
int ciq_size; int ciq_size;
/* Reduce memory usage in kdump environment, disable all offload.
*/
if (is_kdump_kernel()) {
adap->params.offload = 0;
adap->params.crypto = 0;
} else if (adap->num_uld && uld_mem_alloc(adap)) {
adap->params.crypto = 0;
}
for_each_port(adap, i) for_each_port(adap, i)
n10g += is_x_10g_port(&adap2pinfo(adap, i)->link_cfg); n10g += is_x_10g_port(&adap2pinfo(adap, i)->link_cfg);
#ifdef CONFIG_CHELSIO_T4_DCB #ifdef CONFIG_CHELSIO_T4_DCB
...@@ -4405,11 +4419,6 @@ static void cfg_queues(struct adapter *adap) ...@@ -4405,11 +4419,6 @@ static void cfg_queues(struct adapter *adap)
if (q10g > netif_get_num_default_rss_queues()) if (q10g > netif_get_num_default_rss_queues())
q10g = netif_get_num_default_rss_queues(); q10g = netif_get_num_default_rss_queues();
/* Reduce memory usage in kdump environment, disable all offload.
*/
if (is_kdump_kernel())
adap->params.offload = 0;
for_each_port(adap, i) { for_each_port(adap, i) {
struct port_info *pi = adap2pinfo(adap, i); struct port_info *pi = adap2pinfo(adap, i);
...@@ -4538,23 +4547,58 @@ static void reduce_ethqs(struct adapter *adap, int n) ...@@ -4538,23 +4547,58 @@ static void reduce_ethqs(struct adapter *adap, int n)
} }
} }
static int get_msix_info(struct adapter *adap)
{
struct uld_msix_info *msix_info;
int max_ingq = (MAX_OFLD_QSETS * adap->num_uld);
msix_info = kcalloc(max_ingq, sizeof(*msix_info), GFP_KERNEL);
if (!msix_info)
return -ENOMEM;
adap->msix_bmap_ulds.msix_bmap = kcalloc(BITS_TO_LONGS(max_ingq),
sizeof(long), GFP_KERNEL);
if (!adap->msix_bmap_ulds.msix_bmap) {
kfree(msix_info);
return -ENOMEM;
}
spin_lock_init(&adap->msix_bmap_ulds.lock);
adap->msix_info_ulds = msix_info;
return 0;
}
static void free_msix_info(struct adapter *adap)
{
if (!adap->num_uld)
return;
kfree(adap->msix_info_ulds);
kfree(adap->msix_bmap_ulds.msix_bmap);
}
/* 2 MSI-X vectors needed for the FW queue and non-data interrupts */ /* 2 MSI-X vectors needed for the FW queue and non-data interrupts */
#define EXTRA_VECS 2 #define EXTRA_VECS 2
static int enable_msix(struct adapter *adap) static int enable_msix(struct adapter *adap)
{ {
int ofld_need = 0; int ofld_need = 0, uld_need = 0;
int i, want, need, allocated; int i, j, want, need, allocated;
struct sge *s = &adap->sge; struct sge *s = &adap->sge;
unsigned int nchan = adap->params.nports; unsigned int nchan = adap->params.nports;
struct msix_entry *entries; struct msix_entry *entries;
int max_ingq = MAX_INGQ;
entries = kmalloc(sizeof(*entries) * (MAX_INGQ + 1), max_ingq += (MAX_OFLD_QSETS * adap->num_uld);
entries = kmalloc(sizeof(*entries) * (max_ingq + 1),
GFP_KERNEL); GFP_KERNEL);
if (!entries) if (!entries)
return -ENOMEM; return -ENOMEM;
for (i = 0; i < MAX_INGQ + 1; ++i) /* map for msix */
if (is_pci_uld(adap) && get_msix_info(adap))
adap->params.crypto = 0;
for (i = 0; i < max_ingq + 1; ++i)
entries[i].entry = i; entries[i].entry = i;
want = s->max_ethqsets + EXTRA_VECS; want = s->max_ethqsets + EXTRA_VECS;
...@@ -4567,13 +4611,17 @@ static int enable_msix(struct adapter *adap) ...@@ -4567,13 +4611,17 @@ static int enable_msix(struct adapter *adap)
else else
ofld_need = 4 * nchan; ofld_need = 4 * nchan;
} }
if (is_pci_uld(adap)) {
want += netif_get_num_default_rss_queues() * nchan;
uld_need = nchan;
}
#ifdef CONFIG_CHELSIO_T4_DCB #ifdef CONFIG_CHELSIO_T4_DCB
/* For Data Center Bridging we need 8 Ethernet TX Priority Queues for /* For Data Center Bridging we need 8 Ethernet TX Priority Queues for
* each port. * each port.
*/ */
need = 8 * adap->params.nports + EXTRA_VECS + ofld_need; need = 8 * adap->params.nports + EXTRA_VECS + ofld_need + uld_need;
#else #else
need = adap->params.nports + EXTRA_VECS + ofld_need; need = adap->params.nports + EXTRA_VECS + ofld_need + uld_need;
#endif #endif
allocated = pci_enable_msix_range(adap->pdev, entries, need, want); allocated = pci_enable_msix_range(adap->pdev, entries, need, want);
if (allocated < 0) { if (allocated < 0) {
...@@ -4587,12 +4635,20 @@ static int enable_msix(struct adapter *adap) ...@@ -4587,12 +4635,20 @@ static int enable_msix(struct adapter *adap)
* Every group gets its minimum requirement and NIC gets top * Every group gets its minimum requirement and NIC gets top
* priority for leftovers. * priority for leftovers.
*/ */
i = allocated - EXTRA_VECS - ofld_need; i = allocated - EXTRA_VECS - ofld_need - uld_need;
if (i < s->max_ethqsets) { if (i < s->max_ethqsets) {
s->max_ethqsets = i; s->max_ethqsets = i;
if (i < s->ethqsets) if (i < s->ethqsets)
reduce_ethqs(adap, i); reduce_ethqs(adap, i);
} }
if (is_pci_uld(adap)) {
if (allocated < want)
s->nqs_per_uld = nchan;
else
s->nqs_per_uld = netif_get_num_default_rss_queues() *
nchan;
}
if (is_offload(adap)) { if (is_offload(adap)) {
if (allocated < want) { if (allocated < want) {
s->rdmaqs = nchan; s->rdmaqs = nchan;
...@@ -4605,15 +4661,23 @@ static int enable_msix(struct adapter *adap) ...@@ -4605,15 +4661,23 @@ static int enable_msix(struct adapter *adap)
/* leftovers go to OFLD */ /* leftovers go to OFLD */
i = allocated - EXTRA_VECS - s->max_ethqsets - i = allocated - EXTRA_VECS - s->max_ethqsets -
s->rdmaqs - s->rdmaciqs - s->niscsitq; s->rdmaqs - s->rdmaciqs - s->niscsitq;
if (is_pci_uld(adap))
i -= s->nqs_per_uld * adap->num_uld;
s->iscsiqsets = (i / nchan) * nchan; /* round down */ s->iscsiqsets = (i / nchan) * nchan; /* round down */
} }
for (i = 0; i < allocated; ++i)
for (i = 0; i < (allocated - (s->nqs_per_uld * adap->num_uld)); ++i)
adap->msix_info[i].vec = entries[i].vector; adap->msix_info[i].vec = entries[i].vector;
if (is_pci_uld(adap)) {
for (j = 0 ; i < allocated; ++i, j++)
adap->msix_info_ulds[j].vec = entries[i].vector;
adap->msix_bmap_ulds.mapsize = j;
}
dev_info(adap->pdev_dev, "%d MSI-X vectors allocated, " dev_info(adap->pdev_dev, "%d MSI-X vectors allocated, "
"nic %d iscsi %d rdma cpl %d rdma ciq %d\n", "nic %d iscsi %d rdma cpl %d rdma ciq %d uld %d\n",
allocated, s->max_ethqsets, s->iscsiqsets, s->rdmaqs, allocated, s->max_ethqsets, s->iscsiqsets, s->rdmaqs,
s->rdmaciqs); s->rdmaciqs, s->nqs_per_uld);
kfree(entries); kfree(entries);
return 0; return 0;
...@@ -5215,8 +5279,11 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -5215,8 +5279,11 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
/* See what interrupts we'll be using */ /* See what interrupts we'll be using */
if (msi > 1 && enable_msix(adapter) == 0) if (msi > 1 && enable_msix(adapter) == 0)
adapter->flags |= USING_MSIX; adapter->flags |= USING_MSIX;
else if (msi > 0 && pci_enable_msi(pdev) == 0) else if (msi > 0 && pci_enable_msi(pdev) == 0) {
adapter->flags |= USING_MSI; adapter->flags |= USING_MSI;
if (msi > 1)
free_msix_info(adapter);
}
/* check for PCI Express bandwidth capabiltites */ /* check for PCI Express bandwidth capabiltites */
cxgb4_check_pcie_caps(adapter); cxgb4_check_pcie_caps(adapter);
...@@ -5332,6 +5399,10 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -5332,6 +5399,10 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
out_free_dev: out_free_dev:
free_some_resources(adapter); free_some_resources(adapter);
if (adapter->flags & USING_MSIX)
free_msix_info(adapter);
if (adapter->num_uld)
uld_mem_free(adapter);
out_unmap_bar: out_unmap_bar:
if (!is_t4(adapter->params.chip)) if (!is_t4(adapter->params.chip))
iounmap(adapter->bar2); iounmap(adapter->bar2);
...@@ -5393,6 +5464,10 @@ static void remove_one(struct pci_dev *pdev) ...@@ -5393,6 +5464,10 @@ static void remove_one(struct pci_dev *pdev)
if (adapter->flags & FULL_INIT_DONE) if (adapter->flags & FULL_INIT_DONE)
cxgb_down(adapter); cxgb_down(adapter);
if (adapter->flags & USING_MSIX)
free_msix_info(adapter);
if (adapter->num_uld)
uld_mem_free(adapter);
free_some_resources(adapter); free_some_resources(adapter);
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
t4_cleanup_clip_tbl(adapter); t4_cleanup_clip_tbl(adapter);
......
This diff is collapsed.
...@@ -32,8 +32,8 @@ ...@@ -32,8 +32,8 @@
* SOFTWARE. * SOFTWARE.
*/ */
#ifndef __CXGB4_OFLD_H #ifndef __CXGB4_ULD_H
#define __CXGB4_OFLD_H #define __CXGB4_ULD_H
#include <linux/cache.h> #include <linux/cache.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
...@@ -296,8 +296,36 @@ struct cxgb4_uld_info { ...@@ -296,8 +296,36 @@ struct cxgb4_uld_info {
void (*lro_flush)(struct t4_lro_mgr *); void (*lro_flush)(struct t4_lro_mgr *);
}; };
enum cxgb4_pci_uld {
CXGB4_PCI_ULD1,
CXGB4_PCI_ULD_MAX
};
struct cxgb4_pci_uld_info {
const char *name;
bool lro;
void *handle;
unsigned int nrxq;
unsigned int nciq;
unsigned int rxq_size;
unsigned int ciq_size;
void *(*add)(const struct cxgb4_lld_info *p);
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 (*lro_rx_handler)(void *handle, const __be64 *rsp,
const struct pkt_gl *gl,
struct t4_lro_mgr *lro_mgr,
struct napi_struct *napi);
void (*lro_flush)(struct t4_lro_mgr *);
};
int cxgb4_register_uld(enum cxgb4_uld type, const struct cxgb4_uld_info *p); int cxgb4_register_uld(enum cxgb4_uld type, const struct cxgb4_uld_info *p);
int cxgb4_unregister_uld(enum cxgb4_uld type); int cxgb4_unregister_uld(enum cxgb4_uld type);
int cxgb4_register_pci_uld(enum cxgb4_pci_uld type,
struct cxgb4_pci_uld_info *p);
int cxgb4_unregister_pci_uld(enum cxgb4_pci_uld type);
int cxgb4_ofld_send(struct net_device *dev, struct sk_buff *skb); 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_dbfifo_count(const struct net_device *dev, int lpfifo);
unsigned int cxgb4_port_chan(const struct net_device *dev); unsigned int cxgb4_port_chan(const struct net_device *dev);
...@@ -330,4 +358,4 @@ int cxgb4_bar2_sge_qregs(struct net_device *dev, ...@@ -330,4 +358,4 @@ int cxgb4_bar2_sge_qregs(struct net_device *dev,
u64 *pbar2_qoffset, u64 *pbar2_qoffset,
unsigned int *pbar2_qid); unsigned int *pbar2_qid);
#endif /* !__CXGB4_OFLD_H */ #endif /* !__CXGB4_ULD_H */
...@@ -2928,7 +2928,7 @@ static void free_txq(struct adapter *adap, struct sge_txq *q) ...@@ -2928,7 +2928,7 @@ static void free_txq(struct adapter *adap, struct sge_txq *q)
q->desc = NULL; q->desc = NULL;
} }
static void free_rspq_fl(struct adapter *adap, struct sge_rspq *rq, void free_rspq_fl(struct adapter *adap, struct sge_rspq *rq,
struct sge_fl *fl) struct sge_fl *fl)
{ {
struct sge *s = &adap->sge; struct sge *s = &adap->sge;
......
This diff is collapsed.
...@@ -102,6 +102,7 @@ enum fw_wr_opcodes { ...@@ -102,6 +102,7 @@ enum fw_wr_opcodes {
FW_RI_FR_NSMR_WR = 0x19, FW_RI_FR_NSMR_WR = 0x19,
FW_RI_INV_LSTAG_WR = 0x1a, FW_RI_INV_LSTAG_WR = 0x1a,
FW_ISCSI_TX_DATA_WR = 0x45, FW_ISCSI_TX_DATA_WR = 0x45,
FW_CRYPTO_LOOKASIDE_WR = 0X6d,
FW_LASTC2E_WR = 0x70 FW_LASTC2E_WR = 0x70
}; };
...@@ -1060,7 +1061,7 @@ struct fw_caps_config_cmd { ...@@ -1060,7 +1061,7 @@ struct fw_caps_config_cmd {
__be16 niccaps; __be16 niccaps;
__be16 ofldcaps; __be16 ofldcaps;
__be16 rdmacaps; __be16 rdmacaps;
__be16 r4; __be16 cryptocaps;
__be16 iscsicaps; __be16 iscsicaps;
__be16 fcoecaps; __be16 fcoecaps;
__be32 cfcsum; __be32 cfcsum;
...@@ -3249,4 +3250,127 @@ struct fw_devlog_cmd { ...@@ -3249,4 +3250,127 @@ struct fw_devlog_cmd {
#define PCIE_FW_PF_DEVLOG_MEMTYPE_G(x) \ #define PCIE_FW_PF_DEVLOG_MEMTYPE_G(x) \
(((x) >> PCIE_FW_PF_DEVLOG_MEMTYPE_S) & PCIE_FW_PF_DEVLOG_MEMTYPE_M) (((x) >> PCIE_FW_PF_DEVLOG_MEMTYPE_S) & PCIE_FW_PF_DEVLOG_MEMTYPE_M)
#define MAX_IMM_OFLD_TX_DATA_WR_LEN (0xff + sizeof(struct fw_ofld_tx_data_wr))
struct fw_crypto_lookaside_wr {
__be32 op_to_cctx_size;
__be32 len16_pkd;
__be32 session_id;
__be32 rx_chid_to_rx_q_id;
__be32 key_addr;
__be32 pld_size_hash_size;
__be64 cookie;
};
#define FW_CRYPTO_LOOKASIDE_WR_OPCODE_S 24
#define FW_CRYPTO_LOOKASIDE_WR_OPCODE_M 0xff
#define FW_CRYPTO_LOOKASIDE_WR_OPCODE_V(x) \
((x) << FW_CRYPTO_LOOKASIDE_WR_OPCODE_S)
#define FW_CRYPTO_LOOKASIDE_WR_OPCODE_G(x) \
(((x) >> FW_CRYPTO_LOOKASIDE_WR_OPCODE_S) & \
FW_CRYPTO_LOOKASIDE_WR_OPCODE_M)
#define FW_CRYPTO_LOOKASIDE_WR_COMPL_S 23
#define FW_CRYPTO_LOOKASIDE_WR_COMPL_M 0x1
#define FW_CRYPTO_LOOKASIDE_WR_COMPL_V(x) \
((x) << FW_CRYPTO_LOOKASIDE_WR_COMPL_S)
#define FW_CRYPTO_LOOKASIDE_WR_COMPL_G(x) \
(((x) >> FW_CRYPTO_LOOKASIDE_WR_COMPL_S) & \
FW_CRYPTO_LOOKASIDE_WR_COMPL_M)
#define FW_CRYPTO_LOOKASIDE_WR_COMPL_F FW_CRYPTO_LOOKASIDE_WR_COMPL_V(1U)
#define FW_CRYPTO_LOOKASIDE_WR_IMM_LEN_S 15
#define FW_CRYPTO_LOOKASIDE_WR_IMM_LEN_M 0xff
#define FW_CRYPTO_LOOKASIDE_WR_IMM_LEN_V(x) \
((x) << FW_CRYPTO_LOOKASIDE_WR_IMM_LEN_S)
#define FW_CRYPTO_LOOKASIDE_WR_IMM_LEN_G(x) \
(((x) >> FW_CRYPTO_LOOKASIDE_WR_IMM_LEN_S) & \
FW_CRYPTO_LOOKASIDE_WR_IMM_LEN_M)
#define FW_CRYPTO_LOOKASIDE_WR_CCTX_LOC_S 5
#define FW_CRYPTO_LOOKASIDE_WR_CCTX_LOC_M 0x3
#define FW_CRYPTO_LOOKASIDE_WR_CCTX_LOC_V(x) \
((x) << FW_CRYPTO_LOOKASIDE_WR_CCTX_LOC_S)
#define FW_CRYPTO_LOOKASIDE_WR_CCTX_LOC_G(x) \
(((x) >> FW_CRYPTO_LOOKASIDE_WR_CCTX_LOC_S) & \
FW_CRYPTO_LOOKASIDE_WR_CCTX_LOC_M)
#define FW_CRYPTO_LOOKASIDE_WR_CCTX_SIZE_S 0
#define FW_CRYPTO_LOOKASIDE_WR_CCTX_SIZE_M 0x1f
#define FW_CRYPTO_LOOKASIDE_WR_CCTX_SIZE_V(x) \
((x) << FW_CRYPTO_LOOKASIDE_WR_CCTX_SIZE_S)
#define FW_CRYPTO_LOOKASIDE_WR_CCTX_SIZE_G(x) \
(((x) >> FW_CRYPTO_LOOKASIDE_WR_CCTX_SIZE_S) & \
FW_CRYPTO_LOOKASIDE_WR_CCTX_SIZE_M)
#define FW_CRYPTO_LOOKASIDE_WR_LEN16_S 0
#define FW_CRYPTO_LOOKASIDE_WR_LEN16_M 0xff
#define FW_CRYPTO_LOOKASIDE_WR_LEN16_V(x) \
((x) << FW_CRYPTO_LOOKASIDE_WR_LEN16_S)
#define FW_CRYPTO_LOOKASIDE_WR_LEN16_G(x) \
(((x) >> FW_CRYPTO_LOOKASIDE_WR_LEN16_S) & \
FW_CRYPTO_LOOKASIDE_WR_LEN16_M)
#define FW_CRYPTO_LOOKASIDE_WR_RX_CHID_S 29
#define FW_CRYPTO_LOOKASIDE_WR_RX_CHID_M 0x3
#define FW_CRYPTO_LOOKASIDE_WR_RX_CHID_V(x) \
((x) << FW_CRYPTO_LOOKASIDE_WR_RX_CHID_S)
#define FW_CRYPTO_LOOKASIDE_WR_RX_CHID_G(x) \
(((x) >> FW_CRYPTO_LOOKASIDE_WR_RX_CHID_S) & \
FW_CRYPTO_LOOKASIDE_WR_RX_CHID_M)
#define FW_CRYPTO_LOOKASIDE_WR_LCB_S 27
#define FW_CRYPTO_LOOKASIDE_WR_LCB_M 0x3
#define FW_CRYPTO_LOOKASIDE_WR_LCB_V(x) \
((x) << FW_CRYPTO_LOOKASIDE_WR_LCB_S)
#define FW_CRYPTO_LOOKASIDE_WR_LCB_G(x) \
(((x) >> FW_CRYPTO_LOOKASIDE_WR_LCB_S) & FW_CRYPTO_LOOKASIDE_WR_LCB_M)
#define FW_CRYPTO_LOOKASIDE_WR_PHASH_S 25
#define FW_CRYPTO_LOOKASIDE_WR_PHASH_M 0x3
#define FW_CRYPTO_LOOKASIDE_WR_PHASH_V(x) \
((x) << FW_CRYPTO_LOOKASIDE_WR_PHASH_S)
#define FW_CRYPTO_LOOKASIDE_WR_PHASH_G(x) \
(((x) >> FW_CRYPTO_LOOKASIDE_WR_PHASH_S) & \
FW_CRYPTO_LOOKASIDE_WR_PHASH_M)
#define FW_CRYPTO_LOOKASIDE_WR_IV_S 23
#define FW_CRYPTO_LOOKASIDE_WR_IV_M 0x3
#define FW_CRYPTO_LOOKASIDE_WR_IV_V(x) \
((x) << FW_CRYPTO_LOOKASIDE_WR_IV_S)
#define FW_CRYPTO_LOOKASIDE_WR_IV_G(x) \
(((x) >> FW_CRYPTO_LOOKASIDE_WR_IV_S) & FW_CRYPTO_LOOKASIDE_WR_IV_M)
#define FW_CRYPTO_LOOKASIDE_WR_TX_CH_S 10
#define FW_CRYPTO_LOOKASIDE_WR_TX_CH_M 0x3
#define FW_CRYPTO_LOOKASIDE_WR_TX_CH_V(x) \
((x) << FW_CRYPTO_LOOKASIDE_WR_TX_CH_S)
#define FW_CRYPTO_LOOKASIDE_WR_TX_CH_G(x) \
(((x) >> FW_CRYPTO_LOOKASIDE_WR_TX_CH_S) & \
FW_CRYPTO_LOOKASIDE_WR_TX_CH_M)
#define FW_CRYPTO_LOOKASIDE_WR_RX_Q_ID_S 0
#define FW_CRYPTO_LOOKASIDE_WR_RX_Q_ID_M 0x3ff
#define FW_CRYPTO_LOOKASIDE_WR_RX_Q_ID_V(x) \
((x) << FW_CRYPTO_LOOKASIDE_WR_RX_Q_ID_S)
#define FW_CRYPTO_LOOKASIDE_WR_RX_Q_ID_G(x) \
(((x) >> FW_CRYPTO_LOOKASIDE_WR_RX_Q_ID_S) & \
FW_CRYPTO_LOOKASIDE_WR_RX_Q_ID_M)
#define FW_CRYPTO_LOOKASIDE_WR_PLD_SIZE_S 24
#define FW_CRYPTO_LOOKASIDE_WR_PLD_SIZE_M 0xff
#define FW_CRYPTO_LOOKASIDE_WR_PLD_SIZE_V(x) \
((x) << FW_CRYPTO_LOOKASIDE_WR_PLD_SIZE_S)
#define FW_CRYPTO_LOOKASIDE_WR_PLD_SIZE_G(x) \
(((x) >> FW_CRYPTO_LOOKASIDE_WR_PLD_SIZE_S) & \
FW_CRYPTO_LOOKASIDE_WR_PLD_SIZE_M)
#define FW_CRYPTO_LOOKASIDE_WR_HASH_SIZE_S 17
#define FW_CRYPTO_LOOKASIDE_WR_HASH_SIZE_M 0x7f
#define FW_CRYPTO_LOOKASIDE_WR_HASH_SIZE_V(x) \
((x) << FW_CRYPTO_LOOKASIDE_WR_HASH_SIZE_S)
#define FW_CRYPTO_LOOKASIDE_WR_HASH_SIZE_G(x) \
(((x) >> FW_CRYPTO_LOOKASIDE_WR_HASH_SIZE_S) & \
FW_CRYPTO_LOOKASIDE_WR_HASH_SIZE_M)
#endif /* _T4FW_INTERFACE_H_ */ #endif /* _T4FW_INTERFACE_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment