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