aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla4xxx/ql4_os.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/qla4xxx/ql4_os.c')
-rw-r--r--drivers/scsi/qla4xxx/ql4_os.c96
1 files changed, 74 insertions, 22 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 8b92f348f02c..0c786944d2c2 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -71,6 +71,7 @@ static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session);
71static int qla4xxx_queuecommand(struct scsi_cmnd *cmd, 71static int qla4xxx_queuecommand(struct scsi_cmnd *cmd,
72 void (*done) (struct scsi_cmnd *)); 72 void (*done) (struct scsi_cmnd *));
73static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd); 73static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd);
74static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd);
74static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd); 75static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd);
75static int qla4xxx_slave_alloc(struct scsi_device *device); 76static int qla4xxx_slave_alloc(struct scsi_device *device);
76static int qla4xxx_slave_configure(struct scsi_device *device); 77static int qla4xxx_slave_configure(struct scsi_device *device);
@@ -84,6 +85,7 @@ static struct scsi_host_template qla4xxx_driver_template = {
84 .queuecommand = qla4xxx_queuecommand, 85 .queuecommand = qla4xxx_queuecommand,
85 86
86 .eh_device_reset_handler = qla4xxx_eh_device_reset, 87 .eh_device_reset_handler = qla4xxx_eh_device_reset,
88 .eh_target_reset_handler = qla4xxx_eh_target_reset,
87 .eh_host_reset_handler = qla4xxx_eh_host_reset, 89 .eh_host_reset_handler = qla4xxx_eh_host_reset,
88 90
89 .slave_configure = qla4xxx_slave_configure, 91 .slave_configure = qla4xxx_slave_configure,
@@ -1482,7 +1484,7 @@ static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha)
1482} 1484}
1483 1485
1484/** 1486/**
1485 * qla4xxx_eh_wait_for_active_target_commands - wait for active cmds to finish. 1487 * qla4xxx_eh_wait_for_commands - wait for active cmds to finish.
1486 * @ha: pointer to to HBA 1488 * @ha: pointer to to HBA
1487 * @t: target id 1489 * @t: target id
1488 * @l: lun id 1490 * @l: lun id
@@ -1490,20 +1492,22 @@ static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha)
1490 * This function waits for all outstanding commands to a lun to complete. It 1492 * This function waits for all outstanding commands to a lun to complete. It
1491 * returns 0 if all pending commands are returned and 1 otherwise. 1493 * returns 0 if all pending commands are returned and 1 otherwise.
1492 **/ 1494 **/
1493static int qla4xxx_eh_wait_for_active_target_commands(struct scsi_qla_host *ha, 1495static int qla4xxx_eh_wait_for_commands(struct scsi_qla_host *ha,
1494 int t, int l) 1496 struct scsi_target *stgt,
1497 struct scsi_device *sdev)
1495{ 1498{
1496 int cnt; 1499 int cnt;
1497 int status = 0; 1500 int status = 0;
1498 struct scsi_cmnd *cmd; 1501 struct scsi_cmnd *cmd;
1499 1502
1500 /* 1503 /*
1501 * Waiting for all commands for the designated target in the active 1504 * Waiting for all commands for the designated target or dev
1502 * array 1505 * in the active array
1503 */ 1506 */
1504 for (cnt = 0; cnt < ha->host->can_queue; cnt++) { 1507 for (cnt = 0; cnt < ha->host->can_queue; cnt++) {
1505 cmd = scsi_host_find_tag(ha->host, cnt); 1508 cmd = scsi_host_find_tag(ha->host, cnt);
1506 if (cmd && cmd->device->id == t && cmd->device->lun == l) { 1509 if (cmd && stgt == scsi_target(cmd->device) &&
1510 (!sdev || sdev == cmd->device)) {
1507 if (!qla4xxx_eh_wait_on_command(ha, cmd)) { 1511 if (!qla4xxx_eh_wait_on_command(ha, cmd)) {
1508 status++; 1512 status++;
1509 break; 1513 break;
@@ -1548,24 +1552,19 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd)
1548 goto eh_dev_reset_done; 1552 goto eh_dev_reset_done;
1549 } 1553 }
1550 1554
1551 /* Send marker. */ 1555 if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device),
1552 ha->marker_needed = 1; 1556 cmd->device)) {
1553 1557 dev_info(&ha->pdev->dev,
1554 /* 1558 "DEVICE RESET FAILED - waiting for "
1555 * If we are coming down the EH path, wait for all commands to complete 1559 "commands.\n");
1556 * for the device. 1560 goto eh_dev_reset_done;
1557 */
1558 if (cmd->device->host->shost_state == SHOST_RECOVERY) {
1559 if (qla4xxx_eh_wait_for_active_target_commands(ha,
1560 cmd->device->id,
1561 cmd->device->lun)){
1562 dev_info(&ha->pdev->dev,
1563 "DEVICE RESET FAILED - waiting for "
1564 "commands.\n");
1565 goto eh_dev_reset_done;
1566 }
1567 } 1561 }
1568 1562
1563 /* Send marker. */
1564 if (qla4xxx_send_marker_iocb(ha, ddb_entry, cmd->device->lun,
1565 MM_LUN_RESET) != QLA_SUCCESS)
1566 goto eh_dev_reset_done;
1567
1569 dev_info(&ha->pdev->dev, 1568 dev_info(&ha->pdev->dev,
1570 "scsi(%ld:%d:%d:%d): DEVICE RESET SUCCEEDED.\n", 1569 "scsi(%ld:%d:%d:%d): DEVICE RESET SUCCEEDED.\n",
1571 ha->host_no, cmd->device->channel, cmd->device->id, 1570 ha->host_no, cmd->device->channel, cmd->device->id,
@@ -1579,6 +1578,59 @@ eh_dev_reset_done:
1579} 1578}
1580 1579
1581/** 1580/**
1581 * qla4xxx_eh_target_reset - callback for target reset.
1582 * @cmd: Pointer to Linux's SCSI command structure
1583 *
1584 * This routine is called by the Linux OS to reset the target.
1585 **/
1586static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd)
1587{
1588 struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
1589 struct ddb_entry *ddb_entry = cmd->device->hostdata;
1590 int stat;
1591
1592 if (!ddb_entry)
1593 return FAILED;
1594
1595 starget_printk(KERN_INFO, scsi_target(cmd->device),
1596 "WARM TARGET RESET ISSUED.\n");
1597
1598 DEBUG2(printk(KERN_INFO
1599 "scsi%ld: TARGET_DEVICE_RESET cmd=%p jiffies = 0x%lx, "
1600 "to=%x,dpc_flags=%lx, status=%x allowed=%d\n",
1601 ha->host_no, cmd, jiffies, cmd->timeout_per_command / HZ,
1602 ha->dpc_flags, cmd->result, cmd->allowed));
1603
1604 stat = qla4xxx_reset_target(ha, ddb_entry);
1605 if (stat != QLA_SUCCESS) {
1606 starget_printk(KERN_INFO, scsi_target(cmd->device),
1607 "WARM TARGET RESET FAILED.\n");
1608 return FAILED;
1609 }
1610
1611 if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device),
1612 NULL)) {
1613 starget_printk(KERN_INFO, scsi_target(cmd->device),
1614 "WARM TARGET DEVICE RESET FAILED - "
1615 "waiting for commands.\n");
1616 return FAILED;
1617 }
1618
1619 /* Send marker. */
1620 if (qla4xxx_send_marker_iocb(ha, ddb_entry, cmd->device->lun,
1621 MM_TGT_WARM_RESET) != QLA_SUCCESS) {
1622 starget_printk(KERN_INFO, scsi_target(cmd->device),
1623 "WARM TARGET DEVICE RESET FAILED - "
1624 "marker iocb failed.\n");
1625 return FAILED;
1626 }
1627
1628 starget_printk(KERN_INFO, scsi_target(cmd->device),
1629 "WARM TARGET RESET SUCCEEDED.\n");
1630 return SUCCESS;
1631}
1632
1633/**
1582 * qla4xxx_eh_host_reset - kernel callback 1634 * qla4xxx_eh_host_reset - kernel callback
1583 * @cmd: Pointer to Linux's SCSI command structure 1635 * @cmd: Pointer to Linux's SCSI command structure
1584 * 1636 *