diff options
-rw-r--r-- | drivers/scsi/fcoe/libfcoe.c | 60 | ||||
-rw-r--r-- | include/scsi/libfcoe.h | 1 |
2 files changed, 31 insertions, 30 deletions
diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 787e7225ddd..4d857c2aef6 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -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; diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h index 2344a00e92e..e38ffa05dc2 100644 --- a/include/scsi/libfcoe.h +++ b/include/scsi/libfcoe.h @@ -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; |