Loading drivers/scsi/qla2xxx/qla_bsg.c +125 −0 Original line number Diff line number Diff line Loading @@ -1306,6 +1306,125 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job) return rval; } static int qla2x00_optrom_setup(struct fc_bsg_job *bsg_job, struct qla_hw_data *ha, uint8_t is_update) { uint32_t start = 0; int valid = 0; bsg_job->reply->reply_payload_rcv_len = 0; if (unlikely(pci_channel_offline(ha->pdev))) return -EINVAL; start = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1]; if (start > ha->optrom_size) return -EINVAL; if (ha->optrom_state != QLA_SWAITING) return -EBUSY; ha->optrom_region_start = start; if (is_update) { if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0) valid = 1; else if (start == (ha->flt_region_boot * 4) || start == (ha->flt_region_fw * 4)) valid = 1; else if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) || IS_QLA8XXX_TYPE(ha)) valid = 1; if (!valid) { qla_printk(KERN_WARNING, ha, "Invalid start region 0x%x/0x%x.\n", start, bsg_job->request_payload.payload_len); return -EINVAL; } ha->optrom_region_size = start + bsg_job->request_payload.payload_len > ha->optrom_size ? ha->optrom_size - start : bsg_job->request_payload.payload_len; ha->optrom_state = QLA_SWRITING; } else { ha->optrom_region_size = start + bsg_job->reply_payload.payload_len > ha->optrom_size ? ha->optrom_size - start : bsg_job->reply_payload.payload_len; ha->optrom_state = QLA_SREADING; } ha->optrom_buffer = vmalloc(ha->optrom_region_size); if (!ha->optrom_buffer) { qla_printk(KERN_WARNING, ha, "Read: Unable to allocate memory for optrom retrieval " "(%x).\n", ha->optrom_region_size); ha->optrom_state = QLA_SWAITING; return -ENOMEM; } memset(ha->optrom_buffer, 0, ha->optrom_region_size); return 0; } static int qla2x00_read_optrom(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 rval = 0; rval = qla2x00_optrom_setup(bsg_job, ha, 0); if (rval) return rval; ha->isp_ops->read_optrom(vha, ha->optrom_buffer, ha->optrom_region_start, ha->optrom_region_size); sg_copy_from_buffer(bsg_job->reply_payload.sg_list, bsg_job->reply_payload.sg_cnt, ha->optrom_buffer, ha->optrom_region_size); bsg_job->reply->reply_payload_rcv_len = ha->optrom_region_size; bsg_job->reply->result = DID_OK; vfree(ha->optrom_buffer); ha->optrom_buffer = NULL; ha->optrom_state = QLA_SWAITING; bsg_job->job_done(bsg_job); return rval; } static int qla2x00_update_optrom(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 rval = 0; rval = qla2x00_optrom_setup(bsg_job, ha, 1); if (rval) return rval; sg_copy_to_buffer(bsg_job->request_payload.sg_list, bsg_job->request_payload.sg_cnt, ha->optrom_buffer, ha->optrom_region_size); ha->isp_ops->write_optrom(vha, ha->optrom_buffer, ha->optrom_region_start, ha->optrom_region_size); bsg_job->reply->result = DID_OK; vfree(ha->optrom_buffer); ha->optrom_buffer = NULL; ha->optrom_state = QLA_SWAITING; bsg_job->job_done(bsg_job); return rval; } static int qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job) { Loading @@ -1328,6 +1447,12 @@ qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job) case QL_VND_FCP_PRIO_CFG_CMD: return qla24xx_proc_fcp_prio_cfg_cmd(bsg_job); case QL_VND_READ_FLASH: return qla2x00_read_optrom(bsg_job); case QL_VND_UPDATE_FLASH: return qla2x00_update_optrom(bsg_job); default: bsg_job->reply->result = (DID_ERROR << 16); bsg_job->job_done(bsg_job); Loading drivers/scsi/qla2xxx/qla_bsg.h +2 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,8 @@ #define QL_VND_A84_MGMT_CMD 0x04 #define QL_VND_IIDMA 0x05 #define QL_VND_FCP_PRIO_CFG_CMD 0x06 #define QL_VND_READ_FLASH 0x07 #define QL_VND_UPDATE_FLASH 0x08 /* BSG definations for interpreting CommandSent field */ #define INT_DEF_LB_LOOPBACK_CMD 0 Loading Loading
drivers/scsi/qla2xxx/qla_bsg.c +125 −0 Original line number Diff line number Diff line Loading @@ -1306,6 +1306,125 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job) return rval; } static int qla2x00_optrom_setup(struct fc_bsg_job *bsg_job, struct qla_hw_data *ha, uint8_t is_update) { uint32_t start = 0; int valid = 0; bsg_job->reply->reply_payload_rcv_len = 0; if (unlikely(pci_channel_offline(ha->pdev))) return -EINVAL; start = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1]; if (start > ha->optrom_size) return -EINVAL; if (ha->optrom_state != QLA_SWAITING) return -EBUSY; ha->optrom_region_start = start; if (is_update) { if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0) valid = 1; else if (start == (ha->flt_region_boot * 4) || start == (ha->flt_region_fw * 4)) valid = 1; else if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) || IS_QLA8XXX_TYPE(ha)) valid = 1; if (!valid) { qla_printk(KERN_WARNING, ha, "Invalid start region 0x%x/0x%x.\n", start, bsg_job->request_payload.payload_len); return -EINVAL; } ha->optrom_region_size = start + bsg_job->request_payload.payload_len > ha->optrom_size ? ha->optrom_size - start : bsg_job->request_payload.payload_len; ha->optrom_state = QLA_SWRITING; } else { ha->optrom_region_size = start + bsg_job->reply_payload.payload_len > ha->optrom_size ? ha->optrom_size - start : bsg_job->reply_payload.payload_len; ha->optrom_state = QLA_SREADING; } ha->optrom_buffer = vmalloc(ha->optrom_region_size); if (!ha->optrom_buffer) { qla_printk(KERN_WARNING, ha, "Read: Unable to allocate memory for optrom retrieval " "(%x).\n", ha->optrom_region_size); ha->optrom_state = QLA_SWAITING; return -ENOMEM; } memset(ha->optrom_buffer, 0, ha->optrom_region_size); return 0; } static int qla2x00_read_optrom(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 rval = 0; rval = qla2x00_optrom_setup(bsg_job, ha, 0); if (rval) return rval; ha->isp_ops->read_optrom(vha, ha->optrom_buffer, ha->optrom_region_start, ha->optrom_region_size); sg_copy_from_buffer(bsg_job->reply_payload.sg_list, bsg_job->reply_payload.sg_cnt, ha->optrom_buffer, ha->optrom_region_size); bsg_job->reply->reply_payload_rcv_len = ha->optrom_region_size; bsg_job->reply->result = DID_OK; vfree(ha->optrom_buffer); ha->optrom_buffer = NULL; ha->optrom_state = QLA_SWAITING; bsg_job->job_done(bsg_job); return rval; } static int qla2x00_update_optrom(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 rval = 0; rval = qla2x00_optrom_setup(bsg_job, ha, 1); if (rval) return rval; sg_copy_to_buffer(bsg_job->request_payload.sg_list, bsg_job->request_payload.sg_cnt, ha->optrom_buffer, ha->optrom_region_size); ha->isp_ops->write_optrom(vha, ha->optrom_buffer, ha->optrom_region_start, ha->optrom_region_size); bsg_job->reply->result = DID_OK; vfree(ha->optrom_buffer); ha->optrom_buffer = NULL; ha->optrom_state = QLA_SWAITING; bsg_job->job_done(bsg_job); return rval; } static int qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job) { Loading @@ -1328,6 +1447,12 @@ qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job) case QL_VND_FCP_PRIO_CFG_CMD: return qla24xx_proc_fcp_prio_cfg_cmd(bsg_job); case QL_VND_READ_FLASH: return qla2x00_read_optrom(bsg_job); case QL_VND_UPDATE_FLASH: return qla2x00_update_optrom(bsg_job); default: bsg_job->reply->result = (DID_ERROR << 16); bsg_job->job_done(bsg_job); Loading
drivers/scsi/qla2xxx/qla_bsg.h +2 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,8 @@ #define QL_VND_A84_MGMT_CMD 0x04 #define QL_VND_IIDMA 0x05 #define QL_VND_FCP_PRIO_CFG_CMD 0x06 #define QL_VND_READ_FLASH 0x07 #define QL_VND_UPDATE_FLASH 0x08 /* BSG definations for interpreting CommandSent field */ #define INT_DEF_LB_LOOPBACK_CMD 0 Loading