Commit d83a80ee authored by Joe Carnuccio's avatar Joe Carnuccio Committed by Martin K. Petersen

scsi: qla2xxx: Add vendor extended RDP additions and amendments

This patch adds RDP command support in the driver. With the help of new
ql2xsmartsan parameter, driver will use PUREX IOCB mode to send RDP command
to switch and will be able to receive various diagnostic data.

Link: https://lore.kernel.org/r/20200212214436.25532-8-hmadhani@marvell.comSigned-off-by: default avatarJoe Carnuccio <joe.carnuccio@qlogic.com>
Signed-off-by: default avatarHimanshu Madhani <hmadhani@marvell.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 818c7f87
...@@ -1267,6 +1267,9 @@ static inline bool qla2xxx_is_valid_mbs(unsigned int mbs) ...@@ -1267,6 +1267,9 @@ static inline bool qla2xxx_is_valid_mbs(unsigned int mbs)
#define RNID_TYPE_SET_VERSION 0x9 #define RNID_TYPE_SET_VERSION 0x9
#define RNID_TYPE_ASIC_TEMP 0xC #define RNID_TYPE_ASIC_TEMP 0xC
#define ELS_CMD_MAP_SIZE 32
#define ELS_COMMAND_RDP 0x18
/* /*
* Firmware state codes from get firmware state mailbox command * Firmware state codes from get firmware state mailbox command
*/ */
...@@ -3562,6 +3565,133 @@ struct qlfc_fw { ...@@ -3562,6 +3565,133 @@ struct qlfc_fw {
uint32_t len; uint32_t len;
}; };
struct rdp_req_payload {
uint32_t els_request;
uint32_t desc_list_len;
/* NPIV descriptor */
struct {
uint32_t desc_tag;
uint32_t desc_len;
uint8_t reserved;
uint8_t nport_id[3];
} npiv_desc;
};
struct rdp_rsp_payload {
struct {
uint32_t cmd;
uint32_t len;
} hdr;
/* LS Request Info descriptor */
struct {
uint32_t desc_tag;
uint32_t desc_len;
uint32_t req_payload_word_0;
} ls_req_info_desc;
/* LS Request Info descriptor */
struct {
uint32_t desc_tag;
uint32_t desc_len;
uint32_t req_payload_word_0;
} ls_req_info_desc2;
/* SFP diagnostic param descriptor */
struct {
uint32_t desc_tag;
uint32_t desc_len;
uint16_t temperature;
uint16_t vcc;
uint16_t tx_bias;
uint16_t tx_power;
uint16_t rx_power;
uint16_t sfp_flags;
} sfp_diag_desc;
/* Port Speed Descriptor */
struct {
uint32_t desc_tag;
uint32_t desc_len;
uint16_t speed_capab;
uint16_t operating_speed;
} port_speed_desc;
/* Link Error Status Descriptor */
struct {
uint32_t desc_tag;
uint32_t desc_len;
uint32_t link_fail_cnt;
uint32_t loss_sync_cnt;
uint32_t loss_sig_cnt;
uint32_t prim_seq_err_cnt;
uint32_t inval_xmit_word_cnt;
uint32_t inval_crc_cnt;
uint8_t pn_port_phy_type;
uint8_t reserved[3];
} ls_err_desc;
/* Port name description with diag param */
struct {
uint32_t desc_tag;
uint32_t desc_len;
uint8_t WWNN[WWN_SIZE];
uint8_t WWPN[WWN_SIZE];
} port_name_diag_desc;
/* Port Name desc for Direct attached Fx_Port or Nx_Port */
struct {
uint32_t desc_tag;
uint32_t desc_len;
uint8_t WWNN[WWN_SIZE];
uint8_t WWPN[WWN_SIZE];
} port_name_direct_desc;
/* Buffer Credit descriptor */
struct {
uint32_t desc_tag;
uint32_t desc_len;
uint32_t fcport_b2b;
uint32_t attached_fcport_b2b;
uint32_t fcport_rtt;
} buffer_credit_desc;
/* Optical Element Data Descriptor */
struct {
uint32_t desc_tag;
uint32_t desc_len;
uint16_t high_alarm;
uint16_t low_alarm;
uint16_t high_warn;
uint16_t low_warn;
uint32_t element_flags;
} optical_elmt_desc[5];
/* Optical Product Data Descriptor */
struct {
uint32_t desc_tag;
uint32_t desc_len;
uint8_t vendor_name[16];
uint8_t part_number[16];
uint8_t serial_number[16];
uint8_t revision[4];
uint8_t date[8];
} optical_prod_desc;
};
#define RDP_DESC_LEN(obj) \
(sizeof(obj) - sizeof((obj).desc_tag) - sizeof((obj).desc_len))
#define RDP_PORT_SPEED_1GB BIT_15
#define RDP_PORT_SPEED_2GB BIT_14
#define RDP_PORT_SPEED_4GB BIT_13
#define RDP_PORT_SPEED_10GB BIT_12
#define RDP_PORT_SPEED_8GB BIT_11
#define RDP_PORT_SPEED_16GB BIT_10
#define RDP_PORT_SPEED_32GB BIT_9
#define RDP_PORT_SPEED_UNKNOWN BIT_0
struct scsi_qlt_host { struct scsi_qlt_host {
void *target_lport_ptr; void *target_lport_ptr;
struct mutex tgt_mutex; struct mutex tgt_mutex;
...@@ -3965,6 +4095,8 @@ struct qla_hw_data { ...@@ -3965,6 +4095,8 @@ struct qla_hw_data {
#define SFP_DEV_SIZE 512 #define SFP_DEV_SIZE 512
#define SFP_BLOCK_SIZE 64 #define SFP_BLOCK_SIZE 64
#define SFP_RTDI_LEN SFP_BLOCK_SIZE
void *sfp_data; void *sfp_data;
dma_addr_t sfp_data_dma; dma_addr_t sfp_data_dma;
...@@ -4424,6 +4556,8 @@ typedef struct scsi_qla_host { ...@@ -4424,6 +4556,8 @@ typedef struct scsi_qla_host {
#define ISP_ABORT_TO_ROM 33 #define ISP_ABORT_TO_ROM 33
#define VPORT_DELETE 34 #define VPORT_DELETE 34
#define PROCESS_PUREX_IOCB 63
unsigned long pci_flags; unsigned long pci_flags;
#define PFLG_DISCONNECTED 0 /* PCI device removed */ #define PFLG_DISCONNECTED 0 /* PCI device removed */
#define PFLG_DRIVER_REMOVING 1 /* PCI driver .remove */ #define PFLG_DRIVER_REMOVING 1 /* PCI driver .remove */
...@@ -4532,6 +4666,7 @@ typedef struct scsi_qla_host { ...@@ -4532,6 +4666,7 @@ typedef struct scsi_qla_host {
uint16_t ql2xexchoffld; uint16_t ql2xexchoffld;
uint16_t ql2xiniexchg; uint16_t ql2xiniexchg;
void *purex_data;
struct name_list_extended gnl; struct name_list_extended gnl;
/* Count of active session/fcport */ /* Count of active session/fcport */
int fcport_count; int fcport_count;
......
...@@ -723,6 +723,50 @@ struct ct_entry_24xx { ...@@ -723,6 +723,50 @@ struct ct_entry_24xx {
struct dsd64 dsd[2]; struct dsd64 dsd[2];
}; };
/*
* ISP queue - PUREX IOCB entry structure definition
*/
#define PUREX_IOCB_TYPE 0x51 /* CT Pass Through IOCB entry */
typedef struct purex_entry_24xx {
uint8_t entry_type; /* Entry type. */
uint8_t entry_count; /* Entry count. */
uint8_t sys_define; /* System defined. */
uint8_t entry_status; /* Entry Status. */
uint16_t reserved1;
uint8_t vp_idx;
uint8_t reserved2;
uint16_t status_flags;
uint16_t nport_handle;
uint16_t frame_size;
uint16_t trunc_frame_size;
uint32_t rx_xchg_addr;
uint8_t d_id[3];
uint8_t r_ctl;
uint8_t s_id[3];
uint8_t cs_ctl;
uint8_t f_ctl[3];
uint8_t type;
uint16_t seq_cnt;
uint8_t df_ctl;
uint8_t seq_id;
uint16_t rx_id;
uint16_t ox_id;
uint32_t param;
uint8_t els_frame_payload[20];
} purex_entry_24xx_t;
#define PUREX_ENTRY_SIZE (sizeof(purex_entry_24xx_t))
/* /*
* ISP queue - ELS Pass-Through entry structure definition. * ISP queue - ELS Pass-Through entry structure definition.
*/ */
......
...@@ -457,6 +457,9 @@ qla82xx_set_driver_version(scsi_qla_host_t *, char *); ...@@ -457,6 +457,9 @@ qla82xx_set_driver_version(scsi_qla_host_t *, char *);
extern int extern int
qla25xx_set_driver_version(scsi_qla_host_t *, char *); qla25xx_set_driver_version(scsi_qla_host_t *, char *);
extern int
qla25xx_set_els_cmds_supported(scsi_qla_host_t *);
extern int extern int
qla24xx_get_buffer_credits(scsi_qla_host_t *, struct buffer_credit_24xx *, qla24xx_get_buffer_credits(scsi_qla_host_t *, struct buffer_credit_24xx *,
dma_addr_t); dma_addr_t);
......
...@@ -3708,6 +3708,10 @@ qla2x00_setup_chip(scsi_qla_host_t *vha) ...@@ -3708,6 +3708,10 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
"ISP Firmware failed checksum.\n"); "ISP Firmware failed checksum.\n");
goto failed; goto failed;
} }
/* Enable PUREX PASSTHRU */
if (ql2xsmartsan)
qla25xx_set_els_cmds_supported(vha);
} else } else
goto failed; goto failed;
...@@ -3929,7 +3933,7 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha) ...@@ -3929,7 +3933,7 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha)
/* Update Serial Link options. */ /* Update Serial Link options. */
if ((le16_to_cpu(ha->fw_seriallink_options24[0]) & BIT_0) == 0) if ((le16_to_cpu(ha->fw_seriallink_options24[0]) & BIT_0) == 0)
return; goto enable_purex;
rval = qla2x00_set_serdes_params(vha, rval = qla2x00_set_serdes_params(vha,
le16_to_cpu(ha->fw_seriallink_options24[1]), le16_to_cpu(ha->fw_seriallink_options24[1]),
...@@ -3939,6 +3943,12 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha) ...@@ -3939,6 +3943,12 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha)
ql_log(ql_log_warn, vha, 0x0104, ql_log(ql_log_warn, vha, 0x0104,
"Unable to update Serial Link options (%x).\n", rval); "Unable to update Serial Link options (%x).\n", rval);
} }
enable_purex:
if (ql2xsmartsan)
ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB;
qla2x00_set_fw_options(vha, ha->fw_options);
} }
void void
...@@ -8672,6 +8682,9 @@ qla83xx_update_fw_options(scsi_qla_host_t *vha) ...@@ -8672,6 +8682,9 @@ qla83xx_update_fw_options(scsi_qla_host_t *vha)
{ {
struct qla_hw_data *ha = vha->hw; struct qla_hw_data *ha = vha->hw;
if (ql2xsmartsan)
ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB;
qla2x00_set_fw_options(vha, ha->fw_options); qla2x00_set_fw_options(vha, ha->fw_options);
} }
......
...@@ -31,6 +31,13 @@ const char *const port_state_str[] = { ...@@ -31,6 +31,13 @@ const char *const port_state_str[] = {
"ONLINE" "ONLINE"
}; };
static void qla24xx_purex_iocb(scsi_qla_host_t *vha, struct req_que *req,
struct sts_entry_24xx *pkt)
{
memcpy(vha->purex_data, pkt, PUREX_ENTRY_SIZE);
set_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags);
}
/** /**
* qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200. * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200.
* @irq: interrupt number * @irq: interrupt number
...@@ -3128,6 +3135,9 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, ...@@ -3128,6 +3135,9 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
qla_ctrlvp_completed(vha, rsp->req, qla_ctrlvp_completed(vha, rsp->req,
(struct vp_ctrl_entry_24xx *)pkt); (struct vp_ctrl_entry_24xx *)pkt);
break; break;
case PUREX_IOCB_TYPE:
qla24xx_purex_iocb(vha, rsp->req, pkt);
break;
default: default:
/* Type Not Supported. */ /* Type Not Supported. */
ql_dbg(ql_dbg_async, vha, 0x5042, ql_dbg(ql_dbg_async, vha, 0x5042,
......
...@@ -4877,6 +4877,64 @@ qla24xx_get_port_login_templ(scsi_qla_host_t *vha, dma_addr_t buf_dma, ...@@ -4877,6 +4877,64 @@ qla24xx_get_port_login_templ(scsi_qla_host_t *vha, dma_addr_t buf_dma,
return rval; return rval;
} }
int
qla25xx_set_els_cmds_supported(scsi_qla_host_t *vha)
{
int rval;
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
uint8_t *els_cmd_map;
dma_addr_t els_cmd_map_dma;
uint cmd_opcode = ELS_COMMAND_RDP;
uint index = cmd_opcode / 8;
uint bit = cmd_opcode % 8;
struct qla_hw_data *ha = vha->hw;
if (!IS_QLA25XX(ha) && !IS_QLA2031(ha) && !IS_QLA27XX(ha))
return QLA_SUCCESS;
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1197,
"Entered %s.\n", __func__);
els_cmd_map = dma_alloc_coherent(&ha->pdev->dev, ELS_CMD_MAP_SIZE,
&els_cmd_map_dma, GFP_KERNEL);
if (!els_cmd_map) {
ql_log(ql_log_warn, vha, 0x7101,
"Failed to allocate RDP els command param.\n");
return QLA_MEMORY_ALLOC_FAILED;
}
memset(els_cmd_map, 0, ELS_CMD_MAP_SIZE);
els_cmd_map[index] |= 1 << bit;
mcp->mb[0] = MBC_SET_RNID_PARAMS;
mcp->mb[1] = RNID_TYPE_ELS_CMD << 8;
mcp->mb[2] = MSW(LSD(els_cmd_map_dma));
mcp->mb[3] = LSW(LSD(els_cmd_map_dma));
mcp->mb[6] = MSW(MSD(els_cmd_map_dma));
mcp->mb[7] = LSW(MSD(els_cmd_map_dma));
mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
mcp->in_mb = MBX_1|MBX_0;
mcp->tov = MBX_TOV_SECONDS;
mcp->flags = MBX_DMA_OUT;
mcp->buf_size = ELS_CMD_MAP_SIZE;
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
ql_dbg(ql_dbg_mbx, vha, 0x118d,
"Failed=%x (%x,%x).\n", rval, mcp->mb[0], mcp->mb[1]);
} else {
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x118c,
"Done %s.\n", __func__);
}
dma_free_coherent(&ha->pdev->dev, DMA_POOL_SIZE,
els_cmd_map, els_cmd_map_dma);
return rval;
}
int int
qla24xx_get_buffer_credits(scsi_qla_host_t *vha, struct buffer_credit_24xx *bbc, qla24xx_get_buffer_credits(scsi_qla_host_t *vha, struct buffer_credit_24xx *bbc,
dma_addr_t bbc_dma) dma_addr_t bbc_dma)
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment