Commit 52ff878c authored by Vasu Dev's avatar Vasu Dev Committed by James Bottomley

[SCSI] fcoe, fnic, libfc: modifies current code paths to use EM anchor list

Modifies current code to use EM anchor list in EM allocation, EM free,
EM reset, exch allocation and exch lookup code paths.

 1. Modifies fc_exch_mgr_alloc to accept EM match function and then
    have allocated EM added to the lport using fc_exch_mgr_add API
    while also updating EM kref for newly added EM.

 2. Updates fc_exch_mgr_free API to accept only lport pointer instead
    EM and then have this API free all EMs of the lport from EM anchor
    list.

 3. Removes single lport pointer link from the EM, which was used in
    associating lport pointer in newly allocated exchange. Instead have
    lport pointer passed along new exchange allocation call path and
    then store passed lport pointer in newly allocated exchange, this
    will allow a single EM instance to be used across more than one
    lport and used in EM reset to reset only lport specific exchanges.

 4. Modifies fc_exch_mgr_reset to reset all EMs from the EM anchor list
    of the lport, adds additional exch lport pointer (ep->lp) check for
    shared EM case to reset exchange specific to a lport requested reset.

 5. Updates exch allocation API fc_exch_alloc to use EM anchor list and
    its anchor match func pointer. The fc_exch_alloc will walk the list
    of EMs until it finds a match, a match will be either null match
    func pointer or call to match function returning true value.

 6. Updates fc_exch_recv to accept incoming frame on local port using
    only lport pointer and frame pointer without specifying EM instance
    of incoming frame. Instead modified fc_exch_recv to locate EM for the
    incoming frame by matching xid of incoming frame against a EM xid range.
    This change was required to use EM list in libfc Rx path and after this
    change the lport fc_exch_mgr pointer emp is not needed anymore, so
    removed emp pointer.

 7. Updates fnic for removed lport emp pointer and above modified libfc APIs
    fc_exch_recv, fc_exch_mgr_alloc and fc_exch_mgr_free.

 8. Removes exch_get and exch_put from libfc_function_template as these
    are no longer needed with EM anchor list and its match function use.
    Also removes its default function fc_exch_get.

A defect this patch introduced regarding the libfc initialization order in
the fnic driver was fixed by Joe Eykholt <jeykholt@cisco.com>.
Signed-off-by: default avatarVasu Dev <vasu.dev@intel.com>
Signed-off-by: default avatarRobert Love <robert.w.love@intel.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent d459b7ea
......@@ -423,11 +423,8 @@ static int fcoe_shost_config(struct fc_lport *lp, struct Scsi_Host *shost,
*/
static inline int fcoe_em_config(struct fc_lport *lp)
{
BUG_ON(lp->emp);
lp->emp = fc_exch_mgr_alloc(lp, FC_CLASS_3,
FCOE_MIN_XID, FCOE_MAX_XID);
if (!lp->emp)
if (!fc_exch_mgr_alloc(lp, FC_CLASS_3, FCOE_MIN_XID,
FCOE_MAX_XID, NULL))
return -ENOMEM;
return 0;
......@@ -478,8 +475,7 @@ static int fcoe_if_destroy(struct net_device *netdev)
scsi_remove_host(lp->host);
/* There are no more rports or I/O, free the EM */
if (lp->emp)
fc_exch_mgr_free(lp->emp);
fc_exch_mgr_free(lp);
/* Free existing skbs */
fcoe_clean_pending_queue(lp);
......@@ -634,7 +630,7 @@ static int fcoe_if_create(struct net_device *netdev)
return rc;
out_lp_destroy:
fc_exch_mgr_free(lp->emp); /* Free the EM */
fc_exch_mgr_free(lp);
out_netdev_cleanup:
fcoe_netdev_cleanup(fc);
out_host_put:
......@@ -1277,7 +1273,7 @@ int fcoe_percpu_receive_thread(void *arg)
fh = fc_frame_header_get(fp);
if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA &&
fh->fh_type == FC_TYPE_FCP) {
fc_exch_recv(lp, lp->emp, fp);
fc_exch_recv(lp, fp);
continue;
}
if (fr_flags(fp) & FCPHF_CRC_UNCHECKED) {
......@@ -1298,7 +1294,7 @@ int fcoe_percpu_receive_thread(void *arg)
fc_frame_free(fp);
continue;
}
fc_exch_recv(lp, lp->emp, fp);
fc_exch_recv(lp, fp);
}
return 0;
}
......
......@@ -885,7 +885,7 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb)
stats->RxFrames++;
stats->RxWords += skb->len / FIP_BPW;
fc_exch_recv(lp, lp->emp, fp);
fc_exch_recv(lp, fp);
return;
len_err:
......
......@@ -115,7 +115,7 @@ void fnic_handle_frame(struct work_struct *work)
}
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
fc_exch_recv(lp, lp->emp, fp);
fc_exch_recv(lp, fp);
}
}
......
......@@ -671,14 +671,6 @@ static int __devinit fnic_probe(struct pci_dev *pdev,
lp->link_up = 0;
lp->tt = fnic_transport_template;
lp->emp = fc_exch_mgr_alloc(lp, FC_CLASS_3,
FCPIO_HOST_EXCH_RANGE_START,
FCPIO_HOST_EXCH_RANGE_END);
if (!lp->emp) {
err = -ENOMEM;
goto err_out_remove_scsi_host;
}
lp->max_retry_count = fnic->config.flogi_retries;
lp->max_rport_retry_count = fnic->config.plogi_retries;
lp->service_params = (FCP_SPPF_INIT_FCN | FCP_SPPF_RD_XRDY_DIS |
......@@ -693,12 +685,18 @@ static int __devinit fnic_probe(struct pci_dev *pdev,
fc_set_wwnn(lp, fnic->config.node_wwn);
fc_set_wwpn(lp, fnic->config.port_wwn);
fc_exch_init(lp);
fc_lport_init(lp);
fc_exch_init(lp);
fc_elsct_init(lp);
fc_rport_init(lp);
fc_disc_init(lp);
if (!fc_exch_mgr_alloc(lp, FC_CLASS_3, FCPIO_HOST_EXCH_RANGE_START,
FCPIO_HOST_EXCH_RANGE_END, NULL)) {
err = -ENOMEM;
goto err_out_remove_scsi_host;
}
fc_lport_config(lp);
if (fc_set_mfs(lp, fnic->config.maxdatafieldsize +
......@@ -738,7 +736,7 @@ static int __devinit fnic_probe(struct pci_dev *pdev,
return 0;
err_out_free_exch_mgr:
fc_exch_mgr_free(lp->emp);
fc_exch_mgr_free(lp);
err_out_remove_scsi_host:
fc_remove_host(fnic->lport->host);
scsi_remove_host(fnic->lport->host);
......@@ -827,7 +825,7 @@ static void __devexit fnic_remove(struct pci_dev *pdev)
fc_remove_host(fnic->lport->host);
scsi_remove_host(fnic->lport->host);
fc_exch_mgr_free(fnic->lport->emp);
fc_exch_mgr_free(fnic->lport);
vnic_dev_notify_unset(fnic->vdev);
fnic_free_vnic_resources(fnic);
fnic_free_intr(fnic);
......
This diff is collapsed.
......@@ -517,25 +517,6 @@ struct libfc_function_template {
*/
void (*exch_done)(struct fc_seq *sp);
/*
* Assigns a EM and a free XID for an new exchange and then
* allocates a new exchange and sequence pair.
* The fp can be used to determine free XID.
*
* STATUS: OPTIONAL
*/
struct fc_exch *(*exch_get)(struct fc_lport *lp, struct fc_frame *fp);
/*
* Release previously assigned XID by exch_get API.
* The LLD may implement this if XID is assigned by LLD
* in exch_get().
*
* STATUS: OPTIONAL
*/
void (*exch_put)(struct fc_lport *lp, struct fc_exch_mgr *mp,
u16 ex_id);
/*
* Start a new sequence on the same exchange/sequence tuple.
*
......@@ -703,7 +684,6 @@ struct fc_lport {
/* Associations */
struct Scsi_Host *host;
struct fc_exch_mgr *emp;
struct list_head ema_list;
struct fc_rport *dns_rp;
struct fc_rport *ptp_rp;
......@@ -996,27 +976,25 @@ void fc_exch_mgr_del(struct fc_exch_mgr_anchor *ema);
* a new exchange.
* The LLD may choose to have multiple EMs,
* e.g. one EM instance per CPU receive thread in LLD.
* The LLD can use exch_get() of struct libfc_function_template
* to specify XID for a new exchange within
* a specified EM instance.
*
* The em_idx to uniquely identify an EM instance.
* Specified match function is used in allocating exchanges
* from newly allocated EM.
*/
struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
enum fc_class class,
u16 min_xid,
u16 max_xid);
u16 max_xid,
bool (*match)(struct fc_frame *));
/*
* Free an exchange manager.
* Free all exchange managers of a lport.
*/
void fc_exch_mgr_free(struct fc_exch_mgr *mp);
void fc_exch_mgr_free(struct fc_lport *lport);
/*
* Receive a frame on specified local port and exchange manager.
*/
void fc_exch_recv(struct fc_lport *lp, struct fc_exch_mgr *mp,
struct fc_frame *fp);
void fc_exch_recv(struct fc_lport *lp, struct fc_frame *fp);
/*
* This function is for exch_seq_send function pointer in
......@@ -1057,20 +1035,10 @@ int fc_seq_exch_abort(const struct fc_seq *req_sp, unsigned int timer_msec);
*/
void fc_exch_done(struct fc_seq *sp);
/*
* Assigns a EM and XID for a frame and then allocates
* a new exchange and sequence pair.
* The fp can be used to determine free XID.
*/
struct fc_exch *fc_exch_get(struct fc_lport *lp, struct fc_frame *fp);
/*
* Allocate a new exchange and sequence pair.
* if ex_id is zero then next free exchange id
* from specified exchange manger mp will be assigned.
*/
struct fc_exch *fc_exch_alloc(struct fc_exch_mgr *mp,
struct fc_frame *fp, u16 ex_id);
struct fc_exch *fc_exch_alloc(struct fc_lport *lport, struct fc_frame *fp);
/*
* Start a new sequence on the same exchange as the supplied sequence.
*/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment