linux/drivers/scsi/be2iscsi/be_iscsi.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * This file is part of the Emulex Linux Device Driver for Enterprise iSCSI
   4 * Host Bus Adapters. Refer to the README file included with this package
   5 * for driver version and adapter compatibility.
   6 *
   7 * Copyright (c) 2018 Broadcom. All Rights Reserved.
   8 * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
   9 *
  10 * Contact Information:
  11 * linux-drivers@broadcom.com
  12 */
  13
  14#include <scsi/libiscsi.h>
  15#include <scsi/scsi_transport_iscsi.h>
  16#include <scsi/scsi_transport.h>
  17#include <scsi/scsi_cmnd.h>
  18#include <scsi/scsi_device.h>
  19#include <scsi/scsi_host.h>
  20#include <scsi/scsi_netlink.h>
  21#include <net/netlink.h>
  22#include <scsi/scsi.h>
  23
  24#include "be_iscsi.h"
  25
  26extern struct iscsi_transport beiscsi_iscsi_transport;
  27
  28/**
  29 * beiscsi_session_create - creates a new iscsi session
  30 * @ep: pointer to iscsi ep
  31 * @cmds_max: max commands supported
  32 * @qdepth: max queue depth supported
  33 * @initial_cmdsn: initial iscsi CMDSN
  34 */
  35struct iscsi_cls_session *beiscsi_session_create(struct iscsi_endpoint *ep,
  36                                                 u16 cmds_max,
  37                                                 u16 qdepth,
  38                                                 u32 initial_cmdsn)
  39{
  40        struct Scsi_Host *shost;
  41        struct beiscsi_endpoint *beiscsi_ep;
  42        struct iscsi_cls_session *cls_session;
  43        struct beiscsi_hba *phba;
  44        struct iscsi_session *sess;
  45        struct beiscsi_session *beiscsi_sess;
  46        struct beiscsi_io_task *io_task;
  47
  48
  49        if (!ep) {
  50                pr_err("beiscsi_session_create: invalid ep\n");
  51                return NULL;
  52        }
  53        beiscsi_ep = ep->dd_data;
  54        phba = beiscsi_ep->phba;
  55
  56        if (!beiscsi_hba_is_online(phba)) {
  57                beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
  58                            "BS_%d : HBA in error 0x%lx\n", phba->state);
  59                return NULL;
  60        }
  61
  62        beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
  63                    "BS_%d : In beiscsi_session_create\n");
  64        if (cmds_max > beiscsi_ep->phba->params.wrbs_per_cxn) {
  65                beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
  66                            "BS_%d : Cannot handle %d cmds."
  67                            "Max cmds per session supported is %d. Using %d."
  68                            "\n", cmds_max,
  69                            beiscsi_ep->phba->params.wrbs_per_cxn,
  70                            beiscsi_ep->phba->params.wrbs_per_cxn);
  71
  72                cmds_max = beiscsi_ep->phba->params.wrbs_per_cxn;
  73        }
  74
  75        shost = phba->shost;
  76        cls_session = iscsi_session_setup(&beiscsi_iscsi_transport,
  77                                          shost, cmds_max,
  78                                          sizeof(*beiscsi_sess),
  79                                          sizeof(*io_task),
  80                                          initial_cmdsn, ISCSI_MAX_TARGET);
  81        if (!cls_session)
  82                return NULL;
  83        sess = cls_session->dd_data;
  84        beiscsi_sess = sess->dd_data;
  85        beiscsi_sess->bhs_pool =  dma_pool_create("beiscsi_bhs_pool",
  86                                                   &phba->pcidev->dev,
  87                                                   sizeof(struct be_cmd_bhs),
  88                                                   64, 0);
  89        if (!beiscsi_sess->bhs_pool)
  90                goto destroy_sess;
  91
  92        return cls_session;
  93destroy_sess:
  94        iscsi_session_teardown(cls_session);
  95        return NULL;
  96}
  97
  98/**
  99 * beiscsi_session_destroy - destroys iscsi session
 100 * @cls_session:        pointer to iscsi cls session
 101 *
 102 * Destroys iSCSI session instance and releases
 103 * resources allocated for it.
 104 */
 105void beiscsi_session_destroy(struct iscsi_cls_session *cls_session)
 106{
 107        struct iscsi_session *sess = cls_session->dd_data;
 108        struct beiscsi_session *beiscsi_sess = sess->dd_data;
 109
 110        printk(KERN_INFO "In beiscsi_session_destroy\n");
 111        dma_pool_destroy(beiscsi_sess->bhs_pool);
 112        iscsi_session_teardown(cls_session);
 113}
 114
 115/**
 116 * beiscsi_session_fail(): Closing session with appropriate error
 117 * @cls_session: ptr to session
 118 **/
 119void beiscsi_session_fail(struct iscsi_cls_session *cls_session)
 120{
 121        iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED);
 122}
 123
 124
 125/**
 126 * beiscsi_conn_create - create an instance of iscsi connection
 127 * @cls_session: ptr to iscsi_cls_session
 128 * @cid: iscsi cid
 129 */
 130struct iscsi_cls_conn *
 131beiscsi_conn_create(struct iscsi_cls_session *cls_session, u32 cid)
 132{
 133        struct beiscsi_hba *phba;
 134        struct Scsi_Host *shost;
 135        struct iscsi_cls_conn *cls_conn;
 136        struct beiscsi_conn *beiscsi_conn;
 137        struct iscsi_conn *conn;
 138        struct iscsi_session *sess;
 139        struct beiscsi_session *beiscsi_sess;
 140
 141        shost = iscsi_session_to_shost(cls_session);
 142        phba = iscsi_host_priv(shost);
 143
 144        beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
 145                    "BS_%d : In beiscsi_conn_create ,cid"
 146                    "from iscsi layer=%d\n", cid);
 147
 148        cls_conn = iscsi_conn_setup(cls_session, sizeof(*beiscsi_conn), cid);
 149        if (!cls_conn)
 150                return NULL;
 151
 152        conn = cls_conn->dd_data;
 153        beiscsi_conn = conn->dd_data;
 154        beiscsi_conn->ep = NULL;
 155        beiscsi_conn->phba = phba;
 156        beiscsi_conn->conn = conn;
 157        sess = cls_session->dd_data;
 158        beiscsi_sess = sess->dd_data;
 159        beiscsi_conn->beiscsi_sess = beiscsi_sess;
 160        return cls_conn;
 161}
 162
 163/**
 164 * beiscsi_conn_bind - Binds iscsi session/connection with TCP connection
 165 * @cls_session: pointer to iscsi cls session
 166 * @cls_conn: pointer to iscsi cls conn
 167 * @transport_fd: EP handle(64 bit)
 168 * @is_leading: indicate if this is the session leading connection (MCS)
 169 *
 170 * This function binds the TCP Conn with iSCSI Connection and Session.
 171 */
 172int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
 173                      struct iscsi_cls_conn *cls_conn,
 174                      u64 transport_fd, int is_leading)
 175{
 176        struct iscsi_conn *conn = cls_conn->dd_data;
 177        struct beiscsi_conn *beiscsi_conn = conn->dd_data;
 178        struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
 179        struct beiscsi_hba *phba = iscsi_host_priv(shost);
 180        struct hwi_controller *phwi_ctrlr = phba->phwi_ctrlr;
 181        struct hwi_wrb_context *pwrb_context;
 182        struct beiscsi_endpoint *beiscsi_ep;
 183        struct iscsi_endpoint *ep;
 184        uint16_t cri_index;
 185        int rc = 0;
 186
 187        ep = iscsi_lookup_endpoint(transport_fd);
 188        if (!ep)
 189                return -EINVAL;
 190
 191        beiscsi_ep = ep->dd_data;
 192
 193        if (iscsi_conn_bind(cls_session, cls_conn, is_leading)) {
 194                rc = -EINVAL;
 195                goto put_ep;
 196        }
 197
 198        if (beiscsi_ep->phba != phba) {
 199                beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
 200                            "BS_%d : beiscsi_ep->hba=%p not equal to phba=%p\n",
 201                            beiscsi_ep->phba, phba);
 202                rc = -EEXIST;
 203                goto put_ep;
 204        }
 205        cri_index = BE_GET_CRI_FROM_CID(beiscsi_ep->ep_cid);
 206        if (phba->conn_table[cri_index]) {
 207                if (beiscsi_conn != phba->conn_table[cri_index] ||
 208                    beiscsi_ep != phba->conn_table[cri_index]->ep) {
 209                        __beiscsi_log(phba, KERN_ERR,
 210                                      "BS_%d : conn_table not empty at %u: cid %u conn %p:%p\n",
 211                                      cri_index,
 212                                      beiscsi_ep->ep_cid,
 213                                      beiscsi_conn,
 214                                      phba->conn_table[cri_index]);
 215                        rc = -EINVAL;
 216                        goto put_ep;
 217                }
 218        }
 219
 220        beiscsi_conn->beiscsi_conn_cid = beiscsi_ep->ep_cid;
 221        beiscsi_conn->ep = beiscsi_ep;
 222        beiscsi_ep->conn = beiscsi_conn;
 223        /**
 224         * Each connection is associated with a WRBQ kept in wrb_context.
 225         * Store doorbell offset for transmit path.
 226         */
 227        pwrb_context = &phwi_ctrlr->wrb_context[cri_index];
 228        beiscsi_conn->doorbell_offset = pwrb_context->doorbell_offset;
 229        beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
 230                    "BS_%d : cid %d phba->conn_table[%u]=%p\n",
 231                    beiscsi_ep->ep_cid, cri_index, beiscsi_conn);
 232        phba->conn_table[cri_index] = beiscsi_conn;
 233
 234put_ep:
 235        iscsi_put_endpoint(ep);
 236        return rc;
 237}
 238
 239static int beiscsi_iface_create_ipv4(struct beiscsi_hba *phba)
 240{
 241        if (phba->ipv4_iface)
 242                return 0;
 243
 244        phba->ipv4_iface = iscsi_create_iface(phba->shost,
 245                                              &beiscsi_iscsi_transport,
 246                                              ISCSI_IFACE_TYPE_IPV4,
 247                                              0, 0);
 248        if (!phba->ipv4_iface) {
 249                beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
 250                            "BS_%d : Could not "
 251                            "create default IPv4 address.\n");
 252                return -ENODEV;
 253        }
 254
 255        return 0;
 256}
 257
 258static int beiscsi_iface_create_ipv6(struct beiscsi_hba *phba)
 259{
 260        if (phba->ipv6_iface)
 261                return 0;
 262
 263        phba->ipv6_iface = iscsi_create_iface(phba->shost,
 264                                              &beiscsi_iscsi_transport,
 265                                              ISCSI_IFACE_TYPE_IPV6,
 266                                              0, 0);
 267        if (!phba->ipv6_iface) {
 268                beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
 269                            "BS_%d : Could not "
 270                            "create default IPv6 address.\n");
 271                return -ENODEV;
 272        }
 273
 274        return 0;
 275}
 276
 277void beiscsi_iface_create_default(struct beiscsi_hba *phba)
 278{
 279        struct be_cmd_get_if_info_resp *if_info;
 280
 281        if (!beiscsi_if_get_info(phba, BEISCSI_IP_TYPE_V4, &if_info)) {
 282                beiscsi_iface_create_ipv4(phba);
 283                kfree(if_info);
 284        }
 285
 286        if (!beiscsi_if_get_info(phba, BEISCSI_IP_TYPE_V6, &if_info)) {
 287                beiscsi_iface_create_ipv6(phba);
 288                kfree(if_info);
 289        }
 290}
 291
 292void beiscsi_iface_destroy_default(struct beiscsi_hba *phba)
 293{
 294        if (phba->ipv6_iface) {
 295                iscsi_destroy_iface(phba->ipv6_iface);
 296                phba->ipv6_iface = NULL;
 297        }
 298        if (phba->ipv4_iface) {
 299                iscsi_destroy_iface(phba->ipv4_iface);
 300                phba->ipv4_iface = NULL;
 301        }
 302}
 303
 304/**
 305 * beiscsi_iface_config_vlan()- Set the VLAN TAG
 306 * @shost: Scsi Host for the driver instance
 307 * @iface_param: Interface paramters
 308 *
 309 * Set the VLAN TAG for the adapter or disable
 310 * the VLAN config
 311 *
 312 * returns
 313 *      Success: 0
 314 *      Failure: Non-Zero Value
 315 **/
 316static int
 317beiscsi_iface_config_vlan(struct Scsi_Host *shost,
 318                          struct iscsi_iface_param_info *iface_param)
 319{
 320        struct beiscsi_hba *phba = iscsi_host_priv(shost);
 321        int ret = -EPERM;
 322
 323        switch (iface_param->param) {
 324        case ISCSI_NET_PARAM_VLAN_ENABLED:
 325                ret = 0;
 326                if (iface_param->value[0] != ISCSI_VLAN_ENABLE)
 327                        ret = beiscsi_if_set_vlan(phba, BEISCSI_VLAN_DISABLE);
 328                break;
 329        case ISCSI_NET_PARAM_VLAN_TAG:
 330                ret = beiscsi_if_set_vlan(phba,
 331                                          *((uint16_t *)iface_param->value));
 332                break;
 333        }
 334        return ret;
 335}
 336
 337
 338static int
 339beiscsi_iface_config_ipv4(struct Scsi_Host *shost,
 340                          struct iscsi_iface_param_info *info,
 341                          void *data, uint32_t dt_len)
 342{
 343        struct beiscsi_hba *phba = iscsi_host_priv(shost);
 344        u8 *ip = NULL, *subnet = NULL, *gw;
 345        struct nlattr *nla;
 346        int ret = -EPERM;
 347
 348        /* Check the param */
 349        switch (info->param) {
 350        case ISCSI_NET_PARAM_IFACE_ENABLE:
 351                if (info->value[0] == ISCSI_IFACE_ENABLE)
 352                        ret = beiscsi_iface_create_ipv4(phba);
 353                else {
 354                        iscsi_destroy_iface(phba->ipv4_iface);
 355                        phba->ipv4_iface = NULL;
 356                }
 357                break;
 358        case ISCSI_NET_PARAM_IPV4_GW:
 359                gw = info->value;
 360                ret = beiscsi_if_set_gw(phba, BEISCSI_IP_TYPE_V4, gw);
 361                break;
 362        case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
 363                if (info->value[0] == ISCSI_BOOTPROTO_DHCP)
 364                        ret = beiscsi_if_en_dhcp(phba, BEISCSI_IP_TYPE_V4);
 365                else if (info->value[0] == ISCSI_BOOTPROTO_STATIC)
 366                        /* release DHCP IP address */
 367                        ret = beiscsi_if_en_static(phba, BEISCSI_IP_TYPE_V4,
 368                                                   NULL, NULL);
 369                else
 370                        beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
 371                                    "BS_%d : Invalid BOOTPROTO: %d\n",
 372                                    info->value[0]);
 373                break;
 374        case ISCSI_NET_PARAM_IPV4_ADDR:
 375                ip = info->value;
 376                nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_SUBNET);
 377                if (nla) {
 378                        info = nla_data(nla);
 379                        subnet = info->value;
 380                }
 381                ret = beiscsi_if_en_static(phba, BEISCSI_IP_TYPE_V4,
 382                                           ip, subnet);
 383                break;
 384        case ISCSI_NET_PARAM_IPV4_SUBNET:
 385                /*
 386                 * OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR ioctl needs IP
 387                 * and subnet both. Find IP to be applied for this subnet.
 388                 */
 389                subnet = info->value;
 390                nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_ADDR);
 391                if (nla) {
 392                        info = nla_data(nla);
 393                        ip = info->value;
 394                }
 395                ret = beiscsi_if_en_static(phba, BEISCSI_IP_TYPE_V4,
 396                                           ip, subnet);
 397                break;
 398        }
 399
 400        return ret;
 401}
 402
 403static int
 404beiscsi_iface_config_ipv6(struct Scsi_Host *shost,
 405                          struct iscsi_iface_param_info *iface_param,
 406                          void *data, uint32_t dt_len)
 407{
 408        struct beiscsi_hba *phba = iscsi_host_priv(shost);
 409        int ret = -EPERM;
 410
 411        switch (iface_param->param) {
 412        case ISCSI_NET_PARAM_IFACE_ENABLE:
 413                if (iface_param->value[0] == ISCSI_IFACE_ENABLE)
 414                        ret = beiscsi_iface_create_ipv6(phba);
 415                else {
 416                        iscsi_destroy_iface(phba->ipv6_iface);
 417                        phba->ipv6_iface = NULL;
 418                }
 419                break;
 420        case ISCSI_NET_PARAM_IPV6_ADDR:
 421                ret = beiscsi_if_en_static(phba, BEISCSI_IP_TYPE_V6,
 422                                           iface_param->value, NULL);
 423                break;
 424        }
 425
 426        return ret;
 427}
 428
 429int beiscsi_iface_set_param(struct Scsi_Host *shost,
 430                            void *data, uint32_t dt_len)
 431{
 432        struct iscsi_iface_param_info *iface_param = NULL;
 433        struct beiscsi_hba *phba = iscsi_host_priv(shost);
 434        struct nlattr *attrib;
 435        uint32_t rm_len = dt_len;
 436        int ret;
 437
 438        if (!beiscsi_hba_is_online(phba)) {
 439                beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
 440                            "BS_%d : HBA in error 0x%lx\n", phba->state);
 441                return -EBUSY;
 442        }
 443
 444        /* update interface_handle */
 445        ret = beiscsi_if_get_handle(phba);
 446        if (ret) {
 447                beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
 448                            "BS_%d : Getting Interface Handle Failed\n");
 449                return ret;
 450        }
 451
 452        nla_for_each_attr(attrib, data, dt_len, rm_len) {
 453                iface_param = nla_data(attrib);
 454
 455                if (iface_param->param_type != ISCSI_NET_PARAM)
 456                        continue;
 457
 458                /*
 459                 * BE2ISCSI only supports 1 interface
 460                 */
 461                if (iface_param->iface_num) {
 462                        beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
 463                                    "BS_%d : Invalid iface_num %d."
 464                                    "Only iface_num 0 is supported.\n",
 465                                    iface_param->iface_num);
 466
 467                        return -EINVAL;
 468                }
 469
 470                beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
 471                            "BS_%d : %s.0 set param %d",
 472                            (iface_param->iface_type == ISCSI_IFACE_TYPE_IPV4) ?
 473                            "ipv4" : "ipv6", iface_param->param);
 474
 475                ret = -EPERM;
 476                switch (iface_param->param) {
 477                case ISCSI_NET_PARAM_VLAN_ENABLED:
 478                case ISCSI_NET_PARAM_VLAN_TAG:
 479                        ret = beiscsi_iface_config_vlan(shost, iface_param);
 480                        break;
 481                default:
 482                        switch (iface_param->iface_type) {
 483                        case ISCSI_IFACE_TYPE_IPV4:
 484                                ret = beiscsi_iface_config_ipv4(shost,
 485                                                                iface_param,
 486                                                                data, dt_len);
 487                                break;
 488                        case ISCSI_IFACE_TYPE_IPV6:
 489                                ret = beiscsi_iface_config_ipv6(shost,
 490                                                                iface_param,
 491                                                                data, dt_len);
 492                                break;
 493                        }
 494                }
 495
 496                if (ret == -EPERM) {
 497                        __beiscsi_log(phba, KERN_ERR,
 498                                      "BS_%d : %s.0 set param %d not permitted",
 499                                      (iface_param->iface_type ==
 500                                       ISCSI_IFACE_TYPE_IPV4) ? "ipv4" : "ipv6",
 501                                      iface_param->param);
 502                        ret = 0;
 503                }
 504                if (ret)
 505                        break;
 506        }
 507
 508        return ret;
 509}
 510
 511static int __beiscsi_iface_get_param(struct beiscsi_hba *phba,
 512                                     struct iscsi_iface *iface,
 513                                     int param, char *buf)
 514{
 515        struct be_cmd_get_if_info_resp *if_info;
 516        int len, ip_type = BEISCSI_IP_TYPE_V4;
 517
 518        if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6)
 519                ip_type = BEISCSI_IP_TYPE_V6;
 520
 521        len = beiscsi_if_get_info(phba, ip_type, &if_info);
 522        if (len)
 523                return len;
 524
 525        switch (param) {
 526        case ISCSI_NET_PARAM_IPV4_ADDR:
 527                len = sprintf(buf, "%pI4\n", if_info->ip_addr.addr);
 528                break;
 529        case ISCSI_NET_PARAM_IPV6_ADDR:
 530                len = sprintf(buf, "%pI6\n", if_info->ip_addr.addr);
 531                break;
 532        case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
 533                if (!if_info->dhcp_state)
 534                        len = sprintf(buf, "static\n");
 535                else
 536                        len = sprintf(buf, "dhcp\n");
 537                break;
 538        case ISCSI_NET_PARAM_IPV4_SUBNET:
 539                len = sprintf(buf, "%pI4\n", if_info->ip_addr.subnet_mask);
 540                break;
 541        case ISCSI_NET_PARAM_VLAN_ENABLED:
 542                len = sprintf(buf, "%s\n",
 543                              (if_info->vlan_priority == BEISCSI_VLAN_DISABLE) ?
 544                              "disable" : "enable");
 545                break;
 546        case ISCSI_NET_PARAM_VLAN_ID:
 547                if (if_info->vlan_priority == BEISCSI_VLAN_DISABLE)
 548                        len = -EINVAL;
 549                else
 550                        len = sprintf(buf, "%d\n",
 551                                      (if_info->vlan_priority &
 552                                       ISCSI_MAX_VLAN_ID));
 553                break;
 554        case ISCSI_NET_PARAM_VLAN_PRIORITY:
 555                if (if_info->vlan_priority == BEISCSI_VLAN_DISABLE)
 556                        len = -EINVAL;
 557                else
 558                        len = sprintf(buf, "%d\n",
 559                                      ((if_info->vlan_priority >> 13) &
 560                                       ISCSI_MAX_VLAN_PRIORITY));
 561                break;
 562        default:
 563                WARN_ON(1);
 564        }
 565
 566        kfree(if_info);
 567        return len;
 568}
 569
 570int beiscsi_iface_get_param(struct iscsi_iface *iface,
 571                            enum iscsi_param_type param_type,
 572                            int param, char *buf)
 573{
 574        struct Scsi_Host *shost = iscsi_iface_to_shost(iface);
 575        struct beiscsi_hba *phba = iscsi_host_priv(shost);
 576        struct be_cmd_get_def_gateway_resp gateway;
 577        int len = -EPERM;
 578
 579        if (param_type != ISCSI_NET_PARAM)
 580                return 0;
 581        if (!beiscsi_hba_is_online(phba)) {
 582                beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
 583                            "BS_%d : HBA in error 0x%lx\n", phba->state);
 584                return -EBUSY;
 585        }
 586
 587        switch (param) {
 588        case ISCSI_NET_PARAM_IPV4_ADDR:
 589        case ISCSI_NET_PARAM_IPV4_SUBNET:
 590        case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
 591        case ISCSI_NET_PARAM_IPV6_ADDR:
 592        case ISCSI_NET_PARAM_VLAN_ENABLED:
 593        case ISCSI_NET_PARAM_VLAN_ID:
 594        case ISCSI_NET_PARAM_VLAN_PRIORITY:
 595                len = __beiscsi_iface_get_param(phba, iface, param, buf);
 596                break;
 597        case ISCSI_NET_PARAM_IFACE_ENABLE:
 598                if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4)
 599                        len = sprintf(buf, "%s\n",
 600                                      phba->ipv4_iface ? "enable" : "disable");
 601                else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6)
 602                        len = sprintf(buf, "%s\n",
 603                                      phba->ipv6_iface ? "enable" : "disable");
 604                break;
 605        case ISCSI_NET_PARAM_IPV4_GW:
 606                memset(&gateway, 0, sizeof(gateway));
 607                len = beiscsi_if_get_gw(phba, BEISCSI_IP_TYPE_V4, &gateway);
 608                if (!len)
 609                        len = sprintf(buf, "%pI4\n", &gateway.ip_addr.addr);
 610                break;
 611        }
 612
 613        return len;
 614}
 615
 616/**
 617 * beiscsi_ep_get_param - get the iscsi parameter
 618 * @ep: pointer to iscsi ep
 619 * @param: parameter type identifier
 620 * @buf: buffer pointer
 621 *
 622 * returns iscsi parameter
 623 */
 624int beiscsi_ep_get_param(struct iscsi_endpoint *ep,
 625                           enum iscsi_param param, char *buf)
 626{
 627        struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
 628        int len;
 629
 630        beiscsi_log(beiscsi_ep->phba, KERN_INFO,
 631                    BEISCSI_LOG_CONFIG,
 632                    "BS_%d : In beiscsi_ep_get_param,"
 633                    " param= %d\n", param);
 634
 635        switch (param) {
 636        case ISCSI_PARAM_CONN_PORT:
 637                len = sprintf(buf, "%hu\n", beiscsi_ep->dst_tcpport);
 638                break;
 639        case ISCSI_PARAM_CONN_ADDRESS:
 640                if (beiscsi_ep->ip_type == BEISCSI_IP_TYPE_V4)
 641                        len = sprintf(buf, "%pI4\n", &beiscsi_ep->dst_addr);
 642                else
 643                        len = sprintf(buf, "%pI6\n", &beiscsi_ep->dst6_addr);
 644                break;
 645        default:
 646                len = -EPERM;
 647        }
 648        return len;
 649}
 650
 651int beiscsi_set_param(struct iscsi_cls_conn *cls_conn,
 652                      enum iscsi_param param, char *buf, int buflen)
 653{
 654        struct iscsi_conn *conn = cls_conn->dd_data;
 655        struct iscsi_session *session = conn->session;
 656        struct beiscsi_hba *phba = NULL;
 657        int ret;
 658
 659        phba = ((struct beiscsi_conn *)conn->dd_data)->phba;
 660        beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
 661                    "BS_%d : In beiscsi_conn_set_param,"
 662                    " param= %d\n", param);
 663
 664        ret = iscsi_set_param(cls_conn, param, buf, buflen);
 665        if (ret)
 666                return ret;
 667        /*
 668         * If userspace tried to set the value to higher than we can
 669         * support override here.
 670         */
 671        switch (param) {
 672        case ISCSI_PARAM_FIRST_BURST:
 673                if (session->first_burst > 8192)
 674                        session->first_burst = 8192;
 675                break;
 676        case ISCSI_PARAM_MAX_RECV_DLENGTH:
 677                if (conn->max_recv_dlength > 65536)
 678                        conn->max_recv_dlength = 65536;
 679                break;
 680        case ISCSI_PARAM_MAX_BURST:
 681                if (session->max_burst > 262144)
 682                        session->max_burst = 262144;
 683                break;
 684        case ISCSI_PARAM_MAX_XMIT_DLENGTH:
 685                if (conn->max_xmit_dlength > 65536)
 686                        conn->max_xmit_dlength = 65536;
 687                fallthrough;
 688        default:
 689                return 0;
 690        }
 691
 692        return 0;
 693}
 694
 695/**
 696 * beiscsi_get_port_state - Get the Port State
 697 * @shost : pointer to scsi_host structure
 698 *
 699 */
 700static void beiscsi_get_port_state(struct Scsi_Host *shost)
 701{
 702        struct beiscsi_hba *phba = iscsi_host_priv(shost);
 703        struct iscsi_cls_host *ihost = shost->shost_data;
 704
 705        ihost->port_state = test_bit(BEISCSI_HBA_LINK_UP, &phba->state) ?
 706                ISCSI_PORT_STATE_UP : ISCSI_PORT_STATE_DOWN;
 707}
 708
 709/**
 710 * beiscsi_get_port_speed  - Get the Port Speed from Adapter
 711 * @shost : pointer to scsi_host structure
 712 *
 713 */
 714static void beiscsi_get_port_speed(struct Scsi_Host *shost)
 715{
 716        struct beiscsi_hba *phba = iscsi_host_priv(shost);
 717        struct iscsi_cls_host *ihost = shost->shost_data;
 718
 719        switch (phba->port_speed) {
 720        case BE2ISCSI_LINK_SPEED_10MBPS:
 721                ihost->port_speed = ISCSI_PORT_SPEED_10MBPS;
 722                break;
 723        case BE2ISCSI_LINK_SPEED_100MBPS:
 724                ihost->port_speed = ISCSI_PORT_SPEED_100MBPS;
 725                break;
 726        case BE2ISCSI_LINK_SPEED_1GBPS:
 727                ihost->port_speed = ISCSI_PORT_SPEED_1GBPS;
 728                break;
 729        case BE2ISCSI_LINK_SPEED_10GBPS:
 730                ihost->port_speed = ISCSI_PORT_SPEED_10GBPS;
 731                break;
 732        case BE2ISCSI_LINK_SPEED_25GBPS:
 733                ihost->port_speed = ISCSI_PORT_SPEED_25GBPS;
 734                break;
 735        case BE2ISCSI_LINK_SPEED_40GBPS:
 736                ihost->port_speed = ISCSI_PORT_SPEED_40GBPS;
 737                break;
 738        default:
 739                ihost->port_speed = ISCSI_PORT_SPEED_UNKNOWN;
 740        }
 741}
 742
 743/**
 744 * beiscsi_get_host_param - get the iscsi parameter
 745 * @shost: pointer to scsi_host structure
 746 * @param: parameter type identifier
 747 * @buf: buffer pointer
 748 *
 749 */
 750int beiscsi_get_host_param(struct Scsi_Host *shost,
 751                           enum iscsi_host_param param, char *buf)
 752{
 753        struct beiscsi_hba *phba = iscsi_host_priv(shost);
 754        int status = 0;
 755
 756        if (!beiscsi_hba_is_online(phba)) {
 757                beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
 758                            "BS_%d : HBA in error 0x%lx\n", phba->state);
 759                return 0;
 760        }
 761        beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
 762                    "BS_%d : In beiscsi_get_host_param, param = %d\n", param);
 763
 764        switch (param) {
 765        case ISCSI_HOST_PARAM_HWADDRESS:
 766                status = beiscsi_get_macaddr(buf, phba);
 767                if (status < 0) {
 768                        beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
 769                                    "BS_%d : beiscsi_get_macaddr Failed\n");
 770                        return 0;
 771                }
 772                break;
 773        case ISCSI_HOST_PARAM_INITIATOR_NAME:
 774                /* try fetching user configured name first */
 775                status = beiscsi_get_initiator_name(phba, buf, true);
 776                if (status < 0) {
 777                        status = beiscsi_get_initiator_name(phba, buf, false);
 778                        if (status < 0) {
 779                                beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
 780                                            "BS_%d : Retrieving Initiator Name Failed\n");
 781                                status = 0;
 782                        }
 783                }
 784                break;
 785        case ISCSI_HOST_PARAM_PORT_STATE:
 786                beiscsi_get_port_state(shost);
 787                status = sprintf(buf, "%s\n", iscsi_get_port_state_name(shost));
 788                break;
 789        case ISCSI_HOST_PARAM_PORT_SPEED:
 790                beiscsi_get_port_speed(shost);
 791                status = sprintf(buf, "%s\n", iscsi_get_port_speed_name(shost));
 792                break;
 793        default:
 794                return iscsi_host_get_param(shost, param, buf);
 795        }
 796        return status;
 797}
 798
 799int beiscsi_get_macaddr(char *buf, struct beiscsi_hba *phba)
 800{
 801        struct be_cmd_get_nic_conf_resp resp;
 802        int rc;
 803
 804        if (phba->mac_addr_set)
 805                return sysfs_format_mac(buf, phba->mac_address, ETH_ALEN);
 806
 807        memset(&resp, 0, sizeof(resp));
 808        rc = mgmt_get_nic_conf(phba, &resp);
 809        if (rc)
 810                return rc;
 811
 812        phba->mac_addr_set = true;
 813        memcpy(phba->mac_address, resp.mac_address, ETH_ALEN);
 814        return sysfs_format_mac(buf, phba->mac_address, ETH_ALEN);
 815}
 816
 817/**
 818 * beiscsi_conn_get_stats - get the iscsi stats
 819 * @cls_conn: pointer to iscsi cls conn
 820 * @stats: pointer to iscsi_stats structure
 821 *
 822 * returns iscsi stats
 823 */
 824void beiscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn,
 825                            struct iscsi_stats *stats)
 826{
 827        struct iscsi_conn *conn = cls_conn->dd_data;
 828        struct beiscsi_hba *phba = NULL;
 829
 830        phba = ((struct beiscsi_conn *)conn->dd_data)->phba;
 831        beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
 832                    "BS_%d : In beiscsi_conn_get_stats\n");
 833
 834        stats->txdata_octets = conn->txdata_octets;
 835        stats->rxdata_octets = conn->rxdata_octets;
 836        stats->dataout_pdus = conn->dataout_pdus_cnt;
 837        stats->scsirsp_pdus = conn->scsirsp_pdus_cnt;
 838        stats->scsicmd_pdus = conn->scsicmd_pdus_cnt;
 839        stats->datain_pdus = conn->datain_pdus_cnt;
 840        stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
 841        stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt;
 842        stats->r2t_pdus = conn->r2t_pdus_cnt;
 843        stats->digest_err = 0;
 844        stats->timeout_err = 0;
 845        stats->custom_length = 1;
 846        strcpy(stats->custom[0].desc, "eh_abort_cnt");
 847        stats->custom[0].value = conn->eh_abort_cnt;
 848}
 849
 850/**
 851 * beiscsi_set_params_for_offld - get the parameters for offload
 852 * @beiscsi_conn: pointer to beiscsi_conn
 853 * @params: pointer to offload_params structure
 854 */
 855static void  beiscsi_set_params_for_offld(struct beiscsi_conn *beiscsi_conn,
 856                                          struct beiscsi_offload_params *params)
 857{
 858        struct iscsi_conn *conn = beiscsi_conn->conn;
 859        struct iscsi_session *session = conn->session;
 860
 861        AMAP_SET_BITS(struct amap_beiscsi_offload_params, max_burst_length,
 862                      params, session->max_burst);
 863        AMAP_SET_BITS(struct amap_beiscsi_offload_params,
 864                      max_send_data_segment_length, params,
 865                      conn->max_xmit_dlength);
 866        AMAP_SET_BITS(struct amap_beiscsi_offload_params, first_burst_length,
 867                      params, session->first_burst);
 868        AMAP_SET_BITS(struct amap_beiscsi_offload_params, erl, params,
 869                      session->erl);
 870        AMAP_SET_BITS(struct amap_beiscsi_offload_params, dde, params,
 871                      conn->datadgst_en);
 872        AMAP_SET_BITS(struct amap_beiscsi_offload_params, hde, params,
 873                      conn->hdrdgst_en);
 874        AMAP_SET_BITS(struct amap_beiscsi_offload_params, ir2t, params,
 875                      session->initial_r2t_en);
 876        AMAP_SET_BITS(struct amap_beiscsi_offload_params, imd, params,
 877                      session->imm_data_en);
 878        AMAP_SET_BITS(struct amap_beiscsi_offload_params,
 879                      data_seq_inorder, params,
 880                      session->dataseq_inorder_en);
 881        AMAP_SET_BITS(struct amap_beiscsi_offload_params,
 882                      pdu_seq_inorder, params,
 883                      session->pdu_inorder_en);
 884        AMAP_SET_BITS(struct amap_beiscsi_offload_params, max_r2t, params,
 885                      session->max_r2t);
 886        AMAP_SET_BITS(struct amap_beiscsi_offload_params, exp_statsn, params,
 887                      (conn->exp_statsn - 1));
 888        AMAP_SET_BITS(struct amap_beiscsi_offload_params,
 889                      max_recv_data_segment_length, params,
 890                      conn->max_recv_dlength);
 891
 892}
 893
 894/**
 895 * beiscsi_conn_start - offload of session to chip
 896 * @cls_conn: pointer to beiscsi_conn
 897 */
 898int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn)
 899{
 900        struct iscsi_conn *conn = cls_conn->dd_data;
 901        struct beiscsi_conn *beiscsi_conn = conn->dd_data;
 902        struct beiscsi_endpoint *beiscsi_ep;
 903        struct beiscsi_offload_params params;
 904        struct beiscsi_hba *phba;
 905
 906        phba = ((struct beiscsi_conn *)conn->dd_data)->phba;
 907
 908        if (!beiscsi_hba_is_online(phba)) {
 909                beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
 910                            "BS_%d : HBA in error 0x%lx\n", phba->state);
 911                return -EBUSY;
 912        }
 913        beiscsi_log(beiscsi_conn->phba, KERN_INFO, BEISCSI_LOG_CONFIG,
 914                    "BS_%d : In beiscsi_conn_start\n");
 915
 916        memset(&params, 0, sizeof(struct beiscsi_offload_params));
 917        beiscsi_ep = beiscsi_conn->ep;
 918        if (!beiscsi_ep)
 919                beiscsi_log(beiscsi_conn->phba, KERN_ERR,
 920                            BEISCSI_LOG_CONFIG,
 921                            "BS_%d : In beiscsi_conn_start , no beiscsi_ep\n");
 922
 923        beiscsi_conn->login_in_progress = 0;
 924        beiscsi_set_params_for_offld(beiscsi_conn, &params);
 925        beiscsi_offload_connection(beiscsi_conn, &params);
 926        iscsi_conn_start(cls_conn);
 927        return 0;
 928}
 929
 930/**
 931 * beiscsi_get_cid - Allocate a cid
 932 * @phba: The phba instance
 933 */
 934static int beiscsi_get_cid(struct beiscsi_hba *phba)
 935{
 936        uint16_t cid_avlbl_ulp0, cid_avlbl_ulp1;
 937        unsigned short cid, cid_from_ulp;
 938        struct ulp_cid_info *cid_info;
 939
 940        /* Find the ULP which has more CID available */
 941        cid_avlbl_ulp0 = (phba->cid_array_info[BEISCSI_ULP0]) ?
 942                          BEISCSI_ULP0_AVLBL_CID(phba) : 0;
 943        cid_avlbl_ulp1 = (phba->cid_array_info[BEISCSI_ULP1]) ?
 944                          BEISCSI_ULP1_AVLBL_CID(phba) : 0;
 945        cid_from_ulp = (cid_avlbl_ulp0 > cid_avlbl_ulp1) ?
 946                        BEISCSI_ULP0 : BEISCSI_ULP1;
 947        /**
 948         * If iSCSI protocol is loaded only on ULP 0, and when cid_avlbl_ulp
 949         * is ZERO for both, ULP 1 is returned.
 950         * Check if ULP is loaded before getting new CID.
 951         */
 952        if (!test_bit(cid_from_ulp, (void *)&phba->fw_config.ulp_supported))
 953                return BE_INVALID_CID;
 954
 955        cid_info = phba->cid_array_info[cid_from_ulp];
 956        cid = cid_info->cid_array[cid_info->cid_alloc];
 957        if (!cid_info->avlbl_cids || cid == BE_INVALID_CID) {
 958                __beiscsi_log(phba, KERN_ERR,
 959                                "BS_%d : failed to get cid: available %u:%u\n",
 960                                cid_info->avlbl_cids, cid_info->cid_free);
 961                return BE_INVALID_CID;
 962        }
 963        /* empty the slot */
 964        cid_info->cid_array[cid_info->cid_alloc++] = BE_INVALID_CID;
 965        if (cid_info->cid_alloc == BEISCSI_GET_CID_COUNT(phba, cid_from_ulp))
 966                cid_info->cid_alloc = 0;
 967        cid_info->avlbl_cids--;
 968        return cid;
 969}
 970
 971/**
 972 * beiscsi_put_cid - Free the cid
 973 * @phba: The phba for which the cid is being freed
 974 * @cid: The cid to free
 975 */
 976static void beiscsi_put_cid(struct beiscsi_hba *phba, unsigned short cid)
 977{
 978        uint16_t cri_index = BE_GET_CRI_FROM_CID(cid);
 979        struct hwi_wrb_context *pwrb_context;
 980        struct hwi_controller *phwi_ctrlr;
 981        struct ulp_cid_info *cid_info;
 982        uint16_t cid_post_ulp;
 983
 984        phwi_ctrlr = phba->phwi_ctrlr;
 985        pwrb_context = &phwi_ctrlr->wrb_context[cri_index];
 986        cid_post_ulp = pwrb_context->ulp_num;
 987
 988        cid_info = phba->cid_array_info[cid_post_ulp];
 989        /* fill only in empty slot */
 990        if (cid_info->cid_array[cid_info->cid_free] != BE_INVALID_CID) {
 991                __beiscsi_log(phba, KERN_ERR,
 992                              "BS_%d : failed to put cid %u: available %u:%u\n",
 993                              cid, cid_info->avlbl_cids, cid_info->cid_free);
 994                return;
 995        }
 996        cid_info->cid_array[cid_info->cid_free++] = cid;
 997        if (cid_info->cid_free == BEISCSI_GET_CID_COUNT(phba, cid_post_ulp))
 998                cid_info->cid_free = 0;
 999        cid_info->avlbl_cids++;
1000}
1001
1002/**
1003 * beiscsi_free_ep - free endpoint
1004 * @beiscsi_ep: pointer to device endpoint struct
1005 */
1006static void beiscsi_free_ep(struct beiscsi_endpoint *beiscsi_ep)
1007{
1008        struct beiscsi_hba *phba = beiscsi_ep->phba;
1009        struct beiscsi_conn *beiscsi_conn;
1010
1011        beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
1012        beiscsi_ep->phba = NULL;
1013        /* clear this to track freeing in beiscsi_ep_disconnect */
1014        phba->ep_array[BE_GET_CRI_FROM_CID(beiscsi_ep->ep_cid)] = NULL;
1015
1016        /**
1017         * Check if any connection resource allocated by driver
1018         * is to be freed.This case occurs when target redirection
1019         * or connection retry is done.
1020         **/
1021        if (!beiscsi_ep->conn)
1022                return;
1023
1024        beiscsi_conn = beiscsi_ep->conn;
1025        /**
1026         * Break ep->conn link here so that completions after
1027         * this are ignored.
1028         */
1029        beiscsi_ep->conn = NULL;
1030        if (beiscsi_conn->login_in_progress) {
1031                beiscsi_free_mgmt_task_handles(beiscsi_conn,
1032                                               beiscsi_conn->task);
1033                beiscsi_conn->login_in_progress = 0;
1034        }
1035}
1036
1037/**
1038 * beiscsi_open_conn - Ask FW to open a TCP connection
1039 * @ep: pointer to device endpoint struct
1040 * @src_addr: The source IP address
1041 * @dst_addr: The Destination  IP address
1042 * @non_blocking: blocking or non-blocking call
1043 *
1044 * Asks the FW to open a TCP connection
1045 */
1046static int beiscsi_open_conn(struct iscsi_endpoint *ep,
1047                             struct sockaddr *src_addr,
1048                             struct sockaddr *dst_addr, int non_blocking)
1049{
1050        struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
1051        struct beiscsi_hba *phba = beiscsi_ep->phba;
1052        struct tcp_connect_and_offload_out *ptcpcnct_out;
1053        struct be_dma_mem nonemb_cmd;
1054        unsigned int tag, req_memsize;
1055        int ret = -ENOMEM;
1056
1057        beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
1058                    "BS_%d : In beiscsi_open_conn\n");
1059
1060        beiscsi_ep->ep_cid = beiscsi_get_cid(phba);
1061        if (beiscsi_ep->ep_cid == BE_INVALID_CID) {
1062                beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
1063                            "BS_%d : No free cid available\n");
1064                return ret;
1065        }
1066
1067        beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
1068                    "BS_%d : In beiscsi_open_conn, ep_cid=%d\n",
1069                    beiscsi_ep->ep_cid);
1070
1071        phba->ep_array[BE_GET_CRI_FROM_CID
1072                       (beiscsi_ep->ep_cid)] = ep;
1073
1074        beiscsi_ep->cid_vld = 0;
1075
1076        if (is_chip_be2_be3r(phba))
1077                req_memsize = sizeof(struct tcp_connect_and_offload_in);
1078        else
1079                req_memsize = sizeof(struct tcp_connect_and_offload_in_v1);
1080
1081        nonemb_cmd.va = dma_alloc_coherent(&phba->ctrl.pdev->dev,
1082                                req_memsize,
1083                                &nonemb_cmd.dma, GFP_KERNEL);
1084        if (nonemb_cmd.va == NULL) {
1085
1086                beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
1087                            "BS_%d : Failed to allocate memory for"
1088                            " mgmt_open_connection\n");
1089
1090                beiscsi_free_ep(beiscsi_ep);
1091                return -ENOMEM;
1092        }
1093        nonemb_cmd.size = req_memsize;
1094        memset(nonemb_cmd.va, 0, nonemb_cmd.size);
1095        tag = mgmt_open_connection(phba, dst_addr, beiscsi_ep, &nonemb_cmd);
1096        if (!tag) {
1097                beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
1098                            "BS_%d : mgmt_open_connection Failed for cid=%d\n",
1099                            beiscsi_ep->ep_cid);
1100
1101                dma_free_coherent(&phba->ctrl.pdev->dev, nonemb_cmd.size,
1102                                    nonemb_cmd.va, nonemb_cmd.dma);
1103                beiscsi_free_ep(beiscsi_ep);
1104                return -EAGAIN;
1105        }
1106
1107        ret = beiscsi_mccq_compl_wait(phba, tag, NULL, &nonemb_cmd);
1108        if (ret) {
1109                beiscsi_log(phba, KERN_ERR,
1110                            BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
1111                            "BS_%d : mgmt_open_connection Failed");
1112
1113                if (ret != -EBUSY)
1114                        dma_free_coherent(&phba->ctrl.pdev->dev,
1115                                        nonemb_cmd.size, nonemb_cmd.va,
1116                                        nonemb_cmd.dma);
1117
1118                beiscsi_free_ep(beiscsi_ep);
1119                return ret;
1120        }
1121
1122        ptcpcnct_out = (struct tcp_connect_and_offload_out *)nonemb_cmd.va;
1123        beiscsi_ep = ep->dd_data;
1124        beiscsi_ep->fw_handle = ptcpcnct_out->connection_handle;
1125        beiscsi_ep->cid_vld = 1;
1126        beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
1127                    "BS_%d : mgmt_open_connection Success\n");
1128
1129        dma_free_coherent(&phba->ctrl.pdev->dev, nonemb_cmd.size,
1130                            nonemb_cmd.va, nonemb_cmd.dma);
1131        return 0;
1132}
1133
1134/**
1135 * beiscsi_ep_connect - Ask chip to create TCP Conn
1136 * @shost: Pointer to scsi_host structure
1137 * @dst_addr: The IP address of Target
1138 * @non_blocking: blocking or non-blocking call
1139 *
1140 * This routines first asks chip to create a connection and then allocates an EP
1141 */
1142struct iscsi_endpoint *
1143beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
1144                   int non_blocking)
1145{
1146        struct beiscsi_hba *phba;
1147        struct beiscsi_endpoint *beiscsi_ep;
1148        struct iscsi_endpoint *ep;
1149        int ret;
1150
1151        if (!shost) {
1152                ret = -ENXIO;
1153                pr_err("beiscsi_ep_connect shost is NULL\n");
1154                return ERR_PTR(ret);
1155        }
1156
1157        phba = iscsi_host_priv(shost);
1158        if (!beiscsi_hba_is_online(phba)) {
1159                ret = -EIO;
1160                beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
1161                            "BS_%d : HBA in error 0x%lx\n", phba->state);
1162                return ERR_PTR(ret);
1163        }
1164        if (!test_bit(BEISCSI_HBA_LINK_UP, &phba->state)) {
1165                ret = -EBUSY;
1166                beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
1167                            "BS_%d : The Adapter Port state is Down!!!\n");
1168                return ERR_PTR(ret);
1169        }
1170
1171        ep = iscsi_create_endpoint(sizeof(struct beiscsi_endpoint));
1172        if (!ep) {
1173                ret = -ENOMEM;
1174                return ERR_PTR(ret);
1175        }
1176
1177        beiscsi_ep = ep->dd_data;
1178        beiscsi_ep->phba = phba;
1179        beiscsi_ep->openiscsi_ep = ep;
1180        ret = beiscsi_open_conn(ep, NULL, dst_addr, non_blocking);
1181        if (ret) {
1182                beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
1183                            "BS_%d : Failed in beiscsi_open_conn\n");
1184                goto free_ep;
1185        }
1186
1187        return ep;
1188
1189free_ep:
1190        iscsi_destroy_endpoint(ep);
1191        return ERR_PTR(ret);
1192}
1193
1194/**
1195 * beiscsi_ep_poll - Poll to see if connection is established
1196 * @ep: endpoint to be used
1197 * @timeout_ms: timeout specified in millisecs
1198 *
1199 * Poll to see if TCP connection established
1200 */
1201int beiscsi_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
1202{
1203        struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
1204
1205        beiscsi_log(beiscsi_ep->phba, KERN_INFO, BEISCSI_LOG_CONFIG,
1206                    "BS_%d : In  beiscsi_ep_poll\n");
1207
1208        if (beiscsi_ep->cid_vld == 1)
1209                return 1;
1210        else
1211                return 0;
1212}
1213
1214/**
1215 * beiscsi_flush_cq()- Flush the CQ created.
1216 * @phba: ptr device priv structure.
1217 *
1218 * Before the connection resource are freed flush
1219 * all the CQ enteries
1220 **/
1221static void beiscsi_flush_cq(struct beiscsi_hba *phba)
1222{
1223        uint16_t i;
1224        struct be_eq_obj *pbe_eq;
1225        struct hwi_controller *phwi_ctrlr;
1226        struct hwi_context_memory *phwi_context;
1227
1228        phwi_ctrlr = phba->phwi_ctrlr;
1229        phwi_context = phwi_ctrlr->phwi_ctxt;
1230
1231        for (i = 0; i < phba->num_cpus; i++) {
1232                pbe_eq = &phwi_context->be_eq[i];
1233                irq_poll_disable(&pbe_eq->iopoll);
1234                beiscsi_process_cq(pbe_eq, BE2_MAX_NUM_CQ_PROC);
1235                irq_poll_enable(&pbe_eq->iopoll);
1236        }
1237}
1238
1239/**
1240 * beiscsi_conn_close - Invalidate and upload connection
1241 * @beiscsi_ep: pointer to device endpoint struct
1242 *
1243 * Returns 0 on success,  -1 on failure.
1244 */
1245static int beiscsi_conn_close(struct beiscsi_endpoint *beiscsi_ep)
1246{
1247        struct beiscsi_hba *phba = beiscsi_ep->phba;
1248        unsigned int tag, attempts;
1249        int ret;
1250
1251        /**
1252         * Without successfully invalidating and uploading connection
1253         * driver can't reuse the CID so attempt more than once.
1254         */
1255        attempts = 0;
1256        while (attempts++ < 3) {
1257                tag = beiscsi_invalidate_cxn(phba, beiscsi_ep);
1258                if (tag) {
1259                        ret = beiscsi_mccq_compl_wait(phba, tag, NULL, NULL);
1260                        if (!ret)
1261                                break;
1262                        beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
1263                                    "BS_%d : invalidate conn failed cid %d\n",
1264                                    beiscsi_ep->ep_cid);
1265                }
1266        }
1267
1268        /* wait for all completions to arrive, then process them */
1269        msleep(250);
1270        /* flush CQ entries */
1271        beiscsi_flush_cq(phba);
1272
1273        if (attempts > 3)
1274                return -1;
1275
1276        attempts = 0;
1277        while (attempts++ < 3) {
1278                tag = beiscsi_upload_cxn(phba, beiscsi_ep);
1279                if (tag) {
1280                        ret = beiscsi_mccq_compl_wait(phba, tag, NULL, NULL);
1281                        if (!ret)
1282                                break;
1283                        beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
1284                                    "BS_%d : upload conn failed cid %d\n",
1285                                    beiscsi_ep->ep_cid);
1286                }
1287        }
1288        if (attempts > 3)
1289                return -1;
1290
1291        return 0;
1292}
1293
1294/**
1295 * beiscsi_ep_disconnect - Tears down the TCP connection
1296 * @ep: endpoint to be used
1297 *
1298 * Tears down the TCP connection
1299 */
1300void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
1301{
1302        struct beiscsi_endpoint *beiscsi_ep;
1303        struct beiscsi_hba *phba;
1304        uint16_t cri_index;
1305
1306        beiscsi_ep = ep->dd_data;
1307        phba = beiscsi_ep->phba;
1308        beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
1309                    "BS_%d : In beiscsi_ep_disconnect for ep_cid = %u\n",
1310                    beiscsi_ep->ep_cid);
1311
1312        cri_index = BE_GET_CRI_FROM_CID(beiscsi_ep->ep_cid);
1313        if (!phba->ep_array[cri_index]) {
1314                __beiscsi_log(phba, KERN_ERR,
1315                              "BS_%d : ep_array at %u cid %u empty\n",
1316                              cri_index,
1317                              beiscsi_ep->ep_cid);
1318                return;
1319        }
1320
1321        if (!beiscsi_hba_is_online(phba)) {
1322                beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
1323                            "BS_%d : HBA in error 0x%lx\n", phba->state);
1324        } else {
1325                /**
1326                 * Make CID available even if close fails.
1327                 * If not freed, FW might fail open using the CID.
1328                 */
1329                if (beiscsi_conn_close(beiscsi_ep) < 0)
1330                        __beiscsi_log(phba, KERN_ERR,
1331                                      "BS_%d : close conn failed cid %d\n",
1332                                      beiscsi_ep->ep_cid);
1333        }
1334
1335        beiscsi_free_ep(beiscsi_ep);
1336        if (!phba->conn_table[cri_index])
1337                __beiscsi_log(phba, KERN_ERR,
1338                              "BS_%d : conn_table empty at %u: cid %u\n",
1339                              cri_index, beiscsi_ep->ep_cid);
1340        phba->conn_table[cri_index] = NULL;
1341        iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep);
1342}
1343
1344umode_t beiscsi_attr_is_visible(int param_type, int param)
1345{
1346        switch (param_type) {
1347        case ISCSI_NET_PARAM:
1348                switch (param) {
1349                case ISCSI_NET_PARAM_IFACE_ENABLE:
1350                case ISCSI_NET_PARAM_IPV4_ADDR:
1351                case ISCSI_NET_PARAM_IPV4_SUBNET:
1352                case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
1353                case ISCSI_NET_PARAM_IPV4_GW:
1354                case ISCSI_NET_PARAM_IPV6_ADDR:
1355                case ISCSI_NET_PARAM_VLAN_ID:
1356                case ISCSI_NET_PARAM_VLAN_PRIORITY:
1357                case ISCSI_NET_PARAM_VLAN_ENABLED:
1358                        return S_IRUGO;
1359                default:
1360                        return 0;
1361                }
1362        case ISCSI_HOST_PARAM:
1363                switch (param) {
1364                case ISCSI_HOST_PARAM_HWADDRESS:
1365                case ISCSI_HOST_PARAM_INITIATOR_NAME:
1366                case ISCSI_HOST_PARAM_PORT_STATE:
1367                case ISCSI_HOST_PARAM_PORT_SPEED:
1368                        return S_IRUGO;
1369                default:
1370                        return 0;
1371                }
1372        case ISCSI_PARAM:
1373                switch (param) {
1374                case ISCSI_PARAM_MAX_RECV_DLENGTH:
1375                case ISCSI_PARAM_MAX_XMIT_DLENGTH:
1376                case ISCSI_PARAM_HDRDGST_EN:
1377                case ISCSI_PARAM_DATADGST_EN:
1378                case ISCSI_PARAM_CONN_ADDRESS:
1379                case ISCSI_PARAM_CONN_PORT:
1380                case ISCSI_PARAM_EXP_STATSN:
1381                case ISCSI_PARAM_PERSISTENT_ADDRESS:
1382                case ISCSI_PARAM_PERSISTENT_PORT:
1383                case ISCSI_PARAM_PING_TMO:
1384                case ISCSI_PARAM_RECV_TMO:
1385                case ISCSI_PARAM_INITIAL_R2T_EN:
1386                case ISCSI_PARAM_MAX_R2T:
1387                case ISCSI_PARAM_IMM_DATA_EN:
1388                case ISCSI_PARAM_FIRST_BURST:
1389                case ISCSI_PARAM_MAX_BURST:
1390                case ISCSI_PARAM_PDU_INORDER_EN:
1391                case ISCSI_PARAM_DATASEQ_INORDER_EN:
1392                case ISCSI_PARAM_ERL:
1393                case ISCSI_PARAM_TARGET_NAME:
1394                case ISCSI_PARAM_TPGT:
1395                case ISCSI_PARAM_USERNAME:
1396                case ISCSI_PARAM_PASSWORD:
1397                case ISCSI_PARAM_USERNAME_IN:
1398                case ISCSI_PARAM_PASSWORD_IN:
1399                case ISCSI_PARAM_FAST_ABORT:
1400                case ISCSI_PARAM_ABORT_TMO:
1401                case ISCSI_PARAM_LU_RESET_TMO:
1402                case ISCSI_PARAM_IFACE_NAME:
1403                case ISCSI_PARAM_INITIATOR_NAME:
1404                        return S_IRUGO;
1405                default:
1406                        return 0;
1407                }
1408        }
1409
1410        return 0;
1411}
1412