aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorKiran Patil <kiran.patil@intel.com>2011-01-28 19:04:39 -0500
committerJames Bottomley <James.Bottomley@suse.de>2011-02-12 12:04:27 -0500
commit6c8cc1c003cee1c4290f5d8c684912d60354056a (patch)
tree883c9a03940b76da5751f67d7171a235a336c23a /drivers/scsi
parent62bdb6455e8326f864ae1b43b4c4db7f630edc1c (diff)
[SCSI] libfc: Enhanced exchange ID selection mechanism and fix related EMA selection logic.
Problem: In case of exchange responder case, EMA selection was defaulted to the last EMA from EMA list (lport.ema_list). If exchange ID is selected from offload pool and not setup DDP, resulting into incorrect selection of EMA, and eventually dropping the packet because unable to find exchange. Fix: Enhanced the exchange ID selection (depending upon request type and exchange responder) Made necessary enhancement in EMA selection algorithm. Signed-off-by: Kiran Patil <kiran.patil@intel.com> Signed-off-by: Robert Love <robert.w.love@intel.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/libfc/fc_exch.c64
1 files changed, 43 insertions, 21 deletions
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index a3d640289dcc..08bf5fa6afd4 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -2281,16 +2281,45 @@ void fc_exch_mgr_free(struct fc_lport *lport)
2281EXPORT_SYMBOL(fc_exch_mgr_free); 2281EXPORT_SYMBOL(fc_exch_mgr_free);
2282 2282
2283/** 2283/**
2284 * fc_find_ema() - Lookup and return appropriate Exchange Manager Anchor depending
2285 * upon 'xid'.
2286 * @f_ctl: f_ctl
2287 * @lport: The local port the frame was received on
2288 * @fh: The received frame header
2289 */
2290static struct fc_exch_mgr_anchor *fc_find_ema(u32 f_ctl,
2291 struct fc_lport *lport,
2292 struct fc_frame_header *fh)
2293{
2294 struct fc_exch_mgr_anchor *ema;
2295 u16 xid;
2296
2297 if (f_ctl & FC_FC_EX_CTX)
2298 xid = ntohs(fh->fh_ox_id);
2299 else {
2300 xid = ntohs(fh->fh_rx_id);
2301 if (xid == FC_XID_UNKNOWN)
2302 return list_entry(lport->ema_list.prev,
2303 typeof(*ema), ema_list);
2304 }
2305
2306 list_for_each_entry(ema, &lport->ema_list, ema_list) {
2307 if ((xid >= ema->mp->min_xid) &&
2308 (xid <= ema->mp->max_xid))
2309 return ema;
2310 }
2311 return NULL;
2312}
2313/**
2284 * fc_exch_recv() - Handler for received frames 2314 * fc_exch_recv() - Handler for received frames
2285 * @lport: The local port the frame was received on 2315 * @lport: The local port the frame was received on
2286 * @fp: The received frame 2316 * @fp: The received frame
2287 */ 2317 */
2288void fc_exch_recv(struct fc_lport *lport, struct fc_frame *fp) 2318void fc_exch_recv(struct fc_lport *lport, struct fc_frame *fp)
2289{ 2319{
2290 struct fc_frame_header *fh = fc_frame_header_get(fp); 2320 struct fc_frame_header *fh = fc_frame_header_get(fp);
2291 struct fc_exch_mgr_anchor *ema; 2321 struct fc_exch_mgr_anchor *ema;
2292 u32 f_ctl, found = 0; 2322 u32 f_ctl;
2293 u16 oxid;
2294 2323
2295 /* lport lock ? */ 2324 /* lport lock ? */
2296 if (!lport || lport->state == LPORT_ST_DISABLED) { 2325 if (!lport || lport->state == LPORT_ST_DISABLED) {
@@ -2301,24 +2330,17 @@ void fc_exch_recv(struct fc_lport *lport, struct fc_frame *fp)
2301 } 2330 }
2302 2331
2303 f_ctl = ntoh24(fh->fh_f_ctl); 2332 f_ctl = ntoh24(fh->fh_f_ctl);
2304 oxid = ntohs(fh->fh_ox_id); 2333 ema = fc_find_ema(f_ctl, lport, fh);
2305 if (f_ctl & FC_FC_EX_CTX) { 2334 if (!ema) {
2306 list_for_each_entry(ema, &lport->ema_list, ema_list) { 2335 FC_LPORT_DBG(lport, "Unable to find Exchange Manager Anchor,"
2307 if ((oxid >= ema->mp->min_xid) && 2336 "fc_ctl <0x%x>, xid <0x%x>\n",
2308 (oxid <= ema->mp->max_xid)) { 2337 f_ctl,
2309 found = 1; 2338 (f_ctl & FC_FC_EX_CTX) ?
2310 break; 2339 ntohs(fh->fh_ox_id) :
2311 } 2340 ntohs(fh->fh_rx_id));
2312 } 2341 fc_frame_free(fp);
2313 2342 return;
2314 if (!found) { 2343 }
2315 FC_LPORT_DBG(lport, "Received response for out "
2316 "of range oxid:%hx\n", oxid);
2317 fc_frame_free(fp);
2318 return;
2319 }
2320 } else
2321 ema = list_entry(lport->ema_list.prev, typeof(*ema), ema_list);
2322 2344
2323 /* 2345 /*
2324 * If frame is marked invalid, just drop it. 2346 * If frame is marked invalid, just drop it.