mirror of
https://github.com/torvalds/linux.git
synced 2026-05-12 16:18:45 +02:00
scsi: qla2xxx: Add bsg interface to support firmware img validation
Add new bsg interface to issue MPI passthrough sub command to validate the new flash firmware image partition. Signed-off-by: Manish Rangankar <mrangankar@marvell.com> Signed-off-by: Nilesh Javali <njavali@marvell.com> Reviewed-by: Himanshu Madhani <hmadhani2024@gmail.com> Link: https://patch.msgid.link/20251210101604.431868-6-njavali@marvell.com Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
478b152ab3
commit
d74181ca11
|
|
@ -11,6 +11,8 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/bsg-lib.h>
|
||||
|
||||
static int qla28xx_validate_flash_image(struct bsg_job *bsg_job);
|
||||
|
||||
static void qla2xxx_free_fcport_work(struct work_struct *work)
|
||||
{
|
||||
struct fc_port *fcport = container_of(work, typeof(*fcport),
|
||||
|
|
@ -2549,6 +2551,30 @@ qla2x00_get_flash_image_status(struct bsg_job *bsg_job)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
qla2x00_get_drv_attr(struct bsg_job *bsg_job)
|
||||
{
|
||||
struct qla_drv_attr drv_attr;
|
||||
struct fc_bsg_reply *bsg_reply = bsg_job->reply;
|
||||
|
||||
memset(&drv_attr, 0, sizeof(struct qla_drv_attr));
|
||||
drv_attr.ext_attributes |= QLA_IMG_SET_VALID_SUPPORT;
|
||||
|
||||
|
||||
sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
|
||||
bsg_job->reply_payload.sg_cnt, &drv_attr,
|
||||
sizeof(struct qla_drv_attr));
|
||||
|
||||
bsg_reply->reply_payload_rcv_len = sizeof(struct qla_drv_attr);
|
||||
bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
|
||||
|
||||
bsg_job->reply_len = sizeof(struct fc_bsg_reply);
|
||||
bsg_reply->result = DID_OK << 16;
|
||||
bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
qla2x00_manage_host_stats(struct bsg_job *bsg_job)
|
||||
{
|
||||
|
|
@ -2933,6 +2959,12 @@ qla2x00_process_vendor_specific(struct scsi_qla_host *vha, struct bsg_job *bsg_j
|
|||
case QL_VND_GET_FLASH_UPDATE_CAPS:
|
||||
return qla27xx_get_flash_upd_cap(bsg_job);
|
||||
|
||||
case QL_VND_GET_DRV_ATTR:
|
||||
return qla2x00_get_drv_attr(bsg_job);
|
||||
|
||||
case QL_VND_IMG_SET_VALID:
|
||||
return qla28xx_validate_flash_image(bsg_job);
|
||||
|
||||
case QL_VND_SET_FLASH_UPDATE_CAPS:
|
||||
return qla27xx_set_flash_upd_cap(bsg_job);
|
||||
|
||||
|
|
@ -3246,3 +3278,89 @@ int qla2x00_mailbox_passthru(struct bsg_job *bsg_job)
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
qla28xx_do_validate_flash_image(struct bsg_job *bsg_job, uint16_t *state)
|
||||
{
|
||||
struct fc_bsg_request *bsg_request = bsg_job->request;
|
||||
scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
|
||||
uint16_t mstate[16];
|
||||
uint16_t mpi_state = 0;
|
||||
uint16_t img_idx;
|
||||
int rval = QLA_SUCCESS;
|
||||
|
||||
memset(mstate, 0, sizeof(mstate));
|
||||
|
||||
rval = qla2x00_get_firmware_state(vha, mstate);
|
||||
if (rval != QLA_SUCCESS) {
|
||||
ql_log(ql_log_warn, vha, 0xffff,
|
||||
"MBC to get MPI state failed (%d)\n", rval);
|
||||
rval = -EINVAL;
|
||||
goto exit_flash_img;
|
||||
}
|
||||
|
||||
mpi_state = mstate[11];
|
||||
|
||||
if (!(mpi_state & BIT_9 && mpi_state & BIT_8 && mpi_state & BIT_15)) {
|
||||
ql_log(ql_log_warn, vha, 0xffff,
|
||||
"MPI firmware state failed (0x%02x)\n", mpi_state);
|
||||
rval = -EINVAL;
|
||||
goto exit_flash_img;
|
||||
}
|
||||
|
||||
rval = qla81xx_fac_semaphore_access(vha, FAC_SEMAPHORE_LOCK);
|
||||
if (rval != QLA_SUCCESS) {
|
||||
ql_log(ql_log_warn, vha, 0xffff,
|
||||
"Unable to lock flash semaphore.");
|
||||
goto exit_flash_img;
|
||||
}
|
||||
|
||||
img_idx = bsg_request->rqst_data.h_vendor.vendor_cmd[1];
|
||||
|
||||
rval = qla_mpipt_validate_fw(vha, img_idx, state);
|
||||
if (rval != QLA_SUCCESS) {
|
||||
ql_log(ql_log_warn, vha, 0xffff,
|
||||
"Failed to validate Firmware image index [0x%x].\n",
|
||||
img_idx);
|
||||
}
|
||||
|
||||
qla81xx_fac_semaphore_access(vha, FAC_SEMAPHORE_UNLOCK);
|
||||
|
||||
exit_flash_img:
|
||||
return rval;
|
||||
}
|
||||
|
||||
static int qla28xx_validate_flash_image(struct bsg_job *bsg_job)
|
||||
{
|
||||
scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
|
||||
struct fc_bsg_reply *bsg_reply = bsg_job->reply;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
uint16_t state = 0;
|
||||
int rval = 0;
|
||||
|
||||
if (!IS_QLA28XX(ha) || vha->vp_idx != 0)
|
||||
return -EPERM;
|
||||
|
||||
mutex_lock(&ha->optrom_mutex);
|
||||
rval = qla28xx_do_validate_flash_image(bsg_job, &state);
|
||||
if (rval)
|
||||
rval = -EINVAL;
|
||||
mutex_unlock(&ha->optrom_mutex);
|
||||
|
||||
bsg_job->reply_len = sizeof(struct fc_bsg_reply);
|
||||
|
||||
if (rval)
|
||||
bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
|
||||
(state == 39) ? EXT_STATUS_IMG_SET_VALID_ERR :
|
||||
EXT_STATUS_IMG_SET_CONFIG_ERR;
|
||||
else
|
||||
bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
|
||||
|
||||
bsg_reply->result = DID_OK << 16;
|
||||
bsg_reply->reply_payload_rcv_len = 0;
|
||||
bsg_job->reply_len = sizeof(struct fc_bsg_reply);
|
||||
bsg_job_done(bsg_job, bsg_reply->result,
|
||||
bsg_reply->reply_payload_rcv_len);
|
||||
|
||||
return QLA_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,12 +32,14 @@
|
|||
#define QL_VND_GET_PRIV_STATS_EX 0x1A
|
||||
#define QL_VND_SS_GET_FLASH_IMAGE_STATUS 0x1E
|
||||
#define QL_VND_EDIF_MGMT 0X1F
|
||||
#define QL_VND_GET_DRV_ATTR 0x22
|
||||
#define QL_VND_MANAGE_HOST_STATS 0x23
|
||||
#define QL_VND_GET_HOST_STATS 0x24
|
||||
#define QL_VND_GET_TGT_STATS 0x25
|
||||
#define QL_VND_MANAGE_HOST_PORT 0x26
|
||||
#define QL_VND_MBX_PASSTHRU 0x2B
|
||||
#define QL_VND_DPORT_DIAGNOSTICS_V2 0x2C
|
||||
#define QL_VND_IMG_SET_VALID 0x30
|
||||
|
||||
/* BSG Vendor specific subcode returns */
|
||||
#define EXT_STATUS_OK 0
|
||||
|
|
@ -50,6 +52,8 @@
|
|||
#define EXT_STATUS_BUFFER_TOO_SMALL 16
|
||||
#define EXT_STATUS_NO_MEMORY 17
|
||||
#define EXT_STATUS_DEVICE_OFFLINE 22
|
||||
#define EXT_STATUS_IMG_SET_VALID_ERR 47
|
||||
#define EXT_STATUS_IMG_SET_CONFIG_ERR 48
|
||||
|
||||
/*
|
||||
* To support bidirectional iocb
|
||||
|
|
@ -318,6 +322,14 @@ struct qla_active_regions {
|
|||
uint8_t reserved[31];
|
||||
} __packed;
|
||||
|
||||
struct qla_drv_attr {
|
||||
uint32_t attributes;
|
||||
u32 ext_attributes;
|
||||
#define QLA_IMG_SET_VALID_SUPPORT BIT_4
|
||||
u32 status_flags;
|
||||
uint8_t reserved[20];
|
||||
} __packed;
|
||||
|
||||
#include "qla_edif_bsg.h"
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1386,6 +1386,26 @@ static inline bool qla2xxx_is_valid_mbs(unsigned int mbs)
|
|||
#define HCS_WRITE_SERDES 0x3
|
||||
#define HCS_READ_SERDES 0x4
|
||||
|
||||
/*
|
||||
* ISP2[7|8]xx mailbox commands.
|
||||
*/
|
||||
#define MBC_MPI_PASSTHROUGH 0x200
|
||||
|
||||
/* MBC_MPI_PASSTHROUGH */
|
||||
#define MPIPT_REQ_V1 1
|
||||
enum {
|
||||
MPIPT_SUBCMD_GET_SUP_CMD = 0x10,
|
||||
MPIPT_SUBCMD_GET_SUP_FEATURE,
|
||||
MPIPT_SUBCMD_GET_STATUS,
|
||||
MPIPT_SUBCMD_VALIDATE_FW,
|
||||
};
|
||||
|
||||
enum {
|
||||
MPIPT_MPI_STATUS = 1,
|
||||
MPIPT_FCORE_STATUS,
|
||||
MPIPT_LOCKDOWN_STATUS,
|
||||
};
|
||||
|
||||
/* Firmware return data sizes */
|
||||
#define FCAL_MAP_SIZE 128
|
||||
|
||||
|
|
|
|||
|
|
@ -842,6 +842,8 @@ extern int qla82xx_write_optrom_data(struct scsi_qla_host *, void *,
|
|||
extern int qla82xx_abort_isp(scsi_qla_host_t *);
|
||||
extern int qla82xx_restart_isp(scsi_qla_host_t *);
|
||||
|
||||
extern int qla_mpipt_validate_fw(scsi_qla_host_t *vha, u16 img_idx, u16 *state);
|
||||
|
||||
/* IOCB related functions */
|
||||
extern int qla82xx_start_scsi(srb_t *);
|
||||
extern void qla2x00_sp_free(srb_t *sp);
|
||||
|
|
|
|||
|
|
@ -7205,3 +7205,43 @@ int qla_mailbox_passthru(scsi_qla_host_t *vha,
|
|||
|
||||
return rval;
|
||||
}
|
||||
|
||||
int qla_mpipt_validate_fw(scsi_qla_host_t *vha, u16 img_idx, uint16_t *state)
|
||||
{
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
mbx_cmd_t mc;
|
||||
mbx_cmd_t *mcp = &mc;
|
||||
int rval;
|
||||
|
||||
if (!IS_QLA28XX(ha)) {
|
||||
ql_dbg(ql_dbg_mbx, vha, 0xffff, "%s %d\n", __func__, __LINE__);
|
||||
return QLA_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
if (img_idx > 1) {
|
||||
ql_log(ql_log_info, vha, 0xffff,
|
||||
"%s %d Invalid flash image index [%d]\n",
|
||||
__func__, __LINE__, img_idx);
|
||||
return QLA_INVALID_COMMAND;
|
||||
}
|
||||
|
||||
memset(&mc, 0, sizeof(mc));
|
||||
mcp->mb[0] = MBC_MPI_PASSTHROUGH;
|
||||
mcp->mb[1] = MPIPT_SUBCMD_VALIDATE_FW;
|
||||
mcp->mb[2] = img_idx;
|
||||
mcp->out_mb = MBX_1|MBX_0;
|
||||
mcp->in_mb = MBX_2|MBX_1|MBX_0;
|
||||
|
||||
/* send mb via iocb */
|
||||
rval = qla24xx_send_mb_cmd(vha, &mc);
|
||||
if (rval) {
|
||||
ql_log(ql_log_info, vha, 0xffff, "%s:Failed %x (mb=%x,%x)\n",
|
||||
__func__, rval, mcp->mb[0], mcp->mb[1]);
|
||||
*state = mcp->mb[1];
|
||||
} else {
|
||||
ql_log(ql_log_info, vha, 0xffff, "%s: mb=%x,%x,%x\n", __func__,
|
||||
mcp->mb[0], mcp->mb[1], mcp->mb[2]);
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user