linux/net/smc/smc_llc.c
<<
>>
Prefs
   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;
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}
1975