/* bnx2fc_tgt.c: QLogic Linux FCoE offload driver. * Handles operations such as session offload/upload etc, and manages * session resources such as connection id and qp resources. * * Copyright (c) 2008-2013 Broadcom Corporation * Copyright (c) 2014-2016 QLogic Corporation * Copyright (c) 2016-2017 Cavium Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * Written by: Bhanu Prakash Gollapudi (bprakash@broadcom.com)
*/
BNX2FC_TGT_DBG(tgt, "entered bnx2fc_ofld_timer\n"); /* NOTE: This function should never be called, as * offload should never timeout
*/ /* * If the timer has expired, this session is dead * Clear offloaded flag and logout of this device. * Since OFFLOADED flag is cleared, this case * will be considered as offload error and the * port will be logged off, and conn_id, session * resources are freed up in bnx2fc_offload_session
*/
clear_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags);
clear_bit(BNX2FC_FLAG_ENABLED, &tgt->flags);
set_bit(BNX2FC_FLAG_OFLD_REQ_CMPL, &tgt->flags);
wake_up_interruptible(&tgt->ofld_wait);
}
/* * Called with hba->hba_mutex held. * This is a blocking call
*/
clear_bit(BNX2FC_FLAG_UPLD_REQ_COMPL, &tgt->flags);
bnx2fc_send_session_disable_req(port, tgt);
/* * wait for upload to complete. 3 Secs * should be sufficient time for this process to complete.
*/
BNX2FC_TGT_DBG(tgt, "waiting for disable compl\n");
bnx2fc_upld_wait(tgt);
/* * traverse thru the active_q and tmf_q and cleanup * IOs in these lists
*/
BNX2FC_TGT_DBG(tgt, "flush/upload - disable wait flags = 0x%lx\n",
tgt->flags);
bnx2fc_flush_active_ios(tgt);
/* * This event_callback is called after successful completion of libfc * initiated target login. bnx2fc can proceed with initiating the session * establishment.
*/ void bnx2fc_rport_event_handler(struct fc_lport *lport, struct fc_rport_priv *rdata, enum fc_rport_event event)
{ struct fcoe_port *port = lport_priv(lport); struct bnx2fc_interface *interface = port->priv; struct bnx2fc_hba *hba = interface->hba; struct fc_rport *rport = rdata->rport; struct fc_rport_libfc_priv *rp; struct bnx2fc_rport *tgt;
u32 port_id;
BNX2FC_HBA_DBG(lport, "rport_event_hdlr: event = %d, port_id = 0x%x\n",
event, rdata->ids.port_id); switch (event) { case RPORT_EV_READY: if (!rport) {
printk(KERN_ERR PFX "rport is NULL: ERROR!\n"); break;
}
rp = rport->dd_data; if (rport->port_id == FC_FID_DIR_SERV) { /* * bnx2fc_rport structure doesn't exist for * directory server. * We should not come here, as lport will * take care of fabric login
*/
printk(KERN_ERR PFX "%x - rport_event_handler ERROR\n",
rdata->ids.port_id); break;
}
if (rdata->spp_type != FC_TYPE_FCP) {
BNX2FC_HBA_DBG(lport, "not FCP type target." " not offloading\n"); break;
} if (!(rdata->ids.roles & FC_RPORT_ROLE_FCP_TARGET)) {
BNX2FC_HBA_DBG(lport, "not FCP_TARGET" " not offloading\n"); break;
}
/* * Offload process is protected with hba mutex. * Use the same mutex_lock for upload process too
*/
mutex_lock(&hba->hba_mutex);
tgt = (struct bnx2fc_rport *)&rp[1];
/* This can happen when ADISC finds the same target */ if (test_bit(BNX2FC_FLAG_ENABLED, &tgt->flags)) {
BNX2FC_TGT_DBG(tgt, "already offloaded\n");
mutex_unlock(&hba->hba_mutex); return;
}
/* * Offload the session. This is a blocking call, and will * wait until the session is offloaded.
*/
bnx2fc_offload_session(port, tgt, rdata);
if (test_bit(BNX2FC_FLAG_ENABLED, &tgt->flags)) { /* Session is offloaded and enabled. */
BNX2FC_TGT_DBG(tgt, "sess offloaded\n"); /* This counter is protected with hba mutex */
hba->num_ofld_sess++;
set_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags);
} else { /* * Offload or enable would have failed. * In offload/enable completion path, the * rport would have already been removed
*/
BNX2FC_TGT_DBG(tgt, "Port is being logged off as " "offloaded flag not set\n");
}
mutex_unlock(&hba->hba_mutex); break; case RPORT_EV_LOGO: case RPORT_EV_FAILED: case RPORT_EV_STOP:
port_id = rdata->ids.port_id; if (port_id == FC_FID_DIR_SERV) break;
if (!rport) {
printk(KERN_INFO PFX "%x - rport not created Yet!!\n",
port_id); break;
}
rp = rport->dd_data;
mutex_lock(&hba->hba_mutex); /* * Perform session upload. Note that rdata->peers is already * removed from disc->rports list before we get this event.
*/
tgt = (struct bnx2fc_rport *)&rp[1];
if (!(test_bit(BNX2FC_FLAG_ENABLED, &tgt->flags))) {
mutex_unlock(&hba->hba_mutex); break;
}
clear_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags);
bnx2fc_upload_session(port, tgt);
hba->num_ofld_sess--;
BNX2FC_TGT_DBG(tgt, "UPLOAD num_ofld_sess = %d\n",
hba->num_ofld_sess); /* * Try to wake up the linkdown wait thread. If num_ofld_sess * is 0, the waiting therad wakes up
*/ if ((hba->wait_for_link_down) &&
(hba->num_ofld_sess == 0)) {
wake_up_interruptible(&hba->shutdown_wait);
}
mutex_unlock(&hba->hba_mutex);
break;
case RPORT_EV_NONE: break;
}
}
/** * bnx2fc_tgt_lookup() - Lookup a bnx2fc_rport by port_id * * @port: fcoe_port struct to lookup the target port on * @port_id: The remote port ID to look up
*/ struct bnx2fc_rport *bnx2fc_tgt_lookup(struct fcoe_port *port,
u32 port_id)
{ struct bnx2fc_interface *interface = port->priv; struct bnx2fc_hba *hba = interface->hba; struct bnx2fc_rport *tgt; struct fc_rport_priv *rdata; int i;
for (i = 0; i < BNX2FC_NUM_MAX_SESS; i++) {
tgt = hba->tgt_ofld_list[i]; if ((tgt) && (tgt->port == port)) {
rdata = tgt->rdata; if (rdata->ids.port_id == port_id) { if (rdata->rp_state != RPORT_ST_DELETE) {
BNX2FC_TGT_DBG(tgt, "rport " "obtained\n"); return tgt;
} else {
BNX2FC_TGT_DBG(tgt, "rport 0x%x " "is in DELETED state\n",
rdata->ids.port_id); return NULL;
}
}
}
} return NULL;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.