Skip to content

Commit

Permalink
[SCSI] libfcoe: FIP should report link to libfc whether selected or not
Browse files Browse the repository at this point in the history
The fnic driver with FIP is reporting link up, even though it's down.

When the interface is shut down by the switch, we receive a clear
virtual link, and set the state reported to libfc as down, although
we still report it up.  Clearly wrong.  That causes the subsequent
link down event not to be reported, and /sys shows the host "Online".

Currently, in FIP mode, if an FCF times out, then link to libfc
is reported as down, to stop FLOGIs.  That interferes with the LLD
link down being reported.

Users really need to know the physical link information, to diagnose
cabling issues, so physical link status should be reported to libfc.

If the selected FCF needs to be reported, that should be done
separately, in a later patch.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
  • Loading branch information
Joe Eykholt authored and James Bottomley committed Dec 4, 2009
1 parent 1f4aed8 commit dd42dac
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 30 deletions.
60 changes: 30 additions & 30 deletions drivers/scsi/fcoe/libfcoe.c
Original file line number Diff line number Diff line change
Expand Up @@ -277,38 +277,16 @@ EXPORT_SYMBOL(fcoe_ctlr_link_up);
/**
* fcoe_ctlr_reset() - Reset a FCoE controller
* @fip: The FCoE controller to reset
* @new_state: The FIP state to be entered
*
* Returns non-zero if the link was up and now isn't.
*/
static int fcoe_ctlr_reset(struct fcoe_ctlr *fip, enum fip_state new_state)
static void fcoe_ctlr_reset(struct fcoe_ctlr *fip)
{
struct fc_lport *lport = fip->lp;
int link_dropped;

spin_lock_bh(&fip->lock);
fcoe_ctlr_reset_fcfs(fip);
del_timer(&fip->timer);
fip->state = new_state;
fip->ctlr_ka_time = 0;
fip->port_ka_time = 0;
fip->sol_time = 0;
fip->flogi_oxid = FC_XID_UNKNOWN;
fip->map_dest = 0;
fip->last_link = 0;
link_dropped = fip->link;
fip->link = 0;
spin_unlock_bh(&fip->lock);

if (link_dropped)
fc_linkdown(lport);

if (new_state == FIP_ST_ENABLED) {
fcoe_ctlr_solicit(fip, NULL);
fc_linkup(lport);
link_dropped = 0;
}
return link_dropped;
}

/**
Expand All @@ -322,7 +300,20 @@ static int fcoe_ctlr_reset(struct fcoe_ctlr *fip, enum fip_state new_state)
*/
int fcoe_ctlr_link_down(struct fcoe_ctlr *fip)
{
return fcoe_ctlr_reset(fip, FIP_ST_LINK_WAIT);
int link_dropped;

LIBFCOE_FIP_DBG(fip, "link down.\n");
spin_lock_bh(&fip->lock);
fcoe_ctlr_reset(fip);
link_dropped = fip->link;
fip->link = 0;
fip->last_link = 0;
fip->state = FIP_ST_LINK_WAIT;
spin_unlock_bh(&fip->lock);

if (link_dropped)
fc_linkdown(fip->lp);
return link_dropped;
}
EXPORT_SYMBOL(fcoe_ctlr_link_down);

Expand Down Expand Up @@ -994,7 +985,13 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip,
desc_mask);
} else {
LIBFCOE_FIP_DBG(fip, "performing Clear Virtual Link\n");
fcoe_ctlr_reset(fip, FIP_ST_ENABLED);

spin_lock_bh(&fip->lock);
fcoe_ctlr_reset(fip);
spin_unlock_bh(&fip->lock);

fc_lport_reset(fip->lp);
fcoe_ctlr_solicit(fip, NULL);
}
}

Expand Down Expand Up @@ -1152,15 +1149,14 @@ static void fcoe_ctlr_timeout(unsigned long arg)
fip->port_ka_time = jiffies +
msecs_to_jiffies(FIP_VN_KA_PERIOD);
fip->ctlr_ka_time = jiffies + sel->fka_period;
fip->link = 1;
} else {
printk(KERN_NOTICE "libfcoe: host%d: "
"FIP Fibre-Channel Forwarder timed out. "
"Starting FCF discovery.\n",
fip->lp->host->host_no);
fip->link = 0;
fip->reset_req = 1;
schedule_work(&fip->link_work);
}
schedule_work(&fip->link_work);
}

if (sel) {
Expand Down Expand Up @@ -1205,20 +1201,24 @@ static void fcoe_ctlr_link_work(struct work_struct *work)
u8 *mac;
int link;
int last_link;
int reset;

fip = container_of(work, struct fcoe_ctlr, link_work);
spin_lock_bh(&fip->lock);
last_link = fip->last_link;
link = fip->link;
fip->last_link = link;
reset = fip->reset_req;
fip->reset_req = 0;
spin_unlock_bh(&fip->lock);

if (last_link != link) {
if (link)
fc_linkup(fip->lp);
else
fcoe_ctlr_reset(fip, FIP_ST_LINK_WAIT);
}
fc_linkdown(fip->lp);
} else if (reset && link)
fc_lport_reset(fip->lp);

if (fip->send_ctlr_ka) {
fip->send_ctlr_ka = 0;
Expand Down
1 change: 1 addition & 0 deletions include/scsi/libfcoe.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ struct fcoe_ctlr {
u8 flogi_count;
u8 link;
u8 last_link;
u8 reset_req;
u8 map_dest;
u8 spma;
u8 send_ctlr_ka;
Expand Down

0 comments on commit dd42dac

Please sign in to comment.