diff options
| author | Harish Zunjarrao <harish.zunjarrao@qlogic.com> | 2010-10-15 14:27:43 -0400 |
|---|---|---|
| committer | James Bottomley <James.Bottomley@suse.de> | 2010-10-25 17:00:40 -0400 |
| commit | f19af1636bda8454401fa76ce4ad027412d5d07a (patch) | |
| tree | 4f108bd888ce8743584db22206a4dd1a4145fb36 | |
| parent | ff454b01b4ebe60b14092943978000928bf8c551 (diff) | |
[SCSI] qla2xxx: Add flash read/update support using BSG interface
Signed-off-by: Harish Zunjarrao <harish.zunjarrao@qlogic.com>
Signed-off-by: Madhuranath Iyengar <Madhu.Iyengar@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_bsg.c | 125 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_bsg.h | 2 |
2 files changed, 127 insertions, 0 deletions
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index fdfbf83a6330..31a4121a2be1 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c | |||
| @@ -1307,6 +1307,125 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job) | |||
| 1307 | } | 1307 | } |
| 1308 | 1308 | ||
| 1309 | static int | 1309 | static int |
| 1310 | qla2x00_optrom_setup(struct fc_bsg_job *bsg_job, struct qla_hw_data *ha, | ||
| 1311 | uint8_t is_update) | ||
| 1312 | { | ||
| 1313 | uint32_t start = 0; | ||
| 1314 | int valid = 0; | ||
| 1315 | |||
| 1316 | bsg_job->reply->reply_payload_rcv_len = 0; | ||
| 1317 | |||
| 1318 | if (unlikely(pci_channel_offline(ha->pdev))) | ||
| 1319 | return -EINVAL; | ||
| 1320 | |||
| 1321 | start = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1]; | ||
| 1322 | if (start > ha->optrom_size) | ||
| 1323 | return -EINVAL; | ||
| 1324 | |||
| 1325 | if (ha->optrom_state != QLA_SWAITING) | ||
| 1326 | return -EBUSY; | ||
| 1327 | |||
| 1328 | ha->optrom_region_start = start; | ||
| 1329 | |||
| 1330 | if (is_update) { | ||
| 1331 | if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0) | ||
| 1332 | valid = 1; | ||
| 1333 | else if (start == (ha->flt_region_boot * 4) || | ||
| 1334 | start == (ha->flt_region_fw * 4)) | ||
| 1335 | valid = 1; | ||
| 1336 | else if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) || | ||
| 1337 | IS_QLA8XXX_TYPE(ha)) | ||
| 1338 | valid = 1; | ||
| 1339 | if (!valid) { | ||
| 1340 | qla_printk(KERN_WARNING, ha, | ||
| 1341 | "Invalid start region 0x%x/0x%x.\n", | ||
| 1342 | start, bsg_job->request_payload.payload_len); | ||
| 1343 | return -EINVAL; | ||
| 1344 | } | ||
| 1345 | |||
| 1346 | ha->optrom_region_size = start + | ||
| 1347 | bsg_job->request_payload.payload_len > ha->optrom_size ? | ||
| 1348 | ha->optrom_size - start : | ||
| 1349 | bsg_job->request_payload.payload_len; | ||
| 1350 | ha->optrom_state = QLA_SWRITING; | ||
| 1351 | } else { | ||
| 1352 | ha->optrom_region_size = start + | ||
| 1353 | bsg_job->reply_payload.payload_len > ha->optrom_size ? | ||
| 1354 | ha->optrom_size - start : | ||
| 1355 | bsg_job->reply_payload.payload_len; | ||
| 1356 | ha->optrom_state = QLA_SREADING; | ||
| 1357 | } | ||
| 1358 | |||
| 1359 | ha->optrom_buffer = vmalloc(ha->optrom_region_size); | ||
| 1360 | if (!ha->optrom_buffer) { | ||
| 1361 | qla_printk(KERN_WARNING, ha, | ||
| 1362 | "Read: Unable to allocate memory for optrom retrieval " | ||
| 1363 | "(%x).\n", ha->optrom_region_size); | ||
| 1364 | |||
| 1365 | ha->optrom_state = QLA_SWAITING; | ||
| 1366 | return -ENOMEM; | ||
| 1367 | } | ||
| 1368 | |||
| 1369 | memset(ha->optrom_buffer, 0, ha->optrom_region_size); | ||
| 1370 | return 0; | ||
| 1371 | } | ||
| 1372 | |||
| 1373 | static int | ||
| 1374 | qla2x00_read_optrom(struct fc_bsg_job *bsg_job) | ||
| 1375 | { | ||
| 1376 | struct Scsi_Host *host = bsg_job->shost; | ||
| 1377 | scsi_qla_host_t *vha = shost_priv(host); | ||
| 1378 | struct qla_hw_data *ha = vha->hw; | ||
| 1379 | int rval = 0; | ||
| 1380 | |||
| 1381 | rval = qla2x00_optrom_setup(bsg_job, ha, 0); | ||
| 1382 | if (rval) | ||
| 1383 | return rval; | ||
| 1384 | |||
| 1385 | ha->isp_ops->read_optrom(vha, ha->optrom_buffer, | ||
| 1386 | ha->optrom_region_start, ha->optrom_region_size); | ||
| 1387 | |||
| 1388 | sg_copy_from_buffer(bsg_job->reply_payload.sg_list, | ||
| 1389 | bsg_job->reply_payload.sg_cnt, ha->optrom_buffer, | ||
| 1390 | ha->optrom_region_size); | ||
| 1391 | |||
| 1392 | bsg_job->reply->reply_payload_rcv_len = ha->optrom_region_size; | ||
| 1393 | bsg_job->reply->result = DID_OK; | ||
| 1394 | vfree(ha->optrom_buffer); | ||
| 1395 | ha->optrom_buffer = NULL; | ||
| 1396 | ha->optrom_state = QLA_SWAITING; | ||
| 1397 | bsg_job->job_done(bsg_job); | ||
| 1398 | return rval; | ||
| 1399 | } | ||
| 1400 | |||
| 1401 | static int | ||
| 1402 | qla2x00_update_optrom(struct fc_bsg_job *bsg_job) | ||
| 1403 | { | ||
| 1404 | struct Scsi_Host *host = bsg_job->shost; | ||
| 1405 | scsi_qla_host_t *vha = shost_priv(host); | ||
| 1406 | struct qla_hw_data *ha = vha->hw; | ||
| 1407 | int rval = 0; | ||
| 1408 | |||
| 1409 | rval = qla2x00_optrom_setup(bsg_job, ha, 1); | ||
| 1410 | if (rval) | ||
| 1411 | return rval; | ||
| 1412 | |||
| 1413 | sg_copy_to_buffer(bsg_job->request_payload.sg_list, | ||
| 1414 | bsg_job->request_payload.sg_cnt, ha->optrom_buffer, | ||
| 1415 | ha->optrom_region_size); | ||
| 1416 | |||
| 1417 | ha->isp_ops->write_optrom(vha, ha->optrom_buffer, | ||
| 1418 | ha->optrom_region_start, ha->optrom_region_size); | ||
| 1419 | |||
| 1420 | bsg_job->reply->result = DID_OK; | ||
| 1421 | vfree(ha->optrom_buffer); | ||
| 1422 | ha->optrom_buffer = NULL; | ||
| 1423 | ha->optrom_state = QLA_SWAITING; | ||
| 1424 | bsg_job->job_done(bsg_job); | ||
| 1425 | return rval; | ||
| 1426 | } | ||
| 1427 | |||
| 1428 | static int | ||
| 1310 | qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job) | 1429 | qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job) |
| 1311 | { | 1430 | { |
| 1312 | switch (bsg_job->request->rqst_data.h_vendor.vendor_cmd[0]) { | 1431 | switch (bsg_job->request->rqst_data.h_vendor.vendor_cmd[0]) { |
| @@ -1328,6 +1447,12 @@ qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job) | |||
| 1328 | case QL_VND_FCP_PRIO_CFG_CMD: | 1447 | case QL_VND_FCP_PRIO_CFG_CMD: |
| 1329 | return qla24xx_proc_fcp_prio_cfg_cmd(bsg_job); | 1448 | return qla24xx_proc_fcp_prio_cfg_cmd(bsg_job); |
| 1330 | 1449 | ||
| 1450 | case QL_VND_READ_FLASH: | ||
| 1451 | return qla2x00_read_optrom(bsg_job); | ||
| 1452 | |||
| 1453 | case QL_VND_UPDATE_FLASH: | ||
| 1454 | return qla2x00_update_optrom(bsg_job); | ||
| 1455 | |||
| 1331 | default: | 1456 | default: |
| 1332 | bsg_job->reply->result = (DID_ERROR << 16); | 1457 | bsg_job->reply->result = (DID_ERROR << 16); |
| 1333 | bsg_job->job_done(bsg_job); | 1458 | bsg_job->job_done(bsg_job); |
diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h index cc7c52f87a11..074a999c7017 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.h +++ b/drivers/scsi/qla2xxx/qla_bsg.h | |||
| @@ -14,6 +14,8 @@ | |||
| 14 | #define QL_VND_A84_MGMT_CMD 0x04 | 14 | #define QL_VND_A84_MGMT_CMD 0x04 |
| 15 | #define QL_VND_IIDMA 0x05 | 15 | #define QL_VND_IIDMA 0x05 |
| 16 | #define QL_VND_FCP_PRIO_CFG_CMD 0x06 | 16 | #define QL_VND_FCP_PRIO_CFG_CMD 0x06 |
| 17 | #define QL_VND_READ_FLASH 0x07 | ||
| 18 | #define QL_VND_UPDATE_FLASH 0x08 | ||
| 17 | 19 | ||
| 18 | /* BSG definations for interpreting CommandSent field */ | 20 | /* BSG definations for interpreting CommandSent field */ |
| 19 | #define INT_DEF_LB_LOOPBACK_CMD 0 | 21 | #define INT_DEF_LB_LOOPBACK_CMD 0 |
