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