aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/aacraid/commsup.c100
1 files changed, 81 insertions, 19 deletions
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index a1d303f03480..3741be2f4bfa 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -805,7 +805,6 @@ int aac_command_thread(struct aac_dev * dev)
805{ 805{
806 struct hw_fib *hw_fib, *hw_newfib; 806 struct hw_fib *hw_fib, *hw_newfib;
807 struct fib *fib, *newfib; 807 struct fib *fib, *newfib;
808 struct aac_queue_block *queues = dev->queues;
809 struct aac_fib_context *fibctx; 808 struct aac_fib_context *fibctx;
810 unsigned long flags; 809 unsigned long flags;
811 DECLARE_WAITQUEUE(wait, current); 810 DECLARE_WAITQUEUE(wait, current);
@@ -825,21 +824,22 @@ int aac_command_thread(struct aac_dev * dev)
825 * Let the DPC know it has a place to send the AIF's to. 824 * Let the DPC know it has a place to send the AIF's to.
826 */ 825 */
827 dev->aif_thread = 1; 826 dev->aif_thread = 1;
828 add_wait_queue(&queues->queue[HostNormCmdQueue].cmdready, &wait); 827 add_wait_queue(&dev->queues->queue[HostNormCmdQueue].cmdready, &wait);
829 set_current_state(TASK_INTERRUPTIBLE); 828 set_current_state(TASK_INTERRUPTIBLE);
829 dprintk ((KERN_INFO "aac_command_thread start\n"));
830 while(1) 830 while(1)
831 { 831 {
832 spin_lock_irqsave(queues->queue[HostNormCmdQueue].lock, flags); 832 spin_lock_irqsave(dev->queues->queue[HostNormCmdQueue].lock, flags);
833 while(!list_empty(&(queues->queue[HostNormCmdQueue].cmdq))) { 833 while(!list_empty(&(dev->queues->queue[HostNormCmdQueue].cmdq))) {
834 struct list_head *entry; 834 struct list_head *entry;
835 struct aac_aifcmd * aifcmd; 835 struct aac_aifcmd * aifcmd;
836 836
837 set_current_state(TASK_RUNNING); 837 set_current_state(TASK_RUNNING);
838 838
839 entry = queues->queue[HostNormCmdQueue].cmdq.next; 839 entry = dev->queues->queue[HostNormCmdQueue].cmdq.next;
840 list_del(entry); 840 list_del(entry);
841 841
842 spin_unlock_irqrestore(queues->queue[HostNormCmdQueue].lock, flags); 842 spin_unlock_irqrestore(dev->queues->queue[HostNormCmdQueue].lock, flags);
843 fib = list_entry(entry, struct fib, fiblink); 843 fib = list_entry(entry, struct fib, fiblink);
844 /* 844 /*
845 * We will process the FIB here or pass it to a 845 * We will process the FIB here or pass it to a
@@ -869,9 +869,54 @@ int aac_command_thread(struct aac_dev * dev)
869 869
870 u32 time_now, time_last; 870 u32 time_now, time_last;
871 unsigned long flagv; 871 unsigned long flagv;
872 unsigned num;
873 struct hw_fib ** hw_fib_pool, ** hw_fib_p;
874 struct fib ** fib_pool, ** fib_p;
872 875
873 time_now = jiffies/HZ; 876 time_now = jiffies/HZ;
874 877
878 /*
879 * Warning: no sleep allowed while
880 * holding spinlock. We take the estimate
881 * and pre-allocate a set of fibs outside the
882 * lock.
883 */
884 num = le32_to_cpu(dev->init->AdapterFibsSize)
885 / sizeof(struct hw_fib); /* some extra */
886 spin_lock_irqsave(&dev->fib_lock, flagv);
887 entry = dev->fib_list.next;
888 while (entry != &dev->fib_list) {
889 entry = entry->next;
890 ++num;
891 }
892 spin_unlock_irqrestore(&dev->fib_lock, flagv);
893 hw_fib_pool = NULL;
894 fib_pool = NULL;
895 if (num
896 && ((hw_fib_pool = kmalloc(sizeof(struct hw_fib *) * num, GFP_KERNEL)))
897 && ((fib_pool = kmalloc(sizeof(struct fib *) * num, GFP_KERNEL)))) {
898 hw_fib_p = hw_fib_pool;
899 fib_p = fib_pool;
900 while (hw_fib_p < &hw_fib_pool[num]) {
901 if (!(*(hw_fib_p++) = kmalloc(sizeof(struct hw_fib), GFP_KERNEL))) {
902 --hw_fib_p;
903 break;
904 }
905 if (!(*(fib_p++) = kmalloc(sizeof(struct fib), GFP_KERNEL))) {
906 kfree(*(--hw_fib_p));
907 break;
908 }
909 }
910 if ((num = hw_fib_p - hw_fib_pool) == 0) {
911 kfree(fib_pool);
912 fib_pool = NULL;
913 kfree(hw_fib_pool);
914 hw_fib_pool = NULL;
915 }
916 } else if (hw_fib_pool) {
917 kfree(hw_fib_pool);
918 hw_fib_pool = NULL;
919 }
875 spin_lock_irqsave(&dev->fib_lock, flagv); 920 spin_lock_irqsave(&dev->fib_lock, flagv);
876 entry = dev->fib_list.next; 921 entry = dev->fib_list.next;
877 /* 922 /*
@@ -880,6 +925,8 @@ int aac_command_thread(struct aac_dev * dev)
880 * fib, and then set the event to wake up the 925 * fib, and then set the event to wake up the
881 * thread that is waiting for it. 926 * thread that is waiting for it.
882 */ 927 */
928 hw_fib_p = hw_fib_pool;
929 fib_p = fib_pool;
883 while (entry != &dev->fib_list) { 930 while (entry != &dev->fib_list) {
884 /* 931 /*
885 * Extract the fibctx 932 * Extract the fibctx
@@ -912,9 +959,11 @@ int aac_command_thread(struct aac_dev * dev)
912 * Warning: no sleep allowed while 959 * Warning: no sleep allowed while
913 * holding spinlock 960 * holding spinlock
914 */ 961 */
915 hw_newfib = kmalloc(sizeof(struct hw_fib), GFP_ATOMIC); 962 if (hw_fib_p < &hw_fib_pool[num]) {
916 newfib = kmalloc(sizeof(struct fib), GFP_ATOMIC); 963 hw_newfib = *hw_fib_p;
917 if (newfib && hw_newfib) { 964 *(hw_fib_p++) = NULL;
965 newfib = *fib_p;
966 *(fib_p++) = NULL;
918 /* 967 /*
919 * Make the copy of the FIB 968 * Make the copy of the FIB
920 */ 969 */
@@ -929,15 +978,11 @@ int aac_command_thread(struct aac_dev * dev)
929 fibctx->count++; 978 fibctx->count++;
930 /* 979 /*
931 * Set the event to wake up the 980 * Set the event to wake up the
932 * thread that will waiting. 981 * thread that is waiting.
933 */ 982 */
934 up(&fibctx->wait_sem); 983 up(&fibctx->wait_sem);
935 } else { 984 } else {
936 printk(KERN_WARNING "aifd: didn't allocate NewFib.\n"); 985 printk(KERN_WARNING "aifd: didn't allocate NewFib.\n");
937 if(newfib)
938 kfree(newfib);
939 if(hw_newfib)
940 kfree(hw_newfib);
941 } 986 }
942 entry = entry->next; 987 entry = entry->next;
943 } 988 }
@@ -947,21 +992,38 @@ int aac_command_thread(struct aac_dev * dev)
947 *(__le32 *)hw_fib->data = cpu_to_le32(ST_OK); 992 *(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
948 fib_adapter_complete(fib, sizeof(u32)); 993 fib_adapter_complete(fib, sizeof(u32));
949 spin_unlock_irqrestore(&dev->fib_lock, flagv); 994 spin_unlock_irqrestore(&dev->fib_lock, flagv);
995 /* Free up the remaining resources */
996 hw_fib_p = hw_fib_pool;
997 fib_p = fib_pool;
998 while (hw_fib_p < &hw_fib_pool[num]) {
999 if (*hw_fib_p)
1000 kfree(*hw_fib_p);
1001 if (*fib_p)
1002 kfree(*fib_p);
1003 ++fib_p;
1004 ++hw_fib_p;
1005 }
1006 if (hw_fib_pool)
1007 kfree(hw_fib_pool);
1008 if (fib_pool)
1009 kfree(fib_pool);
950 } 1010 }
951 spin_lock_irqsave(queues->queue[HostNormCmdQueue].lock, flags);
952 kfree(fib); 1011 kfree(fib);
1012 spin_lock_irqsave(dev->queues->queue[HostNormCmdQueue].lock, flags);
953 } 1013 }
954 /* 1014 /*
955 * There are no more AIF's 1015 * There are no more AIF's
956 */ 1016 */
957 spin_unlock_irqrestore(queues->queue[HostNormCmdQueue].lock, flags); 1017 spin_unlock_irqrestore(dev->queues->queue[HostNormCmdQueue].lock, flags);
958 schedule(); 1018 schedule();
959 1019
960 if(signal_pending(current)) 1020 if(signal_pending(current))
961 break; 1021 break;
962 set_current_state(TASK_INTERRUPTIBLE); 1022 set_current_state(TASK_INTERRUPTIBLE);
963 } 1023 }
964 remove_wait_queue(&queues->queue[HostNormCmdQueue].cmdready, &wait); 1024 if (dev->queues)
1025 remove_wait_queue(&dev->queues->queue[HostNormCmdQueue].cmdready, &wait);
965 dev->aif_thread = 0; 1026 dev->aif_thread = 0;
966 complete_and_exit(&dev->aif_completion, 0); 1027 complete_and_exit(&dev->aif_completion, 0);
1028 return 0;
967} 1029}