Fix common misspellings
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / scsi / libfc / fc_exch.c
index d21367d3305fd6de6bd68f0505618ff97b6b927b..77035a746f6027e5f232140349e7339c5901f2e9 100644 (file)
@@ -38,7 +38,7 @@ u16   fc_cpu_mask;            /* cpu mask for possible cpus */
 EXPORT_SYMBOL(fc_cpu_mask);
 static u16     fc_cpu_order;   /* 2's power to represent total possible cpus */
 static struct kmem_cache *fc_em_cachep;               /* cache for exchanges */
-struct workqueue_struct *fc_exch_workqueue;
+static struct workqueue_struct *fc_exch_workqueue;
 
 /*
  * Structure and function definitions for managing Fibre Channel Exchanges
@@ -558,6 +558,22 @@ static struct fc_seq *fc_seq_start_next(struct fc_seq *sp)
        return sp;
 }
 
+/*
+ * Set the response handler for the exchange associated with a sequence.
+ */
+static void fc_seq_set_resp(struct fc_seq *sp,
+                           void (*resp)(struct fc_seq *, struct fc_frame *,
+                                        void *),
+                           void *arg)
+{
+       struct fc_exch *ep = fc_seq_exch(sp);
+
+       spin_lock_bh(&ep->ex_lock);
+       ep->resp = resp;
+       ep->arg = arg;
+       spin_unlock_bh(&ep->ex_lock);
+}
+
 /**
  * fc_seq_exch_abort() - Abort an exchange and sequence
  * @req_sp:    The sequence to be aborted
@@ -650,13 +666,10 @@ static void fc_exch_timeout(struct work_struct *work)
                if (e_stat & ESB_ST_ABNORMAL)
                        rc = fc_exch_done_locked(ep);
                spin_unlock_bh(&ep->ex_lock);
+               if (!rc)
+                       fc_exch_delete(ep);
                if (resp)
                        resp(sp, ERR_PTR(-FC_EX_TIMEOUT), arg);
-               if (!rc) {
-                       /* delete the exchange if it's already being aborted */
-                       fc_exch_delete(ep);
-                       return;
-               }
                fc_seq_exch_abort(sp, 2 * ep->r_a_tov);
                goto done;
        }
@@ -1029,7 +1042,7 @@ static void fc_exch_set_addr(struct fc_exch *ep,
 }
 
 /**
- * fc_seq_els_rsp_send() - Send an ELS response using infomation from
+ * fc_seq_els_rsp_send() - Send an ELS response using information from
  *                        the existing sequence/exchange.
  * @fp:              The received frame
  * @els_cmd:  The ELS command to be sent
@@ -1140,7 +1153,7 @@ static void fc_seq_send_ack(struct fc_seq *sp, const struct fc_frame *rx_fp)
  * fc_exch_send_ba_rjt() - Send BLS Reject
  * @rx_fp:  The frame being rejected
  * @reason: The reason the frame is being rejected
- * @explan: The explaination for the rejection
+ * @explan: The explanation for the rejection
  *
  * This is for rejecting BA_ABTS only.
  */
@@ -1266,6 +1279,8 @@ free:
  * @fp:    The request frame
  *
  * On success, the sequence pointer will be returned and also in fr_seq(@fp).
+ * A reference will be held on the exchange/sequence for the caller, which
+ * must call fc_seq_release().
  */
 static struct fc_seq *fc_seq_assign(struct fc_lport *lport, struct fc_frame *fp)
 {
@@ -1282,6 +1297,15 @@ static struct fc_seq *fc_seq_assign(struct fc_lport *lport, struct fc_frame *fp)
        return fr_seq(fp);
 }
 
+/**
+ * fc_seq_release() - Release the hold
+ * @sp:    The sequence.
+ */
+static void fc_seq_release(struct fc_seq *sp)
+{
+       fc_exch_release(fc_seq_exch(sp));
+}
+
 /**
  * fc_exch_recv_req() - Handler for an incoming request
  * @lport: The local port that received the request
@@ -2151,6 +2175,7 @@ err:
                fc_exch_mgr_del(ema);
        return -ENOMEM;
 }
+EXPORT_SYMBOL(fc_exch_mgr_list_clone);
 
 /**
  * fc_exch_mgr_alloc() - Allocate an exchange manager
@@ -2253,17 +2278,46 @@ void fc_exch_mgr_free(struct fc_lport *lport)
 }
 EXPORT_SYMBOL(fc_exch_mgr_free);
 
+/**
+ * fc_find_ema() - Lookup and return appropriate Exchange Manager Anchor depending
+ * upon 'xid'.
+ * @f_ctl: f_ctl
+ * @lport: The local port the frame was received on
+ * @fh: The received frame header
+ */
+static struct fc_exch_mgr_anchor *fc_find_ema(u32 f_ctl,
+                                             struct fc_lport *lport,
+                                             struct fc_frame_header *fh)
+{
+       struct fc_exch_mgr_anchor *ema;
+       u16 xid;
+
+       if (f_ctl & FC_FC_EX_CTX)
+               xid = ntohs(fh->fh_ox_id);
+       else {
+               xid = ntohs(fh->fh_rx_id);
+               if (xid == FC_XID_UNKNOWN)
+                       return list_entry(lport->ema_list.prev,
+                                         typeof(*ema), ema_list);
+       }
+
+       list_for_each_entry(ema, &lport->ema_list, ema_list) {
+               if ((xid >= ema->mp->min_xid) &&
+                   (xid <= ema->mp->max_xid))
+                       return ema;
+       }
+       return NULL;
+}
 /**
  * fc_exch_recv() - Handler for received frames
  * @lport: The local port the frame was received on
- * @fp:           The received frame
+ * @fp:        The received frame
  */
 void fc_exch_recv(struct fc_lport *lport, struct fc_frame *fp)
 {
        struct fc_frame_header *fh = fc_frame_header_get(fp);
        struct fc_exch_mgr_anchor *ema;
-       u32 f_ctl, found = 0;
-       u16 oxid;
+       u32 f_ctl;
 
        /* lport lock ? */
        if (!lport || lport->state == LPORT_ST_DISABLED) {
@@ -2274,24 +2328,17 @@ void fc_exch_recv(struct fc_lport *lport, struct fc_frame *fp)
        }
 
        f_ctl = ntoh24(fh->fh_f_ctl);
-       oxid = ntohs(fh->fh_ox_id);
-       if (f_ctl & FC_FC_EX_CTX) {
-               list_for_each_entry(ema, &lport->ema_list, ema_list) {
-                       if ((oxid >= ema->mp->min_xid) &&
-                           (oxid <= ema->mp->max_xid)) {
-                               found = 1;
-                               break;
-                       }
-               }
-
-               if (!found) {
-                       FC_LPORT_DBG(lport, "Received response for out "
-                                    "of range oxid:%hx\n", oxid);
-                       fc_frame_free(fp);
-                       return;
-               }
-       } else
-               ema = list_entry(lport->ema_list.prev, typeof(*ema), ema_list);
+       ema = fc_find_ema(f_ctl, lport, fh);
+       if (!ema) {
+               FC_LPORT_DBG(lport, "Unable to find Exchange Manager Anchor,"
+                                   "fc_ctl <0x%x>, xid <0x%x>\n",
+                                    f_ctl,
+                                    (f_ctl & FC_FC_EX_CTX) ?
+                                    ntohs(fh->fh_ox_id) :
+                                    ntohs(fh->fh_rx_id));
+               fc_frame_free(fp);
+               return;
+       }
 
        /*
         * If frame is marked invalid, just drop it.
@@ -2329,6 +2376,9 @@ int fc_exch_init(struct fc_lport *lport)
        if (!lport->tt.seq_start_next)
                lport->tt.seq_start_next = fc_seq_start_next;
 
+       if (!lport->tt.seq_set_resp)
+               lport->tt.seq_set_resp = fc_seq_set_resp;
+
        if (!lport->tt.exch_seq_send)
                lport->tt.exch_seq_send = fc_exch_seq_send;
 
@@ -2350,6 +2400,9 @@ int fc_exch_init(struct fc_lport *lport)
        if (!lport->tt.seq_assign)
                lport->tt.seq_assign = fc_seq_assign;
 
+       if (!lport->tt.seq_release)
+               lport->tt.seq_release = fc_seq_release;
+
        return 0;
 }
 EXPORT_SYMBOL(fc_exch_init);
@@ -2357,7 +2410,7 @@ EXPORT_SYMBOL(fc_exch_init);
 /**
  * fc_setup_exch_mgr() - Setup an exchange manager
  */
-int fc_setup_exch_mgr()
+int fc_setup_exch_mgr(void)
 {
        fc_em_cachep = kmem_cache_create("libfc_em", sizeof(struct fc_exch),
                                         0, SLAB_HWCACHE_ALIGN, NULL);
@@ -2395,7 +2448,7 @@ int fc_setup_exch_mgr()
 /**
  * fc_destroy_exch_mgr() - Destroy an exchange manager
  */
-void fc_destroy_exch_mgr()
+void fc_destroy_exch_mgr(void)
 {
        destroy_workqueue(fc_exch_workqueue);
        kmem_cache_destroy(fc_em_cachep);