Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1e128c81 authored by Arun Easi's avatar Arun Easi Committed by David S. Miller
Browse files

qed: Add support for hardware offloaded FCoE.



This adds the backbone required for the various HW initalizations
which are necessary for the FCoE driver (qedf) for QLogic FastLinQ
4xxxx line of adapters - FW notification, resource initializations, etc.

Signed-off-by: default avatarArun Easi <arun.easi@cavium.com>
Signed-off-by: default avatarYuval Mintz <yuval.mintz@cavium.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f787d1de
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -114,4 +114,7 @@ config QED_RDMA
config QED_ISCSI
	bool

config QED_FCOE
	bool

endif # NET_VENDOR_QLOGIC
+1 −0
Original line number Diff line number Diff line
@@ -7,3 +7,4 @@ qed-$(CONFIG_QED_SRIOV) += qed_sriov.o qed_vf.o
qed-$(CONFIG_QED_LL2) += qed_ll2.o
qed-$(CONFIG_QED_RDMA) += qed_roce.o
qed-$(CONFIG_QED_ISCSI) += qed_iscsi.o qed_ooo.o
qed-$(CONFIG_QED_FCOE) += qed_fcoe.o
+11 −0
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ extern const struct qed_common_ops qed_common_ops_pass;
#define QED_WFQ_UNIT	100

#define ISCSI_BDQ_ID(_port_id) (_port_id)
#define FCOE_BDQ_ID(_port_id) ((_port_id) + 2)
#define QED_WID_SIZE            (1024)
#define QED_PF_DEMS_SIZE        (4)

@@ -167,6 +168,7 @@ struct qed_tunn_update_params {
 */
enum qed_pci_personality {
	QED_PCI_ETH,
	QED_PCI_FCOE,
	QED_PCI_ISCSI,
	QED_PCI_ETH_ROCE,
	QED_PCI_DEFAULT /* default in shmem */
@@ -204,6 +206,7 @@ enum QED_FEATURE {
	QED_VF,
	QED_RDMA_CNQ,
	QED_VF_L2_QUE,
	QED_FCOE_CQ,
	QED_MAX_FEATURES,
};

@@ -221,6 +224,7 @@ enum QED_PORT_MODE {

enum qed_dev_cap {
	QED_DEV_CAP_ETH,
	QED_DEV_CAP_FCOE,
	QED_DEV_CAP_ISCSI,
	QED_DEV_CAP_ROCE,
};
@@ -255,6 +259,10 @@ struct qed_hw_info {
	u32				part_num[4];

	unsigned char			hw_mac_addr[ETH_ALEN];
	u64				node_wwn;
	u64				port_wwn;

	u16				num_fcoe_conns;

	struct qed_igu_info		*p_igu_info;

@@ -410,6 +418,7 @@ struct qed_hwfn {
	struct qed_ooo_info		*p_ooo_info;
	struct qed_rdma_info		*p_rdma_info;
	struct qed_iscsi_info		*p_iscsi_info;
	struct qed_fcoe_info		*p_fcoe_info;
	struct qed_pf_params		pf_params;

	bool b_rdma_enabled_in_prs;
@@ -620,11 +629,13 @@ struct qed_dev {

	u8				protocol;
#define IS_QED_ETH_IF(cdev)     ((cdev)->protocol == QED_PROTOCOL_ETH)
#define IS_QED_FCOE_IF(cdev)    ((cdev)->protocol == QED_PROTOCOL_FCOE)

	/* Callbacks to protocol driver */
	union {
		struct qed_common_cb_ops	*common;
		struct qed_eth_cb_ops		*eth;
		struct qed_fcoe_cb_ops		*fcoe;
		struct qed_iscsi_cb_ops		*iscsi;
	} protocol_ops;
	void				*ops_cookie;
+93 −5
Original line number Diff line number Diff line
@@ -90,12 +90,14 @@ union conn_context {
	struct core_conn_context core_ctx;
	struct eth_conn_context eth_ctx;
	struct iscsi_conn_context iscsi_ctx;
	struct fcoe_conn_context fcoe_ctx;
	struct roce_conn_context roce_ctx;
};

/* TYPE-0 task context - iSCSI */
/* TYPE-0 task context - iSCSI, FCOE */
union type0_task_context {
	struct iscsi_task_context iscsi_ctx;
	struct fcoe_task_context fcoe_ctx;
};

/* TYPE-1 task context - ROCE */
@@ -240,15 +242,22 @@ struct qed_cxt_mngr {
static bool src_proto(enum protocol_type type)
{
	return type == PROTOCOLID_ISCSI ||
	       type == PROTOCOLID_FCOE ||
	       type == PROTOCOLID_ROCE;
}

static bool tm_cid_proto(enum protocol_type type)
{
	return type == PROTOCOLID_ISCSI ||
	       type == PROTOCOLID_FCOE ||
	       type == PROTOCOLID_ROCE;
}

static bool tm_tid_proto(enum protocol_type type)
{
	return type == PROTOCOLID_FCOE;
}

/* counts the iids for the CDU/CDUC ILT client configuration */
struct qed_cdu_iids {
	u32 pf_cids;
@@ -307,6 +316,22 @@ static void qed_cxt_tm_iids(struct qed_cxt_mngr *p_mngr,
			iids->pf_cids += p_cfg->cid_count;
			iids->per_vf_cids += p_cfg->cids_per_vf;
		}

		if (tm_tid_proto(i)) {
			struct qed_tid_seg *segs = p_cfg->tid_seg;

			/* for each segment there is at most one
			 * protocol for which count is not 0.
			 */
			for (j = 0; j < NUM_TASK_PF_SEGMENTS; j++)
				iids->pf_tids[j] += segs[j].count;

			/* The last array elelment is for the VFs. As for PF
			 * segments there can be only one protocol for
			 * which this value is not 0.
			 */
			iids->per_vf_tids += segs[NUM_TASK_PF_SEGMENTS].count;
		}
	}

	iids->pf_cids = roundup(iids->pf_cids, TM_ALIGN);
@@ -1694,9 +1719,42 @@ static void qed_tm_init_pf(struct qed_hwfn *p_hwfn)
	/* @@@TBD how to enable the scan for the VFs */
}

static void qed_prs_init_common(struct qed_hwfn *p_hwfn)
{
	if ((p_hwfn->hw_info.personality == QED_PCI_FCOE) &&
	    p_hwfn->pf_params.fcoe_pf_params.is_target)
		STORE_RT_REG(p_hwfn,
			     PRS_REG_SEARCH_RESP_INITIATOR_TYPE_RT_OFFSET, 0);
}

static void qed_prs_init_pf(struct qed_hwfn *p_hwfn)
{
	struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr;
	struct qed_conn_type_cfg *p_fcoe;
	struct qed_tid_seg *p_tid;

	p_fcoe = &p_mngr->conn_cfg[PROTOCOLID_FCOE];

	/* If FCoE is active set the MAX OX_ID (tid) in the Parser */
	if (!p_fcoe->cid_count)
		return;

	p_tid = &p_fcoe->tid_seg[QED_CXT_FCOE_TID_SEG];
	if (p_hwfn->pf_params.fcoe_pf_params.is_target) {
		STORE_RT_REG_AGG(p_hwfn,
				 PRS_REG_TASK_ID_MAX_TARGET_PF_RT_OFFSET,
				 p_tid->count);
	} else {
		STORE_RT_REG_AGG(p_hwfn,
				 PRS_REG_TASK_ID_MAX_INITIATOR_PF_RT_OFFSET,
				 p_tid->count);
	}
}

void qed_cxt_hw_init_common(struct qed_hwfn *p_hwfn)
{
	qed_cdu_init_common(p_hwfn);
	qed_prs_init_common(p_hwfn);
}

void qed_cxt_hw_init_pf(struct qed_hwfn *p_hwfn)
@@ -1708,6 +1766,7 @@ void qed_cxt_hw_init_pf(struct qed_hwfn *p_hwfn)
	qed_ilt_init_pf(p_hwfn);
	qed_src_init_pf(p_hwfn);
	qed_tm_init_pf(p_hwfn);
	qed_prs_init_pf(p_hwfn);
}

int qed_cxt_acquire_cid(struct qed_hwfn *p_hwfn,
@@ -1885,6 +1944,27 @@ int qed_cxt_set_pf_params(struct qed_hwfn *p_hwfn)
					    p_params->num_cons, 1);
		break;
	}
	case QED_PCI_FCOE:
	{
		struct qed_fcoe_pf_params *p_params;

		p_params = &p_hwfn->pf_params.fcoe_pf_params;

		if (p_params->num_cons && p_params->num_tasks) {
			qed_cxt_set_proto_cid_count(p_hwfn,
						    PROTOCOLID_FCOE,
						    p_params->num_cons,
						    0);

			qed_cxt_set_proto_tid_count(p_hwfn, PROTOCOLID_FCOE,
						    QED_CXT_FCOE_TID_SEG, 0,
						    p_params->num_tasks, true);
		} else {
			DP_INFO(p_hwfn->cdev,
				"Fcoe personality used without setting params!\n");
		}
		break;
	}
	case QED_PCI_ISCSI:
	{
		struct qed_iscsi_pf_params *p_params;
@@ -1927,6 +2007,10 @@ int qed_cxt_get_tid_mem_info(struct qed_hwfn *p_hwfn,

	/* Verify the personality */
	switch (p_hwfn->hw_info.personality) {
	case QED_PCI_FCOE:
		proto = PROTOCOLID_FCOE;
		seg = QED_CXT_FCOE_TID_SEG;
		break;
	case QED_PCI_ISCSI:
		proto = PROTOCOLID_ISCSI;
		seg = QED_CXT_ISCSI_TID_SEG;
@@ -2215,15 +2299,19 @@ int qed_cxt_get_task_ctx(struct qed_hwfn *p_hwfn,
{
	struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr;
	struct qed_ilt_client_cfg *p_cli;
	struct qed_ilt_cli_blk *p_seg;
	struct qed_tid_seg *p_seg_info;
	u32 proto, seg;
	u32 total_lines;
	u32 tid_size, ilt_idx;
	struct qed_ilt_cli_blk *p_seg;
	u32 num_tids_per_block;
	u32 tid_size, ilt_idx;
	u32 total_lines;
	u32 proto, seg;

	/* Verify the personality */
	switch (p_hwfn->hw_info.personality) {
	case QED_PCI_FCOE:
		proto = PROTOCOLID_FCOE;
		seg = QED_CXT_FCOE_TID_SEG;
		break;
	case QED_PCI_ISCSI:
		proto = PROTOCOLID_ISCSI;
		seg = QED_CXT_ISCSI_TID_SEG;
+3 −0
Original line number Diff line number Diff line
@@ -91,6 +91,7 @@ int qed_cxt_get_tid_mem_info(struct qed_hwfn *p_hwfn,

#define QED_CXT_ISCSI_TID_SEG	PROTOCOLID_ISCSI
#define QED_CXT_ROCE_TID_SEG	PROTOCOLID_ROCE
#define QED_CXT_FCOE_TID_SEG	PROTOCOLID_FCOE
enum qed_cxt_elem_type {
	QED_ELEM_CXT,
	QED_ELEM_SRQ,
@@ -204,4 +205,6 @@ int qed_cxt_free_proto_ilt(struct qed_hwfn *p_hwfn, enum protocol_type proto);

#define QED_CTX_WORKING_MEM 0
#define QED_CTX_FL_MEM 1
int qed_cxt_get_task_ctx(struct qed_hwfn *p_hwfn,
			 u32 tid, u8 ctx_type, void **task_ctx);
#endif
Loading