Skip to content

Commit

Permalink
qed: Add support for RoCE hw init
Browse files Browse the repository at this point in the history
This adds the backbone required for the various HW initalizations
which are necessary for the qedr driver - FW notification, resource
initializations, etc.

Signed-off-by: Ram Amrani <Ram.Amrani@caviumnetworks.com>
Signed-off-by: Yuval Mintz <Yuval.Mintz@caviumnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Ram Amrani authored and David S. Miller committed Oct 4, 2016
1 parent cee9fbd commit 51ff172
Show file tree
Hide file tree
Showing 17 changed files with 1,620 additions and 8 deletions.
1 change: 1 addition & 0 deletions drivers/net/ethernet/qlogic/qed/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ qed-y := qed_cxt.o qed_dev.o qed_hw.o qed_init_fw_funcs.o qed_init_ops.o \
qed_selftest.o qed_dcbx.o qed_debug.o
qed-$(CONFIG_QED_SRIOV) += qed_sriov.o qed_vf.o
qed-$(CONFIG_QED_LL2) += qed_ll2.o
qed-$(CONFIG_INFINIBAND_QEDR) += qed_roce.o
33 changes: 32 additions & 1 deletion drivers/net/ethernet/qlogic/qed/qed.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ extern const struct qed_common_ops qed_common_ops_pass;

#define QED_WFQ_UNIT 100

#define QED_WID_SIZE (1024)
#define QED_PF_DEMS_SIZE (4)

/* cau states */
enum qed_coalescing_mode {
QED_COAL_MODE_DISABLE,
Expand All @@ -48,6 +51,14 @@ enum qed_mcp_protocol_type;

/* helpers */
static inline u32 qed_db_addr(u32 cid, u32 DEMS)
{
u32 db_addr = FIELD_VALUE(DB_LEGACY_ADDR_DEMS, DEMS) |
(cid * QED_PF_DEMS_SIZE);

return db_addr;
}

static inline u32 qed_db_addr_vf(u32 cid, u32 DEMS)
{
u32 db_addr = FIELD_VALUE(DB_LEGACY_ADDR_DEMS, DEMS) |
FIELD_VALUE(DB_LEGACY_ADDR_ICID, cid);
Expand Down Expand Up @@ -152,14 +163,17 @@ enum QED_RESOURCES {
QED_RL,
QED_MAC,
QED_VLAN,
QED_RDMA_CNQ_RAM,
QED_ILT,
QED_LL2_QUEUE,
QED_RDMA_STATS_QUEUE,
QED_MAX_RESC,
};

enum QED_FEATURE {
QED_PF_L2_QUE,
QED_VF,
QED_RDMA_CNQ,
QED_MAX_FEATURES,
};

Expand Down Expand Up @@ -364,6 +378,7 @@ struct qed_hwfn {
/* Protocol related */
bool using_ll2;
struct qed_ll2_info *p_ll2_info;
struct qed_rdma_info *p_rdma_info;
struct qed_pf_params pf_params;

bool b_rdma_enabled_in_prs;
Expand Down Expand Up @@ -402,6 +417,17 @@ struct qed_hwfn {

struct dbg_tools_data dbg_info;

/* PWM region specific data */
u32 dpi_size;
u32 dpi_count;

/* This is used to calculate the doorbell address */
u32 dpi_start_offset;

/* If one of the following is set then EDPM shouldn't be used */
u8 dcbx_no_edpm;
u8 db_bar_no_edpm;

struct qed_simd_fp_handler simd_proto_handler[64];

#ifdef CONFIG_QED_SRIOV
Expand Down Expand Up @@ -435,6 +461,8 @@ struct qed_int_params {
bool fp_initialized;
u8 fp_msix_base;
u8 fp_msix_cnt;
u8 rdma_msix_base;
u8 rdma_msix_cnt;
};

struct qed_dbg_feature {
Expand Down Expand Up @@ -541,7 +569,6 @@ struct qed_dev {

bool b_is_vf;
u32 drv_type;

struct qed_eth_stats *reset_stats;
struct qed_fw_data *fw_data;

Expand Down Expand Up @@ -574,6 +601,10 @@ struct qed_dev {
#endif

const struct firmware *firmware;

u32 rdma_max_sge;
u32 rdma_max_inline;
u32 rdma_max_srq_sge;
};

#define NUM_OF_VFS(dev) MAX_NUM_VFS_BB
Expand Down
6 changes: 6 additions & 0 deletions drivers/net/ethernet/qlogic/qed/qed_cxt.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,13 @@
#define TM_ELEM_SIZE 4

/* ILT constants */
#if IS_ENABLED(CONFIG_INFINIBAND_QEDR)
/* For RoCE we configure to 64K to cover for RoCE max tasks 256K purpose. */
#define ILT_DEFAULT_HW_P_SIZE 4
#else
#define ILT_DEFAULT_HW_P_SIZE 3
#endif

#define ILT_PAGE_IN_BYTES(hw_p_size) (1U << ((hw_p_size) + 12))
#define ILT_CFG_REG(cli, reg) PSWRQ2_REG_ ## cli ## _ ## reg ## _RT_OFFSET

Expand Down
6 changes: 6 additions & 0 deletions drivers/net/ethernet/qlogic/qed/qed_cxt.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,12 @@ int qed_qm_reconf(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt);
*/
void qed_cxt_release_cid(struct qed_hwfn *p_hwfn,
u32 cid);
int qed_cxt_dynamic_ilt_alloc(struct qed_hwfn *p_hwfn,
enum qed_cxt_elem_type elem_type, u32 iid);
u32 qed_cxt_get_proto_tid_count(struct qed_hwfn *p_hwfn,
enum protocol_type type);
u32 qed_cxt_get_proto_cid_start(struct qed_hwfn *p_hwfn,
enum protocol_type type);

#define QED_CTX_WORKING_MEM 0
#define QED_CTX_FL_MEM 1
Expand Down
154 changes: 154 additions & 0 deletions drivers/net/ethernet/qlogic/qed/qed_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,13 @@
#include "qed_sp.h"
#include "qed_sriov.h"
#include "qed_vf.h"
#include "qed_roce.h"

static DEFINE_SPINLOCK(qm_lock);

#define QED_MIN_DPIS (4)
#define QED_MIN_PWM_REGION (QED_WID_SIZE * QED_MIN_DPIS)

/* API common to all protocols */
enum BAR_ID {
BAR_ID_0, /* used for GRC */
Expand Down Expand Up @@ -787,6 +791,136 @@ static int qed_hw_init_common(struct qed_hwfn *p_hwfn,
return rc;
}

static int
qed_hw_init_dpi_size(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt, u32 pwm_region_size, u32 n_cpus)
{
u32 dpi_page_size_1, dpi_page_size_2, dpi_page_size;
u32 dpi_bit_shift, dpi_count;
u32 min_dpis;

/* Calculate DPI size */
dpi_page_size_1 = QED_WID_SIZE * n_cpus;
dpi_page_size_2 = max_t(u32, QED_WID_SIZE, PAGE_SIZE);
dpi_page_size = max_t(u32, dpi_page_size_1, dpi_page_size_2);
dpi_page_size = roundup_pow_of_two(dpi_page_size);
dpi_bit_shift = ilog2(dpi_page_size / 4096);

dpi_count = pwm_region_size / dpi_page_size;

min_dpis = p_hwfn->pf_params.rdma_pf_params.min_dpis;
min_dpis = max_t(u32, QED_MIN_DPIS, min_dpis);

p_hwfn->dpi_size = dpi_page_size;
p_hwfn->dpi_count = dpi_count;

qed_wr(p_hwfn, p_ptt, DORQ_REG_PF_DPI_BIT_SHIFT, dpi_bit_shift);

if (dpi_count < min_dpis)
return -EINVAL;

return 0;
}

enum QED_ROCE_EDPM_MODE {
QED_ROCE_EDPM_MODE_ENABLE = 0,
QED_ROCE_EDPM_MODE_FORCE_ON = 1,
QED_ROCE_EDPM_MODE_DISABLE = 2,
};

static int
qed_hw_init_pf_doorbell_bar(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
{
u32 pwm_regsize, norm_regsize;
u32 non_pwm_conn, min_addr_reg1;
u32 db_bar_size, n_cpus;
u32 roce_edpm_mode;
u32 pf_dems_shift;
int rc = 0;
u8 cond;

db_bar_size = qed_hw_bar_size(p_hwfn, BAR_ID_1);
if (p_hwfn->cdev->num_hwfns > 1)
db_bar_size /= 2;

/* Calculate doorbell regions */
non_pwm_conn = qed_cxt_get_proto_cid_start(p_hwfn, PROTOCOLID_CORE) +
qed_cxt_get_proto_cid_count(p_hwfn, PROTOCOLID_CORE,
NULL) +
qed_cxt_get_proto_cid_count(p_hwfn, PROTOCOLID_ETH,
NULL);
norm_regsize = roundup(QED_PF_DEMS_SIZE * non_pwm_conn, 4096);
min_addr_reg1 = norm_regsize / 4096;
pwm_regsize = db_bar_size - norm_regsize;

/* Check that the normal and PWM sizes are valid */
if (db_bar_size < norm_regsize) {
DP_ERR(p_hwfn->cdev,
"Doorbell BAR size 0x%x is too small (normal region is 0x%0x )\n",
db_bar_size, norm_regsize);
return -EINVAL;
}

if (pwm_regsize < QED_MIN_PWM_REGION) {
DP_ERR(p_hwfn->cdev,
"PWM region size 0x%0x is too small. Should be at least 0x%0x (Doorbell BAR size is 0x%x and normal region size is 0x%0x)\n",
pwm_regsize,
QED_MIN_PWM_REGION, db_bar_size, norm_regsize);
return -EINVAL;
}

/* Calculate number of DPIs */
roce_edpm_mode = p_hwfn->pf_params.rdma_pf_params.roce_edpm_mode;
if ((roce_edpm_mode == QED_ROCE_EDPM_MODE_ENABLE) ||
((roce_edpm_mode == QED_ROCE_EDPM_MODE_FORCE_ON))) {
/* Either EDPM is mandatory, or we are attempting to allocate a
* WID per CPU.
*/
n_cpus = num_active_cpus();
rc = qed_hw_init_dpi_size(p_hwfn, p_ptt, pwm_regsize, n_cpus);
}

cond = (rc && (roce_edpm_mode == QED_ROCE_EDPM_MODE_ENABLE)) ||
(roce_edpm_mode == QED_ROCE_EDPM_MODE_DISABLE);
if (cond || p_hwfn->dcbx_no_edpm) {
/* Either EDPM is disabled from user configuration, or it is
* disabled via DCBx, or it is not mandatory and we failed to
* allocated a WID per CPU.
*/
n_cpus = 1;
rc = qed_hw_init_dpi_size(p_hwfn, p_ptt, pwm_regsize, n_cpus);

if (cond)
qed_rdma_dpm_bar(p_hwfn, p_ptt);
}

DP_INFO(p_hwfn,
"doorbell bar: normal_region_size=%d, pwm_region_size=%d, dpi_size=%d, dpi_count=%d, roce_edpm=%s\n",
norm_regsize,
pwm_regsize,
p_hwfn->dpi_size,
p_hwfn->dpi_count,
((p_hwfn->dcbx_no_edpm) || (p_hwfn->db_bar_no_edpm)) ?
"disabled" : "enabled");

if (rc) {
DP_ERR(p_hwfn,
"Failed to allocate enough DPIs. Allocated %d but the current minimum is %d.\n",
p_hwfn->dpi_count,
p_hwfn->pf_params.rdma_pf_params.min_dpis);
return -EINVAL;
}

p_hwfn->dpi_start_offset = norm_regsize;

/* DEMS size is configured log2 of DWORDs, hence the division by 4 */
pf_dems_shift = ilog2(QED_PF_DEMS_SIZE / 4);
qed_wr(p_hwfn, p_ptt, DORQ_REG_PF_ICID_BIT_SHIFT_NORM, pf_dems_shift);
qed_wr(p_hwfn, p_ptt, DORQ_REG_PF_MIN_ADDR_REG1, min_addr_reg1);

return 0;
}

static int qed_hw_init_port(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt, int hw_mode)
{
Expand Down Expand Up @@ -860,6 +994,10 @@ static int qed_hw_init_pf(struct qed_hwfn *p_hwfn,
/* Pure runtime initializations - directly to the HW */
qed_int_igu_init_pure_rt(p_hwfn, p_ptt, true, true);

rc = qed_hw_init_pf_doorbell_bar(p_hwfn, p_ptt);
if (rc)
return rc;

if (b_hw_start) {
/* enable interrupts */
qed_int_igu_enable(p_hwfn, p_ptt, int_mode);
Expand Down Expand Up @@ -1284,6 +1422,19 @@ static void qed_hw_set_feat(struct qed_hwfn *p_hwfn)
u32 *feat_num = p_hwfn->hw_info.feat_num;
int num_features = 1;

#if IS_ENABLED(CONFIG_INFINIBAND_QEDR)
/* Roce CNQ each requires: 1 status block + 1 CNQ. We divide the
* status blocks equally between L2 / RoCE but with consideration as
* to how many l2 queues / cnqs we have
*/
if (p_hwfn->hw_info.personality == QED_PCI_ETH_ROCE) {
num_features++;

feat_num[QED_RDMA_CNQ] =
min_t(u32, RESC_NUM(p_hwfn, QED_SB) / num_features,
RESC_NUM(p_hwfn, QED_RDMA_CNQ_RAM));
}
#endif
feat_num[QED_PF_L2_QUE] = min_t(u32, RESC_NUM(p_hwfn, QED_SB) /
num_features,
RESC_NUM(p_hwfn, QED_L2_QUEUE));
Expand Down Expand Up @@ -1325,6 +1476,9 @@ static int qed_hw_get_resc(struct qed_hwfn *p_hwfn)
num_funcs;
resc_num[QED_ILT] = PXP_NUM_ILT_RECORDS_BB / num_funcs;
resc_num[QED_LL2_QUEUE] = MAX_NUM_LL2_RX_QUEUES / num_funcs;
resc_num[QED_RDMA_CNQ_RAM] = NUM_OF_CMDQS_CQS / num_funcs;
resc_num[QED_RDMA_STATS_QUEUE] = RDMA_NUM_STATISTIC_COUNTERS_BB /
num_funcs;

for (i = 0; i < QED_MAX_RESC; i++)
resc_start[i] = resc_num[i] * enabled_func_idx;
Expand Down
44 changes: 42 additions & 2 deletions drivers/net/ethernet/qlogic/qed/qed_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@
#include "qed_hw.h"
#include "qed_selftest.h"

#if IS_ENABLED(CONFIG_INFINIBAND_QEDR)
#define QED_ROCE_QPS (8192)
#define QED_ROCE_DPIS (8)
#endif

static char version[] =
"QLogic FastLinQ 4xxxx Core Module qed " DRV_MODULE_VERSION "\n";

Expand Down Expand Up @@ -206,8 +211,8 @@ int qed_fill_dev_info(struct qed_dev *cdev,
dev_info->pci_mem_start = cdev->pci_params.mem_start;
dev_info->pci_mem_end = cdev->pci_params.mem_end;
dev_info->pci_irq = cdev->pci_params.irq;
dev_info->rdma_supported =
(cdev->hwfns[0].hw_info.personality == QED_PCI_ETH_ROCE);
dev_info->rdma_supported = (cdev->hwfns[0].hw_info.personality ==
QED_PCI_ETH_ROCE);
dev_info->is_mf_default = IS_MF_DEFAULT(&cdev->hwfns[0]);
ether_addr_copy(dev_info->hw_mac, cdev->hwfns[0].hw_info.hw_mac_addr);

Expand Down Expand Up @@ -677,6 +682,9 @@ static int qed_slowpath_setup_int(struct qed_dev *cdev,
enum qed_int_mode int_mode)
{
struct qed_sb_cnt_info sb_cnt_info;
#if IS_ENABLED(CONFIG_INFINIBAND_QEDR)
int num_l2_queues;
#endif
int rc;
int i;

Expand Down Expand Up @@ -707,6 +715,31 @@ static int qed_slowpath_setup_int(struct qed_dev *cdev,
cdev->int_params.fp_msix_cnt = cdev->int_params.out.num_vectors -
cdev->num_hwfns;

#if IS_ENABLED(CONFIG_INFINIBAND_QEDR)
num_l2_queues = 0;
for_each_hwfn(cdev, i)
num_l2_queues += FEAT_NUM(&cdev->hwfns[i], QED_PF_L2_QUE);

DP_VERBOSE(cdev, QED_MSG_RDMA,
"cdev->int_params.fp_msix_cnt=%d num_l2_queues=%d\n",
cdev->int_params.fp_msix_cnt, num_l2_queues);

if (cdev->int_params.fp_msix_cnt > num_l2_queues) {
cdev->int_params.rdma_msix_cnt =
(cdev->int_params.fp_msix_cnt - num_l2_queues)
/ cdev->num_hwfns;
cdev->int_params.rdma_msix_base =
cdev->int_params.fp_msix_base + num_l2_queues;
cdev->int_params.fp_msix_cnt = num_l2_queues;
} else {
cdev->int_params.rdma_msix_cnt = 0;
}

DP_VERBOSE(cdev, QED_MSG_RDMA, "roce_msix_cnt=%d roce_msix_base=%d\n",
cdev->int_params.rdma_msix_cnt,
cdev->int_params.rdma_msix_base);
#endif

return 0;
}

Expand Down Expand Up @@ -810,6 +843,13 @@ static void qed_update_pf_params(struct qed_dev *cdev,
{
int i;

#if IS_ENABLED(CONFIG_INFINIBAND_QEDR)
params->rdma_pf_params.num_qps = QED_ROCE_QPS;
params->rdma_pf_params.min_dpis = QED_ROCE_DPIS;
/* divide by 3 the MRs to avoid MF ILT overflow */
params->rdma_pf_params.num_mrs = RDMA_MAX_TIDS;
params->rdma_pf_params.gl_pi = QED_ROCE_PROTOCOL_INDEX;
#endif
for (i = 0; i < cdev->num_hwfns; i++) {
struct qed_hwfn *p_hwfn = &cdev->hwfns[i];

Expand Down
Loading

0 comments on commit 51ff172

Please sign in to comment.