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