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/libfc | |
| 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/libfc')
| -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 a3d640289dc..08bf5fa6afd 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. |
