diff options
author | Kiran Patil <kiran.patil@intel.com> | 2011-01-28 19:04:39 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2011-02-12 12:04:27 -0500 |
commit | 6c8cc1c003cee1c4290f5d8c684912d60354056a (patch) | |
tree | 883c9a03940b76da5751f67d7171a235a336c23a /drivers/scsi | |
parent | 62bdb6455e8326f864ae1b43b4c4db7f630edc1c (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.c | 64 |
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) | |||
2281 | EXPORT_SYMBOL(fc_exch_mgr_free); | 2281 | EXPORT_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 | */ | ||
2290 | static 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 | */ |
2288 | void fc_exch_recv(struct fc_lport *lport, struct fc_frame *fp) | 2318 | void 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. |