aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/cciss_scsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block/cciss_scsi.c')
-rw-r--r--drivers/block/cciss_scsi.c109
1 files changed, 83 insertions, 26 deletions
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index a3fd87b41444..3315268b4ec7 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -44,20 +44,13 @@
44#define CCISS_ABORT_MSG 0x00 44#define CCISS_ABORT_MSG 0x00
45#define CCISS_RESET_MSG 0x01 45#define CCISS_RESET_MSG 0x01
46 46
47/* some prototypes... */ 47static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff,
48static int sendcmd( 48 size_t size,
49 __u8 cmd, 49 __u8 page_code, unsigned char *scsi3addr,
50 int ctlr,
51 void *buff,
52 size_t size,
53 unsigned int use_unit_num, /* 0: address the controller,
54 1: address logical volume log_unit,
55 2: address is in scsi3addr */
56 unsigned int log_unit,
57 __u8 page_code,
58 unsigned char *scsi3addr,
59 int cmd_type); 50 int cmd_type);
60 51
52static CommandList_struct *cmd_alloc(ctlr_info_t *h, int get_from_pool);
53static void cmd_free(ctlr_info_t *h, CommandList_struct *c, int got_from_pool);
61 54
62static int cciss_scsi_proc_info( 55static int cciss_scsi_proc_info(
63 struct Scsi_Host *sh, 56 struct Scsi_Host *sh,
@@ -1575,6 +1568,75 @@ cciss_seq_tape_report(struct seq_file *seq, int ctlr)
1575 CPQ_TAPE_UNLOCK(ctlr, flags); 1568 CPQ_TAPE_UNLOCK(ctlr, flags);
1576} 1569}
1577 1570
1571static int wait_for_device_to_become_ready(ctlr_info_t *h,
1572 unsigned char lunaddr[])
1573{
1574 int rc;
1575 int count = 0;
1576 int waittime = HZ;
1577 CommandList_struct *c;
1578
1579 c = cmd_alloc(h, 1);
1580 if (!c) {
1581 printk(KERN_WARNING "cciss%d: out of memory in "
1582 "wait_for_device_to_become_ready.\n", h->ctlr);
1583 return IO_ERROR;
1584 }
1585
1586 /* Send test unit ready until device ready, or give up. */
1587 while (count < 20) {
1588
1589 /* Wait for a bit. do this first, because if we send
1590 * the TUR right away, the reset will just abort it.
1591 */
1592 schedule_timeout_uninterruptible(waittime);
1593 count++;
1594
1595 /* Increase wait time with each try, up to a point. */
1596 if (waittime < (HZ * 30))
1597 waittime = waittime * 2;
1598
1599 /* Send the Test Unit Ready */
1600 rc = fill_cmd(c, TEST_UNIT_READY, h->ctlr, NULL, 0, 0,
1601 lunaddr, TYPE_CMD);
1602 if (rc == 0)
1603 rc = sendcmd_withirq_core(h, c, 0);
1604
1605 (void) process_sendcmd_error(h, c);
1606
1607 if (rc != 0)
1608 goto retry_tur;
1609
1610 if (c->err_info->CommandStatus == CMD_SUCCESS)
1611 break;
1612
1613 if (c->err_info->CommandStatus == CMD_TARGET_STATUS &&
1614 c->err_info->ScsiStatus == SAM_STAT_CHECK_CONDITION) {
1615 if (c->err_info->SenseInfo[2] == NO_SENSE)
1616 break;
1617 if (c->err_info->SenseInfo[2] == UNIT_ATTENTION) {
1618 unsigned char asc;
1619 asc = c->err_info->SenseInfo[12];
1620 check_for_unit_attention(h, c);
1621 if (asc == POWER_OR_RESET)
1622 break;
1623 }
1624 }
1625retry_tur:
1626 printk(KERN_WARNING "cciss%d: Waiting %d secs "
1627 "for device to become ready.\n",
1628 h->ctlr, waittime / HZ);
1629 rc = 1; /* device not ready. */
1630 }
1631
1632 if (rc)
1633 printk("cciss%d: giving up on device.\n", h->ctlr);
1634 else
1635 printk(KERN_WARNING "cciss%d: device is ready.\n", h->ctlr);
1636
1637 cmd_free(h, c, 1);
1638 return rc;
1639}
1578 1640
1579/* Need at least one of these error handlers to keep ../scsi/hosts.c from 1641/* Need at least one of these error handlers to keep ../scsi/hosts.c from
1580 * complaining. Doing a host- or bus-reset can't do anything good here. 1642 * complaining. Doing a host- or bus-reset can't do anything good here.
@@ -1591,6 +1653,7 @@ static int cciss_eh_device_reset_handler(struct scsi_cmnd *scsicmd)
1591{ 1653{
1592 int rc; 1654 int rc;
1593 CommandList_struct *cmd_in_trouble; 1655 CommandList_struct *cmd_in_trouble;
1656 unsigned char lunaddr[8];
1594 ctlr_info_t **c; 1657 ctlr_info_t **c;
1595 int ctlr; 1658 int ctlr;
1596 1659
@@ -1600,19 +1663,15 @@ static int cciss_eh_device_reset_handler(struct scsi_cmnd *scsicmd)
1600 return FAILED; 1663 return FAILED;
1601 ctlr = (*c)->ctlr; 1664 ctlr = (*c)->ctlr;
1602 printk(KERN_WARNING "cciss%d: resetting tape drive or medium changer.\n", ctlr); 1665 printk(KERN_WARNING "cciss%d: resetting tape drive or medium changer.\n", ctlr);
1603
1604 /* find the command that's giving us trouble */ 1666 /* find the command that's giving us trouble */
1605 cmd_in_trouble = (CommandList_struct *) scsicmd->host_scribble; 1667 cmd_in_trouble = (CommandList_struct *) scsicmd->host_scribble;
1606 if (cmd_in_trouble == NULL) { /* paranoia */ 1668 if (cmd_in_trouble == NULL) /* paranoia */
1607 return FAILED; 1669 return FAILED;
1608 } 1670 memcpy(lunaddr, &cmd_in_trouble->Header.LUN.LunAddrBytes[0], 8);
1609 /* send a reset to the SCSI LUN which the command was sent to */ 1671 /* send a reset to the SCSI LUN which the command was sent to */
1610 rc = sendcmd(CCISS_RESET_MSG, ctlr, NULL, 0, 2, 0, 0, 1672 rc = sendcmd_withirq(CCISS_RESET_MSG, ctlr, NULL, 0, 0, lunaddr,
1611 (unsigned char *) &cmd_in_trouble->Header.LUN.LunAddrBytes[0],
1612 TYPE_MSG); 1673 TYPE_MSG);
1613 /* sendcmd turned off interrupts on the board, turn 'em back on. */ 1674 if (rc == 0 && wait_for_device_to_become_ready(*c, lunaddr) == 0)
1614 (*c)->access.set_intr_mask(*c, CCISS_INTR_ON);
1615 if (rc == 0)
1616 return SUCCESS; 1675 return SUCCESS;
1617 printk(KERN_WARNING "cciss%d: resetting device failed.\n", ctlr); 1676 printk(KERN_WARNING "cciss%d: resetting device failed.\n", ctlr);
1618 return FAILED; 1677 return FAILED;
@@ -1622,6 +1681,7 @@ static int cciss_eh_abort_handler(struct scsi_cmnd *scsicmd)
1622{ 1681{
1623 int rc; 1682 int rc;
1624 CommandList_struct *cmd_to_abort; 1683 CommandList_struct *cmd_to_abort;
1684 unsigned char lunaddr[8];
1625 ctlr_info_t **c; 1685 ctlr_info_t **c;
1626 int ctlr; 1686 int ctlr;
1627 1687
@@ -1636,12 +1696,9 @@ static int cciss_eh_abort_handler(struct scsi_cmnd *scsicmd)
1636 cmd_to_abort = (CommandList_struct *) scsicmd->host_scribble; 1696 cmd_to_abort = (CommandList_struct *) scsicmd->host_scribble;
1637 if (cmd_to_abort == NULL) /* paranoia */ 1697 if (cmd_to_abort == NULL) /* paranoia */
1638 return FAILED; 1698 return FAILED;
1639 rc = sendcmd(CCISS_ABORT_MSG, ctlr, &cmd_to_abort->Header.Tag, 1699 memcpy(lunaddr, &cmd_to_abort->Header.LUN.LunAddrBytes[0], 8);
1640 0, 2, 0, 0, 1700 rc = sendcmd_withirq(CCISS_ABORT_MSG, ctlr, &cmd_to_abort->Header.Tag,
1641 (unsigned char *) &cmd_to_abort->Header.LUN.LunAddrBytes[0], 1701 0, 0, lunaddr, TYPE_MSG);
1642 TYPE_MSG);
1643 /* sendcmd turned off interrupts on the board, turn 'em back on. */
1644 (*c)->access.set_intr_mask(*c, CCISS_INTR_ON);
1645 if (rc == 0) 1702 if (rc == 0)
1646 return SUCCESS; 1703 return SUCCESS;
1647 return FAILED; 1704 return FAILED;