Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.5.6.
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 *  Shared Memory Communications over RDMA (SMC-R) and RoCE
   4 *
   5 *  Link Layer Control (LLC)
   6 *
   7 *  Copyright IBM Corp. 2016
   8 *
   9 *  Author(s):  Klaus Wacker <Klaus.Wacker@de.ibm.com>
  10 *              Ursula Braun <ubraun@linux.vnet.ibm.com>
  11 */
  12
  13#include <net/tcp.h>
  14#include <rdma/ib_verbs.h>
  15
  16#include "smc.h"
  17#include "smc_core.h"
  18#include "smc_clc.h"
  19#include "smc_llc.h"
  20#include "smc_pnet.h"
  21
  22#define SMC_LLC_DATA_LEN		40
  23
  24struct smc_llc_hdr {
  25	struct smc_wr_rx_hdr common;
  26	u8 length;	/* 44 */
  27#if defined(__BIG_ENDIAN_BITFIELD)
  28	u8 reserved:4,
  29	   add_link_rej_rsn:4;
  30#elif defined(__LITTLE_ENDIAN_BITFIELD)
  31	u8 add_link_rej_rsn:4,
  32	   reserved:4;
  33#endif
  34	u8 flags;
  35};
  36
  37#define SMC_LLC_FLAG_NO_RMBE_EYEC	0x03
  38
  39struct smc_llc_msg_confirm_link {	/* type 0x01 */
  40	struct smc_llc_hdr hd;
  41	u8 sender_mac[ETH_ALEN];
  42	u8 sender_gid[SMC_GID_SIZE];
  43	u8 sender_qp_num[3];
  44	u8 link_num;
  45	u8 link_uid[SMC_LGR_ID_SIZE];
  46	u8 max_links;
  47	u8 reserved[9];
  48};
  49
  50#define SMC_LLC_FLAG_ADD_LNK_REJ	0x40
  51#define SMC_LLC_REJ_RSN_NO_ALT_PATH	1
  52
  53#define SMC_LLC_ADD_LNK_MAX_LINKS	2
  54
  55struct smc_llc_msg_add_link {		/* type 0x02 */
  56	struct smc_llc_hdr hd;
  57	u8 sender_mac[ETH_ALEN];
  58	u8 reserved2[2];
  59	u8 sender_gid[SMC_GID_SIZE];
  60	u8 sender_qp_num[3];
  61	u8 link_num;
  62#if defined(__BIG_ENDIAN_BITFIELD)
  63	u8 reserved3 : 4,
  64	   qp_mtu   : 4;
  65#elif defined(__LITTLE_ENDIAN_BITFIELD)
  66	u8 qp_mtu   : 4,
  67	   reserved3 : 4;
  68#endif
  69	u8 initial_psn[3];
  70	u8 reserved[8];
  71};
  72
  73struct smc_llc_msg_add_link_cont_rt {
  74	__be32 rmb_key;
  75	__be32 rmb_key_new;
  76	__be64 rmb_vaddr_new;
  77};
  78
  79#define SMC_LLC_RKEYS_PER_CONT_MSG	2
  80
  81struct smc_llc_msg_add_link_cont {	/* type 0x03 */
  82	struct smc_llc_hdr hd;
  83	u8 link_num;
  84	u8 num_rkeys;
  85	u8 reserved2[2];
  86	struct smc_llc_msg_add_link_cont_rt rt[SMC_LLC_RKEYS_PER_CONT_MSG];
  87	u8 reserved[4];
  88} __packed;			/* format defined in RFC7609 */
  89
  90#define SMC_LLC_FLAG_DEL_LINK_ALL	0x40
  91#define SMC_LLC_FLAG_DEL_LINK_ORDERLY	0x20
  92
  93struct smc_llc_msg_del_link {		/* type 0x04 */
  94	struct smc_llc_hdr hd;
  95	u8 link_num;
  96	__be32 reason;
  97	u8 reserved[35];
  98} __packed;			/* format defined in RFC7609 */
  99
 100struct smc_llc_msg_test_link {		/* type 0x07 */
 101	struct smc_llc_hdr hd;
 102	u8 user_data[16];
 103	u8 reserved[24];
 104};
 105
 106struct smc_rmb_rtoken {
 107	union {
 108		u8 num_rkeys;	/* first rtoken byte of CONFIRM LINK msg */
 109				/* is actually the num of rtokens, first */
 110				/* rtoken is always for the current link */
 111		u8 link_id;	/* link id of the rtoken */
 112	};
 113	__be32 rmb_key;
 114	__be64 rmb_vaddr;
 115} __packed;			/* format defined in RFC7609 */
 116
 117#define SMC_LLC_RKEYS_PER_MSG	3
 118
 119struct smc_llc_msg_confirm_rkey {	/* type 0x06 */
 120	struct smc_llc_hdr hd;
 121	struct smc_rmb_rtoken rtoken[SMC_LLC_RKEYS_PER_MSG];
 122	u8 reserved;
 123};
 124
 125#define SMC_LLC_DEL_RKEY_MAX	8
 126#define SMC_LLC_FLAG_RKEY_RETRY	0x10
 127#define SMC_LLC_FLAG_RKEY_NEG	0x20
 128
 129struct smc_llc_msg_delete_rkey {	/* type 0x09 */
 130	struct smc_llc_hdr hd;
 131	u8 num_rkeys;
 132	u8 err_mask;
 133	u8 reserved[2];
 134	__be32 rkey[8];
 135	u8 reserved2[4];
 136};
 137
 138union smc_llc_msg {
 139	struct smc_llc_msg_confirm_link confirm_link;
 140	struct smc_llc_msg_add_link add_link;
 141	struct smc_llc_msg_add_link_cont add_link_cont;
 142	struct smc_llc_msg_del_link delete_link;
 143
 144	struct smc_llc_msg_confirm_rkey confirm_rkey;
 145	struct smc_llc_msg_delete_rkey delete_rkey;
 146
 147	struct smc_llc_msg_test_link test_link;
 148	struct {
 149		struct smc_llc_hdr hdr;
 150		u8 data[SMC_LLC_DATA_LEN];
 151	} raw;
 152};
 153
 154#define SMC_LLC_FLAG_RESP		0x80
 155
 156struct smc_llc_qentry {
 157	struct list_head list;
 158	struct smc_link *link;
 159	union smc_llc_msg msg;
 160};
 161
 162static void smc_llc_enqueue(struct smc_link *link, union smc_llc_msg *llc);
 163
 164struct smc_llc_qentry *smc_llc_flow_qentry_clr(struct smc_llc_flow *flow)
 165{
 166	struct smc_llc_qentry *qentry = flow->qentry;
 167
 168	flow->qentry = NULL;
 169	return qentry;
 170}
 171
 172void smc_llc_flow_qentry_del(struct smc_llc_flow *flow)
 173{
 174	struct smc_llc_qentry *qentry;
 175
 176	if (flow->qentry) {
 177		qentry = flow->qentry;
 178		flow->qentry = NULL;
 179		kfree(qentry);
 180	}
 181}
 182
 183static inline void smc_llc_flow_qentry_set(struct smc_llc_flow *flow,
 184					   struct smc_llc_qentry *qentry)
 185{
 186	flow->qentry = qentry;
 187}
 188
 189static void smc_llc_flow_parallel(struct smc_link_group *lgr, u8 flow_type,
 190				  struct smc_llc_qentry *qentry)
 191{
 192	u8 msg_type = qentry->msg.raw.hdr.common.type;
 193
 194	if ((msg_type == SMC_LLC_ADD_LINK || msg_type == SMC_LLC_DELETE_LINK) &&
 195	    flow_type != msg_type && !lgr->delayed_event) {
 196		lgr->delayed_event = qentry;
 197		return;
 198	}
 199	/* drop parallel or already-in-progress llc requests */
 200	if (flow_type != msg_type)
 201		pr_warn_once("smc: SMC-R lg %*phN dropped parallel "
 202			     "LLC msg: msg %d flow %d role %d\n",
 203			     SMC_LGR_ID_SIZE, &lgr->id,
 204			     qentry->msg.raw.hdr.common.type,
 205			     flow_type, lgr->role);
 206	kfree(qentry);
 207}
 208
 209/* try to start a new llc flow, initiated by an incoming llc msg */
 210static bool smc_llc_flow_start(struct smc_llc_flow *flow,
 211			       struct smc_llc_qentry *qentry)
 212{
 213	struct smc_link_group *lgr = qentry->link->lgr;
 214
 215	spin_lock_bh(&lgr->llc_flow_lock);
 216	if (flow->type) {
 217		/* a flow is already active */
 218		smc_llc_flow_parallel(lgr, flow->type, qentry);
 219		spin_unlock_bh(&lgr->llc_flow_lock);
 220		return false;
 221	}
 222	switch (qentry->msg.raw.hdr.common.type) {
 223	case SMC_LLC_ADD_LINK:
 224		flow->type = SMC_LLC_FLOW_ADD_LINK;
 225		break;
 226	case SMC_LLC_DELETE_LINK:
 227		flow->type = SMC_LLC_FLOW_DEL_LINK;
 228		break;
 229	case SMC_LLC_CONFIRM_RKEY:
 230	case SMC_LLC_DELETE_RKEY:
 231		flow->type = SMC_LLC_FLOW_RKEY;
 232		break;
 233	default:
 234		flow->type = SMC_LLC_FLOW_NONE;
 235	}
 236	smc_llc_flow_qentry_set(flow, qentry);
 237	spin_unlock_bh(&lgr->llc_flow_lock);
 238	return true;
 239}
 240
 241/* start a new local llc flow, wait till current flow finished */
 242int smc_llc_flow_initiate(struct smc_link_group *lgr,
 243			  enum smc_llc_flowtype type)
 244{
 245	enum smc_llc_flowtype allowed_remote = SMC_LLC_FLOW_NONE;
 246	int rc;
 247
 248	/* all flows except confirm_rkey and delete_rkey are exclusive,
 249	 * confirm/delete rkey flows can run concurrently (local and remote)
 250	 */
 251	if (type == SMC_LLC_FLOW_RKEY)
 252		allowed_remote = SMC_LLC_FLOW_RKEY;
 253again:
 254	if (list_empty(&lgr->list))
 255		return -ENODEV;
 256	spin_lock_bh(&lgr->llc_flow_lock);
 257	if (lgr->llc_flow_lcl.type == SMC_LLC_FLOW_NONE &&
 258	    (lgr->llc_flow_rmt.type == SMC_LLC_FLOW_NONE ||
 259	     lgr->llc_flow_rmt.type == allowed_remote)) {
 260		lgr->llc_flow_lcl.type = type;
 261		spin_unlock_bh(&lgr->llc_flow_lock);
 262		return 0;
 263	}
 264	spin_unlock_bh(&lgr->llc_flow_lock);
 265	rc = wait_event_timeout(lgr->llc_flow_waiter, (list_empty(&lgr->list) ||
 266				(lgr->llc_flow_lcl.type == SMC_LLC_FLOW_NONE &&
 267				 (lgr->llc_flow_rmt.type == SMC_LLC_FLOW_NONE ||
 268				  lgr->llc_flow_rmt.type == allowed_remote))),
 269				SMC_LLC_WAIT_TIME * 10);
 270	if (!rc)
 271		return -ETIMEDOUT;
 272	goto again;
 273}
 274
 275/* finish the current llc flow */
 276void smc_llc_flow_stop(struct smc_link_group *lgr, struct smc_llc_flow *flow)
 277{
 278	spin_lock_bh(&lgr->llc_flow_lock);
 279	memset(flow, 0, sizeof(*flow));
 280	flow->type = SMC_LLC_FLOW_NONE;
 281	spin_unlock_bh(&lgr->llc_flow_lock);
 282	if (!list_empty(&lgr->list) && lgr->delayed_event &&
 283	    flow == &lgr->llc_flow_lcl)
 284		schedule_work(&lgr->llc_event_work);
 285	else
 286		wake_up(&lgr->llc_flow_waiter);
 287}
 288
 289/* lnk is optional and used for early wakeup when link goes down, useful in
 290 * cases where we wait for a response on the link after we sent a request
 291 */
 292struct smc_llc_qentry *smc_llc_wait(struct smc_link_group *lgr,
 293				    struct smc_link *lnk,
 294				    int time_out, u8 exp_msg)
 295{
 296	struct smc_llc_flow *flow = &lgr->llc_flow_lcl;
 297	u8 rcv_msg;
 298
 299	wait_event_timeout(lgr->llc_msg_waiter,
 300			   (flow->qentry ||
 301			    (lnk && !smc_link_usable(lnk)) ||
 302			    list_empty(&lgr->list)),
 303			   time_out);
 304	if (!flow->qentry ||
 305	    (lnk && !smc_link_usable(lnk)) || list_empty(&lgr->list)) {
 306		smc_llc_flow_qentry_del(flow);
 307		goto out;
 308	}
 309	rcv_msg = flow->qentry->msg.raw.hdr.common.type;
 310	if (exp_msg && rcv_msg != exp_msg) {
 311		if (exp_msg == SMC_LLC_ADD_LINK &&
 312		    rcv_msg == SMC_LLC_DELETE_LINK) {
 313			/* flow_start will delay the unexpected msg */
 314			smc_llc_flow_start(&lgr->llc_flow_lcl,
 315					   smc_llc_flow_qentry_clr(flow));
 316			return NULL;
 317		}
 318		pr_warn_once("smc: SMC-R lg %*phN dropped unexpected LLC msg: "
 319			     "msg %d exp %d flow %d role %d flags %x\n",
 320			     SMC_LGR_ID_SIZE, &lgr->id, rcv_msg, exp_msg,
 321			     flow->type, lgr->role,
 322			     flow->qentry->msg.raw.hdr.flags);
 323		smc_llc_flow_qentry_del(flow);
 324	}
 325out:
 326	return flow->qentry;
 327}
 328
 329/********************************** send *************************************/
 330
 331struct smc_llc_tx_pend {
 332};
 333
 334/* handler for send/transmission completion of an LLC msg */
 335static void smc_llc_tx_handler(struct smc_wr_tx_pend_priv *pend,
 336			       struct smc_link *link,
 337			       enum ib_wc_status wc_status)
 338{
 339	/* future work: handle wc_status error for recovery and failover */
 340}
 341
 342/**
 343 * smc_llc_add_pending_send() - add LLC control message to pending WQE transmits
 344 * @link: Pointer to SMC link used for sending LLC control message.
 345 * @wr_buf: Out variable returning pointer to work request payload buffer.
 346 * @pend: Out variable returning pointer to private pending WR tracking.
 347 *	  It's the context the transmit complete handler will get.
 348 *
 349 * Reserves and pre-fills an entry for a pending work request send/tx.
 350 * Used by mid-level smc_llc_send_msg() to prepare for later actual send/tx.
 351 * Can sleep due to smc_get_ctrl_buf (if not in softirq context).
 352 *
 353 * Return: 0 on success, otherwise an error value.
 354 */
 355static int smc_llc_add_pending_send(struct smc_link *link,
 356				    struct smc_wr_buf **wr_buf,
 357				    struct smc_wr_tx_pend_priv **pend)
 358{
 359	int rc;
 360
 361	rc = smc_wr_tx_get_free_slot(link, smc_llc_tx_handler, wr_buf, NULL,
 362				     pend);
 363	if (rc < 0)
 364		return rc;
 365	BUILD_BUG_ON_MSG(
 366		sizeof(union smc_llc_msg) > SMC_WR_BUF_SIZE,
 367		"must increase SMC_WR_BUF_SIZE to at least sizeof(struct smc_llc_msg)");
 368	BUILD_BUG_ON_MSG(
 369		sizeof(union smc_llc_msg) != SMC_WR_TX_SIZE,
 370		"must adapt SMC_WR_TX_SIZE to sizeof(struct smc_llc_msg); if not all smc_wr upper layer protocols use the same message size any more, must start to set link->wr_tx_sges[i].length on each individual smc_wr_tx_send()");
 371	BUILD_BUG_ON_MSG(
 372		sizeof(struct smc_llc_tx_pend) > SMC_WR_TX_PEND_PRIV_SIZE,
 373		"must increase SMC_WR_TX_PEND_PRIV_SIZE to at least sizeof(struct smc_llc_tx_pend)");
 374	return 0;
 375}
 376
 377/* high-level API to send LLC confirm link */
 378int smc_llc_send_confirm_link(struct smc_link *link,
 379			      enum smc_llc_reqresp reqresp)
 380{
 381	struct smc_llc_msg_confirm_link *confllc;
 382	struct smc_wr_tx_pend_priv *pend;
 383	struct smc_wr_buf *wr_buf;
 384	int rc;
 385
 386	if (!smc_wr_tx_link_hold(link))
 387		return -ENOLINK;
 388	rc = smc_llc_add_pending_send(link, &wr_buf, &pend);
 389	if (rc)
 390		goto put_out;
 391	confllc = (struct smc_llc_msg_confirm_link *)wr_buf;
 392	memset(confllc, 0, sizeof(*confllc));
 393	confllc->hd.common.type = SMC_LLC_CONFIRM_LINK;
 394	confllc->hd.length = sizeof(struct smc_llc_msg_confirm_link);
 395	confllc->hd.flags |= SMC_LLC_FLAG_NO_RMBE_EYEC;
 396	if (reqresp == SMC_LLC_RESP)
 397		confllc->hd.flags |= SMC_LLC_FLAG_RESP;
 398	memcpy(confllc->sender_mac, link->smcibdev->mac[link->ibport - 1],
 399	       ETH_ALEN);
 400	memcpy(confllc->sender_gid, link->gid, SMC_GID_SIZE);
 401	hton24(confllc->sender_qp_num, link->roce_qp->qp_num);
 402	confllc->link_num = link->link_id;
 403	memcpy(confllc->link_uid, link->link_uid, SMC_LGR_ID_SIZE);
 404	confllc->max_links = SMC_LLC_ADD_LNK_MAX_LINKS;
 405	/* send llc message */
 406	rc = smc_wr_tx_send(link, pend);
 407put_out:
 408	smc_wr_tx_link_put(link);
 409	return rc;
 410}
 411
 412/* send LLC confirm rkey request */
 413static int smc_llc_send_confirm_rkey(struct smc_link *send_link,
 414				     struct smc_buf_desc *rmb_desc)
 415{
 416	struct smc_llc_msg_confirm_rkey *rkeyllc;
 417	struct smc_wr_tx_pend_priv *pend;
 418	struct smc_wr_buf *wr_buf;
 419	struct smc_link *link;
 420	int i, rc, rtok_ix;
 421
 422	if (!smc_wr_tx_link_hold(send_link))
 423		return -ENOLINK;
 424	rc = smc_llc_add_pending_send(send_link, &wr_buf, &pend);
 425	if (rc)
 426		goto put_out;
 427	rkeyllc = (struct smc_llc_msg_confirm_rkey *)wr_buf;
 428	memset(rkeyllc, 0, sizeof(*rkeyllc));
 429	rkeyllc->hd.common.type = SMC_LLC_CONFIRM_RKEY;
 430	rkeyllc->hd.length = sizeof(struct smc_llc_msg_confirm_rkey);
 431
 432	rtok_ix = 1;
 433	for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
 434		link = &send_link->lgr->lnk[i];
 435		if (smc_link_active(link) && link != send_link) {
 436			rkeyllc->rtoken[rtok_ix].link_id = link->link_id;
 437			rkeyllc->rtoken[rtok_ix].rmb_key =
 438				htonl(rmb_desc->mr_rx[link->link_idx]->rkey);
 439			rkeyllc->rtoken[rtok_ix].rmb_vaddr = cpu_to_be64(
 440				(u64)sg_dma_address(
 441					rmb_desc->sgt[link->link_idx].sgl));
 442			rtok_ix++;
 443		}
 444	}
 445	/* rkey of send_link is in rtoken[0] */
 446	rkeyllc->rtoken[0].num_rkeys = rtok_ix - 1;
 447	rkeyllc->rtoken[0].rmb_key =
 448		htonl(rmb_desc->mr_rx[send_link->link_idx]->rkey);
 449	rkeyllc->rtoken[0].rmb_vaddr = cpu_to_be64(
 450		(u64)sg_dma_address(rmb_desc->sgt[send_link->link_idx].sgl));
 451	/* send llc message */
 452	rc = smc_wr_tx_send(send_link, pend);
 453put_out:
 454	smc_wr_tx_link_put(send_link);
 455	return rc;
 456}
 457
 458/* send LLC delete rkey request */
 459static int smc_llc_send_delete_rkey(struct smc_link *link,
 460				    struct smc_buf_desc *rmb_desc)
 461{
 462	struct smc_llc_msg_delete_rkey *rkeyllc;
 463	struct smc_wr_tx_pend_priv *pend;
 464	struct smc_wr_buf *wr_buf;
 465	int rc;
 466
 467	if (!smc_wr_tx_link_hold(link))
 468		return -ENOLINK;
 469	rc = smc_llc_add_pending_send(link, &wr_buf, &pend);
 470	if (rc)
 471		goto put_out;
 472	rkeyllc = (struct smc_llc_msg_delete_rkey *)wr_buf;
 473	memset(rkeyllc, 0, sizeof(*rkeyllc));
 474	rkeyllc->hd.common.type = SMC_LLC_DELETE_RKEY;
 475	rkeyllc->hd.length = sizeof(struct smc_llc_msg_delete_rkey);
 476	rkeyllc->num_rkeys = 1;
 477	rkeyllc->rkey[0] = htonl(rmb_desc->mr_rx[link->link_idx]->rkey);
 478	/* send llc message */
 479	rc = smc_wr_tx_send(link, pend);
 480put_out:
 481	smc_wr_tx_link_put(link);
 482	return rc;
 483}
 484
 485/* send ADD LINK request or response */
 486int smc_llc_send_add_link(struct smc_link *link, u8 mac[], u8 gid[],
 487			  struct smc_link *link_new,
 488			  enum smc_llc_reqresp reqresp)
 489{
 490	struct smc_llc_msg_add_link *addllc;
 491	struct smc_wr_tx_pend_priv *pend;
 492	struct smc_wr_buf *wr_buf;
 493	int rc;
 494
 495	if (!smc_wr_tx_link_hold(link))
 496		return -ENOLINK;
 497	rc = smc_llc_add_pending_send(link, &wr_buf, &pend);
 498	if (rc)
 499		goto put_out;
 500	addllc = (struct smc_llc_msg_add_link *)wr_buf;
 501
 502	memset(addllc, 0, sizeof(*addllc));
 503	addllc->hd.common.type = SMC_LLC_ADD_LINK;
 504	addllc->hd.length = sizeof(struct smc_llc_msg_add_link);
 505	if (reqresp == SMC_LLC_RESP)
 506		addllc->hd.flags |= SMC_LLC_FLAG_RESP;
 507	memcpy(addllc->sender_mac, mac, ETH_ALEN);
 508	memcpy(addllc->sender_gid, gid, SMC_GID_SIZE);
 509	if (link_new) {
 510		addllc->link_num = link_new->link_id;
 511		hton24(addllc->sender_qp_num, link_new->roce_qp->qp_num);
 512		hton24(addllc->initial_psn, link_new->psn_initial);
 513		if (reqresp == SMC_LLC_REQ)
 514			addllc->qp_mtu = link_new->path_mtu;
 515		else
 516			addllc->qp_mtu = min(link_new->path_mtu,
 517					     link_new->peer_mtu);
 518	}
 519	/* send llc message */
 520	rc = smc_wr_tx_send(link, pend);
 521put_out:
 522	smc_wr_tx_link_put(link);
 523	return rc;
 524}
 525
 526/* send DELETE LINK request or response */
 527int smc_llc_send_delete_link(struct smc_link *link, u8 link_del_id,
 528			     enum smc_llc_reqresp reqresp, bool orderly,
 529			     u32 reason)
 530{
 531	struct smc_llc_msg_del_link *delllc;
 532	struct smc_wr_tx_pend_priv *pend;
 533	struct smc_wr_buf *wr_buf;
 534	int rc;
 535
 536	if (!smc_wr_tx_link_hold(link))
 537		return -ENOLINK;
 538	rc = smc_llc_add_pending_send(link, &wr_buf, &pend);
 539	if (rc)
 540		goto put_out;
 541	delllc = (struct smc_llc_msg_del_link *)wr_buf;
 542
 543	memset(delllc, 0, sizeof(*delllc));
 544	delllc->hd.common.type = SMC_LLC_DELETE_LINK;
 545	delllc->hd.length = sizeof(struct smc_llc_msg_del_link);
 546	if (reqresp == SMC_LLC_RESP)
 547		delllc->hd.flags |= SMC_LLC_FLAG_RESP;
 548	if (orderly)
 549		delllc->hd.flags |= SMC_LLC_FLAG_DEL_LINK_ORDERLY;
 550	if (link_del_id)
 551		delllc->link_num = link_del_id;
 552	else
 553		delllc->hd.flags |= SMC_LLC_FLAG_DEL_LINK_ALL;
 554	delllc->reason = htonl(reason);
 555	/* send llc message */
 556	rc = smc_wr_tx_send(link, pend);
 557put_out:
 558	smc_wr_tx_link_put(link);
 559	return rc;
 560}
 561
 562/* send LLC test link request */
 563static int smc_llc_send_test_link(struct smc_link *link, u8 user_data[16])
 564{
 565	struct smc_llc_msg_test_link *testllc;
 566	struct smc_wr_tx_pend_priv *pend;
 567	struct smc_wr_buf *wr_buf;
 568	int rc;
 569
 570	if (!smc_wr_tx_link_hold(link))
 571		return -ENOLINK;
 572	rc = smc_llc_add_pending_send(link, &wr_buf, &pend);
 573	if (rc)
 574		goto put_out;
 575	testllc = (struct smc_llc_msg_test_link *)wr_buf;
 576	memset(testllc, 0, sizeof(*testllc));
 577	testllc->hd.common.type = SMC_LLC_TEST_LINK;
 578	testllc->hd.length = sizeof(struct smc_llc_msg_test_link);
 579	memcpy(testllc->user_data, user_data, sizeof(testllc->user_data));
 580	/* send llc message */
 581	rc = smc_wr_tx_send(link, pend);
 582put_out:
 583	smc_wr_tx_link_put(link);
 584	return rc;
 585}
 586
 587/* schedule an llc send on link, may wait for buffers */
 588static int smc_llc_send_message(struct smc_link *link, void *llcbuf)
 589{
 590	struct smc_wr_tx_pend_priv *pend;
 591	struct smc_wr_buf *wr_buf;
 592	int rc;
 593
 594	if (!smc_wr_tx_link_hold(link))
 595		return -ENOLINK;
 596	rc = smc_llc_add_pending_send(link, &wr_buf, &pend);
 597	if (rc)
 598		goto put_out;
 599	memcpy(wr_buf, llcbuf, sizeof(union smc_llc_msg));
 600	rc = smc_wr_tx_send(link, pend);
 601put_out:
 602	smc_wr_tx_link_put(link);
 603	return rc;
 604}
 605
 606/* schedule an llc send on link, may wait for buffers,
 607 * and wait for send completion notification.
 608 * @return 0 on success
 609 */
 610static int smc_llc_send_message_wait(struct smc_link *link, void *llcbuf)
 611{
 612	struct smc_wr_tx_pend_priv *pend;
 613	struct smc_wr_buf *wr_buf;
 614	int rc;
 615
 616	if (!smc_wr_tx_link_hold(link))
 617		return -ENOLINK;
 618	rc = smc_llc_add_pending_send(link, &wr_buf, &pend);
 619	if (rc)
 620		goto put_out;
 621	memcpy(wr_buf, llcbuf, sizeof(union smc_llc_msg));
 622	rc = smc_wr_tx_send_wait(link, pend, SMC_LLC_WAIT_TIME);
 623put_out:
 624	smc_wr_tx_link_put(link);
 625	return rc;
 626}
 627
 628/********************************* receive ***********************************/
 629
 630static int smc_llc_alloc_alt_link(struct smc_link_group *lgr,
 631				  enum smc_lgr_type lgr_new_t)
 632{
 633	int i;
 634
 635	if (lgr->type == SMC_LGR_SYMMETRIC ||
 636	    (lgr->type != SMC_LGR_SINGLE &&
 637	     (lgr_new_t == SMC_LGR_ASYMMETRIC_LOCAL ||
 638	      lgr_new_t == SMC_LGR_ASYMMETRIC_PEER)))
 639		return -EMLINK;
 640
 641	if (lgr_new_t == SMC_LGR_ASYMMETRIC_LOCAL ||
 642	    lgr_new_t == SMC_LGR_ASYMMETRIC_PEER) {
 643		for (i = SMC_LINKS_PER_LGR_MAX - 1; i >= 0; i--)
 644			if (lgr->lnk[i].state == SMC_LNK_UNUSED)
 645				return i;
 646	} else {
 647		for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++)
 648			if (lgr->lnk[i].state == SMC_LNK_UNUSED)
 649				return i;
 650	}
 651	return -EMLINK;
 652}
 653
 654/* return first buffer from any of the next buf lists */
 655static struct smc_buf_desc *_smc_llc_get_next_rmb(struct smc_link_group *lgr,
 656						  int *buf_lst)
 657{
 658	struct smc_buf_desc *buf_pos;
 659
 660	while (*buf_lst < SMC_RMBE_SIZES) {
 661		buf_pos = list_first_entry_or_null(&lgr->rmbs[*buf_lst],
 662						   struct smc_buf_desc, list);
 663		if (buf_pos)
 664			return buf_pos;
 665		(*buf_lst)++;
 666	}
 667	return NULL;
 668}
 669
 670/* return next rmb from buffer lists */
 671static struct smc_buf_desc *smc_llc_get_next_rmb(struct smc_link_group *lgr,
 672						 int *buf_lst,
 673						 struct smc_buf_desc *buf_pos)
 674{
 675	struct smc_buf_desc *buf_next;
 676
 677	if (!buf_pos || list_is_last(&buf_pos->list, &lgr->rmbs[*buf_lst])) {
 678		(*buf_lst)++;
 679		return _smc_llc_get_next_rmb(lgr, buf_lst);
 680	}
 681	buf_next = list_next_entry(buf_pos, list);
 682	return buf_next;
 683}
 684
 685static struct smc_buf_desc *smc_llc_get_first_rmb(struct smc_link_group *lgr,
 686						  int *buf_lst)
 687{
 688	*buf_lst = 0;
 689	return smc_llc_get_next_rmb(lgr, buf_lst, NULL);
 690}
 691
 692/* send one add_link_continue msg */
 693static int smc_llc_add_link_cont(struct smc_link *link,
 694				 struct smc_link *link_new, u8 *num_rkeys_todo,
 695				 int *buf_lst, struct smc_buf_desc **buf_pos)
 696{
 697	struct smc_llc_msg_add_link_cont *addc_llc;
 698	struct smc_link_group *lgr = link->lgr;
 699	int prim_lnk_idx, lnk_idx, i, rc;
 700	struct smc_wr_tx_pend_priv *pend;
 701	struct smc_wr_buf *wr_buf;
 702	struct smc_buf_desc *rmb;
 703	u8 n;
 704
 705	if (!smc_wr_tx_link_hold(link))
 706		return -ENOLINK;
 707	rc = smc_llc_add_pending_send(link, &wr_buf, &pend);
 708	if (rc)
 709		goto put_out;
 710	addc_llc = (struct smc_llc_msg_add_link_cont *)wr_buf;
 711	memset(addc_llc, 0, sizeof(*addc_llc));
 712
 713	prim_lnk_idx = link->link_idx;
 714	lnk_idx = link_new->link_idx;
 715	addc_llc->link_num = link_new->link_id;
 716	addc_llc->num_rkeys = *num_rkeys_todo;
 717	n = *num_rkeys_todo;
 718	for (i = 0; i < min_t(u8, n, SMC_LLC_RKEYS_PER_CONT_MSG); i++) {
 719		if (!*buf_pos) {
 720			addc_llc->num_rkeys = addc_llc->num_rkeys -
 721					      *num_rkeys_todo;
 722			*num_rkeys_todo = 0;
 723			break;
 724		}
 725		rmb = *buf_pos;
 726
 727		addc_llc->rt[i].rmb_key = htonl(rmb->mr_rx[prim_lnk_idx]->rkey);
 728		addc_llc->rt[i].rmb_key_new = htonl(rmb->mr_rx[lnk_idx]->rkey);
 729		addc_llc->rt[i].rmb_vaddr_new =
 730			cpu_to_be64((u64)sg_dma_address(rmb->sgt[lnk_idx].sgl));
 731
 732		(*num_rkeys_todo)--;
 733		*buf_pos = smc_llc_get_next_rmb(lgr, buf_lst, *buf_pos);
 734		while (*buf_pos && !(*buf_pos)->used)
 735			*buf_pos = smc_llc_get_next_rmb(lgr, buf_lst, *buf_pos);
 736	}
 737	addc_llc->hd.common.type = SMC_LLC_ADD_LINK_CONT;
 738	addc_llc->hd.length = sizeof(struct smc_llc_msg_add_link_cont);
 739	if (lgr->role == SMC_CLNT)
 740		addc_llc->hd.flags |= SMC_LLC_FLAG_RESP;
 741	rc = smc_wr_tx_send(link, pend);
 742put_out:
 743	smc_wr_tx_link_put(link);
 744	return rc;
 745}
 746
 747static int smc_llc_cli_rkey_exchange(struct smc_link *link,
 748				     struct smc_link *link_new)
 749{
 750	struct smc_llc_msg_add_link_cont *addc_llc;
 751	struct smc_link_group *lgr = link->lgr;
 752	u8 max, num_rkeys_send, num_rkeys_recv;
 753	struct smc_llc_qentry *qentry;
 754	struct smc_buf_desc *buf_pos;
 755	int buf_lst;
 756	int rc = 0;
 757	int i;
 758
 759	mutex_lock(&lgr->rmbs_lock);
 760	num_rkeys_send = lgr->conns_num;
 761	buf_pos = smc_llc_get_first_rmb(lgr, &buf_lst);
 762	do {
 763		qentry = smc_llc_wait(lgr, NULL, SMC_LLC_WAIT_TIME,
 764				      SMC_LLC_ADD_LINK_CONT);
 765		if (!qentry) {
 766			rc = -ETIMEDOUT;
 767			break;
 768		}
 769		addc_llc = &qentry->msg.add_link_cont;
 770		num_rkeys_recv = addc_llc->num_rkeys;
 771		max = min_t(u8, num_rkeys_recv, SMC_LLC_RKEYS_PER_CONT_MSG);
 772		for (i = 0; i < max; i++) {
 773			smc_rtoken_set(lgr, link->link_idx, link_new->link_idx,
 774				       addc_llc->rt[i].rmb_key,
 775				       addc_llc->rt[i].rmb_vaddr_new,
 776				       addc_llc->rt[i].rmb_key_new);
 777			num_rkeys_recv--;
 778		}
 779		smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
 780		rc = smc_llc_add_link_cont(link, link_new, &num_rkeys_send,
 781					   &buf_lst, &buf_pos);
 782		if (rc)
 783			break;
 784	} while (num_rkeys_send || num_rkeys_recv);
 785
 786	mutex_unlock(&lgr->rmbs_lock);
 787	return rc;
 788}
 789
 790/* prepare and send an add link reject response */
 791static int smc_llc_cli_add_link_reject(struct smc_llc_qentry *qentry)
 792{
 793	qentry->msg.raw.hdr.flags |= SMC_LLC_FLAG_RESP;
 794	qentry->msg.raw.hdr.flags |= SMC_LLC_FLAG_ADD_LNK_REJ;
 795	qentry->msg.raw.hdr.add_link_rej_rsn = SMC_LLC_REJ_RSN_NO_ALT_PATH;
 796	return smc_llc_send_message(qentry->link, &qentry->msg);
 797}
 798
 799static int smc_llc_cli_conf_link(struct smc_link *link,
 800				 struct smc_init_info *ini,
 801				 struct smc_link *link_new,
 802				 enum smc_lgr_type lgr_new_t)
 803{
 804	struct smc_link_group *lgr = link->lgr;
 805	struct smc_llc_qentry *qentry = NULL;
 806	int rc = 0;
 807
 808	/* receive CONFIRM LINK request over RoCE fabric */
 809	qentry = smc_llc_wait(lgr, NULL, SMC_LLC_WAIT_FIRST_TIME, 0);
 810	if (!qentry) {
 811		rc = smc_llc_send_delete_link(link, link_new->link_id,
 812					      SMC_LLC_REQ, false,
 813					      SMC_LLC_DEL_LOST_PATH);
 814		return -ENOLINK;
 815	}
 816	if (qentry->msg.raw.hdr.common.type != SMC_LLC_CONFIRM_LINK) {
 817		/* received DELETE_LINK instead */
 818		qentry->msg.raw.hdr.flags |= SMC_LLC_FLAG_RESP;
 819		smc_llc_send_message(link, &qentry->msg);
 820		smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
 821		return -ENOLINK;
 822	}
 823	smc_llc_save_peer_uid(qentry);
 824	smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
 825
 826	rc = smc_ib_modify_qp_rts(link_new);
 827	if (rc) {
 828		smc_llc_send_delete_link(link, link_new->link_id, SMC_LLC_REQ,
 829					 false, SMC_LLC_DEL_LOST_PATH);
 830		return -ENOLINK;
 831	}
 832	smc_wr_remember_qp_attr(link_new);
 833
 834	rc = smcr_buf_reg_lgr(link_new);
 835	if (rc) {
 836		smc_llc_send_delete_link(link, link_new->link_id, SMC_LLC_REQ,
 837					 false, SMC_LLC_DEL_LOST_PATH);
 838		return -ENOLINK;
 839	}
 840
 841	/* send CONFIRM LINK response over RoCE fabric */
 842	rc = smc_llc_send_confirm_link(link_new, SMC_LLC_RESP);
 843	if (rc) {
 844		smc_llc_send_delete_link(link, link_new->link_id, SMC_LLC_REQ,
 845					 false, SMC_LLC_DEL_LOST_PATH);
 846		return -ENOLINK;
 847	}
 848	smc_llc_link_active(link_new);
 849	if (lgr_new_t == SMC_LGR_ASYMMETRIC_LOCAL ||
 850	    lgr_new_t == SMC_LGR_ASYMMETRIC_PEER)
 851		smcr_lgr_set_type_asym(lgr, lgr_new_t, link_new->link_idx);
 852	else
 853		smcr_lgr_set_type(lgr, lgr_new_t);
 854	return 0;
 855}
 856
 857static void smc_llc_save_add_link_info(struct smc_link *link,
 858				       struct smc_llc_msg_add_link *add_llc)
 859{
 860	link->peer_qpn = ntoh24(add_llc->sender_qp_num);
 861	memcpy(link->peer_gid, add_llc->sender_gid, SMC_GID_SIZE);
 862	memcpy(link->peer_mac, add_llc->sender_mac, ETH_ALEN);
 863	link->peer_psn = ntoh24(add_llc->initial_psn);
 864	link->peer_mtu = add_llc->qp_mtu;
 865}
 866
 867/* as an SMC client, process an add link request */
 868int smc_llc_cli_add_link(struct smc_link *link, struct smc_llc_qentry *qentry)
 869{
 870	struct smc_llc_msg_add_link *llc = &qentry->msg.add_link;
 871	enum smc_lgr_type lgr_new_t = SMC_LGR_SYMMETRIC;
 872	struct smc_link_group *lgr = smc_get_lgr(link);
 873	struct smc_link *lnk_new = NULL;
 874	struct smc_init_info ini;
 875	int lnk_idx, rc = 0;
 876
 877	if (!llc->qp_mtu)
 878		goto out_reject;
 879
 880	ini.vlan_id = lgr->vlan_id;
 881	smc_pnet_find_alt_roce(lgr, &ini, link->smcibdev);
 882	if (!memcmp(llc->sender_gid, link->peer_gid, SMC_GID_SIZE) &&
 883	    !memcmp(llc->sender_mac, link->peer_mac, ETH_ALEN)) {
 884		if (!ini.ib_dev)
 885			goto out_reject;
 886		lgr_new_t = SMC_LGR_ASYMMETRIC_PEER;
 887	}
 888	if (!ini.ib_dev) {
 889		lgr_new_t = SMC_LGR_ASYMMETRIC_LOCAL;
 890		ini.ib_dev = link->smcibdev;
 891		ini.ib_port = link->ibport;
 892	}
 893	lnk_idx = smc_llc_alloc_alt_link(lgr, lgr_new_t);
 894	if (lnk_idx < 0)
 895		goto out_reject;
 896	lnk_new = &lgr->lnk[lnk_idx];
 897	rc = smcr_link_init(lgr, lnk_new, lnk_idx, &ini);
 898	if (rc)
 899		goto out_reject;
 900	smc_llc_save_add_link_info(lnk_new, llc);
 901	lnk_new->link_id = llc->link_num;	/* SMC server assigns link id */
 902	smc_llc_link_set_uid(lnk_new);
 903
 904	rc = smc_ib_ready_link(lnk_new);
 905	if (rc)
 906		goto out_clear_lnk;
 907
 908	rc = smcr_buf_map_lgr(lnk_new);
 909	if (rc)
 910		goto out_clear_lnk;
 911
 912	rc = smc_llc_send_add_link(link,
 913				   lnk_new->smcibdev->mac[ini.ib_port - 1],
 914				   lnk_new->gid, lnk_new, SMC_LLC_RESP);
 915	if (rc)
 916		goto out_clear_lnk;
 917	rc = smc_llc_cli_rkey_exchange(link, lnk_new);
 918	if (rc) {
 919		rc = 0;
 920		goto out_clear_lnk;
 921	}
 922	rc = smc_llc_cli_conf_link(link, &ini, lnk_new, lgr_new_t);
 923	if (!rc)
 924		goto out;
 925out_clear_lnk:
 926	lnk_new->state = SMC_LNK_INACTIVE;
 927	smcr_link_clear(lnk_new, false);
 928out_reject:
 929	smc_llc_cli_add_link_reject(qentry);
 930out:
 931	kfree(qentry);
 932	return rc;
 933}
 934
 935/* as an SMC client, invite server to start the add_link processing */
 936static void smc_llc_cli_add_link_invite(struct smc_link *link,
 937					struct smc_llc_qentry *qentry)
 938{
 939	struct smc_link_group *lgr = smc_get_lgr(link);
 940	struct smc_init_info ini;
 941
 942	if (lgr->type == SMC_LGR_SYMMETRIC ||
 943	    lgr->type == SMC_LGR_ASYMMETRIC_PEER)
 944		goto out;
 945
 946	ini.vlan_id = lgr->vlan_id;
 947	smc_pnet_find_alt_roce(lgr, &ini, link->smcibdev);
 948	if (!ini.ib_dev)
 949		goto out;
 950
 951	smc_llc_send_add_link(link, ini.ib_dev->mac[ini.ib_port - 1],
 952			      ini.ib_gid, NULL, SMC_LLC_REQ);
 953out:
 954	kfree(qentry);
 955}
 956
 957static bool smc_llc_is_empty_llc_message(union smc_llc_msg *llc)
 958{
 959	int i;
 960
 961	for (i = 0; i < ARRAY_SIZE(llc->raw.data); i++)
 962		if (llc->raw.data[i])
 963			return false;
 964	return true;
 965}
 966
 967static bool smc_llc_is_local_add_link(union smc_llc_msg *llc)
 968{
 969	if (llc->raw.hdr.common.type == SMC_LLC_ADD_LINK &&
 970	    smc_llc_is_empty_llc_message(llc))
 971		return true;
 972	return false;
 973}
 974
 975static void smc_llc_process_cli_add_link(struct smc_link_group *lgr)
 976{
 977	struct smc_llc_qentry *qentry;
 978
 979	qentry = smc_llc_flow_qentry_clr(&lgr->llc_flow_lcl);
 980
 981	mutex_lock(&lgr->llc_conf_mutex);
 982	if (smc_llc_is_local_add_link(&qentry->msg))
 983		smc_llc_cli_add_link_invite(qentry->link, qentry);
 984	else
 985		smc_llc_cli_add_link(qentry->link, qentry);
 986	mutex_unlock(&lgr->llc_conf_mutex);
 987}
 988
 989static int smc_llc_active_link_count(struct smc_link_group *lgr)
 990{
 991	int i, link_count = 0;
 992
 993	for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
 994		if (!smc_link_active(&lgr->lnk[i]))
 995			continue;
 996		link_count++;
 997	}
 998	return link_count;
 999}
1000
1001/* find the asymmetric link when 3 links are established  */
1002static struct smc_link *smc_llc_find_asym_link(struct smc_link_group *lgr)
1003{
1004	int asym_idx = -ENOENT;
1005	int i, j, k;
1006	bool found;
1007
1008	/* determine asymmetric link */
1009	found = false;
1010	for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
1011		for (j = i + 1; j < SMC_LINKS_PER_LGR_MAX; j++) {
1012			if (!smc_link_usable(&lgr->lnk[i]) ||
1013			    !smc_link_usable(&lgr->lnk[j]))
1014				continue;
1015			if (!memcmp(lgr->lnk[i].gid, lgr->lnk[j].gid,
1016				    SMC_GID_SIZE)) {
1017				found = true;	/* asym_lnk is i or j */
1018				break;
1019			}
1020		}
1021		if (found)
1022			break;
1023	}
1024	if (!found)
1025		goto out; /* no asymmetric link */
1026	for (k = 0; k < SMC_LINKS_PER_LGR_MAX; k++) {
1027		if (!smc_link_usable(&lgr->lnk[k]))
1028			continue;
1029		if (k != i &&
1030		    !memcmp(lgr->lnk[i].peer_gid, lgr->lnk[k].peer_gid,
1031			    SMC_GID_SIZE)) {
1032			asym_idx = i;
1033			break;
1034		}
1035		if (k != j &&
1036		    !memcmp(lgr->lnk[j].peer_gid, lgr->lnk[k].peer_gid,
1037			    SMC_GID_SIZE)) {
1038			asym_idx = j;
1039			break;
1040		}
1041	}
1042out:
1043	return (asym_idx < 0) ? NULL : &lgr->lnk[asym_idx];
1044}
1045
1046static void smc_llc_delete_asym_link(struct smc_link_group *lgr)
1047{
1048	struct smc_link *lnk_new = NULL, *lnk_asym;
1049	struct smc_llc_qentry *qentry;
1050	int rc;
1051
1052	lnk_asym = smc_llc_find_asym_link(lgr);
1053	if (!lnk_asym)
1054		return; /* no asymmetric link */
1055	if (!smc_link_downing(&lnk_asym->state))
1056		return;
1057	lnk_new = smc_switch_conns(lgr, lnk_asym, false);
1058	smc_wr_tx_wait_no_pending_sends(lnk_asym);
1059	if (!lnk_new)
1060		goto out_free;
1061	/* change flow type from ADD_LINK into DEL_LINK */
1062	lgr->llc_flow_lcl.type = SMC_LLC_FLOW_DEL_LINK;
1063	rc = smc_llc_send_delete_link(lnk_new, lnk_asym->link_id, SMC_LLC_REQ,
1064				      true, SMC_LLC_DEL_NO_ASYM_NEEDED);
1065	if (rc) {
1066		smcr_link_down_cond(lnk_new);
1067		goto out_free;
1068	}
1069	qentry = smc_llc_wait(lgr, lnk_new, SMC_LLC_WAIT_TIME,
1070			      SMC_LLC_DELETE_LINK);
1071	if (!qentry) {
1072		smcr_link_down_cond(lnk_new);
1073		goto out_free;
1074	}
1075	smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
1076out_free:
1077	smcr_link_clear(lnk_asym, true);
1078}
1079
1080static int smc_llc_srv_rkey_exchange(struct smc_link *link,
1081				     struct smc_link *link_new)
1082{
1083	struct smc_llc_msg_add_link_cont *addc_llc;
1084	struct smc_link_group *lgr = link->lgr;
1085	u8 max, num_rkeys_send, num_rkeys_recv;
1086	struct smc_llc_qentry *qentry = NULL;
1087	struct smc_buf_desc *buf_pos;
1088	int buf_lst;
1089	int rc = 0;
1090	int i;
1091
1092	mutex_lock(&lgr->rmbs_lock);
1093	num_rkeys_send = lgr->conns_num;
1094	buf_pos = smc_llc_get_first_rmb(lgr, &buf_lst);
1095	do {
1096		smc_llc_add_link_cont(link, link_new, &num_rkeys_send,
1097				      &buf_lst, &buf_pos);
1098		qentry = smc_llc_wait(lgr, link, SMC_LLC_WAIT_TIME,
1099				      SMC_LLC_ADD_LINK_CONT);
1100		if (!qentry) {
1101			rc = -ETIMEDOUT;
1102			goto out;
1103		}
1104		addc_llc = &qentry->msg.add_link_cont;
1105		num_rkeys_recv = addc_llc->num_rkeys;
1106		max = min_t(u8, num_rkeys_recv, SMC_LLC_RKEYS_PER_CONT_MSG);
1107		for (i = 0; i < max; i++) {
1108			smc_rtoken_set(lgr, link->link_idx, link_new->link_idx,
1109				       addc_llc->rt[i].rmb_key,
1110				       addc_llc->rt[i].rmb_vaddr_new,
1111				       addc_llc->rt[i].rmb_key_new);
1112			num_rkeys_recv--;
1113		}
1114		smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
1115	} while (num_rkeys_send || num_rkeys_recv);
1116out:
1117	mutex_unlock(&lgr->rmbs_lock);
1118	return rc;
1119}
1120
1121static int smc_llc_srv_conf_link(struct smc_link *link,
1122				 struct smc_link *link_new,
1123				 enum smc_lgr_type lgr_new_t)
1124{
1125	struct smc_link_group *lgr = link->lgr;
1126	struct smc_llc_qentry *qentry = NULL;
1127	int rc;
1128
1129	/* send CONFIRM LINK request over the RoCE fabric */
1130	rc = smc_llc_send_confirm_link(link_new, SMC_LLC_REQ);
1131	if (rc)
1132		return -ENOLINK;
1133	/* receive CONFIRM LINK response over the RoCE fabric */
1134	qentry = smc_llc_wait(lgr, link, SMC_LLC_WAIT_FIRST_TIME, 0);
1135	if (!qentry ||
1136	    qentry->msg.raw.hdr.common.type != SMC_LLC_CONFIRM_LINK) {
1137		/* send DELETE LINK */
1138		smc_llc_send_delete_link(link, link_new->link_id, SMC_LLC_REQ,
1139					 false, SMC_LLC_DEL_LOST_PATH);
1140		if (qentry)
1141			smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
1142		return -ENOLINK;
1143	}
1144	smc_llc_save_peer_uid(qentry);
1145	smc_llc_link_active(link_new);
1146	if (lgr_new_t == SMC_LGR_ASYMMETRIC_LOCAL ||
1147	    lgr_new_t == SMC_LGR_ASYMMETRIC_PEER)
1148		smcr_lgr_set_type_asym(lgr, lgr_new_t, link_new->link_idx);
1149	else
1150		smcr_lgr_set_type(lgr, lgr_new_t);
1151	smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
1152	return 0;
1153}
1154
1155int smc_llc_srv_add_link(struct smc_link *link)
1156{
1157	enum smc_lgr_type lgr_new_t = SMC_LGR_SYMMETRIC;
1158	struct smc_link_group *lgr = link->lgr;
1159	struct smc_llc_msg_add_link *add_llc;
1160	struct smc_llc_qentry *qentry = NULL;
1161	struct smc_link *link_new;
1162	struct smc_init_info ini;
1163	int lnk_idx, rc = 0;
1164
1165	/* ignore client add link recommendation, start new flow */
1166	ini.vlan_id = lgr->vlan_id;
1167	smc_pnet_find_alt_roce(lgr, &ini, link->smcibdev);
1168	if (!ini.ib_dev) {
1169		lgr_new_t = SMC_LGR_ASYMMETRIC_LOCAL;
1170		ini.ib_dev = link->smcibdev;
1171		ini.ib_port = link->ibport;
1172	}
1173	lnk_idx = smc_llc_alloc_alt_link(lgr, lgr_new_t);
1174	if (lnk_idx < 0)
1175		return 0;
1176
1177	rc = smcr_link_init(lgr, &lgr->lnk[lnk_idx], lnk_idx, &ini);
1178	if (rc)
1179		return rc;
1180	link_new = &lgr->lnk[lnk_idx];
1181	rc = smc_llc_send_add_link(link,
1182				   link_new->smcibdev->mac[ini.ib_port - 1],
1183				   link_new->gid, link_new, SMC_LLC_REQ);
1184	if (rc)
1185		goto out_err;
1186	/* receive ADD LINK response over the RoCE fabric */
1187	qentry = smc_llc_wait(lgr, link, SMC_LLC_WAIT_TIME, SMC_LLC_ADD_LINK);
1188	if (!qentry) {
1189		rc = -ETIMEDOUT;
1190		goto out_err;
1191	}
1192	add_llc = &qentry->msg.add_link;
1193	if (add_llc->hd.flags & SMC_LLC_FLAG_ADD_LNK_REJ) {
1194		smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
1195		rc = -ENOLINK;
1196		goto out_err;
1197	}
1198	if (lgr->type == SMC_LGR_SINGLE &&
1199	    (!memcmp(add_llc->sender_gid, link->peer_gid, SMC_GID_SIZE) &&
1200	     !memcmp(add_llc->sender_mac, link->peer_mac, ETH_ALEN))) {
1201		lgr_new_t = SMC_LGR_ASYMMETRIC_PEER;
1202	}
1203	smc_llc_save_add_link_info(link_new, add_llc);
1204	smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
1205
1206	rc = smc_ib_ready_link(link_new);
1207	if (rc)
1208		goto out_err;
1209	rc = smcr_buf_map_lgr(link_new);
1210	if (rc)
1211		goto out_err;
1212	rc = smcr_buf_reg_lgr(link_new);
1213	if (rc)
1214		goto out_err;
1215	rc = smc_llc_srv_rkey_exchange(link, link_new);
1216	if (rc)
1217		goto out_err;
1218	rc = smc_llc_srv_conf_link(link, link_new, lgr_new_t);
1219	if (rc)
1220		goto out_err;
1221	return 0;
1222out_err:
1223	link_new->state = SMC_LNK_INACTIVE;
1224	smcr_link_clear(link_new, false);
1225	return rc;
1226}
1227
1228static void smc_llc_process_srv_add_link(struct smc_link_group *lgr)
1229{
1230	struct smc_link *link = lgr->llc_flow_lcl.qentry->link;
1231	int rc;
1232
1233	smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
1234
1235	mutex_lock(&lgr->llc_conf_mutex);
1236	rc = smc_llc_srv_add_link(link);
1237	if (!rc && lgr->type == SMC_LGR_SYMMETRIC) {
1238		/* delete any asymmetric link */
1239		smc_llc_delete_asym_link(lgr);
1240	}
1241	mutex_unlock(&lgr->llc_conf_mutex);
1242}
1243
1244/* enqueue a local add_link req to trigger a new add_link flow */
1245void smc_llc_add_link_local(struct smc_link *link)
1246{
1247	struct smc_llc_msg_add_link add_llc = {};
1248
1249	add_llc.hd.length = sizeof(add_llc);
1250	add_llc.hd.common.type = SMC_LLC_ADD_LINK;
1251	/* no dev and port needed */
1252	smc_llc_enqueue(link, (union smc_llc_msg *)&add_llc);
1253}
1254
1255/* worker to process an add link message */
1256static void smc_llc_add_link_work(struct work_struct *work)
1257{
1258	struct smc_link_group *lgr = container_of(work, struct smc_link_group,
1259						  llc_add_link_work);
1260
1261	if (list_empty(&lgr->list)) {
1262		/* link group is terminating */
1263		smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
1264		goto out;
1265	}
1266
1267	if (lgr->role == SMC_CLNT)
1268		smc_llc_process_cli_add_link(lgr);
1269	else
1270		smc_llc_process_srv_add_link(lgr);
1271out:
1272	smc_llc_flow_stop(lgr, &lgr->llc_flow_lcl);
1273}
1274
1275/* enqueue a local del_link msg to trigger a new del_link flow,
1276 * called only for role SMC_SERV
1277 */
1278void smc_llc_srv_delete_link_local(struct smc_link *link, u8 del_link_id)
1279{
1280	struct smc_llc_msg_del_link del_llc = {};
1281
1282	del_llc.hd.length = sizeof(del_llc);
1283	del_llc.hd.common.type = SMC_LLC_DELETE_LINK;
1284	del_llc.link_num = del_link_id;
1285	del_llc.reason = htonl(SMC_LLC_DEL_LOST_PATH);
1286	del_llc.hd.flags |= SMC_LLC_FLAG_DEL_LINK_ORDERLY;
1287	smc_llc_enqueue(link, (union smc_llc_msg *)&del_llc);
1288}
1289
1290static void smc_llc_process_cli_delete_link(struct smc_link_group *lgr)
1291{
1292	struct smc_link *lnk_del = NULL, *lnk_asym, *lnk;
1293	struct smc_llc_msg_del_link *del_llc;
1294	struct smc_llc_qentry *qentry;
1295	int active_links;
1296	int lnk_idx;
1297
1298	qentry = smc_llc_flow_qentry_clr(&lgr->llc_flow_lcl);
1299	lnk = qentry->link;
1300	del_llc = &qentry->msg.delete_link;
1301
1302	if (del_llc->hd.flags & SMC_LLC_FLAG_DEL_LINK_ALL) {
1303		smc_lgr_terminate_sched(lgr);
1304		goto out;
1305	}
1306	mutex_lock(&lgr->llc_conf_mutex);
1307	/* delete single link */
1308	for (lnk_idx = 0; lnk_idx < SMC_LINKS_PER_LGR_MAX; lnk_idx++) {
1309		if (lgr->lnk[lnk_idx].link_id != del_llc->link_num)
1310			continue;
1311		lnk_del = &lgr->lnk[lnk_idx];
1312		break;
1313	}
1314	del_llc->hd.flags |= SMC_LLC_FLAG_RESP;
1315	if (!lnk_del) {
1316		/* link was not found */
1317		del_llc->reason = htonl(SMC_LLC_DEL_NOLNK);
1318		smc_llc_send_message(lnk, &qentry->msg);
1319		goto out_unlock;
1320	}
1321	lnk_asym = smc_llc_find_asym_link(lgr);
1322
1323	del_llc->reason = 0;
1324	smc_llc_send_message(lnk, &qentry->msg); /* response */
1325
1326	if (smc_link_downing(&lnk_del->state))
1327		smc_switch_conns(lgr, lnk_del, false);
1328	smcr_link_clear(lnk_del, true);
1329
1330	active_links = smc_llc_active_link_count(lgr);
1331	if (lnk_del == lnk_asym) {
1332		/* expected deletion of asym link, don't change lgr state */
1333	} else if (active_links == 1) {
1334		smcr_lgr_set_type(lgr, SMC_LGR_SINGLE);
1335	} else if (!active_links) {
1336		smcr_lgr_set_type(lgr, SMC_LGR_NONE);
1337		smc_lgr_terminate_sched(lgr);
1338	}
1339out_unlock:
1340	mutex_unlock(&lgr->llc_conf_mutex);
1341out:
1342	kfree(qentry);
1343}
1344
1345/* try to send a DELETE LINK ALL request on any active link,
1346 * waiting for send completion
1347 */
1348void smc_llc_send_link_delete_all(struct smc_link_group *lgr, bool ord, u32 rsn)
1349{
1350	struct smc_llc_msg_del_link delllc = {};
1351	int i;
1352
1353	delllc.hd.common.type = SMC_LLC_DELETE_LINK;
1354	delllc.hd.length = sizeof(delllc);
1355	if (ord)
1356		delllc.hd.flags |= SMC_LLC_FLAG_DEL_LINK_ORDERLY;
1357	delllc.hd.flags |= SMC_LLC_FLAG_DEL_LINK_ALL;
1358	delllc.reason = htonl(rsn);
1359
1360	for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
1361		if (!smc_link_usable(&lgr->lnk[i]))
1362			continue;
1363		if (!smc_llc_send_message_wait(&lgr->lnk[i], &delllc))
1364			break;
1365	}
1366}
1367
1368static void smc_llc_process_srv_delete_link(struct smc_link_group *lgr)
1369{
1370	struct smc_llc_msg_del_link *del_llc;
1371	struct smc_link *lnk, *lnk_del;
1372	struct smc_llc_qentry *qentry;
1373	int active_links;
1374	int i;
1375
1376	mutex_lock(&lgr->llc_conf_mutex);
1377	qentry = smc_llc_flow_qentry_clr(&lgr->llc_flow_lcl);
1378	lnk = qentry->link;
1379	del_llc = &qentry->msg.delete_link;
1380
1381	if (qentry->msg.delete_link.hd.flags & SMC_LLC_FLAG_DEL_LINK_ALL) {
1382		/* delete entire lgr */
1383		smc_llc_send_link_delete_all(lgr, true, ntohl(
1384					      qentry->msg.delete_link.reason));
1385		smc_lgr_terminate_sched(lgr);
1386		goto out;
1387	}
1388	/* delete single link */
1389	lnk_del = NULL;
1390	for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
1391		if (lgr->lnk[i].link_id == del_llc->link_num) {
1392			lnk_del = &lgr->lnk[i];
1393			break;
1394		}
1395	}
1396	if (!lnk_del)
1397		goto out; /* asymmetric link already deleted */
1398
1399	if (smc_link_downing(&lnk_del->state)) {
1400		if (smc_switch_conns(lgr, lnk_del, false))
1401			smc_wr_tx_wait_no_pending_sends(lnk_del);
1402	}
1403	if (!list_empty(&lgr->list)) {
1404		/* qentry is either a request from peer (send it back to
1405		 * initiate the DELETE_LINK processing), or a locally
1406		 * enqueued DELETE_LINK request (forward it)
1407		 */
1408		if (!smc_llc_send_message(lnk, &qentry->msg)) {
1409			struct smc_llc_qentry *qentry2;
1410
1411			qentry2 = smc_llc_wait(lgr, lnk, SMC_LLC_WAIT_TIME,
1412					       SMC_LLC_DELETE_LINK);
1413			if (qentry2)
1414				smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
1415		}
1416	}
1417	smcr_link_clear(lnk_del, true);
1418
1419	active_links = smc_llc_active_link_count(lgr);
1420	if (active_links == 1) {
1421		smcr_lgr_set_type(lgr, SMC_LGR_SINGLE);
1422	} else if (!active_links) {
1423		smcr_lgr_set_type(lgr, SMC_LGR_NONE);
1424		smc_lgr_terminate_sched(lgr);
1425	}
1426
1427	if (lgr->type == SMC_LGR_SINGLE && !list_empty(&lgr->list)) {
1428		/* trigger setup of asymm alt link */
1429		smc_llc_add_link_local(lnk);
1430	}
1431out:
1432	mutex_unlock(&lgr->llc_conf_mutex);
1433	kfree(qentry);
1434}
1435
1436static void smc_llc_delete_link_work(struct work_struct *work)
1437{
1438	struct smc_link_group *lgr = container_of(work, struct smc_link_group,
1439						  llc_del_link_work);
1440
1441	if (list_empty(&lgr->list)) {
1442		/* link group is terminating */
1443		smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
1444		goto out;
1445	}
1446
1447	if (lgr->role == SMC_CLNT)
1448		smc_llc_process_cli_delete_link(lgr);
1449	else
1450		smc_llc_process_srv_delete_link(lgr);
1451out:
1452	smc_llc_flow_stop(lgr, &lgr->llc_flow_lcl);
1453}
1454
1455/* process a confirm_rkey request from peer, remote flow */
1456static void smc_llc_rmt_conf_rkey(struct smc_link_group *lgr)
1457{
1458	struct smc_llc_msg_confirm_rkey *llc;
1459	struct smc_llc_qentry *qentry;
1460	struct smc_link *link;
1461	int num_entries;
1462	int rk_idx;
1463	int i;
1464
1465	qentry = lgr->llc_flow_rmt.qentry;
1466	llc = &qentry->msg.confirm_rkey;
1467	link = qentry->link;
1468
1469	num_entries = llc->rtoken[0].num_rkeys;
1470	/* first rkey entry is for receiving link */
1471	rk_idx = smc_rtoken_add(link,
1472				llc->rtoken[0].rmb_vaddr,
1473				llc->rtoken[0].rmb_key);
1474	if (rk_idx < 0)
1475		goto out_err;
1476
1477	for (i = 1; i <= min_t(u8, num_entries, SMC_LLC_RKEYS_PER_MSG - 1); i++)
1478		smc_rtoken_set2(lgr, rk_idx, llc->rtoken[i].link_id,
1479				llc->rtoken[i].rmb_vaddr,
1480				llc->rtoken[i].rmb_key);
1481	/* max links is 3 so there is no need to support conf_rkey_cont msgs */
1482	goto out;
1483out_err:
1484	llc->hd.flags |= SMC_LLC_FLAG_RKEY_NEG;
1485	llc->hd.flags |= SMC_LLC_FLAG_RKEY_RETRY;
1486out:
1487	llc->hd.flags |= SMC_LLC_FLAG_RESP;
1488	smc_llc_send_message(link, &qentry->msg);
1489	smc_llc_flow_qentry_del(&lgr->llc_flow_rmt);
1490}
1491
1492/* process a delete_rkey request from peer, remote flow */
1493static void smc_llc_rmt_delete_rkey(struct smc_link_group *lgr)
1494{
1495	struct smc_llc_msg_delete_rkey *llc;
1496	struct smc_llc_qentry *qentry;
1497	struct smc_link *link;
1498	u8 err_mask = 0;
1499	int i, max;
1500
1501	qentry = lgr->llc_flow_rmt.qentry;
1502	llc = &qentry->msg.delete_rkey;
1503	link = qentry->link;
1504
1505	max = min_t(u8, llc->num_rkeys, SMC_LLC_DEL_RKEY_MAX);
1506	for (i = 0; i < max; i++) {
1507		if (smc_rtoken_delete(link, llc->rkey[i]))
1508			err_mask |= 1 << (SMC_LLC_DEL_RKEY_MAX - 1 - i);
1509	}
1510	if (err_mask) {
1511		llc->hd.flags |= SMC_LLC_FLAG_RKEY_NEG;
1512		llc->err_mask = err_mask;
1513	}
1514	llc->hd.flags |= SMC_LLC_FLAG_RESP;
1515	smc_llc_send_message(link, &qentry->msg);
1516	smc_llc_flow_qentry_del(&lgr->llc_flow_rmt);
1517}
1518
1519static void smc_llc_protocol_violation(struct smc_link_group *lgr, u8 type)
1520{
1521	pr_warn_ratelimited("smc: SMC-R lg %*phN LLC protocol violation: "
1522			    "llc_type %d\n", SMC_LGR_ID_SIZE, &lgr->id, type);
1523	smc_llc_set_termination_rsn(lgr, SMC_LLC_DEL_PROT_VIOL);
1524	smc_lgr_terminate_sched(lgr);
1525}
1526
1527/* flush the llc event queue */
1528static void smc_llc_event_flush(struct smc_link_group *lgr)
1529{
1530	struct smc_llc_qentry *qentry, *q;
1531
1532	spin_lock_bh(&lgr->llc_event_q_lock);
1533	list_for_each_entry_safe(qentry, q, &lgr->llc_event_q, list) {
1534		list_del_init(&qentry->list);
1535		kfree(qentry);
1536	}
1537	spin_unlock_bh(&lgr->llc_event_q_lock);
1538}
1539
1540static void smc_llc_event_handler(struct smc_llc_qentry *qentry)
1541{
1542	union smc_llc_msg *llc = &qentry->msg;
1543	struct smc_link *link = qentry->link;
1544	struct smc_link_group *lgr = link->lgr;
1545
1546	if (!smc_link_usable(link))
1547		goto out;
1548
1549	switch (llc->raw.hdr.common.type) {
1550	case SMC_LLC_TEST_LINK:
1551		llc->test_link.hd.flags |= SMC_LLC_FLAG_RESP;
1552		smc_llc_send_message(link, llc);
1553		break;
1554	case SMC_LLC_ADD_LINK:
1555		if (list_empty(&lgr->list))
1556			goto out;	/* lgr is terminating */
1557		if (lgr->role == SMC_CLNT) {
1558			if (smc_llc_is_local_add_link(llc)) {
1559				if (lgr->llc_flow_lcl.type ==
1560				    SMC_LLC_FLOW_ADD_LINK)
1561					break;	/* add_link in progress */
1562				if (smc_llc_flow_start(&lgr->llc_flow_lcl,
1563						       qentry)) {
1564					schedule_work(&lgr->llc_add_link_work);
1565				}
1566				return;
1567			}
1568			if (lgr->llc_flow_lcl.type == SMC_LLC_FLOW_ADD_LINK &&
1569			    !lgr->llc_flow_lcl.qentry) {
1570				/* a flow is waiting for this message */
1571				smc_llc_flow_qentry_set(&lgr->llc_flow_lcl,
1572							qentry);
1573				wake_up(&lgr->llc_msg_waiter);
1574			} else if (smc_llc_flow_start(&lgr->llc_flow_lcl,
1575						      qentry)) {
1576				schedule_work(&lgr->llc_add_link_work);
1577			}
1578		} else if (smc_llc_flow_start(&lgr->llc_flow_lcl, qentry)) {
1579			/* as smc server, handle client suggestion */
1580			schedule_work(&lgr->llc_add_link_work);
1581		}
1582		return;
1583	case SMC_LLC_CONFIRM_LINK:
1584	case SMC_LLC_ADD_LINK_CONT:
1585		if (lgr->llc_flow_lcl.type != SMC_LLC_FLOW_NONE) {
1586			/* a flow is waiting for this message */
1587			smc_llc_flow_qentry_set(&lgr->llc_flow_lcl, qentry);
1588			wake_up(&lgr->llc_msg_waiter);
1589			return;
1590		}
1591		break;
1592	case SMC_LLC_DELETE_LINK:
1593		if (lgr->llc_flow_lcl.type == SMC_LLC_FLOW_ADD_LINK &&
1594		    !lgr->llc_flow_lcl.qentry) {
1595			/* DEL LINK REQ during ADD LINK SEQ */
1596			smc_llc_flow_qentry_set(&lgr->llc_flow_lcl, qentry);
1597			wake_up(&lgr->llc_msg_waiter);
1598		} else if (smc_llc_flow_start(&lgr->llc_flow_lcl, qentry)) {
1599			schedule_work(&lgr->llc_del_link_work);
1600		}
1601		return;
1602	case SMC_LLC_CONFIRM_RKEY:
1603		/* new request from remote, assign to remote flow */
1604		if (smc_llc_flow_start(&lgr->llc_flow_rmt, qentry)) {
1605			/* process here, does not wait for more llc msgs */
1606			smc_llc_rmt_conf_rkey(lgr);
1607			smc_llc_flow_stop(lgr, &lgr->llc_flow_rmt);
1608		}
1609		return;
1610	case SMC_LLC_CONFIRM_RKEY_CONT:
1611		/* not used because max links is 3, and 3 rkeys fit into
1612		 * one CONFIRM_RKEY message
1613		 */
1614		break;
1615	case SMC_LLC_DELETE_RKEY:
1616		/* new request from remote, assign to remote flow */
1617		if (smc_llc_flow_start(&lgr->llc_flow_rmt, qentry)) {
1618			/* process here, does not wait for more llc msgs */
1619			smc_llc_rmt_delete_rkey(lgr);
1620			smc_llc_flow_stop(lgr, &lgr->llc_flow_rmt);
1621		}
1622		return;
1623	default:
1624		smc_llc_protocol_violation(lgr, llc->raw.hdr.common.type);
1625		break;
1626	}
1627out:
1628	kfree(qentry);
1629}
1630
1631/* worker to process llc messages on the event queue */
1632static void smc_llc_event_work(struct work_struct *work)
1633{
1634	struct smc_link_group *lgr = container_of(work, struct smc_link_group,
1635						  llc_event_work);
1636	struct smc_llc_qentry *qentry;
1637
1638	if (!lgr->llc_flow_lcl.type && lgr->delayed_event) {
1639		qentry = lgr->delayed_event;
1640		lgr->delayed_event = NULL;
1641		if (smc_link_usable(qentry->link))
1642			smc_llc_event_handler(qentry);
1643		else
1644			kfree(qentry);
1645	}
1646
1647again:
1648	spin_lock_bh(&lgr->llc_event_q_lock);
1649	if (!list_empty(&lgr->llc_event_q)) {
1650		qentry = list_first_entry(&lgr->llc_event_q,
1651					  struct smc_llc_qentry, list);
1652		list_del_init(&qentry->list);
1653		spin_unlock_bh(&lgr->llc_event_q_lock);
1654		smc_llc_event_handler(qentry);
1655		goto again;
1656	}
1657	spin_unlock_bh(&lgr->llc_event_q_lock);
1658}
1659
1660/* process llc responses in tasklet context */
1661static void smc_llc_rx_response(struct smc_link *link,
1662				struct smc_llc_qentry *qentry)
1663{
1664	enum smc_llc_flowtype flowtype = link->lgr->llc_flow_lcl.type;
1665	struct smc_llc_flow *flow = &link->lgr->llc_flow_lcl;
1666	u8 llc_type = qentry->msg.raw.hdr.common.type;
1667
1668	switch (llc_type) {
1669	case SMC_LLC_TEST_LINK:
1670		if (smc_link_active(link))
1671			complete(&link->llc_testlink_resp);
1672		break;
1673	case SMC_LLC_ADD_LINK:
1674	case SMC_LLC_ADD_LINK_CONT:
1675	case SMC_LLC_CONFIRM_LINK:
1676		if (flowtype != SMC_LLC_FLOW_ADD_LINK || flow->qentry)
1677			break;	/* drop out-of-flow response */
1678		goto assign;
1679	case SMC_LLC_DELETE_LINK:
1680		if (flowtype != SMC_LLC_FLOW_DEL_LINK || flow->qentry)
1681			break;	/* drop out-of-flow response */
1682		goto assign;
1683	case SMC_LLC_CONFIRM_RKEY:
1684	case SMC_LLC_DELETE_RKEY:
1685		if (flowtype != SMC_LLC_FLOW_RKEY || flow->qentry)
1686			break;	/* drop out-of-flow response */
1687		goto assign;
1688	case SMC_LLC_CONFIRM_RKEY_CONT:
1689		/* not used because max links is 3 */
1690		break;
1691	default:
1692		smc_llc_protocol_violation(link->lgr, llc_type);
1693		break;
1694	}
1695	kfree(qentry);
1696	return;
1697assign:
1698	/* assign responses to the local flow, we requested them */
1699	smc_llc_flow_qentry_set(&link->lgr->llc_flow_lcl, qentry);
1700	wake_up(&link->lgr->llc_msg_waiter);
1701}
1702
1703static void smc_llc_enqueue(struct smc_link *link, union smc_llc_msg *llc)
1704{
1705	struct smc_link_group *lgr = link->lgr;
1706	struct smc_llc_qentry *qentry;
1707	unsigned long flags;
1708
1709	qentry = kmalloc(sizeof(*qentry), GFP_ATOMIC);
1710	if (!qentry)
1711		return;
1712	qentry->link = link;
1713	INIT_LIST_HEAD(&qentry->list);
1714	memcpy(&qentry->msg, llc, sizeof(union smc_llc_msg));
1715
1716	/* process responses immediately */
1717	if (llc->raw.hdr.flags & SMC_LLC_FLAG_RESP) {
1718		smc_llc_rx_response(link, qentry);
1719		return;
1720	}
1721
1722	/* add requests to event queue */
1723	spin_lock_irqsave(&lgr->llc_event_q_lock, flags);
1724	list_add_tail(&qentry->list, &lgr->llc_event_q);
1725	spin_unlock_irqrestore(&lgr->llc_event_q_lock, flags);
1726	queue_work(system_highpri_wq, &lgr->llc_event_work);
1727}
1728
1729/* copy received msg and add it to the event queue */
1730static void smc_llc_rx_handler(struct ib_wc *wc, void *buf)
1731{
1732	struct smc_link *link = (struct smc_link *)wc->qp->qp_context;
1733	union smc_llc_msg *llc = buf;
1734
1735	if (wc->byte_len < sizeof(*llc))
1736		return; /* short message */
1737	if (llc->raw.hdr.length != sizeof(*llc))
1738		return; /* invalid message */
1739
1740	smc_llc_enqueue(link, llc);
1741}
1742
1743/***************************** worker, utils *********************************/
1744
1745static void smc_llc_testlink_work(struct work_struct *work)
1746{
1747	struct smc_link *link = container_of(to_delayed_work(work),
1748					     struct smc_link, llc_testlink_wrk);
1749	unsigned long next_interval;
1750	unsigned long expire_time;
1751	u8 user_data[16] = { 0 };
1752	int rc;
1753
1754	if (!smc_link_active(link))
1755		return;		/* don't reschedule worker */
1756	expire_time = link->wr_rx_tstamp + link->llc_testlink_time;
1757	if (time_is_after_jiffies(expire_time)) {
1758		next_interval = expire_time - jiffies;
1759		goto out;
1760	}
1761	reinit_completion(&link->llc_testlink_resp);
1762	smc_llc_send_test_link(link, user_data);
1763	/* receive TEST LINK response over RoCE fabric */
1764	rc = wait_for_completion_interruptible_timeout(&link->llc_testlink_resp,
1765						       SMC_LLC_WAIT_TIME);
1766	if (!smc_link_active(link))
1767		return;		/* link state changed */
1768	if (rc <= 0) {
1769		smcr_link_down_cond_sched(link);
1770		return;
1771	}
1772	next_interval = link->llc_testlink_time;
1773out:
1774	schedule_delayed_work(&link->llc_testlink_wrk, next_interval);
1775}
1776
1777void smc_llc_lgr_init(struct smc_link_group *lgr, struct smc_sock *smc)
1778{
1779	struct net *net = sock_net(smc->clcsock->sk);
1780
1781	INIT_WORK(&lgr->llc_event_work, smc_llc_event_work);
1782	INIT_WORK(&lgr->llc_add_link_work, smc_llc_add_link_work);
1783	INIT_WORK(&lgr->llc_del_link_work, smc_llc_delete_link_work);
1784	INIT_LIST_HEAD(&lgr->llc_event_q);
1785	spin_lock_init(&lgr->llc_event_q_lock);
1786	spin_lock_init(&lgr->llc_flow_lock);
1787	init_waitqueue_head(&lgr->llc_flow_waiter);
1788	init_waitqueue_head(&lgr->llc_msg_waiter);
1789	mutex_init(&lgr->llc_conf_mutex);
1790	lgr->llc_testlink_time = net->ipv4.sysctl_tcp_keepalive_time;
1791}
1792
1793/* called after lgr was removed from lgr_list */
1794void smc_llc_lgr_clear(struct smc_link_group *lgr)
1795{
1796	smc_llc_event_flush(lgr);
1797	wake_up_all(&lgr->llc_flow_waiter);
1798	wake_up_all(&lgr->llc_msg_waiter);
1799	cancel_work_sync(&lgr->llc_event_work);
1800	cancel_work_sync(&lgr->llc_add_link_work);
1801	cancel_work_sync(&lgr->llc_del_link_work);
1802	if (lgr->delayed_event) {
1803		kfree(lgr->delayed_event);
1804		lgr->delayed_event = NULL;
1805	}
1806}
1807
1808int smc_llc_link_init(struct smc_link *link)
1809{
1810	init_completion(&link->llc_testlink_resp);
1811	INIT_DELAYED_WORK(&link->llc_testlink_wrk, smc_llc_testlink_work);
1812	return 0;
1813}
1814
1815void smc_llc_link_active(struct smc_link *link)
1816{
1817	pr_warn_ratelimited("smc: SMC-R lg %*phN link added: id %*phN, "
1818			    "peerid %*phN, ibdev %s, ibport %d\n",
1819			    SMC_LGR_ID_SIZE, &link->lgr->id,
1820			    SMC_LGR_ID_SIZE, &link->link_uid,
1821			    SMC_LGR_ID_SIZE, &link->peer_link_uid,
1822			    link->smcibdev->ibdev->name, link->ibport);
1823	link->state = SMC_LNK_ACTIVE;
1824	if (link->lgr->llc_testlink_time) {
1825		link->llc_testlink_time = link->lgr->llc_testlink_time * HZ;
1826		schedule_delayed_work(&link->llc_testlink_wrk,
1827				      link->llc_testlink_time);
1828	}
1829}
1830
1831/* called in worker context */
1832void smc_llc_link_clear(struct smc_link *link, bool log)
1833{
1834	if (log)
1835		pr_warn_ratelimited("smc: SMC-R lg %*phN link removed: id %*phN"
1836				    ", peerid %*phN, ibdev %s, ibport %d\n",
1837				    SMC_LGR_ID_SIZE, &link->lgr->id,
1838				    SMC_LGR_ID_SIZE, &link->link_uid,
1839				    SMC_LGR_ID_SIZE, &link->peer_link_uid,
1840				    link->smcibdev->ibdev->name, link->ibport);
1841	complete(&link->llc_testlink_resp);
1842	cancel_delayed_work_sync(&link->llc_testlink_wrk);
1843}
1844
1845/* register a new rtoken at the remote peer (for all links) */
1846int smc_llc_do_confirm_rkey(struct smc_link *send_link,
1847			    struct smc_buf_desc *rmb_desc)
1848{
1849	struct smc_link_group *lgr = send_link->lgr;
1850	struct smc_llc_qentry *qentry = NULL;
1851	int rc = 0;
1852
1853	rc = smc_llc_send_confirm_rkey(send_link, rmb_desc);
1854	if (rc)
1855		goto out;
1856	/* receive CONFIRM RKEY response from server over RoCE fabric */
1857	qentry = smc_llc_wait(lgr, send_link, SMC_LLC_WAIT_TIME,
1858			      SMC_LLC_CONFIRM_RKEY);
1859	if (!qentry || (qentry->msg.raw.hdr.flags & SMC_LLC_FLAG_RKEY_NEG))
1860		rc = -EFAULT;
1861out:
1862	if (qentry)
1863		smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
1864	return rc;
1865}
1866
1867/* unregister an rtoken at the remote peer */
1868int smc_llc_do_delete_rkey(struct smc_link_group *lgr,
1869			   struct smc_buf_desc *rmb_desc)
1870{
1871	struct smc_llc_qentry *qentry = NULL;
1872	struct smc_link *send_link;
1873	int rc = 0;
1874
1875	send_link = smc_llc_usable_link(lgr);
1876	if (!send_link)
1877		return -ENOLINK;
1878
1879	/* protected by llc_flow control */
1880	rc = smc_llc_send_delete_rkey(send_link, rmb_desc);
1881	if (rc)
1882		goto out;
1883	/* receive DELETE RKEY response from server over RoCE fabric */
1884	qentry = smc_llc_wait(lgr, send_link, SMC_LLC_WAIT_TIME,
1885			      SMC_LLC_DELETE_RKEY);
1886	if (!qentry || (qentry->msg.raw.hdr.flags & SMC_LLC_FLAG_RKEY_NEG))
1887		rc = -EFAULT;
1888out:
1889	if (qentry)
1890		smc_llc_flow_qentry_del(&lgr->llc_flow_lcl);
1891	return rc;
1892}
1893
1894void smc_llc_link_set_uid(struct smc_link *link)
1895{
1896	__be32 link_uid;
1897
1898	link_uid = htonl(*((u32 *)link->lgr->id) + link->link_id);
1899	memcpy(link->link_uid, &link_uid, SMC_LGR_ID_SIZE);
1900}
1901
1902/* save peers link user id, used for debug purposes */
1903void smc_llc_save_peer_uid(struct smc_llc_qentry *qentry)
1904{
1905	memcpy(qentry->link->peer_link_uid, qentry->msg.confirm_link.link_uid,
1906	       SMC_LGR_ID_SIZE);
1907}
1908
1909/* evaluate confirm link request or response */
1910int smc_llc_eval_conf_link(struct smc_llc_qentry *qentry,
1911			   enum smc_llc_reqresp type)
1912{
1913	if (type == SMC_LLC_REQ) {	/* SMC server assigns link_id */
1914		qentry->link->link_id = qentry->msg.confirm_link.link_num;
1915		smc_llc_link_set_uid(qentry->link);
1916	}
1917	if (!(qentry->msg.raw.hdr.flags & SMC_LLC_FLAG_NO_RMBE_EYEC))
1918		return -ENOTSUPP;
1919	return 0;
1920}
1921
1922/***************************** init, exit, misc ******************************/
1923
1924static struct smc_wr_rx_handler smc_llc_rx_handlers[] = {
1925	{
1926		.handler	= smc_llc_rx_handler,
1927		.type		= SMC_LLC_CONFIRM_LINK
1928	},
1929	{
1930		.handler	= smc_llc_rx_handler,
1931		.type		= SMC_LLC_TEST_LINK
1932	},
1933	{
1934		.handler	= smc_llc_rx_handler,
1935		.type		= SMC_LLC_ADD_LINK
1936	},
1937	{
1938		.handler	= smc_llc_rx_handler,
1939		.type		= SMC_LLC_ADD_LINK_CONT
1940	},
1941	{
1942		.handler	= smc_llc_rx_handler,
1943		.type		= SMC_LLC_DELETE_LINK
1944	},
1945	{
1946		.handler	= smc_llc_rx_handler,
1947		.type		= SMC_LLC_CONFIRM_RKEY
1948	},
1949	{
1950		.handler	= smc_llc_rx_handler,
1951		.type		= SMC_LLC_CONFIRM_RKEY_CONT
1952	},
1953	{
1954		.handler	= smc_llc_rx_handler,
1955		.type		= SMC_LLC_DELETE_RKEY
1956	},
1957	{
1958		.handler	= NULL,
1959	}
1960};
1961
1962int __init smc_llc_init(void)
1963{
1964	struct smc_wr_rx_handler *handler;
1965	int rc = 0;
1966
1967	for (handler = smc_llc_rx_handlers; handler->handler; handler++) {
1968		INIT_HLIST_NODE(&handler->list);
1969		rc = smc_wr_rx_register_handler(handler);
1970		if (rc)
1971			break;
1972	}
1973	return rc;
1974}