[SCSI] qla2xxx: Add BSG interface for read/write serdes register.
authorJoe Carnuccio <joe.carnuccio@qlogic.com>
Wed, 30 Oct 2013 07:38:18 +0000 (03:38 -0400)
committerJames Bottomley <JBottomley@Parallels.com>
Thu, 19 Dec 2013 15:38:58 +0000 (07:38 -0800)
Signed-off-by: Joe Carnuccio <joe.carnuccio@qlogic.com>
Signed-off-by: Saurav Kashyap <saurav.kashyap@qlogic.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
drivers/scsi/qla2xxx/qla_bsg.c
drivers/scsi/qla2xxx/qla_bsg.h
drivers/scsi/qla2xxx/qla_dbg.c
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_mbx.c

index aa57bf0af574e872ab6e00dae36f7fe4df1a2199..f15d03e6b7eeb1fb98612eaa7b1eafedfc8b7ec5 100644 (file)
@@ -2021,6 +2021,46 @@ done:
        return rval;
 }
 
+static int
+qla26xx_serdes_op(struct fc_bsg_job *bsg_job)
+{
+       struct Scsi_Host *host = bsg_job->shost;
+       scsi_qla_host_t *vha = shost_priv(host);
+       int rval = 0;
+       struct qla_serdes_reg sr;
+
+       memset(&sr, 0, sizeof(sr));
+
+       sg_copy_to_buffer(bsg_job->request_payload.sg_list,
+           bsg_job->request_payload.sg_cnt, &sr, sizeof(sr));
+
+       switch (sr.cmd) {
+       case INT_SC_SERDES_WRITE_REG:
+               rval = qla2x00_write_serdes_word(vha, sr.addr, sr.val);
+               bsg_job->reply->reply_payload_rcv_len = 0;
+               break;
+       case INT_SC_SERDES_READ_REG:
+               rval = qla2x00_read_serdes_word(vha, sr.addr, &sr.val);
+               sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
+                   bsg_job->reply_payload.sg_cnt, &sr, sizeof(sr));
+               bsg_job->reply->reply_payload_rcv_len = sizeof(sr);
+               break;
+       default:
+               ql_log(ql_log_warn, vha, 0x708c,
+                   "Unknown serdes cmd %x.\n", sr.cmd);
+               rval = -EDOM;
+               break;
+       }
+
+       bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
+           rval ? EXT_STATUS_MAILBOX : 0;
+
+       bsg_job->reply_len = sizeof(struct fc_bsg_reply);
+       bsg_job->reply->result = DID_OK << 16;
+       bsg_job->job_done(bsg_job);
+       return 0;
+}
+
 static int
 qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
 {
@@ -2069,6 +2109,10 @@ qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
 
        case QL_VND_FX00_MGMT_CMD:
                return qlafx00_mgmt_cmd(bsg_job);
+
+       case QL_VND_SERDES_OP:
+               return qla26xx_serdes_op(bsg_job);
+
        default:
                return -ENOSYS;
        }
index 04f770332c2b805022fa09110aea2732b7f8a058..e5c2126221e9359b406d5488df6d1d31a1739195 100644 (file)
@@ -23,6 +23,7 @@
 #define QL_VND_WRITE_I2C       0x10
 #define QL_VND_READ_I2C                0x11
 #define QL_VND_FX00_MGMT_CMD   0x12
+#define QL_VND_SERDES_OP       0x13
 
 /* BSG Vendor specific subcode returns */
 #define EXT_STATUS_OK                  0
@@ -212,4 +213,16 @@ struct qla_i2c_access {
        uint8_t  buffer[0x40];
 } __packed;
 
+/* 26xx serdes register interface */
+
+/* serdes reg commands */
+#define INT_SC_SERDES_READ_REG         1
+#define INT_SC_SERDES_WRITE_REG                2
+
+struct qla_serdes_reg {
+       uint16_t cmd;
+       uint16_t addr;
+       uint16_t val;
+} __packed;
+
 #endif
index 66f6597d857b03244b4989847bdd88c1bac6640d..9cd767c26a2758a823565be43ea77c95684fe278 100644 (file)
@@ -12,7 +12,7 @@
  * |             Level            |   Last Value Used  |     Holes     |
  * ----------------------------------------------------------------------
  * | Module Init and Probe        |       0x015b       | 0x4b,0xba,0xfa |
- * | Mailbox commands             |       0x1181       | 0x111a-0x111b  |
+ * | Mailbox commands             |       0x1187       | 0x111a-0x111b  |
  * |                              |                    | 0x1155-0x1158  |
  * |                              |                    | 0x1018-0x1019  |
  * |                              |                    | 0x1115-0x1116  |
index ac62bcacc2d63d186cd21099dede706f529704ae..41d6491d7bd9ec9e376ef93c710774b793df6889 100644 (file)
@@ -862,7 +862,6 @@ struct mbx_cmd_32 {
  */
 #define MBC_LOAD_RAM                   1       /* Load RAM. */
 #define MBC_EXECUTE_FIRMWARE           2       /* Execute firmware. */
-#define MBC_WRITE_RAM_WORD             4       /* Write RAM word. */
 #define MBC_READ_RAM_WORD              5       /* Read RAM word. */
 #define MBC_MAILBOX_REGISTER_TEST      6       /* Wrap incoming mailboxes */
 #define MBC_VERIFY_CHECKSUM            7       /* Verify checksum. */
@@ -937,6 +936,8 @@ struct mbx_cmd_32 {
 /*
  * ISP24xx mailbox commands
  */
+#define MBC_WRITE_SERDES               0x3     /* Write serdes word. */
+#define MBC_READ_SERDES                        0x4     /* Read serdes word. */
 #define MBC_SERDES_PARAMS              0x10    /* Serdes Tx Parameters. */
 #define MBC_GET_IOCB_STATUS            0x12    /* Get IOCB status command. */
 #define MBC_PORT_PARAMS                        0x1A    /* Port iDMA Parameters. */
index 359d0d9e09d9077092b7dbbadc824ce82cf7c4e0..00427e0ff5b2ae3370809f3a9433ba24d116aef3 100644 (file)
@@ -340,6 +340,11 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *, unsigned int,
 extern int
 qla2x00_system_error(scsi_qla_host_t *);
 
+extern int
+qla2x00_write_serdes_word(scsi_qla_host_t *, uint16_t, uint16_t);
+extern int
+qla2x00_read_serdes_word(scsi_qla_host_t *, uint16_t, uint16_t *);
+
 extern int
 qla2x00_set_serdes_params(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t);
 
index 5957fee119c9272cc1dd157a8cbaab172ea7a53f..b94511ae00514a37ac35c73e7014f93627ca720e 100644 (file)
@@ -2800,6 +2800,75 @@ qla2x00_system_error(scsi_qla_host_t *vha)
        return rval;
 }
 
+int
+qla2x00_write_serdes_word(scsi_qla_host_t *vha, uint16_t addr, uint16_t data)
+{
+       int rval;
+       mbx_cmd_t mc;
+       mbx_cmd_t *mcp = &mc;
+
+       if (!IS_QLA2031(vha->hw))
+               return QLA_FUNCTION_FAILED;
+
+       ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1182,
+           "Entered %s.\n", __func__);
+
+       mcp->mb[0] = MBC_WRITE_SERDES;
+       mcp->mb[1] = addr;
+       mcp->mb[2] = data & 0xff;
+       mcp->mb[3] = 0;
+       mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
+       mcp->in_mb = MBX_0;
+       mcp->tov = MBX_TOV_SECONDS;
+       mcp->flags = 0;
+       rval = qla2x00_mailbox_command(vha, mcp);
+
+       if (rval != QLA_SUCCESS) {
+               ql_dbg(ql_dbg_mbx, vha, 0x1183,
+                   "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
+       } else {
+               ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1184,
+                   "Done %s.\n", __func__);
+       }
+
+       return rval;
+}
+
+int
+qla2x00_read_serdes_word(scsi_qla_host_t *vha, uint16_t addr, uint16_t *data)
+{
+       int rval;
+       mbx_cmd_t mc;
+       mbx_cmd_t *mcp = &mc;
+
+       if (!IS_QLA2031(vha->hw))
+               return QLA_FUNCTION_FAILED;
+
+       ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1185,
+           "Entered %s.\n", __func__);
+
+       mcp->mb[0] = MBC_READ_SERDES;
+       mcp->mb[1] = addr;
+       mcp->mb[3] = 0;
+       mcp->out_mb = MBX_3|MBX_1|MBX_0;
+       mcp->in_mb = MBX_1|MBX_0;
+       mcp->tov = MBX_TOV_SECONDS;
+       mcp->flags = 0;
+       rval = qla2x00_mailbox_command(vha, mcp);
+
+       *data = mcp->mb[1] & 0xff;
+
+       if (rval != QLA_SUCCESS) {
+               ql_dbg(ql_dbg_mbx, vha, 0x1186,
+                   "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
+       } else {
+               ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1187,
+                   "Done %s.\n", __func__);
+       }
+
+       return rval;
+}
+
 /**
  * qla2x00_set_serdes_params() -
  * @ha: HA context