[SCSI] be2iscsi: Get Port State and Speed of the Adapter
authorJohn Soni Jose <sony.john-n@emulex.com>
Wed, 4 Apr 2012 04:41:52 +0000 (23:41 -0500)
committerJames Bottomley <JBottomley@Parallels.com>
Wed, 25 Apr 2012 08:36:47 +0000 (09:36 +0100)
Implement ISCSI_HOST_PARAM_PORT_STATE and ISCSI_HOST_PARAM_PORT_SPEED
to get the Adapter port state and port name

Signed-off-by: John Soni Jose <sony.john-n@emulex.com>
Signed-off-by: Jayamohan Kallickal <jayamohan.kallickal@emulex.com>
Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
drivers/scsi/be2iscsi/be_cmds.h
drivers/scsi/be2iscsi/be_iscsi.c
drivers/scsi/be2iscsi/be_mgmt.c

index 60d144550f768511f2ad5a8540fa0119528ddb17..b0b36c6a145f77f0fb3ce38d9c2b45964dc4b99d 100644 (file)
@@ -596,6 +596,28 @@ struct be_cmd_hba_name {
        u8 initiator_alias[BEISCSI_ALIAS_LEN];
 } __packed;
 
+struct be_cmd_ntwk_link_status_req {
+       struct be_cmd_req_hdr hdr;
+       u32 rsvd0;
+} __packed;
+
+/*** Port Speed Values ***/
+#define BE2ISCSI_LINK_SPEED_ZERO       0x00
+#define BE2ISCSI_LINK_SPEED_10MBPS     0x01
+#define BE2ISCSI_LINK_SPEED_100MBPS    0x02
+#define BE2ISCSI_LINK_SPEED_1GBPS      0x03
+#define BE2ISCSI_LINK_SPEED_10GBPS     0x04
+struct be_cmd_ntwk_link_status_resp {
+       struct be_cmd_resp_hdr hdr;
+       u8 phys_port;
+       u8 mac_duplex;
+       u8 mac_speed;
+       u8 mac_fault;
+       u8 mgmt_mac_duplex;
+       u8 mgmt_mac_speed;
+       u16 qos_link_speed;
+       u32 logical_link_speed;
+} __packed;
 
 int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl,
                          struct be_queue_info *eq, int eq_delay);
@@ -615,6 +637,7 @@ int be_poll_mcc(struct be_ctrl_info *ctrl);
 int mgmt_check_supported_fw(struct be_ctrl_info *ctrl,
                                      struct beiscsi_hba *phba);
 unsigned int be_cmd_get_initname(struct beiscsi_hba *phba);
+unsigned int be_cmd_get_port_speed(struct beiscsi_hba *phba);
 
 void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag);
 /*ISCSI Functuions */
@@ -879,6 +902,7 @@ struct be_cmd_get_all_if_id_req {
 } __packed;
 
 #define ISCSI_OPCODE_SCSI_DATA_OUT             5
+#define OPCODE_COMMON_NTWK_LINK_STATUS_QUERY 5
 #define OPCODE_COMMON_MODIFY_EQ_DELAY          41
 #define OPCODE_COMMON_ISCSI_CLEANUP            59
 #define        OPCODE_COMMON_TCP_UPLOAD                56
index 46cc40e83b3676a2366942f0ed6074b98351a269..43f35034585d1a5102b65d3aeaed84cfc00fbe1a 100644 (file)
@@ -617,6 +617,79 @@ static int beiscsi_get_initname(char *buf, struct beiscsi_hba *phba)
        return rc;
 }
 
+/**
+ * beiscsi_get_port_state - Get the Port State
+ * @shost : pointer to scsi_host structure
+ *
+ * returns number of bytes
+ */
+static void beiscsi_get_port_state(struct Scsi_Host *shost)
+{
+       struct beiscsi_hba *phba = iscsi_host_priv(shost);
+       struct iscsi_cls_host *ihost = shost->shost_data;
+
+       ihost->port_state = (phba->state == BE_ADAPTER_UP) ?
+               ISCSI_PORT_STATE_UP : ISCSI_PORT_STATE_DOWN;
+}
+
+/**
+ * beiscsi_get_port_speed  - Get the Port Speed from Adapter
+ * @shost : pointer to scsi_host structure
+ *
+ * returns Success/Failure
+ */
+static int beiscsi_get_port_speed(struct Scsi_Host *shost)
+{
+       unsigned int tag, wrb_num;
+       unsigned short status, extd_status;
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_ntwk_link_status_resp *resp;
+       struct beiscsi_hba *phba = iscsi_host_priv(shost);
+       struct iscsi_cls_host *ihost = shost->shost_data;
+       struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
+
+       tag = be_cmd_get_port_speed(phba);
+       if (!tag) {
+               SE_DEBUG(DBG_LVL_1, "Getting Port Speed Failed\n");
+                return -EBUSY;
+        } 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, "MailBox Command Failed with "
+                               "status = %d extd_status = %d\n",
+                               status, extd_status);
+               free_mcc_tag(&phba->ctrl, tag);
+               return -EAGAIN;
+       }
+       wrb = queue_get_wrb(mccq, wrb_num);
+       free_mcc_tag(&phba->ctrl, tag);
+       resp = embedded_payload(wrb);
+
+       switch (resp->mac_speed) {
+       case BE2ISCSI_LINK_SPEED_10MBPS:
+               ihost->port_speed = ISCSI_PORT_SPEED_10MBPS;
+               break;
+       case BE2ISCSI_LINK_SPEED_100MBPS:
+               ihost->port_speed = BE2ISCSI_LINK_SPEED_100MBPS;
+               break;
+       case BE2ISCSI_LINK_SPEED_1GBPS:
+               ihost->port_speed = ISCSI_PORT_SPEED_1GBPS;
+               break;
+       case BE2ISCSI_LINK_SPEED_10GBPS:
+               ihost->port_speed = ISCSI_PORT_SPEED_10GBPS;
+               break;
+       default:
+               ihost->port_speed = ISCSI_PORT_SPEED_UNKNOWN;
+       }
+       return 0;
+}
+
 /**
  * beiscsi_get_host_param - get the iscsi parameter
  * @shost: pointer to scsi_host structure
@@ -648,6 +721,19 @@ int beiscsi_get_host_param(struct Scsi_Host *shost,
                        return status;
                }
                break;
+       case ISCSI_HOST_PARAM_PORT_STATE:
+               beiscsi_get_port_state(shost);
+               status = sprintf(buf, "%s\n", iscsi_get_port_state_name(shost));
+               break;
+       case ISCSI_HOST_PARAM_PORT_SPEED:
+               status = beiscsi_get_port_speed(shost);
+               if (status) {
+                       SE_DEBUG(DBG_LVL_1,
+                                       "Retreiving Port Speed Failed\n");
+                       return status;
+               }
+               status = sprintf(buf, "%s\n", iscsi_get_port_speed_name(shost));
+               break;
        default:
                return iscsi_host_get_param(shost, param, buf);
        }
@@ -1073,6 +1159,9 @@ umode_t be2iscsi_attr_is_visible(int param_type, int param)
        case ISCSI_HOST_PARAM:
                switch (param) {
                case ISCSI_HOST_PARAM_HWADDRESS:
+               case ISCSI_HOST_PARAM_INITIATOR_NAME:
+               case ISCSI_HOST_PARAM_PORT_STATE:
+               case ISCSI_HOST_PARAM_PORT_SPEED:
                        return S_IRUGO;
                default:
                        return 0;
index e6cb10d2e74e96d4957c391560657c511f724232..01bb04cd9e7516a567b714fcd1f8a1896096aba9 100644 (file)
@@ -898,3 +898,30 @@ unsigned int be_cmd_get_initname(struct beiscsi_hba *phba)
        spin_unlock(&ctrl->mbox_lock);
        return tag;
 }
+
+unsigned int be_cmd_get_port_speed(struct beiscsi_hba *phba)
+{
+       unsigned int tag = 0;
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_ntwk_link_status_req *req;
+       struct be_ctrl_info *ctrl = &phba->ctrl;
+
+       spin_lock(&ctrl->mbox_lock);
+       tag = alloc_mcc_tag(phba);
+       if (!tag) {
+               spin_unlock(&ctrl->mbox_lock);
+               return tag;
+       }
+
+       wrb = wrb_from_mccq(phba);
+       req = embedded_payload(wrb);
+       wrb->tag0 |= tag;
+       be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+       be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+                       OPCODE_COMMON_NTWK_LINK_STATUS_QUERY,
+                       sizeof(*req));
+
+       be_mcc_notify(phba);
+       spin_unlock(&ctrl->mbox_lock);
+       return tag;
+}