[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>
This commit is contained in:
parent
62bdb6455e
commit
6c8cc1c003
1 changed files with 43 additions and 21 deletions
|
@ -2280,17 +2280,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) {
|
||||
|
@ -2301,24 +2330,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.
|
||||
|
|
Loading…
Reference in a new issue