diff options
author | Salyzyn, Mark <mark_salyzyn@adaptec.com> | 2007-07-27 09:48:49 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.localdomain> | 2007-07-28 10:09:07 -0400 |
commit | b90f90d2303f27b9b241ab78419a07b41de5ac62 (patch) | |
tree | fe609680bf9030fdebe38928dc05ca9d0f553590 /drivers/scsi | |
parent | 80b1c7bdc1cc69a804f416761f5faafcb6284086 (diff) |
[SCSI] aacraid: add SCSI SYNCHONIZE_CACHE range checking
Customer running an application that issues SYNCHRONIZE_CACHE calls
directly noticed the broad stroke of the current implementation in the
aacraid driver resulting in multiple applications feeding I/O to the
storage causing the issuing application to stall for long periods of
time. By only waiting for the current WRITE commands, rather than all
commands, to complete; and those that are in range of the
SYNCHRONIZE_CACHE call that would associate more tightly with the
issuing application before telling the Firmware to flush it's dirty
cache, we managed to reduce the stalling. The Firmware itself still
flushes all the dirty cache associated with the array ignoring the
range, it just does so in a more timely manner.
Signed-off-by: Mark Salyzyn <aacraid@adaptec.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/aacraid/aachba.c | 63 |
1 files changed, 55 insertions, 8 deletions
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 54cdfcc929ae..6800e578e4b1 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c | |||
@@ -1688,23 +1688,23 @@ static void synchronize_callback(void *context, struct fib *fibptr) | |||
1688 | if (!aac_valid_context(cmd, fibptr)) | 1688 | if (!aac_valid_context(cmd, fibptr)) |
1689 | return; | 1689 | return; |
1690 | 1690 | ||
1691 | dprintk((KERN_DEBUG "synchronize_callback[cpu %d]: t = %ld.\n", | 1691 | dprintk((KERN_DEBUG "synchronize_callback[cpu %d]: t = %ld.\n", |
1692 | smp_processor_id(), jiffies)); | 1692 | smp_processor_id(), jiffies)); |
1693 | BUG_ON(fibptr == NULL); | 1693 | BUG_ON(fibptr == NULL); |
1694 | 1694 | ||
1695 | 1695 | ||
1696 | synchronizereply = fib_data(fibptr); | 1696 | synchronizereply = fib_data(fibptr); |
1697 | if (le32_to_cpu(synchronizereply->status) == CT_OK) | 1697 | if (le32_to_cpu(synchronizereply->status) == CT_OK) |
1698 | cmd->result = DID_OK << 16 | | 1698 | cmd->result = DID_OK << 16 | |
1699 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | 1699 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; |
1700 | else { | 1700 | else { |
1701 | struct scsi_device *sdev = cmd->device; | 1701 | struct scsi_device *sdev = cmd->device; |
1702 | struct aac_dev *dev = fibptr->dev; | 1702 | struct aac_dev *dev = fibptr->dev; |
1703 | u32 cid = sdev_id(sdev); | 1703 | u32 cid = sdev_id(sdev); |
1704 | printk(KERN_WARNING | 1704 | printk(KERN_WARNING |
1705 | "synchronize_callback: synchronize failed, status = %d\n", | 1705 | "synchronize_callback: synchronize failed, status = %d\n", |
1706 | le32_to_cpu(synchronizereply->status)); | 1706 | le32_to_cpu(synchronizereply->status)); |
1707 | cmd->result = DID_OK << 16 | | 1707 | cmd->result = DID_OK << 16 | |
1708 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION; | 1708 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION; |
1709 | set_sense((u8 *)&dev->fsa_dev[cid].sense_data, | 1709 | set_sense((u8 *)&dev->fsa_dev[cid].sense_data, |
1710 | HARDWARE_ERROR, | 1710 | HARDWARE_ERROR, |
@@ -1712,7 +1712,7 @@ static void synchronize_callback(void *context, struct fib *fibptr) | |||
1712 | ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0, | 1712 | ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0, |
1713 | 0, 0); | 1713 | 0, 0); |
1714 | memcpy(cmd->sense_buffer, &dev->fsa_dev[cid].sense_data, | 1714 | memcpy(cmd->sense_buffer, &dev->fsa_dev[cid].sense_data, |
1715 | min(sizeof(dev->fsa_dev[cid].sense_data), | 1715 | min(sizeof(dev->fsa_dev[cid].sense_data), |
1716 | sizeof(cmd->sense_buffer))); | 1716 | sizeof(cmd->sense_buffer))); |
1717 | } | 1717 | } |
1718 | 1718 | ||
@@ -1730,6 +1730,9 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd) | |||
1730 | struct scsi_device *sdev = scsicmd->device; | 1730 | struct scsi_device *sdev = scsicmd->device; |
1731 | int active = 0; | 1731 | int active = 0; |
1732 | struct aac_dev *aac; | 1732 | struct aac_dev *aac; |
1733 | u64 lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | | ||
1734 | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; | ||
1735 | u32 count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8]; | ||
1733 | unsigned long flags; | 1736 | unsigned long flags; |
1734 | 1737 | ||
1735 | /* | 1738 | /* |
@@ -1738,7 +1741,51 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd) | |||
1738 | */ | 1741 | */ |
1739 | spin_lock_irqsave(&sdev->list_lock, flags); | 1742 | spin_lock_irqsave(&sdev->list_lock, flags); |
1740 | list_for_each_entry(cmd, &sdev->cmd_list, list) | 1743 | list_for_each_entry(cmd, &sdev->cmd_list, list) |
1741 | if (cmd != scsicmd && cmd->SCp.phase == AAC_OWNER_FIRMWARE) { | 1744 | if (cmd->SCp.phase == AAC_OWNER_FIRMWARE) { |
1745 | u64 cmnd_lba; | ||
1746 | u32 cmnd_count; | ||
1747 | |||
1748 | if (cmd->cmnd[0] == WRITE_6) { | ||
1749 | cmnd_lba = ((cmd->cmnd[1] & 0x1F) << 16) | | ||
1750 | (cmd->cmnd[2] << 8) | | ||
1751 | cmd->cmnd[3]; | ||
1752 | cmnd_count = cmd->cmnd[4]; | ||
1753 | if (cmnd_count == 0) | ||
1754 | cmnd_count = 256; | ||
1755 | } else if (cmd->cmnd[0] == WRITE_16) { | ||
1756 | cmnd_lba = ((u64)cmd->cmnd[2] << 56) | | ||
1757 | ((u64)cmd->cmnd[3] << 48) | | ||
1758 | ((u64)cmd->cmnd[4] << 40) | | ||
1759 | ((u64)cmd->cmnd[5] << 32) | | ||
1760 | ((u64)cmd->cmnd[6] << 24) | | ||
1761 | (cmd->cmnd[7] << 16) | | ||
1762 | (cmd->cmnd[8] << 8) | | ||
1763 | cmd->cmnd[9]; | ||
1764 | cmnd_count = (cmd->cmnd[10] << 24) | | ||
1765 | (cmd->cmnd[11] << 16) | | ||
1766 | (cmd->cmnd[12] << 8) | | ||
1767 | cmd->cmnd[13]; | ||
1768 | } else if (cmd->cmnd[0] == WRITE_12) { | ||
1769 | cmnd_lba = ((u64)cmd->cmnd[2] << 24) | | ||
1770 | (cmd->cmnd[3] << 16) | | ||
1771 | (cmd->cmnd[4] << 8) | | ||
1772 | cmd->cmnd[5]; | ||
1773 | cmnd_count = (cmd->cmnd[6] << 24) | | ||
1774 | (cmd->cmnd[7] << 16) | | ||
1775 | (cmd->cmnd[8] << 8) | | ||
1776 | cmd->cmnd[9]; | ||
1777 | } else if (cmd->cmnd[0] == WRITE_10) { | ||
1778 | cmnd_lba = ((u64)cmd->cmnd[2] << 24) | | ||
1779 | (cmd->cmnd[3] << 16) | | ||
1780 | (cmd->cmnd[4] << 8) | | ||
1781 | cmd->cmnd[5]; | ||
1782 | cmnd_count = (cmd->cmnd[7] << 8) | | ||
1783 | cmd->cmnd[8]; | ||
1784 | } else | ||
1785 | continue; | ||
1786 | if (((cmnd_lba + cmnd_count) < lba) || | ||
1787 | (count && ((lba + count) < cmnd_lba))) | ||
1788 | continue; | ||
1742 | ++active; | 1789 | ++active; |
1743 | break; | 1790 | break; |
1744 | } | 1791 | } |
@@ -1767,7 +1814,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd) | |||
1767 | synchronizecmd->command = cpu_to_le32(VM_ContainerConfig); | 1814 | synchronizecmd->command = cpu_to_le32(VM_ContainerConfig); |
1768 | synchronizecmd->type = cpu_to_le32(CT_FLUSH_CACHE); | 1815 | synchronizecmd->type = cpu_to_le32(CT_FLUSH_CACHE); |
1769 | synchronizecmd->cid = cpu_to_le32(scmd_id(scsicmd)); | 1816 | synchronizecmd->cid = cpu_to_le32(scmd_id(scsicmd)); |
1770 | synchronizecmd->count = | 1817 | synchronizecmd->count = |
1771 | cpu_to_le32(sizeof(((struct aac_synchronize_reply *)NULL)->data)); | 1818 | cpu_to_le32(sizeof(((struct aac_synchronize_reply *)NULL)->data)); |
1772 | 1819 | ||
1773 | /* | 1820 | /* |
@@ -1789,7 +1836,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd) | |||
1789 | return 0; | 1836 | return 0; |
1790 | } | 1837 | } |
1791 | 1838 | ||
1792 | printk(KERN_WARNING | 1839 | printk(KERN_WARNING |
1793 | "aac_synchronize: aac_fib_send failed with status: %d.\n", status); | 1840 | "aac_synchronize: aac_fib_send failed with status: %d.\n", status); |
1794 | aac_fib_complete(cmd_fibcontext); | 1841 | aac_fib_complete(cmd_fibcontext); |
1795 | aac_fib_free(cmd_fibcontext); | 1842 | aac_fib_free(cmd_fibcontext); |