Fixes possible crash, caused by q2t_sess_work_fn() called on several CPUs at time...
authorvlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Tue, 3 Nov 2009 18:44:09 +0000 (18:44 +0000)
committervlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Tue, 3 Nov 2009 18:44:09 +0000 (18:44 +0000)
git-svn-id: https://scst.svn.sourceforge.net/svnroot/scst/trunk@1314 d57e44dd-8a1f-0410-8b47-8ef2f437770f

qla2x00t/qla2x00-target/qla2x00t.c
qla2x00t/qla2x00-target/qla2x00t.h

index 3c80ac8..3bddddf 100644 (file)
@@ -3173,9 +3173,10 @@ out_sched:
                prm->cmd = cmd;
 
                spin_lock_irqsave(&tgt->sess_work_lock, flags);
-               if (list_empty(&tgt->sess_works_list))
+               if (!tgt->sess_works_pending)
                        tgt->tm_to_unknown = 0;
                list_add_tail(&prm->sess_works_list_entry, &tgt->sess_works_list);
+               tgt->sess_works_pending = 1;
                spin_unlock_irqrestore(&tgt->sess_work_lock, flags);
 
                schedule_work(&tgt->sess_work);
@@ -4855,18 +4856,18 @@ static void q2t_sess_work_fn(struct work_struct *work)
                        tgt->sess_works_list.next, typeof(*prm),
                        sess_works_list_entry);
 
+               /*
+                * This work can be scheduled on several CPUs at time, so we
+                * must delete the entry to eliminate double processing
+                */
+               list_del(&prm->sess_works_list_entry);
+
                spin_unlock_irq(&tgt->sess_work_lock);
 
                rc = q2t_exec_sess_work(tgt, prm);
 
                spin_lock_irq(&tgt->sess_work_lock);
 
-               /*
-                * Prm must be in the list on the exec time to sync with
-                * tm_to_unknown clearance
-                */
-               list_del(&prm->sess_works_list_entry);
-
                if (rc != 0) {
                        PRINT_CRIT_ERROR("%s", "Unable to complete sess work");
                        q2t_free_cmd(prm->cmd);
@@ -4878,8 +4879,10 @@ static void q2t_sess_work_fn(struct work_struct *work)
 
        spin_lock_irq(&tgt->ha->hardware_lock);
        spin_lock(&tgt->sess_work_lock);
-       if (list_empty(&tgt->sess_works_list))
+       if (list_empty(&tgt->sess_works_list)) {
+               tgt->sess_works_pending = 0;
                tgt->tm_to_unknown = 0;
+       }
        spin_unlock(&tgt->sess_work_lock);
        spin_unlock_irq(&tgt->ha->hardware_lock);
 
index 0fc79a6..4ed229d 100644 (file)
@@ -129,6 +129,7 @@ struct q2t_tgt {
        unsigned int tgt_enable_64bit_addr:1;   /* 64-bits PCI addressing enabled */
        unsigned int link_reinit_iocb_pending:1;
        unsigned int tm_to_unknown:1; /* TM to unknown session was sent */
+       unsigned int sess_works_pending:1; /* there are sess_work entries */
 
        /*
         * Protected by tgt_mutex AND hardware_lock for writing and tgt_mutex