[SCSI] iscsi class: sysfs group is_visible callout for session attrs
[linux-2.6.git] / drivers / scsi / be2iscsi / be_main.c
index 7436c5a..93a3c70 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2005 - 2010 ServerEngines
+ * Copyright (C) 2005 - 2011 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -7,16 +7,16 @@
  * as published by the Free Software Foundation.  The full GNU General
  * Public License is included in this distribution in the file called COPYING.
  *
- * Written by: Jayamohan Kallickal (jayamohank@serverengines.com)
+ * Written by: Jayamohan Kallickal (jayamohan.kallickal@emulex.com)
  *
  * Contact Information:
- * linux-drivers@serverengines.com
- *
- *  ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
+ * linux-drivers@emulex.com
  *
+ * Emulex
+ * 3333 Susan Street
+ * Costa Mesa, CA 92626
  */
+
 #include <linux/reboot.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
@@ -26,6 +26,7 @@
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/semaphore.h>
+#include <linux/iscsi_boot_sysfs.h>
 
 #include <scsi/libiscsi.h>
 #include <scsi/scsi_transport_iscsi.h>
@@ -211,6 +212,174 @@ unlock:
        return rc;
 }
 
+static ssize_t beiscsi_show_boot_tgt_info(void *data, int type, char *buf)
+{
+       struct beiscsi_hba *phba = data;
+       struct mgmt_session_info *boot_sess = &phba->boot_sess;
+       struct mgmt_conn_info *boot_conn = &boot_sess->conn_list[0];
+       char *str = buf;
+       int rc;
+
+       switch (type) {
+       case ISCSI_BOOT_TGT_NAME:
+               rc = sprintf(buf, "%.*s\n",
+                           (int)strlen(boot_sess->target_name),
+                           (char *)&boot_sess->target_name);
+               break;
+       case ISCSI_BOOT_TGT_IP_ADDR:
+               if (boot_conn->dest_ipaddr.ip_type == 0x1)
+                       rc = sprintf(buf, "%pI4\n",
+                               (char *)&boot_conn->dest_ipaddr.ip_address);
+               else
+                       rc = sprintf(str, "%pI6\n",
+                               (char *)&boot_conn->dest_ipaddr.ip_address);
+               break;
+       case ISCSI_BOOT_TGT_PORT:
+               rc = sprintf(str, "%d\n", boot_conn->dest_port);
+               break;
+
+       case ISCSI_BOOT_TGT_CHAP_NAME:
+               rc = sprintf(str,  "%.*s\n",
+                            boot_conn->negotiated_login_options.auth_data.chap.
+                            target_chap_name_length,
+                            (char *)&boot_conn->negotiated_login_options.
+                            auth_data.chap.target_chap_name);
+               break;
+       case ISCSI_BOOT_TGT_CHAP_SECRET:
+               rc = sprintf(str,  "%.*s\n",
+                            boot_conn->negotiated_login_options.auth_data.chap.
+                            target_secret_length,
+                            (char *)&boot_conn->negotiated_login_options.
+                            auth_data.chap.target_secret);
+               break;
+       case ISCSI_BOOT_TGT_REV_CHAP_NAME:
+               rc = sprintf(str,  "%.*s\n",
+                            boot_conn->negotiated_login_options.auth_data.chap.
+                            intr_chap_name_length,
+                            (char *)&boot_conn->negotiated_login_options.
+                            auth_data.chap.intr_chap_name);
+               break;
+       case ISCSI_BOOT_TGT_REV_CHAP_SECRET:
+               rc = sprintf(str,  "%.*s\n",
+                            boot_conn->negotiated_login_options.auth_data.chap.
+                            intr_secret_length,
+                            (char *)&boot_conn->negotiated_login_options.
+                            auth_data.chap.intr_secret);
+               break;
+       case ISCSI_BOOT_TGT_FLAGS:
+               rc = sprintf(str, "2\n");
+               break;
+       case ISCSI_BOOT_TGT_NIC_ASSOC:
+               rc = sprintf(str, "0\n");
+               break;
+       default:
+               rc = -ENOSYS;
+               break;
+       }
+       return rc;
+}
+
+static ssize_t beiscsi_show_boot_ini_info(void *data, int type, char *buf)
+{
+       struct beiscsi_hba *phba = data;
+       char *str = buf;
+       int rc;
+
+       switch (type) {
+       case ISCSI_BOOT_INI_INITIATOR_NAME:
+               rc = sprintf(str, "%s\n", phba->boot_sess.initiator_iscsiname);
+               break;
+       default:
+               rc = -ENOSYS;
+               break;
+       }
+       return rc;
+}
+
+static ssize_t beiscsi_show_boot_eth_info(void *data, int type, char *buf)
+{
+       struct beiscsi_hba *phba = data;
+       char *str = buf;
+       int rc;
+
+       switch (type) {
+       case ISCSI_BOOT_ETH_FLAGS:
+               rc = sprintf(str, "2\n");
+               break;
+       case ISCSI_BOOT_ETH_INDEX:
+               rc = sprintf(str, "0\n");
+               break;
+       case ISCSI_BOOT_ETH_MAC:
+               rc  = beiscsi_get_macaddr(buf, phba);
+               if (rc < 0) {
+                       SE_DEBUG(DBG_LVL_1, "beiscsi_get_macaddr Failed\n");
+                       return rc;
+               }
+       break;
+       default:
+               rc = -ENOSYS;
+               break;
+       }
+       return rc;
+}
+
+
+static mode_t beiscsi_tgt_get_attr_visibility(void *data, int type)
+{
+       int rc;
+
+       switch (type) {
+       case ISCSI_BOOT_TGT_NAME:
+       case ISCSI_BOOT_TGT_IP_ADDR:
+       case ISCSI_BOOT_TGT_PORT:
+       case ISCSI_BOOT_TGT_CHAP_NAME:
+       case ISCSI_BOOT_TGT_CHAP_SECRET:
+       case ISCSI_BOOT_TGT_REV_CHAP_NAME:
+       case ISCSI_BOOT_TGT_REV_CHAP_SECRET:
+       case ISCSI_BOOT_TGT_NIC_ASSOC:
+       case ISCSI_BOOT_TGT_FLAGS:
+               rc = S_IRUGO;
+               break;
+       default:
+               rc = 0;
+               break;
+       }
+       return rc;
+}
+
+static mode_t beiscsi_ini_get_attr_visibility(void *data, int type)
+{
+       int rc;
+
+       switch (type) {
+       case ISCSI_BOOT_INI_INITIATOR_NAME:
+               rc = S_IRUGO;
+               break;
+       default:
+               rc = 0;
+               break;
+       }
+       return rc;
+}
+
+
+static mode_t beiscsi_eth_get_attr_visibility(void *data, int type)
+{
+       int rc;
+
+       switch (type) {
+       case ISCSI_BOOT_ETH_FLAGS:
+       case ISCSI_BOOT_ETH_MAC:
+       case ISCSI_BOOT_ETH_INDEX:
+               rc = S_IRUGO;
+               break;
+       default:
+               rc = 0;
+               break;
+       }
+       return rc;
+}
+
 /*------------------- PCI Driver operations and data ----------------- */
 static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = {
        { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) },
@@ -268,6 +437,7 @@ static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev)
 
        if (iscsi_host_add(shost, &phba->pcidev->dev))
                goto free_devices;
+
        return phba;
 
 free_devices:
@@ -396,7 +566,7 @@ static void beiscsi_get_params(struct beiscsi_hba *phba)
                                    + BE2_NOPOUT_REQ));
        phba->params.cxns_per_ctrl = phba->fw_config.iscsi_cid_count;
        phba->params.asyncpdus_per_ctrl = phba->fw_config.iscsi_cid_count * 2;
-       phba->params.icds_per_ctrl = phba->fw_config.iscsi_icd_count;;
+       phba->params.icds_per_ctrl = phba->fw_config.iscsi_icd_count;
        phba->params.num_sge_per_io = BE2_SGE;
        phba->params.defpdu_hdr_sz = BE2_DEFPDU_HDR_SZ;
        phba->params.defpdu_data_sz = BE2_DEFPDU_DATA_SZ;
@@ -559,7 +729,7 @@ static irqreturn_t be_isr(int irq, void *dev_id)
        int isr;
 
        phba = dev_id;
-       ctrl = &phba->ctrl;;
+       ctrl = &phba->ctrl;
        isr = ioread32(ctrl->csr + CEV_ISR0_OFFSET +
                       (PCI_FUNC(ctrl->pdev->devfn) * CEV_ISR_SIZE));
        if (!isr)
@@ -1818,7 +1988,7 @@ hwi_write_sgl(struct iscsi_wrb *pwrb, struct scatterlist *sg,
              unsigned int num_sg, struct beiscsi_io_task *io_task)
 {
        struct iscsi_sge *psgl;
-       unsigned short sg_len, index;
+       unsigned int sg_len, index;
        unsigned int sge_len = 0;
        unsigned long long addr;
        struct scatterlist *l_sg;
@@ -3242,23 +3412,23 @@ static void hwi_enable_intr(struct beiscsi_hba *phba)
        addr = (u8 __iomem *) ((u8 __iomem *) ctrl->pcicfg +
                        PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET);
        reg = ioread32(addr);
-       SE_DEBUG(DBG_LVL_8, "reg =x%08x\n", reg);
 
        enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
        if (!enabled) {
                reg |= MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
                SE_DEBUG(DBG_LVL_8, "reg =x%08x addr=%p\n", reg, addr);
                iowrite32(reg, addr);
-               if (!phba->msix_enabled) {
-                       eq = &phwi_context->be_eq[0].q;
+       }
+
+       if (!phba->msix_enabled) {
+               eq = &phwi_context->be_eq[0].q;
+               SE_DEBUG(DBG_LVL_8, "eq->id=%d\n", eq->id);
+               hwi_ring_eq_db(phba, eq->id, 0, 0, 1, 1);
+       } else {
+               for (i = 0; i <= phba->num_cpus; i++) {
+                       eq = &phwi_context->be_eq[i].q;
                        SE_DEBUG(DBG_LVL_8, "eq->id=%d\n", eq->id);
                        hwi_ring_eq_db(phba, eq->id, 0, 0, 1, 1);
-               } else {
-                       for (i = 0; i <= phba->num_cpus; i++) {
-                               eq = &phwi_context->be_eq[i].q;
-                               SE_DEBUG(DBG_LVL_8, "eq->id=%d\n", eq->id);
-                               hwi_ring_eq_db(phba, eq->id, 0, 0, 1, 1);
-                       }
                }
        }
 }
@@ -3279,6 +3449,145 @@ static void hwi_disable_intr(struct beiscsi_hba *phba)
                             "In hwi_disable_intr, Already Disabled\n");
 }
 
+static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
+{
+       struct be_cmd_resp_get_boot_target *boot_resp;
+       struct be_cmd_resp_get_session *session_resp;
+       struct be_mcc_wrb *wrb;
+       struct be_dma_mem nonemb_cmd;
+       unsigned int tag, wrb_num;
+       unsigned short status, extd_status;
+       struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
+       int ret = -ENOMEM;
+
+       tag = beiscsi_get_boot_target(phba);
+       if (!tag) {
+               SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed\n");
+               return -EAGAIN;
+       } else
+               wait_event_interruptible(phba->ctrl.mcc_wait[tag],
+                                        phba->ctrl.mcc_numtag[tag]);
+
+       wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
+       extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
+       status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
+       if (status || extd_status) {
+               SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed"
+                                   " status = %d extd_status = %d\n",
+                                   status, extd_status);
+               free_mcc_tag(&phba->ctrl, tag);
+               return -EBUSY;
+       }
+       wrb = queue_get_wrb(mccq, wrb_num);
+       free_mcc_tag(&phba->ctrl, tag);
+       boot_resp = embedded_payload(wrb);
+
+       if (boot_resp->boot_session_handle < 0) {
+               shost_printk(KERN_INFO, phba->shost, "No Boot Session.\n");
+               return -ENXIO;
+       }
+
+       nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev,
+                               sizeof(*session_resp),
+                               &nonemb_cmd.dma);
+       if (nonemb_cmd.va == NULL) {
+               SE_DEBUG(DBG_LVL_1,
+                        "Failed to allocate memory for"
+                        "beiscsi_get_session_info\n");
+               return -ENOMEM;
+       }
+
+       memset(nonemb_cmd.va, 0, sizeof(*session_resp));
+       tag = beiscsi_get_session_info(phba,
+               boot_resp->boot_session_handle, &nonemb_cmd);
+       if (!tag) {
+               SE_DEBUG(DBG_LVL_1, "beiscsi_get_session_info"
+                       " Failed\n");
+               goto boot_freemem;
+       } else
+               wait_event_interruptible(phba->ctrl.mcc_wait[tag],
+                                        phba->ctrl.mcc_numtag[tag]);
+
+       wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
+       extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
+       status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
+       if (status || extd_status) {
+               SE_DEBUG(DBG_LVL_1, "beiscsi_get_session_info Failed"
+                                   " status = %d extd_status = %d\n",
+                                   status, extd_status);
+               free_mcc_tag(&phba->ctrl, tag);
+               goto boot_freemem;
+       }
+       wrb = queue_get_wrb(mccq, wrb_num);
+       free_mcc_tag(&phba->ctrl, tag);
+       session_resp = nonemb_cmd.va ;
+
+       memcpy(&phba->boot_sess, &session_resp->session_info,
+              sizeof(struct mgmt_session_info));
+       ret = 0;
+
+boot_freemem:
+       pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
+                   nonemb_cmd.va, nonemb_cmd.dma);
+       return ret;
+}
+
+static void beiscsi_boot_release(void *data)
+{
+       struct beiscsi_hba *phba = data;
+
+       scsi_host_put(phba->shost);
+}
+
+static int beiscsi_setup_boot_info(struct beiscsi_hba *phba)
+{
+       struct iscsi_boot_kobj *boot_kobj;
+
+       /* get boot info using mgmt cmd */
+       if (beiscsi_get_boot_info(phba))
+               /* Try to see if we can carry on without this */
+               return 0;
+
+       phba->boot_kset = iscsi_boot_create_host_kset(phba->shost->host_no);
+       if (!phba->boot_kset)
+               return -ENOMEM;
+
+       /* get a ref because the show function will ref the phba */
+       if (!scsi_host_get(phba->shost))
+               goto free_kset;
+       boot_kobj = iscsi_boot_create_target(phba->boot_kset, 0, phba,
+                                            beiscsi_show_boot_tgt_info,
+                                            beiscsi_tgt_get_attr_visibility,
+                                            beiscsi_boot_release);
+       if (!boot_kobj)
+               goto put_shost;
+
+       if (!scsi_host_get(phba->shost))
+               goto free_kset;
+       boot_kobj = iscsi_boot_create_initiator(phba->boot_kset, 0, phba,
+                                               beiscsi_show_boot_ini_info,
+                                               beiscsi_ini_get_attr_visibility,
+                                               beiscsi_boot_release);
+       if (!boot_kobj)
+               goto put_shost;
+
+       if (!scsi_host_get(phba->shost))
+               goto free_kset;
+       boot_kobj = iscsi_boot_create_ethernet(phba->boot_kset, 0, phba,
+                                              beiscsi_show_boot_eth_info,
+                                              beiscsi_eth_get_attr_visibility,
+                                              beiscsi_boot_release);
+       if (!boot_kobj)
+               goto put_shost;
+       return 0;
+
+put_shost:
+       scsi_host_put(phba->shost);
+free_kset:
+       iscsi_boot_destroy_kset(phba->boot_kset);
+       return -ENOMEM;
+}
+
 static int beiscsi_init_port(struct beiscsi_hba *phba)
 {
        int ret;
@@ -3480,7 +3789,7 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
        dma_addr_t paddr;
 
        io_task->cmd_bhs = pci_pool_alloc(beiscsi_sess->bhs_pool,
-                                         GFP_KERNEL, &paddr);
+                                         GFP_ATOMIC, &paddr);
        if (!io_task->cmd_bhs)
                return -ENOMEM;
        io_task->bhs_pa.u.a64.address = paddr;
@@ -3609,7 +3918,8 @@ static void beiscsi_cleanup_task(struct iscsi_task *task)
                        io_task->psgl_handle = NULL;
                }
        } else {
-               if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN)
+               if (task->hdr &&
+                  ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN))
                        return;
                if (io_task->psgl_handle) {
                        spin_lock(&phba->mgmt_sgl_lock);
@@ -3656,11 +3966,10 @@ static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg,
        }
        memcpy(&io_task->cmd_bhs->iscsi_data_pdu.
               dw[offsetof(struct amap_pdu_data_out, lun) / 32],
-              io_task->cmd_bhs->iscsi_hdr.lun, sizeof(struct scsi_lun));
+              &io_task->cmd_bhs->iscsi_hdr.lun, sizeof(struct scsi_lun));
 
        AMAP_SET_BITS(struct amap_iscsi_wrb, lun, pwrb,
-                     cpu_to_be16((unsigned short)io_task->cmd_bhs->iscsi_hdr.
-                                 lun[0]));
+                     cpu_to_be16(*(unsigned short *)&io_task->cmd_bhs->iscsi_hdr.lun));
        AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb, xferlen);
        AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb,
                      io_task->pwrb_handle->wrb_index);
@@ -3713,12 +4022,17 @@ static int beiscsi_mtask(struct iscsi_task *task)
                hwi_write_buffer(pwrb, task);
                break;
        case ISCSI_OP_NOOP_OUT:
-               AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
-                             INI_RD_CMD);
-               if (task->hdr->ttt == ISCSI_RESERVED_TAG)
+               if (task->hdr->ttt != ISCSI_RESERVED_TAG) {
+                       AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
+                                     TGT_DM_CMD);
+                       AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt,
+                                     pwrb, 0);
                        AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
-               else
+               } else {
+                       AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
+                                     INI_RD_CMD);
                        AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 1);
+               }
                hwi_write_buffer(pwrb, task);
                break;
        case ISCSI_OP_TEXT:
@@ -3838,6 +4152,7 @@ static void beiscsi_remove(struct pci_dev *pcidev)
                            phba->ctrl.mbox_mem_alloced.size,
                            phba->ctrl.mbox_mem_alloced.va,
                            phba->ctrl.mbox_mem_alloced.dma);
+       iscsi_boot_destroy_kset(phba->boot_kset);
        iscsi_host_remove(phba->shost);
        pci_dev_put(phba->pcidev);
        iscsi_host_free(phba->shost);
@@ -3970,7 +4285,7 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
 
        snprintf(phba->wq_name, sizeof(phba->wq_name), "beiscsi_q_irq%u",
                 phba->shost->host_no);
-       phba->wq = create_workqueue(phba->wq_name);
+       phba->wq = alloc_workqueue(phba->wq_name, WQ_MEM_RECLAIM, 1);
        if (!phba->wq) {
                shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-"
                                "Failed to allocate work queue\n");
@@ -3996,6 +4311,15 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
                goto free_blkenbld;
        }
        hwi_enable_intr(phba);
+
+       if (beiscsi_setup_boot_info(phba))
+               /*
+                * log error but continue, because we may not be using
+                * iscsi boot.
+                */
+               shost_printk(KERN_ERR, phba->shost, "Could not set up "
+                            "iSCSI boot info.");
+
        SE_DEBUG(DBG_LVL_8, "\n\n\n SUCCESS - DRIVER LOADED\n\n\n");
        return 0;
 
@@ -4040,30 +4364,6 @@ struct iscsi_transport beiscsi_iscsi_transport = {
        .name = DRV_NAME,
        .caps = CAP_RECOVERY_L0 | CAP_HDRDGST | CAP_TEXT_NEGO |
                CAP_MULTI_R2T | CAP_DATADGST | CAP_DATA_PATH_OFFLOAD,
-       .param_mask = ISCSI_MAX_RECV_DLENGTH |
-               ISCSI_MAX_XMIT_DLENGTH |
-               ISCSI_HDRDGST_EN |
-               ISCSI_DATADGST_EN |
-               ISCSI_INITIAL_R2T_EN |
-               ISCSI_MAX_R2T |
-               ISCSI_IMM_DATA_EN |
-               ISCSI_FIRST_BURST |
-               ISCSI_MAX_BURST |
-               ISCSI_PDU_INORDER_EN |
-               ISCSI_DATASEQ_INORDER_EN |
-               ISCSI_ERL |
-               ISCSI_CONN_PORT |
-               ISCSI_CONN_ADDRESS |
-               ISCSI_EXP_STATSN |
-               ISCSI_PERSISTENT_PORT |
-               ISCSI_PERSISTENT_ADDRESS |
-               ISCSI_TARGET_NAME | ISCSI_TPGT |
-               ISCSI_USERNAME | ISCSI_PASSWORD |
-               ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
-               ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
-               ISCSI_LU_RESET_TMO |
-               ISCSI_PING_TMO | ISCSI_RECV_TMO |
-               ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
        .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
                                ISCSI_HOST_INITIATOR_NAME,
        .create_session = beiscsi_session_create,
@@ -4071,8 +4371,9 @@ struct iscsi_transport beiscsi_iscsi_transport = {
        .create_conn = beiscsi_conn_create,
        .bind_conn = beiscsi_conn_bind,
        .destroy_conn = iscsi_conn_teardown,
+       .attr_is_visible = be2iscsi_attr_is_visible,
        .set_param = beiscsi_set_param,
-       .get_conn_param = beiscsi_conn_get_param,
+       .get_conn_param = iscsi_conn_get_param,
        .get_session_param = iscsi_session_get_param,
        .get_host_param = beiscsi_get_host_param,
        .start_conn = beiscsi_conn_start,
@@ -4083,6 +4384,7 @@ struct iscsi_transport beiscsi_iscsi_transport = {
        .alloc_pdu = beiscsi_alloc_pdu,
        .parse_pdu_itt = beiscsi_parse_pdu,
        .get_stats = beiscsi_conn_get_stats,
+       .get_ep_param = beiscsi_ep_get_param,
        .ep_connect = beiscsi_ep_connect,
        .ep_poll = beiscsi_ep_poll,
        .ep_disconnect = beiscsi_ep_disconnect,