162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Broadcom NetXtreme-E RoCE driver.
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (c) 2016 - 2017, Broadcom. All rights reserved.  The term
562306a36Sopenharmony_ci * Broadcom refers to Broadcom Limited and/or its subsidiaries.
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * This software is available to you under a choice of one of two
862306a36Sopenharmony_ci * licenses.  You may choose to be licensed under the terms of the GNU
962306a36Sopenharmony_ci * General Public License (GPL) Version 2, available from the file
1062306a36Sopenharmony_ci * COPYING in the main directory of this source tree, or the
1162306a36Sopenharmony_ci * BSD license below:
1262306a36Sopenharmony_ci *
1362306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
1462306a36Sopenharmony_ci * modification, are permitted provided that the following conditions
1562306a36Sopenharmony_ci * are met:
1662306a36Sopenharmony_ci *
1762306a36Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright
1862306a36Sopenharmony_ci *    notice, this list of conditions and the following disclaimer.
1962306a36Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright
2062306a36Sopenharmony_ci *    notice, this list of conditions and the following disclaimer in
2162306a36Sopenharmony_ci *    the documentation and/or other materials provided with the
2262306a36Sopenharmony_ci *    distribution.
2362306a36Sopenharmony_ci *
2462306a36Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
2562306a36Sopenharmony_ci * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
2662306a36Sopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2762306a36Sopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
2862306a36Sopenharmony_ci * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2962306a36Sopenharmony_ci * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
3062306a36Sopenharmony_ci * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
3162306a36Sopenharmony_ci * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
3262306a36Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
3362306a36Sopenharmony_ci * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
3462306a36Sopenharmony_ci * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3562306a36Sopenharmony_ci *
3662306a36Sopenharmony_ci * Description: RDMA Controller HW interface (header)
3762306a36Sopenharmony_ci */
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci#ifndef __BNXT_QPLIB_RCFW_H__
4062306a36Sopenharmony_ci#define __BNXT_QPLIB_RCFW_H__
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci#include "qplib_tlv.h"
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci#define RCFW_CMDQ_TRIG_VAL		1
4562306a36Sopenharmony_ci#define RCFW_COMM_PCI_BAR_REGION	0
4662306a36Sopenharmony_ci#define RCFW_COMM_CONS_PCI_BAR_REGION	2
4762306a36Sopenharmony_ci#define RCFW_COMM_BASE_OFFSET		0x600
4862306a36Sopenharmony_ci#define RCFW_PF_VF_COMM_PROD_OFFSET	0xc
4962306a36Sopenharmony_ci#define RCFW_COMM_TRIG_OFFSET		0x100
5062306a36Sopenharmony_ci#define RCFW_COMM_SIZE			0x104
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci#define RCFW_DBR_PCI_BAR_REGION		2
5362306a36Sopenharmony_ci#define RCFW_DBR_BASE_PAGE_SHIFT	12
5462306a36Sopenharmony_ci#define RCFW_FW_STALL_MAX_TIMEOUT	40
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci/* Cmdq contains a fix number of a 16-Byte slots */
5762306a36Sopenharmony_cistruct bnxt_qplib_cmdqe {
5862306a36Sopenharmony_ci	u8		data[16];
5962306a36Sopenharmony_ci};
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci#define BNXT_QPLIB_CMDQE_UNITS		sizeof(struct bnxt_qplib_cmdqe)
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cistatic inline void bnxt_qplib_rcfw_cmd_prep(struct cmdq_base *req,
6462306a36Sopenharmony_ci					    u8 opcode, u8 cmd_size)
6562306a36Sopenharmony_ci{
6662306a36Sopenharmony_ci	req->opcode = opcode;
6762306a36Sopenharmony_ci	req->cmd_size = cmd_size;
6862306a36Sopenharmony_ci}
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci/* Shadow queue depth for non blocking command */
7162306a36Sopenharmony_ci#define RCFW_CMD_NON_BLOCKING_SHADOW_QD	64
7262306a36Sopenharmony_ci#define RCFW_CMD_WAIT_TIME_MS		20000 /* 20 Seconds timeout */
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci/* CMDQ elements */
7562306a36Sopenharmony_ci#define BNXT_QPLIB_CMDQE_MAX_CNT	8192
7662306a36Sopenharmony_ci#define BNXT_QPLIB_CMDQE_BYTES(depth)	((depth) * BNXT_QPLIB_CMDQE_UNITS)
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_cistatic inline u32 bnxt_qplib_cmdqe_npages(u32 depth)
7962306a36Sopenharmony_ci{
8062306a36Sopenharmony_ci	u32 npages;
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	npages = BNXT_QPLIB_CMDQE_BYTES(depth) / PAGE_SIZE;
8362306a36Sopenharmony_ci	if (BNXT_QPLIB_CMDQE_BYTES(depth) % PAGE_SIZE)
8462306a36Sopenharmony_ci		npages++;
8562306a36Sopenharmony_ci	return npages;
8662306a36Sopenharmony_ci}
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_cistatic inline u32 bnxt_qplib_cmdqe_page_size(u32 depth)
8962306a36Sopenharmony_ci{
9062306a36Sopenharmony_ci	return (bnxt_qplib_cmdqe_npages(depth) * PAGE_SIZE);
9162306a36Sopenharmony_ci}
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci/* Get the number of command units required for the req. The
9462306a36Sopenharmony_ci * function returns correct value only if called before
9562306a36Sopenharmony_ci * setting using bnxt_qplib_set_cmd_slots
9662306a36Sopenharmony_ci */
9762306a36Sopenharmony_cistatic inline u32 bnxt_qplib_get_cmd_slots(struct cmdq_base *req)
9862306a36Sopenharmony_ci{
9962306a36Sopenharmony_ci	u32 cmd_units = 0;
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	if (HAS_TLV_HEADER(req)) {
10262306a36Sopenharmony_ci		struct roce_tlv *tlv_req = (struct roce_tlv *)req;
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci		cmd_units = tlv_req->total_size;
10562306a36Sopenharmony_ci	} else {
10662306a36Sopenharmony_ci		cmd_units = (req->cmd_size + BNXT_QPLIB_CMDQE_UNITS - 1) /
10762306a36Sopenharmony_ci			    BNXT_QPLIB_CMDQE_UNITS;
10862306a36Sopenharmony_ci	}
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci	return cmd_units;
11162306a36Sopenharmony_ci}
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_cistatic inline u32 bnxt_qplib_set_cmd_slots(struct cmdq_base *req)
11462306a36Sopenharmony_ci{
11562306a36Sopenharmony_ci	u32 cmd_byte = 0;
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	if (HAS_TLV_HEADER(req)) {
11862306a36Sopenharmony_ci		struct roce_tlv *tlv_req = (struct roce_tlv *)req;
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci		cmd_byte = tlv_req->total_size * BNXT_QPLIB_CMDQE_UNITS;
12162306a36Sopenharmony_ci	} else {
12262306a36Sopenharmony_ci		cmd_byte = req->cmd_size;
12362306a36Sopenharmony_ci		req->cmd_size = (req->cmd_size + BNXT_QPLIB_CMDQE_UNITS - 1) /
12462306a36Sopenharmony_ci				 BNXT_QPLIB_CMDQE_UNITS;
12562306a36Sopenharmony_ci	}
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	return cmd_byte;
12862306a36Sopenharmony_ci}
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci#define RCFW_MAX_COOKIE_VALUE		(BNXT_QPLIB_CMDQE_MAX_CNT - 1)
13162306a36Sopenharmony_ci#define RCFW_CMD_IS_BLOCKING		0x8000
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci#define HWRM_VERSION_DEV_ATTR_MAX_DPI  0x1000A0000000DULL
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci/* Crsq buf is 1024-Byte */
13662306a36Sopenharmony_cistruct bnxt_qplib_crsbe {
13762306a36Sopenharmony_ci	u8			data[1024];
13862306a36Sopenharmony_ci};
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci/* CREQ */
14162306a36Sopenharmony_ci/* Allocate 1 per QP for async error notification for now */
14262306a36Sopenharmony_ci#define BNXT_QPLIB_CREQE_MAX_CNT	(64 * 1024)
14362306a36Sopenharmony_ci#define BNXT_QPLIB_CREQE_UNITS		16	/* 16-Bytes per prod unit */
14462306a36Sopenharmony_ci#define CREQ_CMP_VALID(hdr, raw_cons, cp_bit)			\
14562306a36Sopenharmony_ci	(!!((hdr)->v & CREQ_BASE_V) ==				\
14662306a36Sopenharmony_ci	   !((raw_cons) & (cp_bit)))
14762306a36Sopenharmony_ci#define CREQ_ENTRY_POLL_BUDGET		0x100
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci/* HWQ */
15062306a36Sopenharmony_citypedef int (*aeq_handler_t)(struct bnxt_qplib_rcfw *, void *, void *);
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_cistruct bnxt_qplib_crsqe {
15362306a36Sopenharmony_ci	struct creq_qp_event	*resp;
15462306a36Sopenharmony_ci	u32			req_size;
15562306a36Sopenharmony_ci	/* Free slots at the time of submission */
15662306a36Sopenharmony_ci	u32			free_slots;
15762306a36Sopenharmony_ci	u8			opcode;
15862306a36Sopenharmony_ci	bool			is_waiter_alive;
15962306a36Sopenharmony_ci	bool			is_internal_cmd;
16062306a36Sopenharmony_ci	bool			is_in_used;
16162306a36Sopenharmony_ci};
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_cistruct bnxt_qplib_rcfw_sbuf {
16462306a36Sopenharmony_ci	void *sb;
16562306a36Sopenharmony_ci	dma_addr_t dma_addr;
16662306a36Sopenharmony_ci	u32 size;
16762306a36Sopenharmony_ci};
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_cistruct bnxt_qplib_qp_node {
17062306a36Sopenharmony_ci	u32 qp_id;              /* QP id */
17162306a36Sopenharmony_ci	void *qp_handle;        /* ptr to qplib_qp */
17262306a36Sopenharmony_ci};
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci#define BNXT_QPLIB_OOS_COUNT_MASK 0xFFFFFFFF
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci#define FIRMWARE_INITIALIZED_FLAG	(0)
17762306a36Sopenharmony_ci#define FIRMWARE_FIRST_FLAG		(31)
17862306a36Sopenharmony_ci#define FIRMWARE_STALL_DETECTED		(3)
17962306a36Sopenharmony_ci#define ERR_DEVICE_DETACHED             (4)
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_cistruct bnxt_qplib_cmdq_mbox {
18262306a36Sopenharmony_ci	struct bnxt_qplib_reg_desc	reg;
18362306a36Sopenharmony_ci	void __iomem			*prod;
18462306a36Sopenharmony_ci	void __iomem			*db;
18562306a36Sopenharmony_ci};
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_cistruct bnxt_qplib_cmdq_ctx {
18862306a36Sopenharmony_ci	struct bnxt_qplib_hwq		hwq;
18962306a36Sopenharmony_ci	struct bnxt_qplib_cmdq_mbox	cmdq_mbox;
19062306a36Sopenharmony_ci	wait_queue_head_t		waitq;
19162306a36Sopenharmony_ci	unsigned long			flags;
19262306a36Sopenharmony_ci	unsigned long			last_seen;
19362306a36Sopenharmony_ci	u32				seq_num;
19462306a36Sopenharmony_ci};
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_cistruct bnxt_qplib_creq_db {
19762306a36Sopenharmony_ci	struct bnxt_qplib_reg_desc	reg;
19862306a36Sopenharmony_ci	struct bnxt_qplib_db_info	dbinfo;
19962306a36Sopenharmony_ci};
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_cistruct bnxt_qplib_creq_stat {
20262306a36Sopenharmony_ci	u64	creq_qp_event_processed;
20362306a36Sopenharmony_ci	u64	creq_func_event_processed;
20462306a36Sopenharmony_ci};
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_cistruct bnxt_qplib_creq_ctx {
20762306a36Sopenharmony_ci	struct bnxt_qplib_hwq		hwq;
20862306a36Sopenharmony_ci	struct bnxt_qplib_creq_db	creq_db;
20962306a36Sopenharmony_ci	struct bnxt_qplib_creq_stat	stats;
21062306a36Sopenharmony_ci	struct tasklet_struct		creq_tasklet;
21162306a36Sopenharmony_ci	aeq_handler_t			aeq_handler;
21262306a36Sopenharmony_ci	u16				ring_id;
21362306a36Sopenharmony_ci	int				msix_vec;
21462306a36Sopenharmony_ci	bool				requested; /*irq handler installed */
21562306a36Sopenharmony_ci	char				*irq_name;
21662306a36Sopenharmony_ci};
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci/* RCFW Communication Channels */
21962306a36Sopenharmony_cistruct bnxt_qplib_rcfw {
22062306a36Sopenharmony_ci	struct pci_dev		*pdev;
22162306a36Sopenharmony_ci	struct bnxt_qplib_res	*res;
22262306a36Sopenharmony_ci	struct bnxt_qplib_cmdq_ctx	cmdq;
22362306a36Sopenharmony_ci	struct bnxt_qplib_creq_ctx	creq;
22462306a36Sopenharmony_ci	struct bnxt_qplib_crsqe		*crsqe_tbl;
22562306a36Sopenharmony_ci	int qp_tbl_size;
22662306a36Sopenharmony_ci	struct bnxt_qplib_qp_node *qp_tbl;
22762306a36Sopenharmony_ci	u64 oos_prev;
22862306a36Sopenharmony_ci	u32 init_oos_stats;
22962306a36Sopenharmony_ci	u32 cmdq_depth;
23062306a36Sopenharmony_ci	atomic_t rcfw_intr_enabled;
23162306a36Sopenharmony_ci	struct semaphore rcfw_inflight;
23262306a36Sopenharmony_ci	atomic_t timeout_send;
23362306a36Sopenharmony_ci	/* cached from chip cctx for quick reference in slow path */
23462306a36Sopenharmony_ci	u16 max_timeout;
23562306a36Sopenharmony_ci};
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_cistruct bnxt_qplib_cmdqmsg {
23862306a36Sopenharmony_ci	struct cmdq_base	*req;
23962306a36Sopenharmony_ci	struct creq_base	*resp;
24062306a36Sopenharmony_ci	void			*sb;
24162306a36Sopenharmony_ci	u32			req_sz;
24262306a36Sopenharmony_ci	u32			res_sz;
24362306a36Sopenharmony_ci	u8			block;
24462306a36Sopenharmony_ci};
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_cistatic inline void bnxt_qplib_fill_cmdqmsg(struct bnxt_qplib_cmdqmsg *msg,
24762306a36Sopenharmony_ci					   void *req, void *resp, void *sb,
24862306a36Sopenharmony_ci					   u32 req_sz, u32 res_sz, u8 block)
24962306a36Sopenharmony_ci{
25062306a36Sopenharmony_ci	msg->req = req;
25162306a36Sopenharmony_ci	msg->resp = resp;
25262306a36Sopenharmony_ci	msg->sb = sb;
25362306a36Sopenharmony_ci	msg->req_sz = req_sz;
25462306a36Sopenharmony_ci	msg->res_sz = res_sz;
25562306a36Sopenharmony_ci	msg->block = block;
25662306a36Sopenharmony_ci}
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_civoid bnxt_qplib_free_rcfw_channel(struct bnxt_qplib_rcfw *rcfw);
25962306a36Sopenharmony_ciint bnxt_qplib_alloc_rcfw_channel(struct bnxt_qplib_res *res,
26062306a36Sopenharmony_ci				  struct bnxt_qplib_rcfw *rcfw,
26162306a36Sopenharmony_ci				  struct bnxt_qplib_ctx *ctx,
26262306a36Sopenharmony_ci				  int qp_tbl_sz);
26362306a36Sopenharmony_civoid bnxt_qplib_rcfw_stop_irq(struct bnxt_qplib_rcfw *rcfw, bool kill);
26462306a36Sopenharmony_civoid bnxt_qplib_disable_rcfw_channel(struct bnxt_qplib_rcfw *rcfw);
26562306a36Sopenharmony_ciint bnxt_qplib_rcfw_start_irq(struct bnxt_qplib_rcfw *rcfw, int msix_vector,
26662306a36Sopenharmony_ci			      bool need_init);
26762306a36Sopenharmony_ciint bnxt_qplib_enable_rcfw_channel(struct bnxt_qplib_rcfw *rcfw,
26862306a36Sopenharmony_ci				   int msix_vector,
26962306a36Sopenharmony_ci				   int cp_bar_reg_off,
27062306a36Sopenharmony_ci				   aeq_handler_t aeq_handler);
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_cistruct bnxt_qplib_rcfw_sbuf *bnxt_qplib_rcfw_alloc_sbuf(
27362306a36Sopenharmony_ci				struct bnxt_qplib_rcfw *rcfw,
27462306a36Sopenharmony_ci				u32 size);
27562306a36Sopenharmony_civoid bnxt_qplib_rcfw_free_sbuf(struct bnxt_qplib_rcfw *rcfw,
27662306a36Sopenharmony_ci			       struct bnxt_qplib_rcfw_sbuf *sbuf);
27762306a36Sopenharmony_ciint bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw,
27862306a36Sopenharmony_ci				 struct bnxt_qplib_cmdqmsg *msg);
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ciint bnxt_qplib_deinit_rcfw(struct bnxt_qplib_rcfw *rcfw);
28162306a36Sopenharmony_ciint bnxt_qplib_init_rcfw(struct bnxt_qplib_rcfw *rcfw,
28262306a36Sopenharmony_ci			 struct bnxt_qplib_ctx *ctx, int is_virtfn);
28362306a36Sopenharmony_civoid bnxt_qplib_mark_qp_error(void *qp_handle);
28462306a36Sopenharmony_cistatic inline u32 map_qp_id_to_tbl_indx(u32 qid, struct bnxt_qplib_rcfw *rcfw)
28562306a36Sopenharmony_ci{
28662306a36Sopenharmony_ci	/* Last index of the qp_tbl is for QP1 ie. qp_tbl_size - 1*/
28762306a36Sopenharmony_ci	return (qid == 1) ? rcfw->qp_tbl_size - 1 : qid % rcfw->qp_tbl_size - 2;
28862306a36Sopenharmony_ci}
28962306a36Sopenharmony_ci#endif /* __BNXT_QPLIB_RCFW_H__ */
290