scsi: qedf: Look at all descriptors when processing a clear virtual link.

If there are multiple descriptors for a particular type in a clear virtual
link we receive, we will not process it correctly but rather take the last
value. This can cause us not to not flap the virtual link as the value from
the descriptors that we compare against the our stored FCF or fc_lport values
may not match.

Change this to do a comparison when processing the each descriptor instead of at
the end and then set a bool if we need to do the reset.

Signed-off-by: Chad Dupuis <chad.dupuis@cavium.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Chad Dupuis 2017-05-31 06:33:51 -07:00 committed by Martin K. Petersen
parent 914fff102e
commit 53c51adbe6
1 changed files with 9 additions and 11 deletions

View File

@ -156,10 +156,9 @@ void qedf_fip_recv(struct qedf_ctx *qedf, struct sk_buff *skb)
struct fip_wwn_desc *wp; struct fip_wwn_desc *wp;
struct fip_vn_desc *vp; struct fip_vn_desc *vp;
size_t rlen, dlen; size_t rlen, dlen;
uint32_t cvl_port_id;
__u8 cvl_mac[ETH_ALEN];
u16 op; u16 op;
u8 sub; u8 sub;
bool do_reset = false;
eth_hdr = (struct ethhdr *)skb_mac_header(skb); eth_hdr = (struct ethhdr *)skb_mac_header(skb);
fiph = (struct fip_header *) ((void *)skb->data + 2 * ETH_ALEN + 2); fiph = (struct fip_header *) ((void *)skb->data + 2 * ETH_ALEN + 2);
@ -190,8 +189,6 @@ void qedf_fip_recv(struct qedf_ctx *qedf, struct sk_buff *skb)
return; return;
} }
cvl_port_id = 0;
memset(cvl_mac, 0, ETH_ALEN);
/* /*
* We need to loop through the CVL descriptors to determine * We need to loop through the CVL descriptors to determine
* if we want to reset the fcoe link * if we want to reset the fcoe link
@ -205,7 +202,9 @@ void qedf_fip_recv(struct qedf_ctx *qedf, struct sk_buff *skb)
mp = (struct fip_mac_desc *)desc; mp = (struct fip_mac_desc *)desc;
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_LL2, QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_LL2,
"fd_mac=%pM\n", mp->fd_mac); "fd_mac=%pM\n", mp->fd_mac);
ether_addr_copy(cvl_mac, mp->fd_mac); if (ether_addr_equal(mp->fd_mac,
qedf->ctlr.sel_fcf->fcf_mac))
do_reset = true;
break; break;
case FIP_DT_NAME: case FIP_DT_NAME:
wp = (struct fip_wwn_desc *)desc; wp = (struct fip_wwn_desc *)desc;
@ -217,7 +216,9 @@ void qedf_fip_recv(struct qedf_ctx *qedf, struct sk_buff *skb)
vp = (struct fip_vn_desc *)desc; vp = (struct fip_vn_desc *)desc;
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_LL2, QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_LL2,
"fd_fc_id=%x.\n", ntoh24(vp->fd_fc_id)); "fd_fc_id=%x.\n", ntoh24(vp->fd_fc_id));
cvl_port_id = ntoh24(vp->fd_fc_id); if (ntoh24(vp->fd_fc_id) ==
qedf->lport->port_id)
do_reset = true;
break; break;
default: default:
/* Ignore anything else */ /* Ignore anything else */
@ -228,11 +229,8 @@ void qedf_fip_recv(struct qedf_ctx *qedf, struct sk_buff *skb)
} }
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_LL2, QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_LL2,
"cvl_port_id=%06x cvl_mac=%pM.\n", cvl_port_id, "do_reset=%d.\n", do_reset);
cvl_mac); if (do_reset) {
if (cvl_port_id == qedf->lport->port_id &&
ether_addr_equal(cvl_mac,
qedf->ctlr.sel_fcf->fcf_mac)) {
fcoe_ctlr_link_down(&qedf->ctlr); fcoe_ctlr_link_down(&qedf->ctlr);
qedf_wait_for_upload(qedf); qedf_wait_for_upload(qedf);
fcoe_ctlr_link_up(&qedf->ctlr); fcoe_ctlr_link_up(&qedf->ctlr);