[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:
committed by
James Bottomley
parent
62bdb6455e
commit
6c8cc1c003
@@ -2280,6 +2280,36 @@ void fc_exch_mgr_free(struct fc_lport *lport)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(fc_exch_mgr_free);
|
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
|
* fc_exch_recv() - Handler for received frames
|
||||||
* @lport: The local port the frame was received on
|
* @lport: The local port the frame was received on
|
||||||
@@ -2289,8 +2319,7 @@ void fc_exch_recv(struct fc_lport *lport, struct fc_frame *fp)
|
|||||||
{
|
{
|
||||||
struct fc_frame_header *fh = fc_frame_header_get(fp);
|
struct fc_frame_header *fh = fc_frame_header_get(fp);
|
||||||
struct fc_exch_mgr_anchor *ema;
|
struct fc_exch_mgr_anchor *ema;
|
||||||
u32 f_ctl, found = 0;
|
u32 f_ctl;
|
||||||
u16 oxid;
|
|
||||||
|
|
||||||
/* lport lock ? */
|
/* lport lock ? */
|
||||||
if (!lport || lport->state == LPORT_ST_DISABLED) {
|
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);
|
f_ctl = ntoh24(fh->fh_f_ctl);
|
||||||
oxid = ntohs(fh->fh_ox_id);
|
ema = fc_find_ema(f_ctl, lport, fh);
|
||||||
if (f_ctl & FC_FC_EX_CTX) {
|
if (!ema) {
|
||||||
list_for_each_entry(ema, &lport->ema_list, ema_list) {
|
FC_LPORT_DBG(lport, "Unable to find Exchange Manager Anchor,"
|
||||||
if ((oxid >= ema->mp->min_xid) &&
|
"fc_ctl <0x%x>, xid <0x%x>\n",
|
||||||
(oxid <= ema->mp->max_xid)) {
|
f_ctl,
|
||||||
found = 1;
|
(f_ctl & FC_FC_EX_CTX) ?
|
||||||
break;
|
ntohs(fh->fh_ox_id) :
|
||||||
}
|
ntohs(fh->fh_rx_id));
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) {
|
|
||||||
FC_LPORT_DBG(lport, "Received response for out "
|
|
||||||
"of range oxid:%hx\n", oxid);
|
|
||||||
fc_frame_free(fp);
|
fc_frame_free(fp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else
|
|
||||||
ema = list_entry(lport->ema_list.prev, typeof(*ema), ema_list);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If frame is marked invalid, just drop it.
|
* If frame is marked invalid, just drop it.
|
||||||
|
Reference in New Issue
Block a user