[SCSI] qla2xxx: Add APEX support.
Allows priority setting for FCP_CMNDs. Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
This commit is contained in:
parent
6e98016ca0
commit
09ff701a17
7 changed files with 518 additions and 4 deletions
|
@ -35,6 +35,166 @@ done:
|
||||||
return sp;
|
return sp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
qla24xx_fcp_prio_cfg_valid(struct qla_fcp_prio_cfg *pri_cfg, uint8_t flag)
|
||||||
|
{
|
||||||
|
int i, ret, num_valid;
|
||||||
|
uint8_t *bcode;
|
||||||
|
struct qla_fcp_prio_entry *pri_entry;
|
||||||
|
|
||||||
|
ret = 1;
|
||||||
|
num_valid = 0;
|
||||||
|
bcode = (uint8_t *)pri_cfg;
|
||||||
|
|
||||||
|
if (bcode[0x0] != 'H' || bcode[0x1] != 'Q' || bcode[0x2] != 'O' ||
|
||||||
|
bcode[0x3] != 'S') {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (flag != 1)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
pri_entry = &pri_cfg->entry[0];
|
||||||
|
for (i = 0; i < pri_cfg->num_entries; i++) {
|
||||||
|
if (pri_entry->flags & FCP_PRIO_ENTRY_TAG_VALID)
|
||||||
|
num_valid++;
|
||||||
|
pri_entry++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_valid == 0)
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job)
|
||||||
|
{
|
||||||
|
struct Scsi_Host *host = bsg_job->shost;
|
||||||
|
scsi_qla_host_t *vha = shost_priv(host);
|
||||||
|
struct qla_hw_data *ha = vha->hw;
|
||||||
|
int ret = 0;
|
||||||
|
uint32_t len;
|
||||||
|
uint32_t oper;
|
||||||
|
|
||||||
|
bsg_job->reply->reply_payload_rcv_len = 0;
|
||||||
|
|
||||||
|
if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
|
||||||
|
test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
|
||||||
|
test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
|
||||||
|
ret = -EBUSY;
|
||||||
|
goto exit_fcp_prio_cfg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the sub command */
|
||||||
|
oper = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
|
||||||
|
|
||||||
|
/* Only set config is allowed if config memory is not allocated */
|
||||||
|
if (!ha->fcp_prio_cfg && (oper != QLFC_FCP_PRIO_SET_CONFIG)) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto exit_fcp_prio_cfg;
|
||||||
|
}
|
||||||
|
switch (oper) {
|
||||||
|
case QLFC_FCP_PRIO_DISABLE:
|
||||||
|
if (ha->flags.fcp_prio_enabled) {
|
||||||
|
ha->flags.fcp_prio_enabled = 0;
|
||||||
|
ha->fcp_prio_cfg->attributes &=
|
||||||
|
~FCP_PRIO_ATTR_ENABLE;
|
||||||
|
qla24xx_update_all_fcp_prio(vha);
|
||||||
|
bsg_job->reply->result = DID_OK;
|
||||||
|
} else {
|
||||||
|
ret = -EINVAL;
|
||||||
|
bsg_job->reply->result = (DID_ERROR << 16);
|
||||||
|
goto exit_fcp_prio_cfg;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QLFC_FCP_PRIO_ENABLE:
|
||||||
|
if (!ha->flags.fcp_prio_enabled) {
|
||||||
|
if (ha->fcp_prio_cfg) {
|
||||||
|
ha->flags.fcp_prio_enabled = 1;
|
||||||
|
ha->fcp_prio_cfg->attributes |=
|
||||||
|
FCP_PRIO_ATTR_ENABLE;
|
||||||
|
qla24xx_update_all_fcp_prio(vha);
|
||||||
|
bsg_job->reply->result = DID_OK;
|
||||||
|
} else {
|
||||||
|
ret = -EINVAL;
|
||||||
|
bsg_job->reply->result = (DID_ERROR << 16);
|
||||||
|
goto exit_fcp_prio_cfg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QLFC_FCP_PRIO_GET_CONFIG:
|
||||||
|
len = bsg_job->reply_payload.payload_len;
|
||||||
|
if (!len || len > FCP_PRIO_CFG_SIZE) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
bsg_job->reply->result = (DID_ERROR << 16);
|
||||||
|
goto exit_fcp_prio_cfg;
|
||||||
|
}
|
||||||
|
|
||||||
|
bsg_job->reply->result = DID_OK;
|
||||||
|
bsg_job->reply->reply_payload_rcv_len =
|
||||||
|
sg_copy_from_buffer(
|
||||||
|
bsg_job->reply_payload.sg_list,
|
||||||
|
bsg_job->reply_payload.sg_cnt, ha->fcp_prio_cfg,
|
||||||
|
len);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QLFC_FCP_PRIO_SET_CONFIG:
|
||||||
|
len = bsg_job->request_payload.payload_len;
|
||||||
|
if (!len || len > FCP_PRIO_CFG_SIZE) {
|
||||||
|
bsg_job->reply->result = (DID_ERROR << 16);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto exit_fcp_prio_cfg;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ha->fcp_prio_cfg) {
|
||||||
|
ha->fcp_prio_cfg = vmalloc(FCP_PRIO_CFG_SIZE);
|
||||||
|
if (!ha->fcp_prio_cfg) {
|
||||||
|
qla_printk(KERN_WARNING, ha,
|
||||||
|
"Unable to allocate memory "
|
||||||
|
"for fcp prio config data (%x).\n",
|
||||||
|
FCP_PRIO_CFG_SIZE);
|
||||||
|
bsg_job->reply->result = (DID_ERROR << 16);
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto exit_fcp_prio_cfg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(ha->fcp_prio_cfg, 0, FCP_PRIO_CFG_SIZE);
|
||||||
|
sg_copy_to_buffer(bsg_job->request_payload.sg_list,
|
||||||
|
bsg_job->request_payload.sg_cnt, ha->fcp_prio_cfg,
|
||||||
|
FCP_PRIO_CFG_SIZE);
|
||||||
|
|
||||||
|
/* validate fcp priority data */
|
||||||
|
if (!qla24xx_fcp_prio_cfg_valid(
|
||||||
|
(struct qla_fcp_prio_cfg *)
|
||||||
|
ha->fcp_prio_cfg, 1)) {
|
||||||
|
bsg_job->reply->result = (DID_ERROR << 16);
|
||||||
|
ret = -EINVAL;
|
||||||
|
/* If buffer was invalidatic int
|
||||||
|
* fcp_prio_cfg is of no use
|
||||||
|
*/
|
||||||
|
vfree(ha->fcp_prio_cfg);
|
||||||
|
ha->fcp_prio_cfg = NULL;
|
||||||
|
goto exit_fcp_prio_cfg;
|
||||||
|
}
|
||||||
|
|
||||||
|
ha->flags.fcp_prio_enabled = 0;
|
||||||
|
if (ha->fcp_prio_cfg->attributes & FCP_PRIO_ATTR_ENABLE)
|
||||||
|
ha->flags.fcp_prio_enabled = 1;
|
||||||
|
qla24xx_update_all_fcp_prio(vha);
|
||||||
|
bsg_job->reply->result = DID_OK;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = -EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
exit_fcp_prio_cfg:
|
||||||
|
bsg_job->job_done(bsg_job);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
static int
|
static int
|
||||||
qla2x00_process_els(struct fc_bsg_job *bsg_job)
|
qla2x00_process_els(struct fc_bsg_job *bsg_job)
|
||||||
{
|
{
|
||||||
|
@ -948,6 +1108,9 @@ qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
|
||||||
case QL_VND_IIDMA:
|
case QL_VND_IIDMA:
|
||||||
return qla24xx_iidma(bsg_job);
|
return qla24xx_iidma(bsg_job);
|
||||||
|
|
||||||
|
case QL_VND_FCP_PRIO_CFG_CMD:
|
||||||
|
return qla24xx_proc_fcp_prio_cfg_cmd(bsg_job);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
bsg_job->reply->result = (DID_ERROR << 16);
|
bsg_job->reply->result = (DID_ERROR << 16);
|
||||||
bsg_job->job_done(bsg_job);
|
bsg_job->job_done(bsg_job);
|
||||||
|
|
|
@ -1580,6 +1580,8 @@ typedef struct fc_port {
|
||||||
uint16_t loop_id;
|
uint16_t loop_id;
|
||||||
uint16_t old_loop_id;
|
uint16_t old_loop_id;
|
||||||
|
|
||||||
|
uint8_t fcp_prio;
|
||||||
|
|
||||||
uint8_t fabric_port_name[WWN_SIZE];
|
uint8_t fabric_port_name[WWN_SIZE];
|
||||||
uint16_t fp_speed;
|
uint16_t fp_speed;
|
||||||
|
|
||||||
|
@ -2296,6 +2298,7 @@ struct qla_hw_data {
|
||||||
uint32_t eeh_busy :1;
|
uint32_t eeh_busy :1;
|
||||||
uint32_t cpu_affinity_enabled :1;
|
uint32_t cpu_affinity_enabled :1;
|
||||||
uint32_t disable_msix_handshake :1;
|
uint32_t disable_msix_handshake :1;
|
||||||
|
uint32_t fcp_prio_enabled :1;
|
||||||
} flags;
|
} flags;
|
||||||
|
|
||||||
/* This spinlock is used to protect "io transactions", you must
|
/* This spinlock is used to protect "io transactions", you must
|
||||||
|
@ -2599,6 +2602,7 @@ struct qla_hw_data {
|
||||||
uint32_t flt_region_nvram;
|
uint32_t flt_region_nvram;
|
||||||
uint32_t flt_region_npiv_conf;
|
uint32_t flt_region_npiv_conf;
|
||||||
uint32_t flt_region_gold_fw;
|
uint32_t flt_region_gold_fw;
|
||||||
|
uint32_t flt_region_fcp_prio;
|
||||||
|
|
||||||
/* Needed for BEACON */
|
/* Needed for BEACON */
|
||||||
uint16_t beacon_blink_led;
|
uint16_t beacon_blink_led;
|
||||||
|
@ -2627,6 +2631,9 @@ struct qla_hw_data {
|
||||||
struct isp_operations *isp_ops;
|
struct isp_operations *isp_ops;
|
||||||
struct workqueue_struct *wq;
|
struct workqueue_struct *wq;
|
||||||
struct qlfc_fw fw_buf;
|
struct qlfc_fw fw_buf;
|
||||||
|
|
||||||
|
/* FCP_CMND priority support */
|
||||||
|
struct qla_fcp_prio_cfg *fcp_prio_cfg;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -841,6 +841,8 @@ struct device_reg_24xx {
|
||||||
#define FA_HW_EVENT_ENTRY_SIZE 4
|
#define FA_HW_EVENT_ENTRY_SIZE 4
|
||||||
#define FA_NPIV_CONF0_ADDR 0x5C000
|
#define FA_NPIV_CONF0_ADDR 0x5C000
|
||||||
#define FA_NPIV_CONF1_ADDR 0x5D000
|
#define FA_NPIV_CONF1_ADDR 0x5D000
|
||||||
|
#define FA_FCP_PRIO0_ADDR 0x10000
|
||||||
|
#define FA_FCP_PRIO1_ADDR 0x12000
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flash Error Log Event Codes.
|
* Flash Error Log Event Codes.
|
||||||
|
@ -1274,6 +1276,8 @@ struct qla_flt_header {
|
||||||
#define FLT_REG_NPIV_CONF_0 0x29
|
#define FLT_REG_NPIV_CONF_0 0x29
|
||||||
#define FLT_REG_NPIV_CONF_1 0x2a
|
#define FLT_REG_NPIV_CONF_1 0x2a
|
||||||
#define FLT_REG_GOLD_FW 0x2f
|
#define FLT_REG_GOLD_FW 0x2f
|
||||||
|
#define FLT_REG_FCP_PRIO_0 0x87
|
||||||
|
#define FLT_REG_FCP_PRIO_1 0x88
|
||||||
|
|
||||||
struct qla_flt_region {
|
struct qla_flt_region {
|
||||||
uint32_t code;
|
uint32_t code;
|
||||||
|
@ -1750,6 +1754,61 @@ struct ex_init_cb_81xx {
|
||||||
#define FARX_ACCESS_FLASH_CONF_81XX 0x7FFD0000
|
#define FARX_ACCESS_FLASH_CONF_81XX 0x7FFD0000
|
||||||
#define FARX_ACCESS_FLASH_DATA_81XX 0x7F800000
|
#define FARX_ACCESS_FLASH_DATA_81XX 0x7F800000
|
||||||
|
|
||||||
|
/* FCP priority config defines *************************************/
|
||||||
|
/* operations */
|
||||||
|
#define QLFC_FCP_PRIO_DISABLE 0x0
|
||||||
|
#define QLFC_FCP_PRIO_ENABLE 0x1
|
||||||
|
#define QLFC_FCP_PRIO_GET_CONFIG 0x2
|
||||||
|
#define QLFC_FCP_PRIO_SET_CONFIG 0x3
|
||||||
|
|
||||||
|
struct qla_fcp_prio_entry {
|
||||||
|
uint16_t flags; /* Describes parameter(s) in FCP */
|
||||||
|
/* priority entry that are valid */
|
||||||
|
#define FCP_PRIO_ENTRY_VALID 0x1
|
||||||
|
#define FCP_PRIO_ENTRY_TAG_VALID 0x2
|
||||||
|
#define FCP_PRIO_ENTRY_SPID_VALID 0x4
|
||||||
|
#define FCP_PRIO_ENTRY_DPID_VALID 0x8
|
||||||
|
#define FCP_PRIO_ENTRY_LUNB_VALID 0x10
|
||||||
|
#define FCP_PRIO_ENTRY_LUNE_VALID 0x20
|
||||||
|
#define FCP_PRIO_ENTRY_SWWN_VALID 0x40
|
||||||
|
#define FCP_PRIO_ENTRY_DWWN_VALID 0x80
|
||||||
|
uint8_t tag; /* Priority value */
|
||||||
|
uint8_t reserved; /* Reserved for future use */
|
||||||
|
uint32_t src_pid; /* Src port id. high order byte */
|
||||||
|
/* unused; -1 (wild card) */
|
||||||
|
uint32_t dst_pid; /* Src port id. high order byte */
|
||||||
|
/* unused; -1 (wild card) */
|
||||||
|
uint16_t lun_beg; /* 1st lun num of lun range. */
|
||||||
|
/* -1 (wild card) */
|
||||||
|
uint16_t lun_end; /* 2nd lun num of lun range. */
|
||||||
|
/* -1 (wild card) */
|
||||||
|
uint8_t src_wwpn[8]; /* Source WWPN: -1 (wild card) */
|
||||||
|
uint8_t dst_wwpn[8]; /* Destination WWPN: -1 (wild card) */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct qla_fcp_prio_cfg {
|
||||||
|
uint8_t signature[4]; /* "HQOS" signature of config data */
|
||||||
|
uint16_t version; /* 1: Initial version */
|
||||||
|
uint16_t length; /* config data size in num bytes */
|
||||||
|
uint16_t checksum; /* config data bytes checksum */
|
||||||
|
uint16_t num_entries; /* Number of entries */
|
||||||
|
uint16_t size_of_entry; /* Size of each entry in num bytes */
|
||||||
|
uint8_t attributes; /* enable/disable, persistence */
|
||||||
|
#define FCP_PRIO_ATTR_DISABLE 0x0
|
||||||
|
#define FCP_PRIO_ATTR_ENABLE 0x1
|
||||||
|
#define FCP_PRIO_ATTR_PERSIST 0x2
|
||||||
|
uint8_t reserved; /* Reserved for future use */
|
||||||
|
#define FCP_PRIO_CFG_HDR_SIZE 0x10
|
||||||
|
struct qla_fcp_prio_entry entry[1]; /* fcp priority entries */
|
||||||
|
#define FCP_PRIO_CFG_ENTRY_SIZE 0x20
|
||||||
|
};
|
||||||
|
|
||||||
|
#define FCP_PRIO_CFG_SIZE (32*1024) /* fcp prio data per port*/
|
||||||
|
|
||||||
|
/* 25XX Support ****************************************************/
|
||||||
|
#define FA_FCP_PRIO0_ADDR_25 0x3C000
|
||||||
|
#define FA_FCP_PRIO1_ADDR_25 0x3E000
|
||||||
|
|
||||||
/* 81XX Flash locations -- occupies second 2MB region. */
|
/* 81XX Flash locations -- occupies second 2MB region. */
|
||||||
#define FA_BOOT_CODE_ADDR_81 0x80000
|
#define FA_BOOT_CODE_ADDR_81 0x80000
|
||||||
#define FA_RISC_CODE_ADDR_81 0xA0000
|
#define FA_RISC_CODE_ADDR_81 0xA0000
|
||||||
|
|
|
@ -328,6 +328,9 @@ extern int
|
||||||
qla2x00_write_ram_word(scsi_qla_host_t *, uint32_t, uint32_t);
|
qla2x00_write_ram_word(scsi_qla_host_t *, uint32_t, uint32_t);
|
||||||
|
|
||||||
extern int qla2x00_get_data_rate(scsi_qla_host_t *);
|
extern int qla2x00_get_data_rate(scsi_qla_host_t *);
|
||||||
|
extern int qla24xx_set_fcp_prio(scsi_qla_host_t *, uint16_t, uint16_t,
|
||||||
|
uint16_t *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Global Function Prototypes in qla_isr.c source file.
|
* Global Function Prototypes in qla_isr.c source file.
|
||||||
*/
|
*/
|
||||||
|
@ -384,6 +387,7 @@ extern int qla2xxx_get_flash_info(scsi_qla_host_t *);
|
||||||
extern int qla2xxx_get_vpd_field(scsi_qla_host_t *, char *, char *, size_t);
|
extern int qla2xxx_get_vpd_field(scsi_qla_host_t *, char *, char *, size_t);
|
||||||
|
|
||||||
extern void qla2xxx_flash_npiv_conf(scsi_qla_host_t *);
|
extern void qla2xxx_flash_npiv_conf(scsi_qla_host_t *);
|
||||||
|
extern int qla24xx_read_fcp_prio_cfg(scsi_qla_host_t *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Global Function Prototypes in qla_dbg.c source file.
|
* Global Function Prototypes in qla_dbg.c source file.
|
||||||
|
@ -430,7 +434,10 @@ extern void qla2x00_init_host_attr(scsi_qla_host_t *);
|
||||||
extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *);
|
extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *);
|
||||||
extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *);
|
extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *);
|
||||||
extern int qla2x00_loopback_test(scsi_qla_host_t *, struct msg_echo_lb *, uint16_t *);
|
extern int qla2x00_loopback_test(scsi_qla_host_t *, struct msg_echo_lb *, uint16_t *);
|
||||||
extern int qla2x00_echo_test(scsi_qla_host_t *, struct msg_echo_lb *, uint16_t *);
|
extern int qla2x00_echo_test(scsi_qla_host_t *,
|
||||||
|
struct msg_echo_lb *, uint16_t *);
|
||||||
|
extern int qla24xx_update_all_fcp_prio(scsi_qla_host_t *);
|
||||||
|
extern int qla24xx_fcp_prio_cfg_valid(struct qla_fcp_prio_cfg *, uint8_t);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Global Function Prototypes in qla_dfs.c source file.
|
* Global Function Prototypes in qla_dfs.c source file.
|
||||||
|
|
|
@ -349,6 +349,12 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha)) {
|
||||||
|
if (qla24xx_read_fcp_prio_cfg(vha))
|
||||||
|
qla_printk(KERN_ERR, ha,
|
||||||
|
"Unable to read FCP priority data.\n");
|
||||||
|
}
|
||||||
|
|
||||||
return (rval);
|
return (rval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4905,3 +4911,165 @@ qla81xx_update_fw_options(scsi_qla_host_t *vha)
|
||||||
ha->fw_options[2] |= BIT_9;
|
ha->fw_options[2] |= BIT_9;
|
||||||
qla2x00_set_fw_options(vha, ha->fw_options);
|
qla2x00_set_fw_options(vha, ha->fw_options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* qla24xx_get_fcp_prio
|
||||||
|
* Gets the fcp cmd priority value for the logged in port.
|
||||||
|
* Looks for a match of the port descriptors within
|
||||||
|
* each of the fcp prio config entries. If a match is found,
|
||||||
|
* the tag (priority) value is returned.
|
||||||
|
*
|
||||||
|
* Input:
|
||||||
|
* ha = adapter block po
|
||||||
|
* fcport = port structure pointer.
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* non-zero (if found)
|
||||||
|
* 0 (if not found)
|
||||||
|
*
|
||||||
|
* Context:
|
||||||
|
* Kernel context
|
||||||
|
*/
|
||||||
|
uint8_t
|
||||||
|
qla24xx_get_fcp_prio(scsi_qla_host_t *vha, fc_port_t *fcport)
|
||||||
|
{
|
||||||
|
int i, entries;
|
||||||
|
uint8_t pid_match, wwn_match;
|
||||||
|
uint8_t priority;
|
||||||
|
uint32_t pid1, pid2;
|
||||||
|
uint64_t wwn1, wwn2;
|
||||||
|
struct qla_fcp_prio_entry *pri_entry;
|
||||||
|
struct qla_hw_data *ha = vha->hw;
|
||||||
|
|
||||||
|
if (!ha->fcp_prio_cfg || !ha->flags.fcp_prio_enabled)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
priority = 0;
|
||||||
|
entries = ha->fcp_prio_cfg->num_entries;
|
||||||
|
pri_entry = &ha->fcp_prio_cfg->entry[0];
|
||||||
|
|
||||||
|
for (i = 0; i < entries; i++) {
|
||||||
|
pid_match = wwn_match = 0;
|
||||||
|
|
||||||
|
if (!(pri_entry->flags & FCP_PRIO_ENTRY_VALID)) {
|
||||||
|
pri_entry++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check source pid for a match */
|
||||||
|
if (pri_entry->flags & FCP_PRIO_ENTRY_SPID_VALID) {
|
||||||
|
pid1 = pri_entry->src_pid & INVALID_PORT_ID;
|
||||||
|
pid2 = vha->d_id.b24 & INVALID_PORT_ID;
|
||||||
|
if (pid1 == INVALID_PORT_ID)
|
||||||
|
pid_match++;
|
||||||
|
else if (pid1 == pid2)
|
||||||
|
pid_match++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check destination pid for a match */
|
||||||
|
if (pri_entry->flags & FCP_PRIO_ENTRY_DPID_VALID) {
|
||||||
|
pid1 = pri_entry->dst_pid & INVALID_PORT_ID;
|
||||||
|
pid2 = fcport->d_id.b24 & INVALID_PORT_ID;
|
||||||
|
if (pid1 == INVALID_PORT_ID)
|
||||||
|
pid_match++;
|
||||||
|
else if (pid1 == pid2)
|
||||||
|
pid_match++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check source WWN for a match */
|
||||||
|
if (pri_entry->flags & FCP_PRIO_ENTRY_SWWN_VALID) {
|
||||||
|
wwn1 = wwn_to_u64(vha->port_name);
|
||||||
|
wwn2 = wwn_to_u64(pri_entry->src_wwpn);
|
||||||
|
if (wwn2 == (uint64_t)-1)
|
||||||
|
wwn_match++;
|
||||||
|
else if (wwn1 == wwn2)
|
||||||
|
wwn_match++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check destination WWN for a match */
|
||||||
|
if (pri_entry->flags & FCP_PRIO_ENTRY_DWWN_VALID) {
|
||||||
|
wwn1 = wwn_to_u64(fcport->port_name);
|
||||||
|
wwn2 = wwn_to_u64(pri_entry->dst_wwpn);
|
||||||
|
if (wwn2 == (uint64_t)-1)
|
||||||
|
wwn_match++;
|
||||||
|
else if (wwn1 == wwn2)
|
||||||
|
wwn_match++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pid_match == 2 || wwn_match == 2) {
|
||||||
|
/* Found a matching entry */
|
||||||
|
if (pri_entry->flags & FCP_PRIO_ENTRY_TAG_VALID)
|
||||||
|
priority = pri_entry->tag;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pri_entry++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* qla24xx_update_fcport_fcp_prio
|
||||||
|
* Activates fcp priority for the logged in fc port
|
||||||
|
*
|
||||||
|
* Input:
|
||||||
|
* ha = adapter block pointer.
|
||||||
|
* fcp = port structure pointer.
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* QLA_SUCCESS or QLA_FUNCTION_FAILED
|
||||||
|
*
|
||||||
|
* Context:
|
||||||
|
* Kernel context.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *ha, fc_port_t *fcport)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
uint8_t priority;
|
||||||
|
uint16_t mb[5];
|
||||||
|
|
||||||
|
if (atomic_read(&fcport->state) == FCS_UNCONFIGURED ||
|
||||||
|
fcport->port_type != FCT_TARGET ||
|
||||||
|
fcport->loop_id == FC_NO_LOOP_ID)
|
||||||
|
return QLA_FUNCTION_FAILED;
|
||||||
|
|
||||||
|
priority = qla24xx_get_fcp_prio(ha, fcport);
|
||||||
|
ret = qla24xx_set_fcp_prio(ha, fcport->loop_id, priority, mb);
|
||||||
|
if (ret == QLA_SUCCESS)
|
||||||
|
fcport->fcp_prio = priority;
|
||||||
|
else
|
||||||
|
DEBUG2(printk(KERN_WARNING
|
||||||
|
"scsi(%ld): Unable to activate fcp priority, "
|
||||||
|
" ret=0x%x\n", ha->host_no, ret));
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* qla24xx_update_all_fcp_prio
|
||||||
|
* Activates fcp priority for all the logged in ports
|
||||||
|
*
|
||||||
|
* Input:
|
||||||
|
* ha = adapter block pointer.
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* QLA_SUCCESS or QLA_FUNCTION_FAILED
|
||||||
|
*
|
||||||
|
* Context:
|
||||||
|
* Kernel context.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
qla24xx_update_all_fcp_prio(scsi_qla_host_t *vha)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
fc_port_t *fcport;
|
||||||
|
|
||||||
|
ret = QLA_FUNCTION_FAILED;
|
||||||
|
/* We need to set priority for all logged in ports */
|
||||||
|
list_for_each_entry(fcport, &vha->vp_fcports, list)
|
||||||
|
ret = qla24xx_update_fcport_fcp_prio(vha, fcport);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
|
@ -3896,3 +3896,50 @@ qla2x00_get_data_rate(scsi_qla_host_t *vha)
|
||||||
|
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
qla24xx_set_fcp_prio(scsi_qla_host_t *vha, uint16_t loop_id, uint16_t priority,
|
||||||
|
uint16_t *mb)
|
||||||
|
{
|
||||||
|
int rval;
|
||||||
|
mbx_cmd_t mc;
|
||||||
|
mbx_cmd_t *mcp = &mc;
|
||||||
|
struct qla_hw_data *ha = vha->hw;
|
||||||
|
|
||||||
|
if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha))
|
||||||
|
return QLA_FUNCTION_FAILED;
|
||||||
|
|
||||||
|
DEBUG11(printk(KERN_INFO
|
||||||
|
"%s(%ld): entered.\n", __func__, ha->host_no));
|
||||||
|
|
||||||
|
mcp->mb[0] = MBC_PORT_PARAMS;
|
||||||
|
mcp->mb[1] = loop_id;
|
||||||
|
if (ha->flags.fcp_prio_enabled)
|
||||||
|
mcp->mb[2] = BIT_1;
|
||||||
|
else
|
||||||
|
mcp->mb[2] = BIT_2;
|
||||||
|
mcp->mb[4] = priority & 0xf;
|
||||||
|
mcp->mb[9] = vha->vp_idx;
|
||||||
|
mcp->out_mb = MBX_9|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
|
||||||
|
mcp->in_mb = MBX_4|MBX_3|MBX_1|MBX_0;
|
||||||
|
mcp->tov = 30;
|
||||||
|
mcp->flags = 0;
|
||||||
|
rval = qla2x00_mailbox_command(vha, mcp);
|
||||||
|
if (mb != NULL) {
|
||||||
|
mb[0] = mcp->mb[0];
|
||||||
|
mb[1] = mcp->mb[1];
|
||||||
|
mb[3] = mcp->mb[3];
|
||||||
|
mb[4] = mcp->mb[4];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rval != QLA_SUCCESS) {
|
||||||
|
DEBUG2_3_11(printk(KERN_WARNING
|
||||||
|
"%s(%ld): failed=%x.\n", __func__,
|
||||||
|
vha->host_no, rval));
|
||||||
|
} else {
|
||||||
|
DEBUG11(printk(KERN_INFO
|
||||||
|
"%s(%ld): done.\n", __func__, vha->host_no));
|
||||||
|
}
|
||||||
|
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
|
@ -648,6 +648,12 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
|
||||||
const uint32_t def_npiv_conf1[] =
|
const uint32_t def_npiv_conf1[] =
|
||||||
{ FA_NPIV_CONF1_ADDR_24, FA_NPIV_CONF1_ADDR,
|
{ FA_NPIV_CONF1_ADDR_24, FA_NPIV_CONF1_ADDR,
|
||||||
FA_NPIV_CONF1_ADDR_81 };
|
FA_NPIV_CONF1_ADDR_81 };
|
||||||
|
const uint32_t fcp_prio_cfg0[] =
|
||||||
|
{ FA_FCP_PRIO0_ADDR, FA_FCP_PRIO0_ADDR_25,
|
||||||
|
0 };
|
||||||
|
const uint32_t fcp_prio_cfg1[] =
|
||||||
|
{ FA_FCP_PRIO1_ADDR, FA_FCP_PRIO1_ADDR_25,
|
||||||
|
0 };
|
||||||
uint32_t def;
|
uint32_t def;
|
||||||
uint16_t *wptr;
|
uint16_t *wptr;
|
||||||
uint16_t cnt, chksum;
|
uint16_t cnt, chksum;
|
||||||
|
@ -732,6 +738,14 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
|
||||||
case FLT_REG_GOLD_FW:
|
case FLT_REG_GOLD_FW:
|
||||||
ha->flt_region_gold_fw = start;
|
ha->flt_region_gold_fw = start;
|
||||||
break;
|
break;
|
||||||
|
case FLT_REG_FCP_PRIO_0:
|
||||||
|
if (!(PCI_FUNC(ha->pdev->devfn) & 1))
|
||||||
|
ha->flt_region_fcp_prio = start;
|
||||||
|
break;
|
||||||
|
case FLT_REG_FCP_PRIO_1:
|
||||||
|
if (PCI_FUNC(ha->pdev->devfn) & 1)
|
||||||
|
ha->flt_region_fcp_prio = start;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -750,12 +764,14 @@ no_flash_data:
|
||||||
ha->flt_region_boot = def_boot[def];
|
ha->flt_region_boot = def_boot[def];
|
||||||
ha->flt_region_vpd_nvram = def_vpd_nvram[def];
|
ha->flt_region_vpd_nvram = def_vpd_nvram[def];
|
||||||
ha->flt_region_vpd = ha->flags.port0 ?
|
ha->flt_region_vpd = ha->flags.port0 ?
|
||||||
def_vpd0[def]: def_vpd1[def];
|
def_vpd0[def] : def_vpd1[def];
|
||||||
ha->flt_region_nvram = ha->flags.port0 ?
|
ha->flt_region_nvram = ha->flags.port0 ?
|
||||||
def_nvram0[def]: def_nvram1[def];
|
def_nvram0[def] : def_nvram1[def];
|
||||||
ha->flt_region_fdt = def_fdt[def];
|
ha->flt_region_fdt = def_fdt[def];
|
||||||
ha->flt_region_npiv_conf = ha->flags.port0 ?
|
ha->flt_region_npiv_conf = ha->flags.port0 ?
|
||||||
def_npiv_conf0[def]: def_npiv_conf1[def];
|
def_npiv_conf0[def] : def_npiv_conf1[def];
|
||||||
|
ha->flt_region_fcp_prio = ha->flags.port0 ?
|
||||||
|
fcp_prio_cfg0[def] : fcp_prio_cfg1[def];
|
||||||
done:
|
done:
|
||||||
DEBUG2(qla_printk(KERN_DEBUG, ha, "FLT[%s]: boot=0x%x fw=0x%x "
|
DEBUG2(qla_printk(KERN_DEBUG, ha, "FLT[%s]: boot=0x%x fw=0x%x "
|
||||||
"vpd_nvram=0x%x vpd=0x%x nvram=0x%x fdt=0x%x flt=0x%x "
|
"vpd_nvram=0x%x vpd=0x%x nvram=0x%x fdt=0x%x flt=0x%x "
|
||||||
|
@ -2722,3 +2738,50 @@ qla2xxx_get_vpd_field(scsi_qla_host_t *vha, char *key, char *str, size_t size)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
qla24xx_read_fcp_prio_cfg(scsi_qla_host_t *vha)
|
||||||
|
{
|
||||||
|
int len, max_len;
|
||||||
|
uint32_t fcp_prio_addr;
|
||||||
|
struct qla_hw_data *ha = vha->hw;
|
||||||
|
|
||||||
|
if (!ha->fcp_prio_cfg) {
|
||||||
|
ha->fcp_prio_cfg = vmalloc(FCP_PRIO_CFG_SIZE);
|
||||||
|
if (!ha->fcp_prio_cfg) {
|
||||||
|
qla_printk(KERN_WARNING, ha,
|
||||||
|
"Unable to allocate memory for fcp priority data "
|
||||||
|
"(%x).\n", FCP_PRIO_CFG_SIZE);
|
||||||
|
return QLA_FUNCTION_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memset(ha->fcp_prio_cfg, 0, FCP_PRIO_CFG_SIZE);
|
||||||
|
|
||||||
|
fcp_prio_addr = ha->flt_region_fcp_prio;
|
||||||
|
|
||||||
|
/* first read the fcp priority data header from flash */
|
||||||
|
ha->isp_ops->read_optrom(vha, (uint8_t *)ha->fcp_prio_cfg,
|
||||||
|
fcp_prio_addr << 2, FCP_PRIO_CFG_HDR_SIZE);
|
||||||
|
|
||||||
|
if (!qla24xx_fcp_prio_cfg_valid(ha->fcp_prio_cfg, 0))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/* read remaining FCP CMD config data from flash */
|
||||||
|
fcp_prio_addr += (FCP_PRIO_CFG_HDR_SIZE >> 2);
|
||||||
|
len = ha->fcp_prio_cfg->num_entries * FCP_PRIO_CFG_ENTRY_SIZE;
|
||||||
|
max_len = FCP_PRIO_CFG_SIZE - FCP_PRIO_CFG_HDR_SIZE;
|
||||||
|
|
||||||
|
ha->isp_ops->read_optrom(vha, (uint8_t *)&ha->fcp_prio_cfg->entry[0],
|
||||||
|
fcp_prio_addr << 2, (len < max_len ? len : max_len));
|
||||||
|
|
||||||
|
/* revalidate the entire FCP priority config data, including entries */
|
||||||
|
if (!qla24xx_fcp_prio_cfg_valid(ha->fcp_prio_cfg, 1))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
ha->flags.fcp_prio_enabled = 1;
|
||||||
|
return QLA_SUCCESS;
|
||||||
|
fail:
|
||||||
|
vfree(ha->fcp_prio_cfg);
|
||||||
|
ha->fcp_prio_cfg = NULL;
|
||||||
|
return QLA_FUNCTION_FAILED;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue