|
@@ -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;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -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);
|
|
|
|
|
@@ -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);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -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) {
|
|
@@ -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;
|