162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2016 Chelsio Communications, Inc.
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#ifndef __CXGBIT_H__
762306a36Sopenharmony_ci#define __CXGBIT_H__
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <linux/mutex.h>
1062306a36Sopenharmony_ci#include <linux/list.h>
1162306a36Sopenharmony_ci#include <linux/spinlock.h>
1262306a36Sopenharmony_ci#include <linux/idr.h>
1362306a36Sopenharmony_ci#include <linux/completion.h>
1462306a36Sopenharmony_ci#include <linux/netdevice.h>
1562306a36Sopenharmony_ci#include <linux/sched.h>
1662306a36Sopenharmony_ci#include <linux/pci.h>
1762306a36Sopenharmony_ci#include <linux/dma-mapping.h>
1862306a36Sopenharmony_ci#include <linux/inet.h>
1962306a36Sopenharmony_ci#include <linux/wait.h>
2062306a36Sopenharmony_ci#include <linux/kref.h>
2162306a36Sopenharmony_ci#include <linux/timer.h>
2262306a36Sopenharmony_ci#include <linux/io.h>
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci#include <asm/byteorder.h>
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#include <net/net_namespace.h>
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci#include <target/iscsi/iscsi_transport.h>
2962306a36Sopenharmony_ci#include <iscsi_target_parameters.h>
3062306a36Sopenharmony_ci#include <iscsi_target_login.h>
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci#include "t4_regs.h"
3362306a36Sopenharmony_ci#include "t4_msg.h"
3462306a36Sopenharmony_ci#include "cxgb4.h"
3562306a36Sopenharmony_ci#include "cxgb4_uld.h"
3662306a36Sopenharmony_ci#include "l2t.h"
3762306a36Sopenharmony_ci#include "libcxgb_ppm.h"
3862306a36Sopenharmony_ci#include "cxgbit_lro.h"
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ciextern struct mutex cdev_list_lock;
4162306a36Sopenharmony_ciextern struct list_head cdev_list_head;
4262306a36Sopenharmony_cistruct cxgbit_np;
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cistruct cxgbit_sock;
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_cistruct cxgbit_cmd {
4762306a36Sopenharmony_ci	struct scatterlist sg;
4862306a36Sopenharmony_ci	struct cxgbi_task_tag_info ttinfo;
4962306a36Sopenharmony_ci	bool setup_ddp;
5062306a36Sopenharmony_ci	bool release;
5162306a36Sopenharmony_ci};
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci#define CXGBIT_MAX_ISO_PAYLOAD	\
5462306a36Sopenharmony_ci	min_t(u32, MAX_SKB_FRAGS * PAGE_SIZE, 65535)
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_cistruct cxgbit_iso_info {
5762306a36Sopenharmony_ci	u8 flags;
5862306a36Sopenharmony_ci	u32 mpdu;
5962306a36Sopenharmony_ci	u32 len;
6062306a36Sopenharmony_ci	u32 burst_len;
6162306a36Sopenharmony_ci};
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cienum cxgbit_skcb_flags {
6462306a36Sopenharmony_ci	SKCBF_TX_NEED_HDR	= (1 << 0), /* packet needs a header */
6562306a36Sopenharmony_ci	SKCBF_TX_FLAG_COMPL	= (1 << 1), /* wr completion flag */
6662306a36Sopenharmony_ci	SKCBF_TX_ISO		= (1 << 2), /* iso cpl in tx skb */
6762306a36Sopenharmony_ci	SKCBF_RX_LRO		= (1 << 3), /* lro skb */
6862306a36Sopenharmony_ci};
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_cistruct cxgbit_skb_rx_cb {
7162306a36Sopenharmony_ci	u8 opcode;
7262306a36Sopenharmony_ci	void *pdu_cb;
7362306a36Sopenharmony_ci	void (*backlog_fn)(struct cxgbit_sock *, struct sk_buff *);
7462306a36Sopenharmony_ci};
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_cistruct cxgbit_skb_tx_cb {
7762306a36Sopenharmony_ci	u8 submode;
7862306a36Sopenharmony_ci	u32 extra_len;
7962306a36Sopenharmony_ci};
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ciunion cxgbit_skb_cb {
8262306a36Sopenharmony_ci	struct {
8362306a36Sopenharmony_ci		u8 flags;
8462306a36Sopenharmony_ci		union {
8562306a36Sopenharmony_ci			struct cxgbit_skb_tx_cb tx;
8662306a36Sopenharmony_ci			struct cxgbit_skb_rx_cb rx;
8762306a36Sopenharmony_ci		};
8862306a36Sopenharmony_ci	};
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	struct {
9162306a36Sopenharmony_ci		/* This member must be first. */
9262306a36Sopenharmony_ci		struct l2t_skb_cb l2t;
9362306a36Sopenharmony_ci		struct sk_buff *wr_next;
9462306a36Sopenharmony_ci	};
9562306a36Sopenharmony_ci};
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci#define CXGBIT_SKB_CB(skb)	((union cxgbit_skb_cb *)&((skb)->cb[0]))
9862306a36Sopenharmony_ci#define cxgbit_skcb_flags(skb)		(CXGBIT_SKB_CB(skb)->flags)
9962306a36Sopenharmony_ci#define cxgbit_skcb_submode(skb)	(CXGBIT_SKB_CB(skb)->tx.submode)
10062306a36Sopenharmony_ci#define cxgbit_skcb_tx_wr_next(skb)	(CXGBIT_SKB_CB(skb)->wr_next)
10162306a36Sopenharmony_ci#define cxgbit_skcb_tx_extralen(skb)	(CXGBIT_SKB_CB(skb)->tx.extra_len)
10262306a36Sopenharmony_ci#define cxgbit_skcb_rx_opcode(skb)	(CXGBIT_SKB_CB(skb)->rx.opcode)
10362306a36Sopenharmony_ci#define cxgbit_skcb_rx_backlog_fn(skb)	(CXGBIT_SKB_CB(skb)->rx.backlog_fn)
10462306a36Sopenharmony_ci#define cxgbit_rx_pdu_cb(skb)		(CXGBIT_SKB_CB(skb)->rx.pdu_cb)
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_cistatic inline void *cplhdr(struct sk_buff *skb)
10762306a36Sopenharmony_ci{
10862306a36Sopenharmony_ci	return skb->data;
10962306a36Sopenharmony_ci}
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_cienum cxgbit_cdev_flags {
11262306a36Sopenharmony_ci	CDEV_STATE_UP = 0,
11362306a36Sopenharmony_ci	CDEV_ISO_ENABLE,
11462306a36Sopenharmony_ci	CDEV_DDP_ENABLE,
11562306a36Sopenharmony_ci};
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci#define NP_INFO_HASH_SIZE 32
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_cistruct np_info {
12062306a36Sopenharmony_ci	struct np_info *next;
12162306a36Sopenharmony_ci	struct cxgbit_np *cnp;
12262306a36Sopenharmony_ci	unsigned int stid;
12362306a36Sopenharmony_ci};
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_cistruct cxgbit_list_head {
12662306a36Sopenharmony_ci	struct list_head list;
12762306a36Sopenharmony_ci	/* device lock */
12862306a36Sopenharmony_ci	spinlock_t lock;
12962306a36Sopenharmony_ci};
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_cistruct cxgbit_device {
13262306a36Sopenharmony_ci	struct list_head list;
13362306a36Sopenharmony_ci	struct cxgb4_lld_info lldi;
13462306a36Sopenharmony_ci	struct np_info *np_hash_tab[NP_INFO_HASH_SIZE];
13562306a36Sopenharmony_ci	/* np lock */
13662306a36Sopenharmony_ci	spinlock_t np_lock;
13762306a36Sopenharmony_ci	u8 selectq[MAX_NPORTS][2];
13862306a36Sopenharmony_ci	struct cxgbit_list_head cskq;
13962306a36Sopenharmony_ci	u32 mdsl;
14062306a36Sopenharmony_ci	struct kref kref;
14162306a36Sopenharmony_ci	unsigned long flags;
14262306a36Sopenharmony_ci};
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_cistruct cxgbit_wr_wait {
14562306a36Sopenharmony_ci	struct completion completion;
14662306a36Sopenharmony_ci	int ret;
14762306a36Sopenharmony_ci};
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_cienum cxgbit_csk_state {
15062306a36Sopenharmony_ci	CSK_STATE_IDLE = 0,
15162306a36Sopenharmony_ci	CSK_STATE_LISTEN,
15262306a36Sopenharmony_ci	CSK_STATE_CONNECTING,
15362306a36Sopenharmony_ci	CSK_STATE_ESTABLISHED,
15462306a36Sopenharmony_ci	CSK_STATE_ABORTING,
15562306a36Sopenharmony_ci	CSK_STATE_CLOSING,
15662306a36Sopenharmony_ci	CSK_STATE_MORIBUND,
15762306a36Sopenharmony_ci	CSK_STATE_DEAD,
15862306a36Sopenharmony_ci};
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_cienum cxgbit_csk_flags {
16162306a36Sopenharmony_ci	CSK_TX_DATA_SENT = 0,
16262306a36Sopenharmony_ci	CSK_LOGIN_PDU_DONE,
16362306a36Sopenharmony_ci	CSK_LOGIN_DONE,
16462306a36Sopenharmony_ci	CSK_DDP_ENABLE,
16562306a36Sopenharmony_ci	CSK_ABORT_RPL_WAIT,
16662306a36Sopenharmony_ci};
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_cistruct cxgbit_sock_common {
16962306a36Sopenharmony_ci	struct cxgbit_device *cdev;
17062306a36Sopenharmony_ci	struct sockaddr_storage local_addr;
17162306a36Sopenharmony_ci	struct sockaddr_storage remote_addr;
17262306a36Sopenharmony_ci	struct cxgbit_wr_wait wr_wait;
17362306a36Sopenharmony_ci	enum cxgbit_csk_state state;
17462306a36Sopenharmony_ci	unsigned long flags;
17562306a36Sopenharmony_ci};
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_cistruct cxgbit_np {
17862306a36Sopenharmony_ci	struct cxgbit_sock_common com;
17962306a36Sopenharmony_ci	wait_queue_head_t accept_wait;
18062306a36Sopenharmony_ci	struct iscsi_np *np;
18162306a36Sopenharmony_ci	struct completion accept_comp;
18262306a36Sopenharmony_ci	struct list_head np_accept_list;
18362306a36Sopenharmony_ci	/* np accept lock */
18462306a36Sopenharmony_ci	spinlock_t np_accept_lock;
18562306a36Sopenharmony_ci	struct kref kref;
18662306a36Sopenharmony_ci	unsigned int stid;
18762306a36Sopenharmony_ci};
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_cistruct cxgbit_sock {
19062306a36Sopenharmony_ci	struct cxgbit_sock_common com;
19162306a36Sopenharmony_ci	struct cxgbit_np *cnp;
19262306a36Sopenharmony_ci	struct iscsit_conn *conn;
19362306a36Sopenharmony_ci	struct l2t_entry *l2t;
19462306a36Sopenharmony_ci	struct dst_entry *dst;
19562306a36Sopenharmony_ci	struct list_head list;
19662306a36Sopenharmony_ci	struct sk_buff_head rxq;
19762306a36Sopenharmony_ci	struct sk_buff_head txq;
19862306a36Sopenharmony_ci	struct sk_buff_head ppodq;
19962306a36Sopenharmony_ci	struct sk_buff_head backlogq;
20062306a36Sopenharmony_ci	struct sk_buff_head skbq;
20162306a36Sopenharmony_ci	struct sk_buff *wr_pending_head;
20262306a36Sopenharmony_ci	struct sk_buff *wr_pending_tail;
20362306a36Sopenharmony_ci	struct sk_buff *skb;
20462306a36Sopenharmony_ci	struct sk_buff *lro_skb;
20562306a36Sopenharmony_ci	struct sk_buff *lro_hskb;
20662306a36Sopenharmony_ci	struct list_head accept_node;
20762306a36Sopenharmony_ci	/* socket lock */
20862306a36Sopenharmony_ci	spinlock_t lock;
20962306a36Sopenharmony_ci	wait_queue_head_t waitq;
21062306a36Sopenharmony_ci	bool lock_owner;
21162306a36Sopenharmony_ci	struct kref kref;
21262306a36Sopenharmony_ci	u32 max_iso_npdu;
21362306a36Sopenharmony_ci	u32 wr_cred;
21462306a36Sopenharmony_ci	u32 wr_una_cred;
21562306a36Sopenharmony_ci	u32 wr_max_cred;
21662306a36Sopenharmony_ci	u32 snd_una;
21762306a36Sopenharmony_ci	u32 tid;
21862306a36Sopenharmony_ci	u32 snd_nxt;
21962306a36Sopenharmony_ci	u32 rcv_nxt;
22062306a36Sopenharmony_ci	u32 smac_idx;
22162306a36Sopenharmony_ci	u32 tx_chan;
22262306a36Sopenharmony_ci	u32 mtu;
22362306a36Sopenharmony_ci	u32 write_seq;
22462306a36Sopenharmony_ci	u32 rx_credits;
22562306a36Sopenharmony_ci	u32 snd_win;
22662306a36Sopenharmony_ci	u32 rcv_win;
22762306a36Sopenharmony_ci	u16 mss;
22862306a36Sopenharmony_ci	u16 emss;
22962306a36Sopenharmony_ci	u16 plen;
23062306a36Sopenharmony_ci	u16 rss_qid;
23162306a36Sopenharmony_ci	u16 txq_idx;
23262306a36Sopenharmony_ci	u16 ctrlq_idx;
23362306a36Sopenharmony_ci	u8 tos;
23462306a36Sopenharmony_ci	u8 port_id;
23562306a36Sopenharmony_ci#define CXGBIT_SUBMODE_HCRC 0x1
23662306a36Sopenharmony_ci#define CXGBIT_SUBMODE_DCRC 0x2
23762306a36Sopenharmony_ci	u8 submode;
23862306a36Sopenharmony_ci#ifdef CONFIG_CHELSIO_T4_DCB
23962306a36Sopenharmony_ci	u8 dcb_priority;
24062306a36Sopenharmony_ci#endif
24162306a36Sopenharmony_ci	u8 snd_wscale;
24262306a36Sopenharmony_ci};
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_civoid _cxgbit_free_cdev(struct kref *kref);
24562306a36Sopenharmony_civoid _cxgbit_free_csk(struct kref *kref);
24662306a36Sopenharmony_civoid _cxgbit_free_cnp(struct kref *kref);
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_cistatic inline void cxgbit_get_cdev(struct cxgbit_device *cdev)
24962306a36Sopenharmony_ci{
25062306a36Sopenharmony_ci	kref_get(&cdev->kref);
25162306a36Sopenharmony_ci}
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_cistatic inline void cxgbit_put_cdev(struct cxgbit_device *cdev)
25462306a36Sopenharmony_ci{
25562306a36Sopenharmony_ci	kref_put(&cdev->kref, _cxgbit_free_cdev);
25662306a36Sopenharmony_ci}
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_cistatic inline void cxgbit_get_csk(struct cxgbit_sock *csk)
25962306a36Sopenharmony_ci{
26062306a36Sopenharmony_ci	kref_get(&csk->kref);
26162306a36Sopenharmony_ci}
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_cistatic inline void cxgbit_put_csk(struct cxgbit_sock *csk)
26462306a36Sopenharmony_ci{
26562306a36Sopenharmony_ci	kref_put(&csk->kref, _cxgbit_free_csk);
26662306a36Sopenharmony_ci}
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_cistatic inline void cxgbit_get_cnp(struct cxgbit_np *cnp)
26962306a36Sopenharmony_ci{
27062306a36Sopenharmony_ci	kref_get(&cnp->kref);
27162306a36Sopenharmony_ci}
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_cistatic inline void cxgbit_put_cnp(struct cxgbit_np *cnp)
27462306a36Sopenharmony_ci{
27562306a36Sopenharmony_ci	kref_put(&cnp->kref, _cxgbit_free_cnp);
27662306a36Sopenharmony_ci}
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_cistatic inline void cxgbit_sock_reset_wr_list(struct cxgbit_sock *csk)
27962306a36Sopenharmony_ci{
28062306a36Sopenharmony_ci	csk->wr_pending_tail = NULL;
28162306a36Sopenharmony_ci	csk->wr_pending_head = NULL;
28262306a36Sopenharmony_ci}
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_cistatic inline struct sk_buff *cxgbit_sock_peek_wr(const struct cxgbit_sock *csk)
28562306a36Sopenharmony_ci{
28662306a36Sopenharmony_ci	return csk->wr_pending_head;
28762306a36Sopenharmony_ci}
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_cistatic inline void
29062306a36Sopenharmony_cicxgbit_sock_enqueue_wr(struct cxgbit_sock *csk, struct sk_buff *skb)
29162306a36Sopenharmony_ci{
29262306a36Sopenharmony_ci	cxgbit_skcb_tx_wr_next(skb) = NULL;
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	skb_get(skb);
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	if (!csk->wr_pending_head)
29762306a36Sopenharmony_ci		csk->wr_pending_head = skb;
29862306a36Sopenharmony_ci	else
29962306a36Sopenharmony_ci		cxgbit_skcb_tx_wr_next(csk->wr_pending_tail) = skb;
30062306a36Sopenharmony_ci	csk->wr_pending_tail = skb;
30162306a36Sopenharmony_ci}
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_cistatic inline struct sk_buff *cxgbit_sock_dequeue_wr(struct cxgbit_sock *csk)
30462306a36Sopenharmony_ci{
30562306a36Sopenharmony_ci	struct sk_buff *skb = csk->wr_pending_head;
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci	if (likely(skb)) {
30862306a36Sopenharmony_ci		csk->wr_pending_head = cxgbit_skcb_tx_wr_next(skb);
30962306a36Sopenharmony_ci		cxgbit_skcb_tx_wr_next(skb) = NULL;
31062306a36Sopenharmony_ci	}
31162306a36Sopenharmony_ci	return skb;
31262306a36Sopenharmony_ci}
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_citypedef void (*cxgbit_cplhandler_func)(struct cxgbit_device *,
31562306a36Sopenharmony_ci				       struct sk_buff *);
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ciint cxgbit_setup_np(struct iscsi_np *, struct sockaddr_storage *);
31862306a36Sopenharmony_ciint cxgbit_setup_conn_digest(struct cxgbit_sock *);
31962306a36Sopenharmony_ciint cxgbit_accept_np(struct iscsi_np *, struct iscsit_conn *);
32062306a36Sopenharmony_civoid cxgbit_free_np(struct iscsi_np *);
32162306a36Sopenharmony_civoid cxgbit_abort_conn(struct cxgbit_sock *csk);
32262306a36Sopenharmony_civoid cxgbit_free_conn(struct iscsit_conn *);
32362306a36Sopenharmony_ciextern cxgbit_cplhandler_func cxgbit_cplhandlers[NUM_CPL_CMDS];
32462306a36Sopenharmony_ciint cxgbit_get_login_rx(struct iscsit_conn *, struct iscsi_login *);
32562306a36Sopenharmony_ciint cxgbit_rx_data_ack(struct cxgbit_sock *);
32662306a36Sopenharmony_ciint cxgbit_l2t_send(struct cxgbit_device *, struct sk_buff *,
32762306a36Sopenharmony_ci		    struct l2t_entry *);
32862306a36Sopenharmony_civoid cxgbit_push_tx_frames(struct cxgbit_sock *);
32962306a36Sopenharmony_ciint cxgbit_put_login_tx(struct iscsit_conn *, struct iscsi_login *, u32);
33062306a36Sopenharmony_ciint cxgbit_xmit_pdu(struct iscsit_conn *, struct iscsit_cmd *,
33162306a36Sopenharmony_ci		    struct iscsi_datain_req *, const void *, u32);
33262306a36Sopenharmony_civoid cxgbit_get_r2t_ttt(struct iscsit_conn *, struct iscsit_cmd *,
33362306a36Sopenharmony_ci			struct iscsi_r2t *);
33462306a36Sopenharmony_ciu32 cxgbit_send_tx_flowc_wr(struct cxgbit_sock *);
33562306a36Sopenharmony_ciint cxgbit_ofld_send(struct cxgbit_device *, struct sk_buff *);
33662306a36Sopenharmony_civoid cxgbit_get_rx_pdu(struct iscsit_conn *);
33762306a36Sopenharmony_ciint cxgbit_validate_params(struct iscsit_conn *);
33862306a36Sopenharmony_cistruct cxgbit_device *cxgbit_find_device(struct net_device *, u8 *);
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci/* DDP */
34162306a36Sopenharmony_ciint cxgbit_ddp_init(struct cxgbit_device *);
34262306a36Sopenharmony_ciint cxgbit_setup_conn_pgidx(struct cxgbit_sock *, u32);
34362306a36Sopenharmony_ciint cxgbit_reserve_ttt(struct cxgbit_sock *, struct iscsit_cmd *);
34462306a36Sopenharmony_civoid cxgbit_unmap_cmd(struct iscsit_conn *, struct iscsit_cmd *);
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_cistatic inline
34762306a36Sopenharmony_cistruct cxgbi_ppm *cdev2ppm(struct cxgbit_device *cdev)
34862306a36Sopenharmony_ci{
34962306a36Sopenharmony_ci	return (struct cxgbi_ppm *)(*cdev->lldi.iscsi_ppm);
35062306a36Sopenharmony_ci}
35162306a36Sopenharmony_ci#endif /* __CXGBIT_H__ */
352