diff options
author | bo yang <bo.yang@lsi.com> | 2007-11-09 04:35:44 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-01-11 19:22:43 -0500 |
commit | 7343eb6570ae3b299e7b5185b139d8335ef60e9b (patch) | |
tree | 1d2c354b15e7ad00618fcc1c03404125f0aca9e0 /drivers/scsi/megaraid/megaraid_sas.c | |
parent | b10c36a57552f03582c0ab3ece04f3cce791922d (diff) |
[SCSI] megaraid_sas: call cmd completion from reset
Driver will call cmd completion routine from Reset path without waiting for cmd completion from isr context.
Signed-off-by: Bo Yang <bo.yang@lsi.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/megaraid/megaraid_sas.c')
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas.c | 122 |
1 files changed, 68 insertions, 54 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index a58ad61aa36a..08c3d4315eb8 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c | |||
@@ -77,6 +77,10 @@ static DEFINE_MUTEX(megasas_async_queue_mutex); | |||
77 | 77 | ||
78 | static u32 megasas_dbg_lvl; | 78 | static u32 megasas_dbg_lvl; |
79 | 79 | ||
80 | static void | ||
81 | megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, | ||
82 | u8 alt_status); | ||
83 | |||
80 | /** | 84 | /** |
81 | * megasas_get_cmd - Get a command from the free pool | 85 | * megasas_get_cmd - Get a command from the free pool |
82 | * @instance: Adapter soft state | 86 | * @instance: Adapter soft state |
@@ -887,6 +891,64 @@ static int megasas_slave_configure(struct scsi_device *sdev) | |||
887 | } | 891 | } |
888 | 892 | ||
889 | /** | 893 | /** |
894 | * megasas_complete_cmd_dpc - Returns FW's controller structure | ||
895 | * @instance_addr: Address of adapter soft state | ||
896 | * | ||
897 | * Tasklet to complete cmds | ||
898 | */ | ||
899 | static void megasas_complete_cmd_dpc(unsigned long instance_addr) | ||
900 | { | ||
901 | u32 producer; | ||
902 | u32 consumer; | ||
903 | u32 context; | ||
904 | struct megasas_cmd *cmd; | ||
905 | struct megasas_instance *instance = | ||
906 | (struct megasas_instance *)instance_addr; | ||
907 | unsigned long flags; | ||
908 | |||
909 | /* If we have already declared adapter dead, donot complete cmds */ | ||
910 | if (instance->hw_crit_error) | ||
911 | return; | ||
912 | |||
913 | spin_lock_irqsave(&instance->completion_lock, flags); | ||
914 | |||
915 | producer = *instance->producer; | ||
916 | consumer = *instance->consumer; | ||
917 | |||
918 | while (consumer != producer) { | ||
919 | context = instance->reply_queue[consumer]; | ||
920 | |||
921 | cmd = instance->cmd_list[context]; | ||
922 | |||
923 | megasas_complete_cmd(instance, cmd, DID_OK); | ||
924 | |||
925 | consumer++; | ||
926 | if (consumer == (instance->max_fw_cmds + 1)) { | ||
927 | consumer = 0; | ||
928 | } | ||
929 | } | ||
930 | |||
931 | *instance->consumer = producer; | ||
932 | |||
933 | spin_unlock_irqrestore(&instance->completion_lock, flags); | ||
934 | |||
935 | /* | ||
936 | * Check if we can restore can_queue | ||
937 | */ | ||
938 | if (instance->flag & MEGASAS_FW_BUSY | ||
939 | && time_after(jiffies, instance->last_time + 5 * HZ) | ||
940 | && atomic_read(&instance->fw_outstanding) < 17) { | ||
941 | |||
942 | spin_lock_irqsave(instance->host->host_lock, flags); | ||
943 | instance->flag &= ~MEGASAS_FW_BUSY; | ||
944 | instance->host->can_queue = | ||
945 | instance->max_fw_cmds - MEGASAS_INT_CMDS; | ||
946 | |||
947 | spin_unlock_irqrestore(instance->host->host_lock, flags); | ||
948 | } | ||
949 | } | ||
950 | |||
951 | /** | ||
890 | * megasas_wait_for_outstanding - Wait for all outstanding cmds | 952 | * megasas_wait_for_outstanding - Wait for all outstanding cmds |
891 | * @instance: Adapter soft state | 953 | * @instance: Adapter soft state |
892 | * | 954 | * |
@@ -909,6 +971,11 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance) | |||
909 | if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) { | 971 | if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) { |
910 | printk(KERN_NOTICE "megasas: [%2d]waiting for %d " | 972 | printk(KERN_NOTICE "megasas: [%2d]waiting for %d " |
911 | "commands to complete\n",i,outstanding); | 973 | "commands to complete\n",i,outstanding); |
974 | /* | ||
975 | * Call cmd completion routine. Cmd to be | ||
976 | * be completed directly without depending on isr. | ||
977 | */ | ||
978 | megasas_complete_cmd_dpc((unsigned long)instance); | ||
912 | } | 979 | } |
913 | 980 | ||
914 | msleep(1000); | 981 | msleep(1000); |
@@ -1750,60 +1817,6 @@ megasas_get_ctrl_info(struct megasas_instance *instance, | |||
1750 | } | 1817 | } |
1751 | 1818 | ||
1752 | /** | 1819 | /** |
1753 | * megasas_complete_cmd_dpc - Returns FW's controller structure | ||
1754 | * @instance_addr: Address of adapter soft state | ||
1755 | * | ||
1756 | * Tasklet to complete cmds | ||
1757 | */ | ||
1758 | static void megasas_complete_cmd_dpc(unsigned long instance_addr) | ||
1759 | { | ||
1760 | u32 producer; | ||
1761 | u32 consumer; | ||
1762 | u32 context; | ||
1763 | struct megasas_cmd *cmd; | ||
1764 | struct megasas_instance *instance = (struct megasas_instance *)instance_addr; | ||
1765 | unsigned long flags; | ||
1766 | |||
1767 | /* If we have already declared adapter dead, donot complete cmds */ | ||
1768 | if (instance->hw_crit_error) | ||
1769 | return; | ||
1770 | |||
1771 | producer = *instance->producer; | ||
1772 | consumer = *instance->consumer; | ||
1773 | |||
1774 | while (consumer != producer) { | ||
1775 | context = instance->reply_queue[consumer]; | ||
1776 | |||
1777 | cmd = instance->cmd_list[context]; | ||
1778 | |||
1779 | megasas_complete_cmd(instance, cmd, DID_OK); | ||
1780 | |||
1781 | consumer++; | ||
1782 | if (consumer == (instance->max_fw_cmds + 1)) { | ||
1783 | consumer = 0; | ||
1784 | } | ||
1785 | } | ||
1786 | |||
1787 | *instance->consumer = producer; | ||
1788 | |||
1789 | /* | ||
1790 | * Check if we can restore can_queue | ||
1791 | */ | ||
1792 | if (instance->flag & MEGASAS_FW_BUSY | ||
1793 | && time_after(jiffies, instance->last_time + 5 * HZ) | ||
1794 | && atomic_read(&instance->fw_outstanding) < 17) { | ||
1795 | |||
1796 | spin_lock_irqsave(instance->host->host_lock, flags); | ||
1797 | instance->flag &= ~MEGASAS_FW_BUSY; | ||
1798 | instance->host->can_queue = | ||
1799 | instance->max_fw_cmds - MEGASAS_INT_CMDS; | ||
1800 | |||
1801 | spin_unlock_irqrestore(instance->host->host_lock, flags); | ||
1802 | } | ||
1803 | |||
1804 | } | ||
1805 | |||
1806 | /** | ||
1807 | * megasas_issue_init_mfi - Initializes the FW | 1820 | * megasas_issue_init_mfi - Initializes the FW |
1808 | * @instance: Adapter soft state | 1821 | * @instance: Adapter soft state |
1809 | * | 1822 | * |
@@ -2395,6 +2408,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2395 | init_waitqueue_head(&instance->abort_cmd_wait_q); | 2408 | init_waitqueue_head(&instance->abort_cmd_wait_q); |
2396 | 2409 | ||
2397 | spin_lock_init(&instance->cmd_pool_lock); | 2410 | spin_lock_init(&instance->cmd_pool_lock); |
2411 | spin_lock_init(&instance->completion_lock); | ||
2398 | 2412 | ||
2399 | mutex_init(&instance->aen_mutex); | 2413 | mutex_init(&instance->aen_mutex); |
2400 | sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS); | 2414 | sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS); |