/*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2009 Emulex.  All rights reserved.                *
+ * Copyright (C) 2009-2010 Emulex.  All rights reserved.                *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  *                                                                 *
 #include "lpfc_sli.h"
 #include "lpfc_sli4.h"
 #include "lpfc_nl.h"
+#include "lpfc_bsg.h"
 #include "lpfc_disc.h"
 #include "lpfc_scsi.h"
 #include "lpfc.h"
  * This function is called when an unsolicited CT command is received.  It
  * forwards the event to any processes registerd to receive CT events.
  */
-void
+int
 lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                        struct lpfc_iocbq *piocbq)
 {
        struct lpfc_dmabuf *bdeBuf2 = piocbq->context3;
        struct lpfc_hbq_entry *hbqe;
        struct lpfc_sli_ct_request *ct_req;
+       unsigned long flags;
 
        INIT_LIST_HEAD(&head);
        list_add_tail(&head, &piocbq->list);
        if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED))
                lpfc_sli_ringpostbuf_put(phba, pring, dmabuf);
 
-       mutex_lock(&phba->ct_event_mutex);
+       spin_lock_irqsave(&phba->ct_ev_lock, flags);
        list_for_each_entry(evt, &phba->ct_ev_waiters, node) {
                if (evt->req_id != evt_req_id)
                        continue;
                        break;
                }
 
-               mutex_unlock(&phba->ct_event_mutex);
+               spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
 
                if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
                        /* take accumulated byte count from the last iocbq */
                                        "CT event data, size %d\n",
                                        evt_dat->len);
                        kfree(evt_dat);
-                       mutex_lock(&phba->ct_event_mutex);
+                       spin_lock_irqsave(&phba->ct_ev_lock, flags);
                        lpfc_ct_event_unref(evt);
-                       mutex_unlock(&phba->ct_event_mutex);
+                       spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
                        goto error_ct_unsol_exit;
                }
 
                                                iocbq);
                                        kfree(evt_dat->data);
                                        kfree(evt_dat);
-                                       mutex_lock(&phba->ct_event_mutex);
+                                       spin_lock_irqsave(&phba->ct_ev_lock,
+                                               flags);
                                        lpfc_ct_event_unref(evt);
-                                       mutex_unlock(&phba->ct_event_mutex);
+                                       spin_unlock_irqrestore(
+                                               &phba->ct_ev_lock, flags);
                                        goto error_ct_unsol_exit;
                                }
                                memcpy((char *)(evt_dat->data) + offset,
                        }
                }
 
-               mutex_lock(&phba->ct_event_mutex);
+               spin_lock_irqsave(&phba->ct_ev_lock, flags);
                if (phba->sli_rev == LPFC_SLI_REV4) {
                        evt_dat->immed_dat = phba->ctx_idx;
                        phba->ctx_idx = (phba->ctx_idx + 1) % 64;
                if (evt_req_id == SLI_CT_ELX_LOOPBACK)
                        break;
        }
-       mutex_unlock(&phba->ct_event_mutex);
+       spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
 
 error_ct_unsol_exit:
        if (!list_empty(&head))
                list_del(&head);
 
-       return;
+       return 1;
 }
 
 /**
        struct lpfc_hba *phba = vport->phba;
        struct set_ct_event *event_req;
        struct lpfc_ct_event *evt;
+       unsigned long flags;
        int rc = 0;
 
        if (job->request_len <
        event_req = (struct set_ct_event *)
                job->request->rqst_data.h_vendor.vendor_cmd;
 
-       mutex_lock(&phba->ct_event_mutex);
+       spin_lock_irqsave(&phba->ct_ev_lock, flags);
        list_for_each_entry(evt, &phba->ct_ev_waiters, node) {
                if (evt->reg_id == event_req->ev_reg_id) {
                        lpfc_ct_event_ref(evt);
                        break;
                }
        }
-       mutex_unlock(&phba->ct_event_mutex);
+       spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
 
        if (&evt->node == &phba->ct_ev_waiters) {
                /* no event waiting struct yet - first call */
                        return -ENOMEM;
                }
 
-               mutex_lock(&phba->ct_event_mutex);
+               spin_lock_irqsave(&phba->ct_ev_lock, flags);
                list_add(&evt->node, &phba->ct_ev_waiters);
                lpfc_ct_event_ref(evt);
-               mutex_unlock(&phba->ct_event_mutex);
+               spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
        }
 
        evt->waiting = 1;
        if (wait_event_interruptible(evt->wq,
                                     !list_empty(&evt->events_to_see))) {
-               mutex_lock(&phba->ct_event_mutex);
+               spin_lock_irqsave(&phba->ct_ev_lock, flags);
                lpfc_ct_event_unref(evt); /* release ref */
                lpfc_ct_event_unref(evt); /* delete */
-               mutex_unlock(&phba->ct_event_mutex);
+               spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
                rc = -EINTR;
                goto set_event_out;
        }
        evt->wait_time_stamp = jiffies;
        evt->waiting = 0;
 
-       mutex_lock(&phba->ct_event_mutex);
+       spin_lock_irqsave(&phba->ct_ev_lock, flags);
        list_move(evt->events_to_see.prev, &evt->events_to_get);
        lpfc_ct_event_unref(evt); /* release ref */
-       mutex_unlock(&phba->ct_event_mutex);
+       spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
 
 set_event_out:
        /* set_event carries no reply payload */
        struct get_ct_event_reply *event_reply;
        struct lpfc_ct_event *evt;
        struct event_data *evt_dat = NULL;
+       unsigned long flags;
        int rc = 0;
 
        if (job->request_len <
        event_reply = (struct get_ct_event_reply *)
                job->reply->reply_data.vendor_reply.vendor_rsp;
 
-       mutex_lock(&phba->ct_event_mutex);
+       spin_lock_irqsave(&phba->ct_ev_lock, flags);
        list_for_each_entry(evt, &phba->ct_ev_waiters, node) {
                if (evt->reg_id == event_req->ev_reg_id) {
                        if (list_empty(&evt->events_to_get))
                        break;
                }
        }
-       mutex_unlock(&phba->ct_event_mutex);
+       spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
 
        if (!evt_dat) {
                job->reply->reply_payload_rcv_len = 0;
        if (evt_dat)
                kfree(evt_dat->data);
        kfree(evt_dat);
-       mutex_lock(&phba->ct_event_mutex);
+       spin_lock_irqsave(&phba->ct_ev_lock, flags);
        lpfc_ct_event_unref(evt);
-       mutex_unlock(&phba->ct_event_mutex);
+       spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
 
 error_get_event_exit:
        /* make error code available to userspace */