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.c135
1 files changed, 123 insertions, 12 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 2ccad36bee9f..38b1d38afca5 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -74,6 +74,7 @@ static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc);
74 */ 74 */
75static int qla4xxx_queuecommand(struct scsi_cmnd *cmd, 75static int qla4xxx_queuecommand(struct scsi_cmnd *cmd,
76 void (*done) (struct scsi_cmnd *)); 76 void (*done) (struct scsi_cmnd *));
77static int qla4xxx_eh_abort(struct scsi_cmnd *cmd);
77static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd); 78static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd);
78static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd); 79static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd);
79static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd); 80static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd);
@@ -88,6 +89,7 @@ static struct scsi_host_template qla4xxx_driver_template = {
88 .proc_name = DRIVER_NAME, 89 .proc_name = DRIVER_NAME,
89 .queuecommand = qla4xxx_queuecommand, 90 .queuecommand = qla4xxx_queuecommand,
90 91
92 .eh_abort_handler = qla4xxx_eh_abort,
91 .eh_device_reset_handler = qla4xxx_eh_device_reset, 93 .eh_device_reset_handler = qla4xxx_eh_device_reset,
92 .eh_target_reset_handler = qla4xxx_eh_target_reset, 94 .eh_target_reset_handler = qla4xxx_eh_target_reset,
93 .eh_host_reset_handler = qla4xxx_eh_host_reset, 95 .eh_host_reset_handler = qla4xxx_eh_host_reset,
@@ -384,12 +386,12 @@ static struct srb* qla4xxx_get_new_srb(struct scsi_qla_host *ha,
384 if (!srb) 386 if (!srb)
385 return srb; 387 return srb;
386 388
387 atomic_set(&srb->ref_count, 1); 389 kref_init(&srb->srb_ref);
388 srb->ha = ha; 390 srb->ha = ha;
389 srb->ddb = ddb_entry; 391 srb->ddb = ddb_entry;
390 srb->cmd = cmd; 392 srb->cmd = cmd;
391 srb->flags = 0; 393 srb->flags = 0;
392 cmd->SCp.ptr = (void *)srb; 394 CMD_SP(cmd) = (void *)srb;
393 cmd->scsi_done = done; 395 cmd->scsi_done = done;
394 396
395 return srb; 397 return srb;
@@ -403,12 +405,14 @@ static void qla4xxx_srb_free_dma(struct scsi_qla_host *ha, struct srb *srb)
403 scsi_dma_unmap(cmd); 405 scsi_dma_unmap(cmd);
404 srb->flags &= ~SRB_DMA_VALID; 406 srb->flags &= ~SRB_DMA_VALID;
405 } 407 }
406 cmd->SCp.ptr = NULL; 408 CMD_SP(cmd) = NULL;
407} 409}
408 410
409void qla4xxx_srb_compl(struct scsi_qla_host *ha, struct srb *srb) 411void qla4xxx_srb_compl(struct kref *ref)
410{ 412{
413 struct srb *srb = container_of(ref, struct srb, srb_ref);
411 struct scsi_cmnd *cmd = srb->cmd; 414 struct scsi_cmnd *cmd = srb->cmd;
415 struct scsi_qla_host *ha = srb->ha;
412 416
413 qla4xxx_srb_free_dma(ha, srb); 417 qla4xxx_srb_free_dma(ha, srb);
414 418
@@ -685,6 +689,7 @@ static void qla4xxx_timer(struct scsi_qla_host *ha)
685 test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags) || 689 test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags) ||
686 test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || 690 test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) ||
687 test_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags) || 691 test_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags) ||
692 test_bit(DPC_LINK_CHANGED, &ha->dpc_flags) ||
688 test_bit(DPC_AEN, &ha->dpc_flags)) && 693 test_bit(DPC_AEN, &ha->dpc_flags)) &&
689 ha->dpc_thread) { 694 ha->dpc_thread) {
690 DEBUG2(printk("scsi%ld: %s: scheduling dpc routine" 695 DEBUG2(printk("scsi%ld: %s: scheduling dpc routine"
@@ -886,11 +891,10 @@ static void qla4xxx_flush_active_srbs(struct scsi_qla_host *ha)
886 srb = qla4xxx_del_from_active_array(ha, i); 891 srb = qla4xxx_del_from_active_array(ha, i);
887 if (srb != NULL) { 892 if (srb != NULL) {
888 srb->cmd->result = DID_RESET << 16; 893 srb->cmd->result = DID_RESET << 16;
889 qla4xxx_srb_compl(ha, srb); 894 kref_put(&srb->srb_ref, qla4xxx_srb_compl);
890 } 895 }
891 } 896 }
892 spin_unlock_irqrestore(&ha->hardware_lock, flags); 897 spin_unlock_irqrestore(&ha->hardware_lock, flags);
893
894} 898}
895 899
896/** 900/**
@@ -1069,6 +1073,54 @@ static void qla4xxx_do_dpc(struct work_struct *work)
1069 if (test_and_clear_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags)) 1073 if (test_and_clear_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags))
1070 qla4xxx_get_dhcp_ip_address(ha); 1074 qla4xxx_get_dhcp_ip_address(ha);
1071 1075
1076 /* ---- link change? --- */
1077 if (test_and_clear_bit(DPC_LINK_CHANGED, &ha->dpc_flags)) {
1078 if (!test_bit(AF_LINK_UP, &ha->flags)) {
1079 /* ---- link down? --- */
1080 list_for_each_entry_safe(ddb_entry, dtemp,
1081 &ha->ddb_list, list) {
1082 if (atomic_read(&ddb_entry->state) ==
1083 DDB_STATE_ONLINE)
1084 qla4xxx_mark_device_missing(ha,
1085 ddb_entry);
1086 }
1087 } else {
1088 /* ---- link up? --- *
1089 * F/W will auto login to all devices ONLY ONCE after
1090 * link up during driver initialization and runtime
1091 * fatal error recovery. Therefore, the driver must
1092 * manually relogin to devices when recovering from
1093 * connection failures, logouts, expired KATO, etc. */
1094
1095 list_for_each_entry_safe(ddb_entry, dtemp,
1096 &ha->ddb_list, list) {
1097 if ((atomic_read(&ddb_entry->state) ==
1098 DDB_STATE_MISSING) ||
1099 (atomic_read(&ddb_entry->state) ==
1100 DDB_STATE_DEAD)) {
1101 if (ddb_entry->fw_ddb_device_state ==
1102 DDB_DS_SESSION_ACTIVE) {
1103 atomic_set(&ddb_entry->state,
1104 DDB_STATE_ONLINE);
1105 dev_info(&ha->pdev->dev,
1106 "scsi%ld: %s: ddb[%d]"
1107 " os[%d] marked"
1108 " ONLINE\n",
1109 ha->host_no, __func__,
1110 ddb_entry->fw_ddb_index,
1111 ddb_entry->os_target_id);
1112
1113 iscsi_unblock_session(
1114 ddb_entry->sess);
1115 } else
1116 qla4xxx_relogin_device(
1117 ha, ddb_entry);
1118 }
1119
1120 }
1121 }
1122 }
1123
1072 /* ---- relogin device? --- */ 1124 /* ---- relogin device? --- */
1073 if (adapter_up(ha) && 1125 if (adapter_up(ha) &&
1074 test_and_clear_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags)) { 1126 test_and_clear_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags)) {
@@ -1430,12 +1482,14 @@ static void qla4xxx_slave_destroy(struct scsi_device *sdev)
1430struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha, uint32_t index) 1482struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha, uint32_t index)
1431{ 1483{
1432 struct srb *srb = NULL; 1484 struct srb *srb = NULL;
1433 struct scsi_cmnd *cmd; 1485 struct scsi_cmnd *cmd = NULL;
1434 1486
1435 if (!(cmd = scsi_host_find_tag(ha->host, index))) 1487 cmd = scsi_host_find_tag(ha->host, index);
1488 if (!cmd)
1436 return srb; 1489 return srb;
1437 1490
1438 if (!(srb = (struct srb *)cmd->host_scribble)) 1491 srb = (struct srb *)CMD_SP(cmd);
1492 if (!srb)
1439 return srb; 1493 return srb;
1440 1494
1441 /* update counters */ 1495 /* update counters */
@@ -1443,14 +1497,15 @@ struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha, uint32_t in
1443 ha->req_q_count += srb->iocb_cnt; 1497 ha->req_q_count += srb->iocb_cnt;
1444 ha->iocb_cnt -= srb->iocb_cnt; 1498 ha->iocb_cnt -= srb->iocb_cnt;
1445 if (srb->cmd) 1499 if (srb->cmd)
1446 srb->cmd->host_scribble = NULL; 1500 srb->cmd->host_scribble =
1501 (unsigned char *)(unsigned long) MAX_SRBS;
1447 } 1502 }
1448 return srb; 1503 return srb;
1449} 1504}
1450 1505
1451/** 1506/**
1452 * qla4xxx_eh_wait_on_command - waits for command to be returned by firmware 1507 * qla4xxx_eh_wait_on_command - waits for command to be returned by firmware
1453 * @ha: actual ha whose done queue will contain the comd returned by firmware. 1508 * @ha: Pointer to host adapter structure.
1454 * @cmd: Scsi Command to wait on. 1509 * @cmd: Scsi Command to wait on.
1455 * 1510 *
1456 * This routine waits for the command to be returned by the Firmware 1511 * This routine waits for the command to be returned by the Firmware
@@ -1465,7 +1520,7 @@ static int qla4xxx_eh_wait_on_command(struct scsi_qla_host *ha,
1465 1520
1466 do { 1521 do {
1467 /* Checking to see if its returned to OS */ 1522 /* Checking to see if its returned to OS */
1468 rp = (struct srb *) cmd->SCp.ptr; 1523 rp = (struct srb *) CMD_SP(cmd);
1469 if (rp == NULL) { 1524 if (rp == NULL) {
1470 done++; 1525 done++;
1471 break; 1526 break;
@@ -1534,6 +1589,62 @@ static int qla4xxx_eh_wait_for_commands(struct scsi_qla_host *ha,
1534} 1589}
1535 1590
1536/** 1591/**
1592 * qla4xxx_eh_abort - callback for abort task.
1593 * @cmd: Pointer to Linux's SCSI command structure
1594 *
1595 * This routine is called by the Linux OS to abort the specified
1596 * command.
1597 **/
1598static int qla4xxx_eh_abort(struct scsi_cmnd *cmd)
1599{
1600 struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
1601 unsigned int id = cmd->device->id;
1602 unsigned int lun = cmd->device->lun;
1603 unsigned long serial = cmd->serial_number;
1604 struct srb *srb = NULL;
1605 int ret = SUCCESS;
1606 int wait = 0;
1607
1608 dev_info(&ha->pdev->dev,
1609 "scsi%ld:%d:%d: Abort command issued cmd=%p, pid=%ld\n",
1610 ha->host_no, id, lun, cmd, serial);
1611
1612 srb = (struct srb *) CMD_SP(cmd);
1613
1614 if (!srb)
1615 return SUCCESS;
1616
1617 kref_get(&srb->srb_ref);
1618
1619 if (qla4xxx_abort_task(ha, srb) != QLA_SUCCESS) {
1620 DEBUG3(printk("scsi%ld:%d:%d: Abort_task mbx failed.\n",
1621 ha->host_no, id, lun));
1622 ret = FAILED;
1623 } else {
1624 DEBUG3(printk("scsi%ld:%d:%d: Abort_task mbx success.\n",
1625 ha->host_no, id, lun));
1626 wait = 1;
1627 }
1628
1629 kref_put(&srb->srb_ref, qla4xxx_srb_compl);
1630
1631 /* Wait for command to complete */
1632 if (wait) {
1633 if (!qla4xxx_eh_wait_on_command(ha, cmd)) {
1634 DEBUG2(printk("scsi%ld:%d:%d: Abort handler timed out\n",
1635 ha->host_no, id, lun));
1636 ret = FAILED;
1637 }
1638 }
1639
1640 dev_info(&ha->pdev->dev,
1641 "scsi%ld:%d:%d: Abort command - %s\n",
1642 ha->host_no, id, lun, (ret == SUCCESS) ? "succeded" : "failed");
1643
1644 return ret;
1645}
1646
1647/**
1537 * qla4xxx_eh_device_reset - callback for target reset. 1648 * qla4xxx_eh_device_reset - callback for target reset.
1538 * @cmd: Pointer to Linux's SCSI command structure 1649 * @cmd: Pointer to Linux's SCSI command structure
1539 * 1650 *