|
|
|
@@ -763,50 +763,86 @@ static void fdls_send_fabric_abts(struct fnic_iport_s *iport)
|
|
|
|
|
iport->fabric.timer_pending = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void fdls_send_fdmi_abts(struct fnic_iport_s *iport)
|
|
|
|
|
static uint8_t *fdls_alloc_init_fdmi_abts_frame(struct fnic_iport_s *iport,
|
|
|
|
|
uint16_t oxid)
|
|
|
|
|
{
|
|
|
|
|
uint8_t *frame;
|
|
|
|
|
struct fc_frame_header *pfdmi_abts;
|
|
|
|
|
uint8_t d_id[3];
|
|
|
|
|
uint8_t *frame;
|
|
|
|
|
struct fnic *fnic = iport->fnic;
|
|
|
|
|
struct fc_frame_header *pfabric_abts;
|
|
|
|
|
unsigned long fdmi_tov;
|
|
|
|
|
uint16_t oxid;
|
|
|
|
|
uint16_t frame_size = FNIC_ETH_FCOE_HDRS_OFFSET +
|
|
|
|
|
sizeof(struct fc_frame_header);
|
|
|
|
|
|
|
|
|
|
frame = fdls_alloc_frame(iport);
|
|
|
|
|
if (frame == NULL) {
|
|
|
|
|
FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
|
|
|
|
|
"Failed to allocate frame to send FDMI ABTS");
|
|
|
|
|
return;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pfabric_abts = (struct fc_frame_header *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET);
|
|
|
|
|
pfdmi_abts = (struct fc_frame_header *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET);
|
|
|
|
|
fdls_init_fabric_abts_frame(frame, iport);
|
|
|
|
|
|
|
|
|
|
hton24(d_id, FC_FID_MGMT_SERV);
|
|
|
|
|
FNIC_STD_SET_D_ID(*pfabric_abts, d_id);
|
|
|
|
|
FNIC_STD_SET_D_ID(*pfdmi_abts, d_id);
|
|
|
|
|
FNIC_STD_SET_OX_ID(*pfdmi_abts, oxid);
|
|
|
|
|
|
|
|
|
|
return frame;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void fdls_send_fdmi_abts(struct fnic_iport_s *iport)
|
|
|
|
|
{
|
|
|
|
|
uint8_t *frame;
|
|
|
|
|
struct fnic *fnic = iport->fnic;
|
|
|
|
|
unsigned long fdmi_tov;
|
|
|
|
|
uint16_t frame_size = FNIC_ETH_FCOE_HDRS_OFFSET +
|
|
|
|
|
sizeof(struct fc_frame_header);
|
|
|
|
|
|
|
|
|
|
if (iport->fabric.fdmi_pending & FDLS_FDMI_PLOGI_PENDING) {
|
|
|
|
|
oxid = iport->active_oxid_fdmi_plogi;
|
|
|
|
|
FNIC_STD_SET_OX_ID(*pfabric_abts, oxid);
|
|
|
|
|
frame = fdls_alloc_init_fdmi_abts_frame(iport,
|
|
|
|
|
iport->active_oxid_fdmi_plogi);
|
|
|
|
|
if (frame == NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
|
|
|
|
|
"0x%x: FDLS send FDMI PLOGI abts. iport->fabric.state: %d oxid: 0x%x",
|
|
|
|
|
iport->fcid, iport->fabric.state, iport->active_oxid_fdmi_plogi);
|
|
|
|
|
fnic_send_fcoe_frame(iport, frame, frame_size);
|
|
|
|
|
} else {
|
|
|
|
|
if (iport->fabric.fdmi_pending & FDLS_FDMI_REG_HBA_PENDING) {
|
|
|
|
|
oxid = iport->active_oxid_fdmi_rhba;
|
|
|
|
|
FNIC_STD_SET_OX_ID(*pfabric_abts, oxid);
|
|
|
|
|
frame = fdls_alloc_init_fdmi_abts_frame(iport,
|
|
|
|
|
iport->active_oxid_fdmi_rhba);
|
|
|
|
|
if (frame == NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
|
|
|
|
|
"0x%x: FDLS send FDMI RHBA abts. iport->fabric.state: %d oxid: 0x%x",
|
|
|
|
|
iport->fcid, iport->fabric.state, iport->active_oxid_fdmi_rhba);
|
|
|
|
|
fnic_send_fcoe_frame(iport, frame, frame_size);
|
|
|
|
|
}
|
|
|
|
|
if (iport->fabric.fdmi_pending & FDLS_FDMI_RPA_PENDING) {
|
|
|
|
|
oxid = iport->active_oxid_fdmi_rpa;
|
|
|
|
|
FNIC_STD_SET_OX_ID(*pfabric_abts, oxid);
|
|
|
|
|
frame = fdls_alloc_init_fdmi_abts_frame(iport,
|
|
|
|
|
iport->active_oxid_fdmi_rpa);
|
|
|
|
|
if (frame == NULL) {
|
|
|
|
|
if (iport->fabric.fdmi_pending & FDLS_FDMI_REG_HBA_PENDING)
|
|
|
|
|
goto arm_timer;
|
|
|
|
|
else
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
|
|
|
|
|
"0x%x: FDLS send FDMI RPA abts. iport->fabric.state: %d oxid: 0x%x",
|
|
|
|
|
iport->fcid, iport->fabric.state, iport->active_oxid_fdmi_rpa);
|
|
|
|
|
fnic_send_fcoe_frame(iport, frame, frame_size);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
arm_timer:
|
|
|
|
|
fdmi_tov = jiffies + msecs_to_jiffies(2 * iport->e_d_tov);
|
|
|
|
|
mod_timer(&iport->fabric.fdmi_timer, round_jiffies(fdmi_tov));
|
|
|
|
|
iport->fabric.fdmi_pending |= FDLS_FDMI_ABORT_PENDING;
|
|
|
|
|
|
|
|
|
|
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
|
|
|
|
|
"0x%x: iport->fabric.fdmi_pending: 0x%x",
|
|
|
|
|
iport->fcid, iport->fabric.fdmi_pending);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void fdls_send_fabric_flogi(struct fnic_iport_s *iport)
|
|
|
|
@@ -2245,6 +2281,21 @@ void fdls_fabric_timer_callback(struct timer_list *t)
|
|
|
|
|
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void fdls_fdmi_retry_plogi(struct fnic_iport_s *iport)
|
|
|
|
|
{
|
|
|
|
|
struct fnic *fnic = iport->fnic;
|
|
|
|
|
|
|
|
|
|
iport->fabric.fdmi_pending = 0;
|
|
|
|
|
/* If max retries not exhausted, start over from fdmi plogi */
|
|
|
|
|
if (iport->fabric.fdmi_retry < FDLS_FDMI_MAX_RETRY) {
|
|
|
|
|
iport->fabric.fdmi_retry++;
|
|
|
|
|
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
|
|
|
|
|
"Retry FDMI PLOGI. FDMI retry: %d",
|
|
|
|
|
iport->fabric.fdmi_retry);
|
|
|
|
|
fdls_send_fdmi_plogi(iport);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void fdls_fdmi_timer_callback(struct timer_list *t)
|
|
|
|
|
{
|
|
|
|
|
struct fnic_fdls_fabric_s *fabric = timer_container_of(fabric, t,
|
|
|
|
@@ -2257,7 +2308,7 @@ void fdls_fdmi_timer_callback(struct timer_list *t)
|
|
|
|
|
spin_lock_irqsave(&fnic->fnic_lock, flags);
|
|
|
|
|
|
|
|
|
|
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
|
|
|
|
|
"fdmi timer callback : 0x%x\n", iport->fabric.fdmi_pending);
|
|
|
|
|
"iport->fabric.fdmi_pending: 0x%x\n", iport->fabric.fdmi_pending);
|
|
|
|
|
|
|
|
|
|
if (!iport->fabric.fdmi_pending) {
|
|
|
|
|
/* timer expired after fdmi responses received. */
|
|
|
|
@@ -2265,7 +2316,7 @@ void fdls_fdmi_timer_callback(struct timer_list *t)
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
|
|
|
|
|
"fdmi timer callback : 0x%x\n", iport->fabric.fdmi_pending);
|
|
|
|
|
"iport->fabric.fdmi_pending: 0x%x\n", iport->fabric.fdmi_pending);
|
|
|
|
|
|
|
|
|
|
/* if not abort pending, send an abort */
|
|
|
|
|
if (!(iport->fabric.fdmi_pending & FDLS_FDMI_ABORT_PENDING)) {
|
|
|
|
@@ -2274,33 +2325,37 @@ void fdls_fdmi_timer_callback(struct timer_list *t)
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
|
|
|
|
|
"fdmi timer callback : 0x%x\n", iport->fabric.fdmi_pending);
|
|
|
|
|
"iport->fabric.fdmi_pending: 0x%x\n", iport->fabric.fdmi_pending);
|
|
|
|
|
|
|
|
|
|
/* ABTS pending for an active fdmi request that is pending.
|
|
|
|
|
* That means FDMI ABTS timed out
|
|
|
|
|
* Schedule to free the OXID after 2*r_a_tov and proceed
|
|
|
|
|
*/
|
|
|
|
|
if (iport->fabric.fdmi_pending & FDLS_FDMI_PLOGI_PENDING) {
|
|
|
|
|
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
|
|
|
|
|
"FDMI PLOGI ABTS timed out. Schedule oxid free: 0x%x\n",
|
|
|
|
|
iport->active_oxid_fdmi_plogi);
|
|
|
|
|
fdls_schedule_oxid_free(iport, &iport->active_oxid_fdmi_plogi);
|
|
|
|
|
} else {
|
|
|
|
|
if (iport->fabric.fdmi_pending & FDLS_FDMI_REG_HBA_PENDING)
|
|
|
|
|
if (iport->fabric.fdmi_pending & FDLS_FDMI_REG_HBA_PENDING) {
|
|
|
|
|
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
|
|
|
|
|
"FDMI RHBA ABTS timed out. Schedule oxid free: 0x%x\n",
|
|
|
|
|
iport->active_oxid_fdmi_rhba);
|
|
|
|
|
fdls_schedule_oxid_free(iport, &iport->active_oxid_fdmi_rhba);
|
|
|
|
|
if (iport->fabric.fdmi_pending & FDLS_FDMI_RPA_PENDING)
|
|
|
|
|
}
|
|
|
|
|
if (iport->fabric.fdmi_pending & FDLS_FDMI_RPA_PENDING) {
|
|
|
|
|
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
|
|
|
|
|
"FDMI RPA ABTS timed out. Schedule oxid free: 0x%x\n",
|
|
|
|
|
iport->active_oxid_fdmi_rpa);
|
|
|
|
|
fdls_schedule_oxid_free(iport, &iport->active_oxid_fdmi_rpa);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
|
|
|
|
|
"fdmi timer callback : 0x%x\n", iport->fabric.fdmi_pending);
|
|
|
|
|
"iport->fabric.fdmi_pending: 0x%x\n", iport->fabric.fdmi_pending);
|
|
|
|
|
|
|
|
|
|
iport->fabric.fdmi_pending = 0;
|
|
|
|
|
/* If max retries not exhaused, start over from fdmi plogi */
|
|
|
|
|
if (iport->fabric.fdmi_retry < FDLS_FDMI_MAX_RETRY) {
|
|
|
|
|
iport->fabric.fdmi_retry++;
|
|
|
|
|
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
|
|
|
|
|
"retry fdmi timer %d", iport->fabric.fdmi_retry);
|
|
|
|
|
fdls_send_fdmi_plogi(iport);
|
|
|
|
|
}
|
|
|
|
|
fdls_fdmi_retry_plogi(iport);
|
|
|
|
|
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
|
|
|
|
|
"fdmi timer callback : 0x%x\n", iport->fabric.fdmi_pending);
|
|
|
|
|
"iport->fabric.fdmi_pending: 0x%x\n", iport->fabric.fdmi_pending);
|
|
|
|
|
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -3715,13 +3770,60 @@ static void fdls_process_fdmi_abts_rsp(struct fnic_iport_s *iport,
|
|
|
|
|
|
|
|
|
|
switch (FNIC_FRAME_TYPE(oxid)) {
|
|
|
|
|
case FNIC_FRAME_TYPE_FDMI_PLOGI:
|
|
|
|
|
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
|
|
|
|
|
"Received FDMI PLOGI ABTS rsp with oxid: 0x%x", oxid);
|
|
|
|
|
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
|
|
|
|
|
"0x%x: iport->fabric.fdmi_pending: 0x%x",
|
|
|
|
|
iport->fcid, iport->fabric.fdmi_pending);
|
|
|
|
|
fdls_free_oxid(iport, oxid, &iport->active_oxid_fdmi_plogi);
|
|
|
|
|
|
|
|
|
|
iport->fabric.fdmi_pending &= ~FDLS_FDMI_PLOGI_PENDING;
|
|
|
|
|
iport->fabric.fdmi_pending &= ~FDLS_FDMI_ABORT_PENDING;
|
|
|
|
|
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
|
|
|
|
|
"0x%x: iport->fabric.fdmi_pending: 0x%x",
|
|
|
|
|
iport->fcid, iport->fabric.fdmi_pending);
|
|
|
|
|
break;
|
|
|
|
|
case FNIC_FRAME_TYPE_FDMI_RHBA:
|
|
|
|
|
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
|
|
|
|
|
"Received FDMI RHBA ABTS rsp with oxid: 0x%x", oxid);
|
|
|
|
|
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
|
|
|
|
|
"0x%x: iport->fabric.fdmi_pending: 0x%x",
|
|
|
|
|
iport->fcid, iport->fabric.fdmi_pending);
|
|
|
|
|
|
|
|
|
|
iport->fabric.fdmi_pending &= ~FDLS_FDMI_REG_HBA_PENDING;
|
|
|
|
|
|
|
|
|
|
/* If RPA is still pending, don't turn off ABORT PENDING.
|
|
|
|
|
* We count on the timer to detect the ABTS timeout and take
|
|
|
|
|
* corrective action.
|
|
|
|
|
*/
|
|
|
|
|
if (!(iport->fabric.fdmi_pending & FDLS_FDMI_RPA_PENDING))
|
|
|
|
|
iport->fabric.fdmi_pending &= ~FDLS_FDMI_ABORT_PENDING;
|
|
|
|
|
|
|
|
|
|
fdls_free_oxid(iport, oxid, &iport->active_oxid_fdmi_rhba);
|
|
|
|
|
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
|
|
|
|
|
"0x%x: iport->fabric.fdmi_pending: 0x%x",
|
|
|
|
|
iport->fcid, iport->fabric.fdmi_pending);
|
|
|
|
|
break;
|
|
|
|
|
case FNIC_FRAME_TYPE_FDMI_RPA:
|
|
|
|
|
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
|
|
|
|
|
"Received FDMI RPA ABTS rsp with oxid: 0x%x", oxid);
|
|
|
|
|
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
|
|
|
|
|
"0x%x: iport->fabric.fdmi_pending: 0x%x",
|
|
|
|
|
iport->fcid, iport->fabric.fdmi_pending);
|
|
|
|
|
|
|
|
|
|
iport->fabric.fdmi_pending &= ~FDLS_FDMI_RPA_PENDING;
|
|
|
|
|
|
|
|
|
|
/* If RHBA is still pending, don't turn off ABORT PENDING.
|
|
|
|
|
* We count on the timer to detect the ABTS timeout and take
|
|
|
|
|
* corrective action.
|
|
|
|
|
*/
|
|
|
|
|
if (!(iport->fabric.fdmi_pending & FDLS_FDMI_REG_HBA_PENDING))
|
|
|
|
|
iport->fabric.fdmi_pending &= ~FDLS_FDMI_ABORT_PENDING;
|
|
|
|
|
|
|
|
|
|
fdls_free_oxid(iport, oxid, &iport->active_oxid_fdmi_rpa);
|
|
|
|
|
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
|
|
|
|
|
"0x%x: iport->fabric.fdmi_pending: 0x%x",
|
|
|
|
|
iport->fcid, iport->fabric.fdmi_pending);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
|
|
|
|
@@ -3730,10 +3832,16 @@ static void fdls_process_fdmi_abts_rsp(struct fnic_iport_s *iport,
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
timer_delete_sync(&iport->fabric.fdmi_timer);
|
|
|
|
|
iport->fabric.fdmi_pending &= ~FDLS_FDMI_ABORT_PENDING;
|
|
|
|
|
|
|
|
|
|
fdls_send_fdmi_plogi(iport);
|
|
|
|
|
/*
|
|
|
|
|
* Only if ABORT PENDING is off, delete the timer, and if no other
|
|
|
|
|
* operations are pending, retry FDMI.
|
|
|
|
|
* Otherwise, let the timer pop and take the appropriate action.
|
|
|
|
|
*/
|
|
|
|
|
if (!(iport->fabric.fdmi_pending & FDLS_FDMI_ABORT_PENDING)) {
|
|
|
|
|
timer_delete_sync(&iport->fabric.fdmi_timer);
|
|
|
|
|
if (!iport->fabric.fdmi_pending)
|
|
|
|
|
fdls_fdmi_retry_plogi(iport);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
@@ -4972,9 +5080,12 @@ void fnic_fdls_link_down(struct fnic_iport_s *iport)
|
|
|
|
|
fdls_delete_tport(iport, tport);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((fnic_fdmi_support == 1) && (iport->fabric.fdmi_pending > 0)) {
|
|
|
|
|
timer_delete_sync(&iport->fabric.fdmi_timer);
|
|
|
|
|
iport->fabric.fdmi_pending = 0;
|
|
|
|
|
if (fnic_fdmi_support == 1) {
|
|
|
|
|
if (iport->fabric.fdmi_pending > 0) {
|
|
|
|
|
timer_delete_sync(&iport->fabric.fdmi_timer);
|
|
|
|
|
iport->fabric.fdmi_pending = 0;
|
|
|
|
|
}
|
|
|
|
|
iport->flags &= ~FNIC_FDMI_ACTIVE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
|
|
|
|
|