aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_isr.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_isr.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c77
1 files changed, 77 insertions, 0 deletions
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index eed71ea1d947..be3d8bed2ecf 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -10,6 +10,7 @@
10#include <linux/slab.h> 10#include <linux/slab.h>
11#include <scsi/scsi_tcq.h> 11#include <scsi/scsi_tcq.h>
12#include <scsi/scsi_bsg_fc.h> 12#include <scsi/scsi_bsg_fc.h>
13#include <scsi/scsi_eh.h>
13 14
14static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t); 15static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t);
15static void qla2x00_process_completed_request(struct scsi_qla_host *, 16static void qla2x00_process_completed_request(struct scsi_qla_host *,
@@ -1364,6 +1365,78 @@ qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t sense_len,
1364 DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, sense_len)); 1365 DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, sense_len));
1365} 1366}
1366 1367
1368struct scsi_dif_tuple {
1369 __be16 guard; /* Checksum */
1370 __be16 app_tag; /* APPL identifer */
1371 __be32 ref_tag; /* Target LBA or indirect LBA */
1372};
1373
1374/*
1375 * Checks the guard or meta-data for the type of error
1376 * detected by the HBA. In case of errors, we set the
1377 * ASC/ASCQ fields in the sense buffer with ILLEGAL_REQUEST
1378 * to indicate to the kernel that the HBA detected error.
1379 */
1380static inline void
1381qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24)
1382{
1383 struct scsi_cmnd *cmd = sp->cmd;
1384 struct scsi_dif_tuple *ep =
1385 (struct scsi_dif_tuple *)&sts24->data[20];
1386 struct scsi_dif_tuple *ap =
1387 (struct scsi_dif_tuple *)&sts24->data[12];
1388 uint32_t e_ref_tag, a_ref_tag;
1389 uint16_t e_app_tag, a_app_tag;
1390 uint16_t e_guard, a_guard;
1391
1392 e_ref_tag = be32_to_cpu(ep->ref_tag);
1393 a_ref_tag = be32_to_cpu(ap->ref_tag);
1394 e_app_tag = be16_to_cpu(ep->app_tag);
1395 a_app_tag = be16_to_cpu(ap->app_tag);
1396 e_guard = be16_to_cpu(ep->guard);
1397 a_guard = be16_to_cpu(ap->guard);
1398
1399 DEBUG18(printk(KERN_DEBUG
1400 "%s(): iocb(s) %p Returned STATUS\n", __func__, sts24));
1401
1402 DEBUG18(printk(KERN_ERR "DIF ERROR in cmd 0x%x lba 0x%llx act ref"
1403 " tag=0x%x, exp ref_tag=0x%x, act app tag=0x%x, exp app"
1404 " tag=0x%x, act guard=0x%x, exp guard=0x%x\n",
1405 cmd->cmnd[0], (u64)scsi_get_lba(cmd), a_ref_tag, e_ref_tag,
1406 a_app_tag, e_app_tag, a_guard, e_guard));
1407
1408
1409 /* check guard */
1410 if (e_guard != a_guard) {
1411 scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
1412 0x10, 0x1);
1413 set_driver_byte(cmd, DRIVER_SENSE);
1414 set_host_byte(cmd, DID_ABORT);
1415 cmd->result |= SAM_STAT_CHECK_CONDITION << 1;
1416 return;
1417 }
1418
1419 /* check appl tag */
1420 if (e_app_tag != a_app_tag) {
1421 scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
1422 0x10, 0x2);
1423 set_driver_byte(cmd, DRIVER_SENSE);
1424 set_host_byte(cmd, DID_ABORT);
1425 cmd->result |= SAM_STAT_CHECK_CONDITION << 1;
1426 return;
1427 }
1428
1429 /* check ref tag */
1430 if (e_ref_tag != a_ref_tag) {
1431 scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
1432 0x10, 0x3);
1433 set_driver_byte(cmd, DRIVER_SENSE);
1434 set_host_byte(cmd, DID_ABORT);
1435 cmd->result |= SAM_STAT_CHECK_CONDITION << 1;
1436 return;
1437 }
1438}
1439
1367/** 1440/**
1368 * qla2x00_status_entry() - Process a Status IOCB entry. 1441 * qla2x00_status_entry() - Process a Status IOCB entry.
1369 * @ha: SCSI driver HA context 1442 * @ha: SCSI driver HA context
@@ -1630,6 +1703,10 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
1630 case CS_ABORTED: 1703 case CS_ABORTED:
1631 cp->result = DID_RESET << 16; 1704 cp->result = DID_RESET << 16;
1632 break; 1705 break;
1706
1707 case CS_DIF_ERROR:
1708 qla2x00_handle_dif_error(sp, sts24);
1709 break;
1633 default: 1710 default:
1634 cp->result = DID_ERROR << 16; 1711 cp->result = DID_ERROR << 16;
1635 break; 1712 break;