This patch contains the necessary changes to support
the bsg interface

Signed-off-by: Jayamohan Kallickal <jayamoh...@serverengines.com>
---
 drivers/scsi/be2iscsi/be_cmds.h  |  137 ++++++++++++++++++++---
 drivers/scsi/be2iscsi/be_iscsi.c |    3 +-
 drivers/scsi/be2iscsi/be_main.c  |   99 ++++++++++++++--
 drivers/scsi/be2iscsi/be_main.h  |    6 +-
 drivers/scsi/be2iscsi/be_mgmt.c  |  230 +++++++++++++++++++++++++++++++++++++-
 drivers/scsi/be2iscsi/be_mgmt.h  |  107 ++++++++++++++++++
 include/scsi/scsi_bsg_iscsi.h    |    1 +
 7 files changed, 547 insertions(+), 36 deletions(-)

diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h
index 49fcc78..d5c14cf 100644
--- a/drivers/scsi/be2iscsi/be_cmds.h
+++ b/drivers/scsi/be2iscsi/be_cmds.h
@@ -18,6 +18,7 @@
 #ifndef BEISCSI_CMDS_H
 #define BEISCSI_CMDS_H
 
+#include <scsi/scsi_bsg_iscsi.h>
 /**
  * The driver sends configuration and managements command requests to the
  * firmware in the BE. These requests are communicated to the processor
@@ -162,6 +163,13 @@ struct be_mcc_mailbox {
 #define OPCODE_COMMON_ISCSI_CFG_POST_SGL_PAGES         2
 #define OPCODE_COMMON_ISCSI_CFG_REMOVE_SGL_PAGES        3
 #define OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG                7
+#define OPCODE_COMMON_ISCSI_NTWK_SET_VLAN              14
+#define OPCODE_COMMON_ISCSI_NTWK_CONFIGURE_STATELESS_IP_ADDR   17
+#define OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR                21
+#define OPCODE_COMMON_ISCSI_NTWK_GET_DEFAULT_GATEWAY   22
+#define OPCODE_COMMON_ISCSI_NTWK_MODIFY_DEFAULT_GATEWAY 23
+#define OPCODE_COMMON_ISCSI_NTWK_GET_ALL_IF_ID         24
+#define OPCODE_COMMON_ISCSI_NTWK_GET_IF_INFO           25
 #define OPCODE_COMMON_ISCSI_SET_FRAGNUM_BITS_FOR_SGL_CRA 61
 #define OPCODE_COMMON_ISCSI_DEFQ_CREATE                 64
 #define OPCODE_COMMON_ISCSI_DEFQ_DESTROY               65
@@ -237,6 +245,86 @@ struct be_cmd_resp_eq_create {
        u16 rsvd0;              /* sword */
 } __packed;
 
+struct mgmt_chap_format {
+       u32 flags;
+       u8  intr_chap_name[256];
+       u8  intr_secret[16];
+       u8  target_chap_name[256];
+       u8  target_secret[16];
+       u16 intr_chap_name_length;
+       u16 intr_secret_length;
+       u16 target_chap_name_length;
+       u16 target_secret_length;
+} __packed;
+
+struct mgmt_auth_method_format {
+       u8      auth_method_type;
+       u8      padding[3];
+       struct  mgmt_chap_format chap;
+} __packed;
+
+struct mgmt_conn_login_options {
+       u8 flags;
+       u8 header_digest;
+       u8 data_digest;
+       u8 rsvd0;
+       u32 max_recv_datasegment_len_ini;
+       u32 max_recv_datasegment_len_tgt;
+       u32 tcp_mss;
+       u32 tcp_window_size;
+       struct  mgmt_auth_method_format auth_data;
+} __packed;
+
+struct mgmt_conn_info {
+       u32     connection_handle;
+       u32     connection_status;
+       u16     src_port;
+       u16     dest_port;
+       u16     dest_port_redirected;
+       u16     cid;
+       u32     estimated_throughput;
+       struct  ip_address_format       src_ipaddr;
+       struct  ip_address_format       dest_ipaddr;
+       struct  ip_address_format       dest_ipaddr_redirected;
+       struct  mgmt_conn_login_options negotiated_login_options;
+} __packed;
+
+struct mgmt_session_login_options {
+       u8      flags;
+       u8      error_recovery_level;
+       u16     rsvd0;
+       u32     first_burst_length;
+       u32     max_burst_length;
+       u16     max_connections;
+       u16     max_outstanding_r2t;
+       u16     default_time2wait;
+       u16     default_time2retain;
+} __packed;
+
+struct mgmt_session_info {
+       u32     session_handle;
+       u32     status;
+       u8      isid[6];
+       u16     tsih;
+       u32     session_flags;
+       u16     conn_count;
+       u16     pad;
+       u8      target_name[224];
+       u8      initiator_iscsiname[224];
+       struct  mgmt_session_login_options      negotiated_login_options;
+       struct  mgmt_conn_info  conn_list[1];
+} __packed;
+
+struct  be_cmd_req_geta_session {
+       struct be_cmd_resp_hdr resp_hdr;
+       u32 session_handle;
+} __packed;
+
+struct  be_cmd_resp_geta_session {
+       struct be_cmd_resp_hdr resp_hdr;
+       struct mgmt_session_info session_info;
+} __packed;
+
 struct mac_addr {
        u16 size_of_struct;
        u8 addr[ETH_ALEN];
@@ -254,6 +342,16 @@ struct be_cmd_resp_mac_query {
        struct mac_addr mac;
 };
 
+struct be_cmd_req_get_boot_target {
+       struct be_cmd_req_hdr hdr;
+} __packed;
+
+struct be_cmd_resp_get_boot_target {
+       struct be_cmd_resp_hdr hdr;
+       u32  boot_session_count;
+       u32  boot_session_handle;
+};
+
 /******************** Create CQ ***************************/
 /**
  * Pseudo amap definition in which each bit of the actual structure is defined
@@ -601,14 +699,6 @@ struct be_eq_delay_params_in {
        struct eq_delay delay[8];
 } __packed;
 
-struct ip_address_format {
-       u16 size_of_structure;
-       u8 reserved;
-       u8 ip_type;
-       u8 ip_address[16];
-       u32 rsvd0;
-} __packed;
-
 struct tcp_connect_and_offload_in {
        struct be_cmd_req_hdr hdr;
        struct ip_address_format ip_address;
@@ -688,18 +778,31 @@ struct be_fw_cfg {
        u32 function_caps;
 } __packed;
 
-#define CMD_ISCSI_COMMAND_INVALIDATE  1
-#define ISCSI_OPCODE_SCSI_DATA_OUT      5
+struct be_all_if_id {
+       struct be_cmd_req_hdr hdr;
+       u32 if_count;
+       u32 if_hndl_list[1];
+} __packed;
+
+
+#define ISCSI_OPCODE_SCSI_DATA_OUT             5
 #define OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD 70
-#define OPCODE_ISCSI_INI_DRIVER_OFFLOAD_SESSION 41
-#define OPCODE_COMMON_MODIFY_EQ_DELAY  41
-#define OPCODE_COMMON_ISCSI_CLEANUP    59
-#define        OPCODE_COMMON_TCP_UPLOAD        56
+#define OPCODE_COMMON_MODIFY_EQ_DELAY          41
+#define OPCODE_COMMON_ISCSI_CLEANUP            59
+#define        OPCODE_COMMON_TCP_UPLOAD                56
 #define OPCODE_COMMON_ISCSI_ERROR_RECOVERY_INVALIDATE_COMMANDS 1
-/* --- CMD_ISCSI_INVALIDATE_CONNECTION_TYPE --- */
-#define CMD_ISCSI_CONNECTION_INVALIDATE 0x8001
-#define CMD_ISCSI_CONNECTION_ISSUE_TCP_RST 0x8002
+#define OPCODE_ISCSI_INI_CFG_GET_HBA_NAME      6
+#define OPCODE_ISCSI_INI_CFG_SET_HBA_NAME      7
+#define OPCODE_ISCSI_INI_SESSION_GET_A_SESSION  14
+#define OPCODE_ISCSI_INI_DRIVER_OFFLOAD_SESSION 41
 #define OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION 42
+#define OPCODE_ISCSI_INI_BOOT_GET_BOOT_TARGET  52
+
+/* --- CMD_ISCSI_INVALIDATE_CONNECTION_TYPE --- */
+#define CMD_ISCSI_COMMAND_INVALIDATE           1
+#define CMD_ISCSI_CONNECTION_INVALIDATE                0x8001
+#define CMD_ISCSI_CONNECTION_ISSUE_TCP_RST     0x8002
+
 
 #define INI_WR_CMD                     1       /* Initiator write command */
 #define INI_TMF_CMD                    2       /* Initiator TMF command */
diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c
index c3928cb..eae98de 100644
--- a/drivers/scsi/be2iscsi/be_iscsi.c
+++ b/drivers/scsi/be2iscsi/be_iscsi.c
@@ -696,8 +696,7 @@ void beiscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int 
flag)
        SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_stop  ep_cid = %d\n",
                             beiscsi_ep->ep_cid);
        tag = mgmt_invalidate_connection(phba, beiscsi_ep,
-                                           beiscsi_ep->ep_cid, 1,
-                                           savecfg_flag);
+                                        beiscsi_ep->ep_cid, 0, savecfg_flag);
        if (!tag) {
                SE_DEBUG(DBG_LVL_1,
                         "mgmt_invalidate_connection Failed for cid=%d \n",
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index fcfb29e..82ec2cc 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -28,6 +28,7 @@
 
 #include <scsi/libiscsi.h>
 #include <scsi/scsi_transport_iscsi.h>
+#include <scsi/scsi_bsg_iscsi.h>
 #include <scsi/scsi_transport.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
@@ -73,6 +74,7 @@ static int beiscsi_eh_abort(struct scsi_cmnd *sc)
        cls_session = starget_to_session(scsi_target(sc->device));
        session = cls_session->dd_data;
 
+
        spin_lock_bh(&session->lock);
        if (!aborted_task || !aborted_task->sc) {
                /* we raced */
@@ -229,6 +231,7 @@ static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev 
*pcidev)
        phba->shost = shost;
        phba->pcidev = pci_dev_get(pcidev);
        pci_set_drvdata(pcidev, phba);
+       phba->interface_handle = 0xFFFFFFFF;
 
        if (iscsi_host_add(shost, &phba->pcidev->dev))
                goto free_devices;
@@ -1074,7 +1077,6 @@ static void hwi_complete_cmd(struct beiscsi_conn 
*beiscsi_conn,
                        be_complete_logout(beiscsi_conn, task, psol);
                else
                        be_complete_tmf(beiscsi_conn, task, psol);
-
                break;
 
        case HWH_TYPE_LOGIN:
@@ -1763,7 +1765,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;
@@ -3201,7 +3203,9 @@ static unsigned char hwi_enable_intr(struct beiscsi_hba 
*phba)
                                hwi_ring_eq_db(phba, eq->id, 0, 0, 1, 1);
                        }
                }
-       }
+       } else
+               shost_printk(KERN_WARNING, phba->shost,
+                            "In hwi_enable_intr, Not Enabled \n");
        return true;
 }
 
@@ -3427,21 +3431,23 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, 
uint8_t opcode)
                return -ENOMEM;
        io_task->bhs_pa.u.a64.address = paddr;
        io_task->libiscsi_itt = (itt_t)task->itt;
-       io_task->pwrb_handle = alloc_wrb_handle(phba,
-                                               beiscsi_conn->beiscsi_conn_cid -
-                                               phba->fw_config.iscsi_cid_start
-                                               );
        io_task->conn = beiscsi_conn;
 
        task->hdr = (struct iscsi_hdr *)&io_task->cmd_bhs->iscsi_hdr;
        task->hdr_max = sizeof(struct be_cmd_bhs);
-
+       io_task->psgl_handle = NULL;
+       io_task->psgl_handle = NULL;
        if (task->sc) {
                spin_lock(&phba->io_sgl_lock);
                io_task->psgl_handle = alloc_io_sgl_handle(phba);
                spin_unlock(&phba->io_sgl_lock);
                if (!io_task->psgl_handle)
                        goto free_hndls;
+               io_task->pwrb_handle = alloc_wrb_handle(phba,
+                                       beiscsi_conn->beiscsi_conn_cid -
+                                       phba->fw_config.iscsi_cid_start);
+               if (!io_task->pwrb_handle)
+                       goto free_io_hndls;
        } else {
                io_task->scsi_cmnd = NULL;
                if ((opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN) {
@@ -3456,9 +3462,19 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, 
uint8_t opcode)
                                beiscsi_conn->login_in_progress = 1;
                                beiscsi_conn->plogin_sgl_handle =
                                                        io_task->psgl_handle;
+                               io_task->pwrb_handle =
+                                       alloc_wrb_handle(phba,
+                                       beiscsi_conn->beiscsi_conn_cid -
+                                       phba->fw_config.iscsi_cid_start);
+                               if (!io_task->pwrb_handle)
+                                       goto free_io_hndls;
+                               beiscsi_conn->plogin_wrb_handle =
+                                                       io_task->pwrb_handle;
                        } else {
                                io_task->psgl_handle =
                                                beiscsi_conn->plogin_sgl_handle;
+                               io_task->pwrb_handle =
+                                               beiscsi_conn->plogin_wrb_handle;
                        }
                } else {
                        spin_lock(&phba->mgmt_sgl_lock);
@@ -3466,6 +3482,12 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, 
uint8_t opcode)
                        spin_unlock(&phba->mgmt_sgl_lock);
                        if (!io_task->psgl_handle)
                                goto free_hndls;
+                       io_task->pwrb_handle =
+                                       alloc_wrb_handle(phba,
+                                       beiscsi_conn->beiscsi_conn_cid -
+                                       phba->fw_config.iscsi_cid_start);
+                       if (!io_task->pwrb_handle)
+                               goto free_mgmt_hndls;
                }
        }
        itt = (itt_t) cpu_to_be32(((unsigned int)io_task->pwrb_handle->
@@ -3475,13 +3497,22 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, 
uint8_t opcode)
 
        io_task->cmd_bhs->iscsi_hdr.itt = itt;
        return 0;
-
+free_io_hndls:
+       spin_lock(&phba->io_sgl_lock);
+       free_io_sgl_handle(phba, io_task->psgl_handle);
+       spin_unlock(&phba->io_sgl_lock);
+       goto free_hndls;
+free_mgmt_hndls:
+       spin_lock(&phba->mgmt_sgl_lock);
+       free_mgmt_sgl_handle(phba, io_task->psgl_handle);
+       spin_unlock(&phba->mgmt_sgl_lock);
 free_hndls:
        phwi_ctrlr = phba->phwi_ctrlr;
        pwrb_context = &phwi_ctrlr->wrb_context[
                        beiscsi_conn->beiscsi_conn_cid -
                        phba->fw_config.iscsi_cid_start];
-       free_wrb_handle(phba, pwrb_context, io_task->pwrb_handle);
+       if (io_task->pwrb_handle)
+               free_wrb_handle(phba, pwrb_context, io_task->pwrb_handle);
        io_task->pwrb_handle = NULL;
        pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs,
                      io_task->bhs_pa.u.a64.address);
@@ -3688,8 +3719,6 @@ static int beiscsi_task_xmit(struct iscsi_task *task)
                SE_DEBUG(DBG_LVL_1, " scsi_dma_map Failed\n")
                return num_sg;
        }
-       SE_DEBUG(DBG_LVL_4, "xferlen=0x%08x scmd=%p num_sg=%d sernum=%lu\n",
-                 (scsi_bufflen(sc)), sc, num_sg, sc->serial_number);
        xferlen = scsi_bufflen(sc);
        sg = scsi_sglist(sc);
        if (sc->sc_data_direction == DMA_TO_DEVICE) {
@@ -3701,6 +3730,50 @@ static int beiscsi_task_xmit(struct iscsi_task *task)
        return beiscsi_iotask(task, sg, num_sg, xferlen, writedir);
 }
 
+/**
+* beiscsi_bsg_request - handle bsg request from ISCSI transport
+ * @job: iscsi_bsg_job to handle
+ */
+static int beiscsi_bsg_request(struct iscsi_bsg_job *job)
+{
+       uint32_t msgcode;
+       int rc = -EINVAL;
+       unsigned int tag;
+       unsigned short status, extd_status;
+       struct beiscsi_hba *phba;
+
+       msgcode = job->request->msgcode;
+       phba = iscsi_host_priv(job->shost);
+       switch (msgcode) {
+       case ISCSI_BSG_HST_VENDOR:
+               shost_printk(KERN_ERR, phba->shost,
+                       "No Vendor Specific Commands Supported \n");
+               break;
+       case ISCSI_BSG_HST_NET_CONFIG:
+               tag = mgmt_netcfg_fw_cmd(&phba->ctrl, phba, job);
+               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]);
+
+               extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
+               status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
+               free_mcc_tag(&phba->ctrl, tag);
+               if (status || extd_status) {
+                       SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed"
+                                           " status = %d extd_status = %d \n",
+                                           status, extd_status);
+                       return -EIO;
+               }
+
+       default:
+               break;
+       }
+       return rc;
+}
+
 static void beiscsi_remove(struct pci_dev *pcidev)
 {
        struct beiscsi_hba *phba = NULL;
@@ -3736,6 +3809,7 @@ static void beiscsi_remove(struct pci_dev *pcidev)
 
        beiscsi_clean_port(phba);
        beiscsi_free_mem(phba);
+
        beiscsi_unmap_pci_function(phba);
        pci_free_consistent(phba->pcidev,
                            phba->ctrl.mbox_mem_alloced.size,
@@ -3965,6 +4039,7 @@ struct iscsi_transport beiscsi_iscsi_transport = {
        .ep_poll = beiscsi_ep_poll,
        .ep_disconnect = beiscsi_ep_disconnect,
        .session_recovery_timedout = iscsi_session_recovery_timedout,
+       .bsg_request = beiscsi_bsg_request,
 };
 
 static struct pci_driver beiscsi_pci_driver = {
diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h
index 87ec212..18a02a7 100644
--- a/drivers/scsi/be2iscsi/be_main.h
+++ b/drivers/scsi/be2iscsi/be_main.h
@@ -62,7 +62,7 @@
 #define BEISCSI_SGLIST_ELEMENTS        30
 
 #define BEISCSI_CMD_PER_LUN    128     /* scsi_host->cmd_per_lun */
-#define BEISCSI_MAX_SECTORS    256     /* scsi_host->max_sectors */
+#define BEISCSI_MAX_SECTORS    2048    /* scsi_host->max_sectors */
 
 #define BEISCSI_MAX_CMD_LEN    16      /* scsi_host->max_cmd_len */
 #define BEISCSI_NUM_MAX_LUN    256     /* scsi_host->max_lun */
@@ -77,7 +77,7 @@
 #define MAX_CMD_SZ                     65536
 #define IIOC_SCSI_DATA                  0x05   /* Write Operation */
 
-#define DBG_LVL                                0x00000001
+#define DBG_LVL                                0x000000FF
 #define DBG_LVL_1                      0x00000001
 #define DBG_LVL_2                      0x00000002
 #define DBG_LVL_3                      0x00000004
@@ -334,6 +334,7 @@ struct beiscsi_hba {
        struct work_struct work_cqs;    /* The work being queued */
        struct be_ctrl_info ctrl;
        unsigned int generation;
+       unsigned int interface_handle;
        struct invalidate_command_table inv_tbl[128];
 
 };
@@ -353,6 +354,7 @@ struct beiscsi_conn {
        struct beiscsi_endpoint *ep;
        unsigned short login_in_progress;
        struct sgl_handle *plogin_sgl_handle;
+       struct wrb_handle *plogin_wrb_handle;
        struct beiscsi_session *beiscsi_sess;
        struct iscsi_task *task;
 };
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c
index 72617b6..15f8203 100644
--- a/drivers/scsi/be2iscsi/be_mgmt.c
+++ b/drivers/scsi/be2iscsi/be_mgmt.c
@@ -20,6 +20,8 @@
 
 #include "be_mgmt.h"
 #include "be_iscsi.h"
+#include <scsi/scsi_transport_iscsi.h>
+#include <scsi/scsi_bsg_iscsi.h>
 
 unsigned char mgmt_get_fw_config(struct be_ctrl_info *ctrl,
                                struct beiscsi_hba *phba)
@@ -112,11 +114,210 @@ unsigned char mgmt_check_supported_fw(struct 
be_ctrl_info *ctrl,
        spin_unlock(&ctrl->mbox_lock);
        if (nonemb_cmd.va)
                pci_free_consistent(ctrl->pdev, nonemb_cmd.size,
-                                   nonemb_cmd.va, nonemb_cmd.dma);
+                           nonemb_cmd.va, nonemb_cmd.dma);
+
+       return status;
+}
+
+unsigned char mgmt_get_all_if_id(struct be_ctrl_info *ctrl,
+                               struct beiscsi_hba *phba)
+{
+       struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+       struct be_all_if_id *req = embedded_payload(wrb);
+       struct be_all_if_id *pbe_allid = req;
+       int status = 0;
+
+       spin_lock(&ctrl->mbox_lock);
+       memset(wrb, 0, sizeof(*wrb));
+
+       be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
 
+       be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
+                          OPCODE_COMMON_ISCSI_NTWK_GET_ALL_IF_ID,
+                          sizeof(*req));
+       status = be_mbox_notify(ctrl);
+       if (!status) {
+
+               phba->interface_handle = pbe_allid->if_hndl_list[0];
+       } else {
+               shost_printk(KERN_WARNING, phba->shost,
+                            "Failed in mgmt_get_all_if_id\n");
+       }
+       spin_unlock(&ctrl->mbox_lock);
        return status;
 }
 
+int  mgmt_netcfg_fw_cmd(struct be_ctrl_info *ctrl,
+                struct beiscsi_hba *phba,
+                struct iscsi_bsg_job *job)
+{
+       struct be_dma_mem nonemb_cmd;
+       unsigned char *pdata;
+       int num, i, status = -EIO;
+       struct scatterlist *sge = NULL;
+       struct be_cmd_resp_hdr *resp;
+       struct be_mcc_wrb *wrb = wrb_from_mccq(phba);
+       struct be_cmd_req_hdr *phdr;
+       struct be_sge *mcc_sge = nonembedded_sgl(wrb);
+       struct iscsi_bsg_common_format *bsgdata;
+       struct be_modify_ip_addr *setip;
+       struct be_modify_default_gateway *setdefgw;
+       struct be_set_vlan *setvlan;
+       struct be_set_get_hba_name *sethbaname;
+       struct be_stateless_ip_addr *dhcp;
+       struct be_get_default_gateway_request *getdefgw;
+       struct be_get_if_info_request *getifinfo;
+       unsigned int tag = 0;
+
+       if (phba->interface_handle == 0xFFFFFFFF) {
+               if (mgmt_get_all_if_id(ctrl, phba)) {
+                       shost_printk(KERN_WARNING, phba->shost,
+                               "Did not get Interface ID \n");
+                       return -EAGAIN;
+               }
+       }
+
+
+       nonemb_cmd.va = pci_alloc_consistent(ctrl->pdev,
+                                            job->request_payload.size,
+                                            &nonemb_cmd.dma);
+       if (nonemb_cmd.va == NULL) {
+               SE_DEBUG(DBG_LVL_1,
+                        "Failed to allocate memory for mgmt_netcfg_fw_cmd\n");
+               return -EIO;
+       }
+
+       phdr = nonemb_cmd.va;
+       nonemb_cmd.size = job->request_payload.size;
+       memset(nonemb_cmd.va, 0, nonemb_cmd.size);
+       resp = nonemb_cmd.va;
+
+       bsgdata = (struct iscsi_bsg_common_format *)job->request_payload.va;
+       switch (job->request->rqst_data.h_netconfig.set_op) {
+       case ISCSI_SET_IP_ADDR:
+               be_cmd_hdr_prepare(phdr, CMD_SUBSYSTEM_ISCSI,
+                       OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR,
+                       sizeof(struct be_modify_ip_addr));
+               setip = nonemb_cmd.va;
+               setip->ip_params.record_entry_count = bsgdata->ip_params.
+                                                     record_entry_count;
+               for (i = 0; i < setip->ip_params.record_entry_count; i++) {
+                       memcpy(&setip->ip_params.ip_record[i],
+                               &bsgdata->ip_params.ip_record[i],
+                               sizeof(struct iscsi_ip_addr_record));
+               }
+               break;
+
+       case ISCSI_SET_DEFAULT_GATEWAY:
+               be_cmd_hdr_prepare(phdr, CMD_SUBSYSTEM_ISCSI,
+                       OPCODE_COMMON_ISCSI_NTWK_MODIFY_DEFAULT_GATEWAY,
+                       sizeof(struct be_modify_default_gateway));
+               setdefgw = nonemb_cmd.va;
+               setdefgw->action =  bsgdata->action;
+               memcpy(&setdefgw->gateway, &bsgdata->gateway,
+                       sizeof(struct ip_address_format));
+
+               break;
+
+       case ISCSI_SET_VLAN:
+               be_cmd_hdr_prepare(phdr, CMD_SUBSYSTEM_ISCSI,
+                       OPCODE_COMMON_ISCSI_NTWK_SET_VLAN,
+                       sizeof(struct be_set_vlan));
+               setvlan = nonemb_cmd.va;
+               setvlan->interface_hndl = bsgdata->interface_hndl;
+               setvlan->vlan_priority = bsgdata->vlan_priority;
+
+               break;
+
+       case ISCSI_SET_HBA_NAME:
+               be_cmd_hdr_prepare(phdr, CMD_SUBSYSTEM_ISCSI_INI,
+                       OPCODE_ISCSI_INI_CFG_SET_HBA_NAME,
+                       sizeof(struct be_set_get_hba_name));
+               sethbaname = nonemb_cmd.va;
+               sethbaname->flags = bsgdata->flags;
+               memcpy(&sethbaname->iscsiname, &bsgdata->iscsiname, 224);
+               memcpy(&sethbaname->iscsialias, &bsgdata->iscsialias, 32);
+               break;
+
+       case ISCSI_CONFIGURE_STATELESS_IP:
+               be_cmd_hdr_prepare(phdr, CMD_SUBSYSTEM_ISCSI,
+                       OPCODE_COMMON_ISCSI_NTWK_CONFIGURE_STATELESS_IP_ADDR,
+                       sizeof(struct be_stateless_ip_addr));
+               dhcp = nonemb_cmd.va;
+               dhcp->interface_hndl = bsgdata->interface_hndl;
+               dhcp->ip_type = bsgdata->ip_type;
+               dhcp->flags = bsgdata->flags;
+               dhcp->retry_count = bsgdata->retry_count;
+               break;
+
+       case ISCSI_GET_HBA_NAME:
+               be_cmd_hdr_prepare(phdr, CMD_SUBSYSTEM_ISCSI_INI,
+                       OPCODE_ISCSI_INI_CFG_GET_HBA_NAME,
+                       sizeof(struct be_set_get_hba_name));
+               sethbaname = nonemb_cmd.va;
+               sethbaname->flags = bsgdata->flags;
+               break;
+       case ISCSI_GET_IF_INFO:
+               be_cmd_hdr_prepare(phdr, CMD_SUBSYSTEM_ISCSI,
+                       OPCODE_COMMON_ISCSI_NTWK_GET_IF_INFO,
+                       sizeof(struct be_get_if_info_request));
+               getifinfo = nonemb_cmd.va;
+               getifinfo->interface_hndl = phba->interface_handle;
+               getifinfo->ip_type = bsgdata->ip_type;
+               break;
+       case ISCSI_GET_DEFAULT_GATEWAY:
+               be_cmd_hdr_prepare(phdr, CMD_SUBSYSTEM_ISCSI,
+                       OPCODE_COMMON_ISCSI_NTWK_GET_DEFAULT_GATEWAY,
+                       sizeof(struct be_get_default_gateway_request));
+               getdefgw = nonemb_cmd.va;
+               getdefgw->ip_type = bsgdata->ip_type;
+               break;
+       case ISCSI_GET_MAC_ADDRESS:
+       be_cmd_hdr_prepare(phdr, CMD_SUBSYSTEM_ISCSI,
+                          OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG,
+                          sizeof(struct be_cmd_req_get_mac_addr));
+
+       default:
+               pci_free_consistent(ctrl->pdev, nonemb_cmd.size,
+                                   nonemb_cmd.va, nonemb_cmd.dma);
+               return -EIO;
+       }
+
+       spin_lock(&ctrl->mbox_lock);
+       tag = alloc_mcc_tag(phba);
+       if (!tag) {
+               spin_unlock(&ctrl->mbox_lock);
+               return tag;
+       }
+
+       memset(wrb, 0, sizeof(*wrb));
+       be_wrb_hdr_prepare(wrb, nonemb_cmd.size, false,
+                          job->request_payload.sg_cnt);
+       mcc_sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma));
+       mcc_sge->pa_lo = cpu_to_le32(nonemb_cmd.dma & 0xFFFFFFFF);
+       mcc_sge->len = cpu_to_le32(nonemb_cmd.size);
+       wrb->tag0 |= tag;
+
+       be_mcc_notify(phba);
+
+       pdata = nonemb_cmd.va;
+       for_each_sg(job->reply_payload.sg_list, sge,
+                   job->reply_payload.sg_cnt, num) {
+               if (sge->length) {
+                       memcpy(sg_virt(sge), pdata, sge->length);
+                       pdata += sge->length;
+               }
+       }
+
+       pci_free_consistent(ctrl->pdev, nonemb_cmd.size,
+                                   nonemb_cmd.va, nonemb_cmd.dma);
+
+       spin_unlock(&ctrl->mbox_lock);
+       job->reply->reply_payload_rcv_len = resp->response_length;
+       job->reply->result = status;
+       job->job_done(job);
+       return tag;
+ }
 
 unsigned char mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute)
 {
@@ -169,6 +370,7 @@ unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba,
                SE_DEBUG(DBG_LVL_1,
                         "Failed to allocate memory for"
                         "mgmt_invalidate_icds \n");
+               spin_unlock(&ctrl->mbox_lock);
                return -1;
        }
        nonemb_cmd.size = sizeof(struct invalidate_commands_params_in);
@@ -277,6 +479,7 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
        struct sockaddr_in6 *daddr_in6 = (struct sockaddr_in6 *)dst_addr;
        struct be_ctrl_info *ctrl = &phba->ctrl;
        struct be_mcc_wrb *wrb;
+       struct be_dma_mem nonemb_cmd;
        struct tcp_connect_and_offload_in *req;
        unsigned short def_hdr_id;
        unsigned short def_data_id;
@@ -285,6 +488,7 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
        unsigned int tag = 0;
        unsigned int i;
        unsigned short cid = beiscsi_ep->ep_cid;
+       struct be_sge *sge;
 
        phwi_ctrlr = phba->phwi_ctrlr;
        phwi_context = phwi_ctrlr->phwi_ctxt;
@@ -293,17 +497,34 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
 
        ptemplate_address = &template_address;
        ISCSI_GET_PDU_TEMPLATE_ADDRESS(phba, ptemplate_address);
+
        spin_lock(&ctrl->mbox_lock);
        tag = alloc_mcc_tag(phba);
        if (!tag) {
                spin_unlock(&ctrl->mbox_lock);
                return tag;
        }
+
+       nonemb_cmd.va = pci_alloc_consistent(ctrl->pdev,
+                               sizeof(struct tcp_connect_and_offload_in),
+                               &nonemb_cmd.dma);
+       if (nonemb_cmd.va == NULL) {
+               SE_DEBUG(DBG_LVL_1,
+                        "Failed to allocate memory for mgmt_open_connection"
+                        "\n");
+               return -1;
+       }
+       nonemb_cmd.size = sizeof(struct tcp_connect_and_offload_in);
+
        wrb = wrb_from_mccq(phba);
-       req = embedded_payload(wrb);
+       memset(wrb, 0, sizeof(*wrb));
+       sge = nonembedded_sgl(wrb);
+
+       req = nonemb_cmd.va;
+       memset(req, 0, sizeof(*req));
        wrb->tag0 |= tag;
 
-       be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+       be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1);
        be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
                           OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD,
                           sizeof(*req));
@@ -346,6 +567,9 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
        req->do_offload = 1;
        req->dataout_template_pa.lo = ptemplate_address->lo;
        req->dataout_template_pa.hi = ptemplate_address->hi;
+       sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma));
+       sge->pa_lo = cpu_to_le32(nonemb_cmd.dma & 0xFFFFFFFF);
+       sge->len = cpu_to_le32(nonemb_cmd.size);
        be_mcc_notify(phba);
        spin_unlock(&ctrl->mbox_lock);
        return tag;
diff --git a/drivers/scsi/be2iscsi/be_mgmt.h b/drivers/scsi/be2iscsi/be_mgmt.h
index 3d316b8..ed878d1 100644
--- a/drivers/scsi/be2iscsi/be_mgmt.h
+++ b/drivers/scsi/be2iscsi/be_mgmt.h
@@ -25,6 +25,7 @@
 #include <linux/list.h>
 #include "be_iscsi.h"
 #include "be_main.h"
+#include <scsi/scsi_bsg_iscsi.h>
 
 /**
  * Pseudo amap definition in which each bit of the actual structure is defined
@@ -202,6 +203,106 @@ struct be_mgmt_controller_attributes_resp {
        struct mgmt_controller_attributes params;
 } __packed;
 
+/*
+struct ip_address_subnet_format {
+       u16 sizeofstructure;
+       u8  iptype;
+       u8  ipv6_prefix_length;
+       u8  ipaddress[16];
+       u8  subnetmask[16];
+       u32 rsvd0;
+} __packed;
+
+struct iscsi_ip_addr_record {
+       u32  action;
+       u32  interface_hndl;
+       struct ip_address_subnet_format ip_address;
+       u32  status;
+} __packed;
+
+struct iscsi_ip_addr_record_params {
+       u32 record_entry_count;
+       struct iscsi_ip_addr_record ip_record[1];
+} __packed;
+*/
+struct be_modify_ip_addr {
+       struct be_cmd_req_hdr hdr;
+       struct iscsi_ip_addr_record_params ip_params;
+} __packed;
+
+struct be_modify_default_gateway {
+       struct be_cmd_req_hdr hdr;
+       u32    action;
+       struct ip_address_format gateway;
+} __packed;
+
+struct be_set_vlan {
+       struct be_cmd_req_hdr hdr;
+       u32  interface_hndl;
+       u32  vlan_priority;
+} __packed;
+
+struct be_set_get_hba_name {
+       struct be_cmd_req_hdr hdr;
+       u16 flags;
+       u16 rsvd0;
+       u8  iscsiname[224];
+       u8  iscsialias[32];
+} __packed;
+
+struct be_stateless_ip_addr {
+       struct be_cmd_req_hdr hdr;
+       u32  interface_hndl;
+       u32  ip_type;
+       u32  flags;
+       u32  retry_count;
+} __packed;
+
+struct be_get_if_info_request {
+       struct be_cmd_req_hdr hdr;
+       u32 interface_hndl;
+       u32 ip_type;
+} __packed;
+
+struct be_get_if_info_response {
+       struct be_cmd_req_hdr hdr;
+       u32    interface_hndl;
+       u32    vlan_priority;
+       u32    ip_address_count;
+       u32    dhcp_state;
+       struct ip_address_subnet_format ip_address[1];
+} __packed;
+
+struct be_get_default_gateway_request {
+       struct be_cmd_req_hdr hdr;
+       u32    ip_type;
+} __packed;
+
+struct be_get_default_gateway_response {
+       struct be_cmd_req_hdr hdr;
+       struct ip_address_format gateway;
+} __packed;
+
+struct be_bsg_common_format {
+       u8 opcode;              /* dword 0 */
+       u8 subsystem;           /* dword 0 */
+       u8 port_number;         /* dword 0 */
+       u8 domain;              /* dword 0 */
+       u32 timeout;            /* dword 1 */
+       u32 request_length;     /* dword 2 */
+       u32 rsvd0;              /* dword 3 */
+       u32    action;
+       struct ip_address_format gateway;
+       u32  interface_hndl;
+       u32  vlan_priority;
+       u32  flags;
+       u8   iscsiname[224];
+       u8   iscsialias[32];
+       u32  ip_type;
+       u32  retry_count;
+       struct iscsi_ip_addr_record_params ip_params;
+} __packed;
+
 /* configuration management */
 
 #define GET_MGMT_CONTROLLER_WS(phba)    (phba->pmgmt_ws)
@@ -246,4 +347,10 @@ unsigned char mgmt_invalidate_connection(struct 
beiscsi_hba *phba,
                                         unsigned short issue_reset,
                                         unsigned short savecfg_flag);
 
+unsigned char mgmt_get_all_if_id(struct be_ctrl_info *ctrl,
+                               struct beiscsi_hba *phba);
+
+int  mgmt_netcfg_fw_cmd(struct be_ctrl_info *ctrl,
+                struct beiscsi_hba *phba,
+                struct iscsi_bsg_job *job);
 #endif
diff --git a/include/scsi/scsi_bsg_iscsi.h b/include/scsi/scsi_bsg_iscsi.h
index 10c91c3..2c85dd0 100644
--- a/include/scsi/scsi_bsg_iscsi.h
+++ b/include/scsi/scsi_bsg_iscsi.h
@@ -56,6 +56,7 @@
 #define ISCSI_GET_HBA_NAME             6
 #define ISCSI_GET_IF_INFO              7
 #define ISCSI_GET_DEFAULT_GATEWAY      8
+#define ISCSI_GET_MAC_ADDRESS           9
 
 /*
  * iSCSI Host Messages
-- 
1.6.4

-- 
You received this message because you are subscribed to the Google Groups 
"open-iscsi" group.
To post to this group, send email to open-is...@googlegroups.com.
To unsubscribe from this group, send email to 
open-iscsi+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/open-iscsi?hl=en.

Reply via email to