Loading drivers/scsi/qla2xxx/qla_bsg.c +163 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,166 @@ qla2x00_get_ctx_bsg_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size) 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 qla2x00_process_els(struct fc_bsg_job *bsg_job) { Loading Loading @@ -948,6 +1108,9 @@ qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job) case QL_VND_IIDMA: return qla24xx_iidma(bsg_job); case QL_VND_FCP_PRIO_CFG_CMD: return qla24xx_proc_fcp_prio_cfg_cmd(bsg_job); default: bsg_job->reply->result = (DID_ERROR << 16); bsg_job->job_done(bsg_job); Loading drivers/scsi/qla2xxx/qla_def.h +7 −0 Original line number Diff line number Diff line Loading @@ -1580,6 +1580,8 @@ typedef struct fc_port { uint16_t loop_id; uint16_t old_loop_id; uint8_t fcp_prio; uint8_t fabric_port_name[WWN_SIZE]; uint16_t fp_speed; Loading Loading @@ -2296,6 +2298,7 @@ struct qla_hw_data { uint32_t eeh_busy :1; uint32_t cpu_affinity_enabled :1; uint32_t disable_msix_handshake :1; uint32_t fcp_prio_enabled :1; } flags; /* This spinlock is used to protect "io transactions", you must Loading Loading @@ -2599,6 +2602,7 @@ struct qla_hw_data { uint32_t flt_region_nvram; uint32_t flt_region_npiv_conf; uint32_t flt_region_gold_fw; uint32_t flt_region_fcp_prio; /* Needed for BEACON */ uint16_t beacon_blink_led; Loading Loading @@ -2627,6 +2631,9 @@ struct qla_hw_data { struct isp_operations *isp_ops; struct workqueue_struct *wq; struct qlfc_fw fw_buf; /* FCP_CMND priority support */ struct qla_fcp_prio_cfg *fcp_prio_cfg; }; /* Loading drivers/scsi/qla2xxx/qla_fw.h +59 −0 Original line number Diff line number Diff line Loading @@ -841,6 +841,8 @@ struct device_reg_24xx { #define FA_HW_EVENT_ENTRY_SIZE 4 #define FA_NPIV_CONF0_ADDR 0x5C000 #define FA_NPIV_CONF1_ADDR 0x5D000 #define FA_FCP_PRIO0_ADDR 0x10000 #define FA_FCP_PRIO1_ADDR 0x12000 /* * Flash Error Log Event Codes. Loading Loading @@ -1274,6 +1276,8 @@ struct qla_flt_header { #define FLT_REG_NPIV_CONF_0 0x29 #define FLT_REG_NPIV_CONF_1 0x2a #define FLT_REG_GOLD_FW 0x2f #define FLT_REG_FCP_PRIO_0 0x87 #define FLT_REG_FCP_PRIO_1 0x88 struct qla_flt_region { uint32_t code; Loading Loading @@ -1750,6 +1754,61 @@ struct ex_init_cb_81xx { #define FARX_ACCESS_FLASH_CONF_81XX 0x7FFD0000 #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. */ #define FA_BOOT_CODE_ADDR_81 0x80000 #define FA_RISC_CODE_ADDR_81 0xA0000 Loading drivers/scsi/qla2xxx/qla_gbl.h +8 −1 Original line number Diff line number Diff line Loading @@ -328,6 +328,9 @@ extern int qla2x00_write_ram_word(scsi_qla_host_t *, uint32_t, uint32_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. */ Loading Loading @@ -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 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. Loading Loading @@ -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_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_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. Loading drivers/scsi/qla2xxx/qla_init.c +168 −0 Original line number Diff line number Diff line Loading @@ -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); } Loading Loading @@ -4905,3 +4911,165 @@ qla81xx_update_fw_options(scsi_qla_host_t *vha) ha->fw_options[2] |= BIT_9; 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; } Loading
drivers/scsi/qla2xxx/qla_bsg.c +163 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,166 @@ qla2x00_get_ctx_bsg_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size) 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 qla2x00_process_els(struct fc_bsg_job *bsg_job) { Loading Loading @@ -948,6 +1108,9 @@ qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job) case QL_VND_IIDMA: return qla24xx_iidma(bsg_job); case QL_VND_FCP_PRIO_CFG_CMD: return qla24xx_proc_fcp_prio_cfg_cmd(bsg_job); default: bsg_job->reply->result = (DID_ERROR << 16); bsg_job->job_done(bsg_job); Loading
drivers/scsi/qla2xxx/qla_def.h +7 −0 Original line number Diff line number Diff line Loading @@ -1580,6 +1580,8 @@ typedef struct fc_port { uint16_t loop_id; uint16_t old_loop_id; uint8_t fcp_prio; uint8_t fabric_port_name[WWN_SIZE]; uint16_t fp_speed; Loading Loading @@ -2296,6 +2298,7 @@ struct qla_hw_data { uint32_t eeh_busy :1; uint32_t cpu_affinity_enabled :1; uint32_t disable_msix_handshake :1; uint32_t fcp_prio_enabled :1; } flags; /* This spinlock is used to protect "io transactions", you must Loading Loading @@ -2599,6 +2602,7 @@ struct qla_hw_data { uint32_t flt_region_nvram; uint32_t flt_region_npiv_conf; uint32_t flt_region_gold_fw; uint32_t flt_region_fcp_prio; /* Needed for BEACON */ uint16_t beacon_blink_led; Loading Loading @@ -2627,6 +2631,9 @@ struct qla_hw_data { struct isp_operations *isp_ops; struct workqueue_struct *wq; struct qlfc_fw fw_buf; /* FCP_CMND priority support */ struct qla_fcp_prio_cfg *fcp_prio_cfg; }; /* Loading
drivers/scsi/qla2xxx/qla_fw.h +59 −0 Original line number Diff line number Diff line Loading @@ -841,6 +841,8 @@ struct device_reg_24xx { #define FA_HW_EVENT_ENTRY_SIZE 4 #define FA_NPIV_CONF0_ADDR 0x5C000 #define FA_NPIV_CONF1_ADDR 0x5D000 #define FA_FCP_PRIO0_ADDR 0x10000 #define FA_FCP_PRIO1_ADDR 0x12000 /* * Flash Error Log Event Codes. Loading Loading @@ -1274,6 +1276,8 @@ struct qla_flt_header { #define FLT_REG_NPIV_CONF_0 0x29 #define FLT_REG_NPIV_CONF_1 0x2a #define FLT_REG_GOLD_FW 0x2f #define FLT_REG_FCP_PRIO_0 0x87 #define FLT_REG_FCP_PRIO_1 0x88 struct qla_flt_region { uint32_t code; Loading Loading @@ -1750,6 +1754,61 @@ struct ex_init_cb_81xx { #define FARX_ACCESS_FLASH_CONF_81XX 0x7FFD0000 #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. */ #define FA_BOOT_CODE_ADDR_81 0x80000 #define FA_RISC_CODE_ADDR_81 0xA0000 Loading
drivers/scsi/qla2xxx/qla_gbl.h +8 −1 Original line number Diff line number Diff line Loading @@ -328,6 +328,9 @@ extern int qla2x00_write_ram_word(scsi_qla_host_t *, uint32_t, uint32_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. */ Loading Loading @@ -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 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. Loading Loading @@ -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_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_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. Loading
drivers/scsi/qla2xxx/qla_init.c +168 −0 Original line number Diff line number Diff line Loading @@ -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); } Loading Loading @@ -4905,3 +4911,165 @@ qla81xx_update_fw_options(scsi_qla_host_t *vha) ha->fw_options[2] |= BIT_9; 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; }