mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
scsi: fnic: Add support for fabric based solicited requests and responses
Add fdls_disc.c to support fabric based solicited requests and responses. Clean up obsolete code but keep the function template so as to not break compilation. Remove duplicate definitions from header files. Modify definitions of data members. Reported-by: kernel test robot <lkp@intel.com> Closes: https://lore.kernel.org/oe-kbuild-all/202406112309.8GiDUvIM-lkp@intel.com/ Closes: https://lore.kernel.org/oe-kbuild-all/202406120201.VakI9Dly-lkp@intel.com/ Closes: https://lore.kernel.org/oe-kbuild-all/202412080837.2JU0r2Ny-lkp@intel.com/ Reviewed-by: Sesidhar Baddela <sebaddel@cisco.com> Co-developed-by: Gian Carlo Boffa <gcboffa@cisco.com> Signed-off-by: Gian Carlo Boffa <gcboffa@cisco.com> Co-developed-by: Arulprabhu Ponnusamy <arulponn@cisco.com> Signed-off-by: Arulprabhu Ponnusamy <arulponn@cisco.com> Co-developed-by: Arun Easi <aeasi@cisco.com> Signed-off-by: Arun Easi <aeasi@cisco.com> Co-developed-by: Karan Tilak Kumar <kartilak@cisco.com> Signed-off-by: Karan Tilak Kumar <kartilak@cisco.com> Link: https://lore.kernel.org/r/20241212020312.4786-4-kartilak@cisco.com Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
d859d05ceb
commit
a63e78eb2b
8 changed files with 2592 additions and 192 deletions
|
@ -7,6 +7,7 @@ fnic-y := \
|
|||
fnic_main.o \
|
||||
fnic_res.o \
|
||||
fnic_fcs.o \
|
||||
fdls_disc.o \
|
||||
fnic_scsi.o \
|
||||
fnic_trace.o \
|
||||
fnic_debugfs.o \
|
||||
|
|
2180
drivers/scsi/fnic/fdls_disc.c
Normal file
2180
drivers/scsi/fnic/fdls_disc.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -12,6 +12,10 @@
|
|||
#include <linux/bitops.h>
|
||||
#include <scsi/libfc.h>
|
||||
#include <scsi/libfcoe.h>
|
||||
#include <scsi/scsi_cmnd.h>
|
||||
#include <scsi/scsi_transport.h>
|
||||
#include <scsi/scsi_transport_fc.h>
|
||||
#include <scsi/fc_frame.h>
|
||||
#include "fnic_io.h"
|
||||
#include "fnic_res.h"
|
||||
#include "fnic_trace.h"
|
||||
|
@ -24,6 +28,7 @@
|
|||
#include "vnic_intr.h"
|
||||
#include "vnic_stats.h"
|
||||
#include "vnic_scsi.h"
|
||||
#include "fnic_fdls.h"
|
||||
|
||||
#define DRV_NAME "fnic"
|
||||
#define DRV_DESCRIPTION "Cisco FCoE HBA Driver"
|
||||
|
@ -31,6 +36,7 @@
|
|||
#define PFX DRV_NAME ": "
|
||||
#define DFX DRV_NAME "%d: "
|
||||
|
||||
#define FABRIC_LOGO_MAX_RETRY 3
|
||||
#define DESC_CLEAN_LOW_WATERMARK 8
|
||||
#define FNIC_UCSM_DFLT_THROTTLE_CNT_BLD 16 /* UCSM default throttle count */
|
||||
#define FNIC_MIN_IO_REQ 256 /* Min IO throttle count */
|
||||
|
@ -38,6 +44,7 @@
|
|||
#define FNIC_DFLT_IO_REQ 256 /* Default scsi_cmnd tag map entries */
|
||||
#define FNIC_DFLT_QUEUE_DEPTH 256
|
||||
#define FNIC_STATS_RATE_LIMIT 4 /* limit rate at which stats are pulled up */
|
||||
#define LUN0_DELAY_TIME 9
|
||||
|
||||
/*
|
||||
* Tag bits used for special requests.
|
||||
|
@ -75,6 +82,8 @@
|
|||
#define FNIC_DEV_RST_TERM_DONE BIT(20)
|
||||
#define FNIC_DEV_RST_ABTS_PENDING BIT(21)
|
||||
|
||||
#define IS_FNIC_FCP_INITIATOR(fnic) (fnic->role == FNIC_ROLE_FCP_INITIATOR)
|
||||
|
||||
/*
|
||||
* fnic private data per SCSI command.
|
||||
* These fields are locked by the hashed io_req_lock.
|
||||
|
@ -213,12 +222,26 @@ enum fnic_state {
|
|||
|
||||
struct mempool;
|
||||
|
||||
enum fnic_role_e {
|
||||
FNIC_ROLE_FCP_INITIATOR = 0,
|
||||
};
|
||||
|
||||
enum fnic_evt {
|
||||
FNIC_EVT_START_VLAN_DISC = 1,
|
||||
FNIC_EVT_START_FCF_DISC = 2,
|
||||
FNIC_EVT_MAX,
|
||||
};
|
||||
|
||||
struct fnic_frame_list {
|
||||
/*
|
||||
* Link to frame lists
|
||||
*/
|
||||
struct list_head links;
|
||||
void *fp;
|
||||
int frame_len;
|
||||
int rx_ethhdr_stripped;
|
||||
};
|
||||
|
||||
struct fnic_event {
|
||||
struct list_head list;
|
||||
struct fnic *fnic;
|
||||
|
@ -235,6 +258,8 @@ struct fnic_cpy_wq {
|
|||
/* Per-instance private data structure */
|
||||
struct fnic {
|
||||
int fnic_num;
|
||||
enum fnic_role_e role;
|
||||
struct fnic_iport_s iport;
|
||||
struct fc_lport *lport;
|
||||
struct fcoe_ctlr ctlr; /* FIP FCoE controller structure */
|
||||
struct vnic_dev_bar bar0;
|
||||
|
@ -278,6 +303,7 @@ struct fnic {
|
|||
unsigned long state_flags; /* protected by host lock */
|
||||
enum fnic_state state;
|
||||
spinlock_t fnic_lock;
|
||||
unsigned long lock_flags;
|
||||
|
||||
u16 vlan_id; /* VLAN tag including priority */
|
||||
u8 data_src_addr[ETH_ALEN];
|
||||
|
@ -307,7 +333,9 @@ struct fnic {
|
|||
struct work_struct frame_work;
|
||||
struct work_struct flush_work;
|
||||
struct sk_buff_head frame_queue;
|
||||
struct sk_buff_head tx_queue;
|
||||
struct list_head tx_queue;
|
||||
mempool_t *frame_pool;
|
||||
mempool_t *frame_elem_pool;
|
||||
|
||||
/*** FIP related data members -- start ***/
|
||||
void (*set_vlan)(struct fnic *, u16 vlan);
|
||||
|
@ -361,6 +389,9 @@ void fnic_free_wq_buf(struct vnic_wq *wq, struct vnic_wq_buf *buf);
|
|||
void fnic_handle_frame(struct work_struct *work);
|
||||
void fnic_handle_link(struct work_struct *work);
|
||||
void fnic_handle_event(struct work_struct *work);
|
||||
void fdls_reclaim_oxid_handler(struct work_struct *work);
|
||||
void fdls_schedule_oxid_free(struct fnic_iport_s *iport, uint16_t *active_oxid);
|
||||
void fdls_schedule_oxid_free_retry_work(struct work_struct *work);
|
||||
int fnic_rq_cmpl_handler(struct fnic *fnic, int);
|
||||
int fnic_alloc_rq_frame(struct vnic_rq *rq);
|
||||
void fnic_free_rq_buf(struct vnic_rq *rq, struct vnic_rq_buf *buf);
|
||||
|
@ -397,7 +428,6 @@ void fnic_handle_fip_frame(struct work_struct *work);
|
|||
void fnic_handle_fip_event(struct fnic *fnic);
|
||||
void fnic_fcoe_reset_vlans(struct fnic *fnic);
|
||||
void fnic_fcoe_evlist_free(struct fnic *fnic);
|
||||
extern void fnic_handle_fip_timer(struct fnic *fnic);
|
||||
|
||||
static inline int
|
||||
fnic_chk_state_flags_locked(struct fnic *fnic, unsigned long st_flags)
|
||||
|
@ -406,4 +436,74 @@ fnic_chk_state_flags_locked(struct fnic *fnic, unsigned long st_flags)
|
|||
}
|
||||
void __fnic_set_state_flags(struct fnic *, unsigned long, unsigned long);
|
||||
void fnic_dump_fchost_stats(struct Scsi_Host *, struct fc_host_statistics *);
|
||||
void fnic_free_txq(struct list_head *head);
|
||||
|
||||
struct fnic_scsi_iter_data {
|
||||
struct fnic *fnic;
|
||||
void *data1;
|
||||
void *data2;
|
||||
bool (*fn)(struct fnic *fnic, struct scsi_cmnd *sc,
|
||||
void *data1, void *data2);
|
||||
};
|
||||
|
||||
static inline bool
|
||||
fnic_io_iter_handler(struct scsi_cmnd *sc, void *iter_data)
|
||||
{
|
||||
struct fnic_scsi_iter_data *iter = iter_data;
|
||||
|
||||
return iter->fn(iter->fnic, sc, iter->data1, iter->data2);
|
||||
}
|
||||
|
||||
static inline void
|
||||
fnic_scsi_io_iter(struct fnic *fnic,
|
||||
bool (*fn)(struct fnic *fnic, struct scsi_cmnd *sc,
|
||||
void *data1, void *data2),
|
||||
void *data1, void *data2)
|
||||
{
|
||||
struct fnic_scsi_iter_data iter_data = {
|
||||
.fn = fn,
|
||||
.fnic = fnic,
|
||||
.data1 = data1,
|
||||
.data2 = data2,
|
||||
};
|
||||
scsi_host_busy_iter(fnic->lport->host, fnic_io_iter_handler, &iter_data);
|
||||
}
|
||||
|
||||
#ifdef FNIC_DEBUG
|
||||
static inline void
|
||||
fnic_debug_dump(struct fnic *fnic, uint8_t *u8arr, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i = i+8) {
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
|
||||
"%d: %02x %02x %02x %02x %02x %02x %02x %02x", i / 8,
|
||||
u8arr[i + 0], u8arr[i + 1], u8arr[i + 2], u8arr[i + 3],
|
||||
u8arr[i + 4], u8arr[i + 5], u8arr[i + 6], u8arr[i + 7]);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
fnic_debug_dump_fc_frame(struct fnic *fnic, struct fc_frame_header *fchdr,
|
||||
int len, char *pfx)
|
||||
{
|
||||
uint32_t s_id, d_id;
|
||||
|
||||
s_id = ntoh24(fchdr->fh_s_id);
|
||||
d_id = ntoh24(fchdr->fh_d_id);
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
|
||||
"%s packet contents: sid/did/type/oxid = 0x%x/0x%x/0x%x/0x%x (len = %d)\n",
|
||||
pfx, s_id, d_id, fchdr->fh_type,
|
||||
FNIC_STD_GET_OX_ID(fchdr), len);
|
||||
|
||||
fnic_debug_dump(fnic, (uint8_t *)fchdr, len);
|
||||
|
||||
}
|
||||
#else /* FNIC_DEBUG */
|
||||
static inline void
|
||||
fnic_debug_dump(struct fnic *fnic, uint8_t *u8arr, int len) {}
|
||||
static inline void
|
||||
fnic_debug_dump_fc_frame(struct fnic *fnic, struct fc_frame_header *fchdr,
|
||||
uint32_t len, char *pfx) {}
|
||||
#endif /* FNIC_DEBUG */
|
||||
#endif /* _FNIC_H_ */
|
||||
|
|
|
@ -17,9 +17,12 @@
|
|||
#include <scsi/fc/fc_fcoe.h>
|
||||
#include <scsi/fc_frame.h>
|
||||
#include <scsi/libfc.h>
|
||||
#include <scsi/scsi_transport_fc.h>
|
||||
#include "fnic_io.h"
|
||||
#include "fnic.h"
|
||||
#include "fnic_fip.h"
|
||||
#include "fnic_fdls.h"
|
||||
#include "fdls_fc.h"
|
||||
#include "cq_enet_desc.h"
|
||||
#include "cq_exch_desc.h"
|
||||
|
||||
|
@ -28,12 +31,91 @@ struct workqueue_struct *fnic_fip_queue;
|
|||
struct workqueue_struct *fnic_event_queue;
|
||||
|
||||
static void fnic_set_eth_mode(struct fnic *);
|
||||
static void fnic_fcoe_send_vlan_req(struct fnic *fnic);
|
||||
static void fnic_fcoe_start_fcf_disc(struct fnic *fnic);
|
||||
static void fnic_fcoe_process_vlan_resp(struct fnic *fnic, struct sk_buff *);
|
||||
static int fnic_fcoe_vlan_check(struct fnic *fnic, u16 flag);
|
||||
static int fnic_fcoe_handle_fip_frame(struct fnic *fnic, struct sk_buff *skb);
|
||||
|
||||
static uint8_t FCOE_ALL_FCF_MAC[6] = FC_FCOE_FLOGI_MAC;
|
||||
|
||||
/*
|
||||
* Internal Functions
|
||||
* This function will initialize the src_mac address to be
|
||||
* used in outgoing frames
|
||||
*/
|
||||
static inline void fnic_fdls_set_fcoe_srcmac(struct fnic *fnic,
|
||||
uint8_t *src_mac)
|
||||
{
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"Setting src mac: %02x:%02x:%02x:%02x:%02x:%02x",
|
||||
src_mac[0], src_mac[1], src_mac[2], src_mac[3],
|
||||
src_mac[4], src_mac[5]);
|
||||
|
||||
memcpy(fnic->iport.fpma, src_mac, 6);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function will initialize the dst_mac address to be
|
||||
* used in outgoing frames
|
||||
*/
|
||||
static inline void fnic_fdls_set_fcoe_dstmac(struct fnic *fnic,
|
||||
uint8_t *dst_mac)
|
||||
{
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"Setting dst mac: %02x:%02x:%02x:%02x:%02x:%02x",
|
||||
dst_mac[0], dst_mac[1], dst_mac[2], dst_mac[3],
|
||||
dst_mac[4], dst_mac[5]);
|
||||
|
||||
memcpy(fnic->iport.fcfmac, dst_mac, 6);
|
||||
}
|
||||
|
||||
/*
|
||||
* FPMA can be either taken from ethhdr(dst_mac) or flogi resp
|
||||
* or derive from FC_MAP and FCID combination. While it should be
|
||||
* same, revisit this if there is any possibility of not-correct.
|
||||
*/
|
||||
void fnic_fdls_learn_fcoe_macs(struct fnic_iport_s *iport, void *rx_frame,
|
||||
uint8_t *fcid)
|
||||
{
|
||||
struct fnic *fnic = iport->fnic;
|
||||
struct ethhdr *ethhdr = (struct ethhdr *) rx_frame;
|
||||
uint8_t fcmac[6] = { 0x0E, 0xFC, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
memcpy(&fcmac[3], fcid, 3);
|
||||
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"learn fcoe: dst_mac: %02x:%02x:%02x:%02x:%02x:%02x",
|
||||
ethhdr->h_dest[0], ethhdr->h_dest[1],
|
||||
ethhdr->h_dest[2], ethhdr->h_dest[3],
|
||||
ethhdr->h_dest[4], ethhdr->h_dest[5]);
|
||||
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"learn fcoe: fc_mac: %02x:%02x:%02x:%02x:%02x:%02x",
|
||||
fcmac[0], fcmac[1], fcmac[2], fcmac[3], fcmac[4],
|
||||
fcmac[5]);
|
||||
|
||||
fnic_fdls_set_fcoe_srcmac(fnic, fcmac);
|
||||
fnic_fdls_set_fcoe_dstmac(fnic, ethhdr->h_source);
|
||||
}
|
||||
|
||||
void fnic_fdls_init(struct fnic *fnic, int usefip)
|
||||
{
|
||||
struct fnic_iport_s *iport = &fnic->iport;
|
||||
|
||||
/* Initialize iPort structure */
|
||||
iport->state = FNIC_IPORT_STATE_INIT;
|
||||
iport->fnic = fnic;
|
||||
iport->usefip = usefip;
|
||||
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"iportsrcmac: %02x:%02x:%02x:%02x:%02x:%02x",
|
||||
iport->hwmac[0], iport->hwmac[1], iport->hwmac[2],
|
||||
iport->hwmac[3], iport->hwmac[4], iport->hwmac[5]);
|
||||
|
||||
INIT_LIST_HEAD(&iport->tport_list);
|
||||
INIT_LIST_HEAD(&iport->tport_list_pending_del);
|
||||
}
|
||||
|
||||
void fnic_handle_link(struct work_struct *work)
|
||||
{
|
||||
struct fnic *fnic = container_of(work, struct fnic, link_work);
|
||||
|
@ -363,7 +445,7 @@ static inline int is_fnic_fip_flogi_reject(struct fcoe_ctlr *fip,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void fnic_fcoe_send_vlan_req(struct fnic *fnic)
|
||||
void fnic_fcoe_send_vlan_req(struct fnic *fnic)
|
||||
{
|
||||
struct fcoe_ctlr *fip = &fnic->ctlr;
|
||||
struct fnic_stats *fnic_stats = &fnic->fnic_stats;
|
||||
|
@ -1068,116 +1150,137 @@ free_skb:
|
|||
/*
|
||||
* Send FC frame.
|
||||
*/
|
||||
static int fnic_send_frame(struct fnic *fnic, struct fc_frame *fp)
|
||||
static int fnic_send_frame(struct fnic *fnic, void *frame, int frame_len)
|
||||
{
|
||||
struct vnic_wq *wq = &fnic->wq[0];
|
||||
struct sk_buff *skb;
|
||||
dma_addr_t pa;
|
||||
struct ethhdr *eth_hdr;
|
||||
struct vlan_ethhdr *vlan_hdr;
|
||||
struct fcoe_hdr *fcoe_hdr;
|
||||
struct fc_frame_header *fh;
|
||||
u32 tot_len, eth_hdr_len;
|
||||
int ret = 0;
|
||||
unsigned long flags;
|
||||
|
||||
fh = fc_frame_header_get(fp);
|
||||
skb = fp_skb(fp);
|
||||
pa = dma_map_single(&fnic->pdev->dev, frame, frame_len, DMA_TO_DEVICE);
|
||||
|
||||
if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ) &&
|
||||
fcoe_ctlr_els_send(&fnic->ctlr, fnic->lport, skb))
|
||||
return 0;
|
||||
|
||||
if (!fnic->vlan_hw_insert) {
|
||||
eth_hdr_len = sizeof(*vlan_hdr) + sizeof(*fcoe_hdr);
|
||||
vlan_hdr = skb_push(skb, eth_hdr_len);
|
||||
eth_hdr = (struct ethhdr *)vlan_hdr;
|
||||
vlan_hdr->h_vlan_proto = htons(ETH_P_8021Q);
|
||||
vlan_hdr->h_vlan_encapsulated_proto = htons(ETH_P_FCOE);
|
||||
vlan_hdr->h_vlan_TCI = htons(fnic->vlan_id);
|
||||
fcoe_hdr = (struct fcoe_hdr *)(vlan_hdr + 1);
|
||||
} else {
|
||||
eth_hdr_len = sizeof(*eth_hdr) + sizeof(*fcoe_hdr);
|
||||
eth_hdr = skb_push(skb, eth_hdr_len);
|
||||
eth_hdr->h_proto = htons(ETH_P_FCOE);
|
||||
fcoe_hdr = (struct fcoe_hdr *)(eth_hdr + 1);
|
||||
}
|
||||
|
||||
if (fnic->ctlr.map_dest)
|
||||
fc_fcoe_set_mac(eth_hdr->h_dest, fh->fh_d_id);
|
||||
else
|
||||
memcpy(eth_hdr->h_dest, fnic->ctlr.dest_addr, ETH_ALEN);
|
||||
memcpy(eth_hdr->h_source, fnic->data_src_addr, ETH_ALEN);
|
||||
|
||||
tot_len = skb->len;
|
||||
BUG_ON(tot_len % 4);
|
||||
|
||||
memset(fcoe_hdr, 0, sizeof(*fcoe_hdr));
|
||||
fcoe_hdr->fcoe_sof = fr_sof(fp);
|
||||
if (FC_FCOE_VER)
|
||||
FC_FCOE_ENCAPS_VER(fcoe_hdr, FC_FCOE_VER);
|
||||
|
||||
pa = dma_map_single(&fnic->pdev->dev, eth_hdr, tot_len, DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(&fnic->pdev->dev, pa)) {
|
||||
ret = -ENOMEM;
|
||||
printk(KERN_ERR "DMA map failed with error %d\n", ret);
|
||||
goto free_skb_on_err;
|
||||
}
|
||||
|
||||
if ((fnic_fc_trace_set_data(fnic->lport->host->host_no, FNIC_FC_SEND,
|
||||
(char *)eth_hdr, tot_len)) != 0) {
|
||||
printk(KERN_ERR "fnic ctlr frame trace error!!!");
|
||||
if ((fnic_fc_trace_set_data(fnic->fnic_num,
|
||||
FNIC_FC_SEND | 0x80, (char *) frame,
|
||||
frame_len)) != 0) {
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"fnic ctlr frame trace error");
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&fnic->wq_lock[0], flags);
|
||||
|
||||
if (!vnic_wq_desc_avail(wq)) {
|
||||
dma_unmap_single(&fnic->pdev->dev, pa, tot_len, DMA_TO_DEVICE);
|
||||
dma_unmap_single(&fnic->pdev->dev, pa, frame_len, DMA_TO_DEVICE);
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"vnic work queue descriptor is not available");
|
||||
ret = -1;
|
||||
goto irq_restore;
|
||||
goto fnic_send_frame_end;
|
||||
}
|
||||
|
||||
fnic_queue_wq_desc(wq, skb, pa, tot_len, fr_eof(fp),
|
||||
0 /* hw inserts cos value */,
|
||||
fnic->vlan_id, 1, 1, 1);
|
||||
/* hw inserts cos value */
|
||||
fnic_queue_wq_desc(wq, frame, pa, frame_len, FC_EOF_T,
|
||||
0, fnic->vlan_id, 1, 1, 1);
|
||||
|
||||
irq_restore:
|
||||
fnic_send_frame_end:
|
||||
spin_unlock_irqrestore(&fnic->wq_lock[0], flags);
|
||||
|
||||
free_skb_on_err:
|
||||
if (ret)
|
||||
dev_kfree_skb_any(fp_skb(fp));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* fnic_send
|
||||
* Routine to send a raw frame
|
||||
/**
|
||||
* fdls_send_fcoe_frame - send a filled-in FC frame, filling in eth and FCoE
|
||||
* info. This interface is used only in the non fast path. (login, fabric
|
||||
* registrations etc.)
|
||||
*
|
||||
* @fnic: fnic instance
|
||||
* @frame: frame structure with FC payload filled in
|
||||
* @frame_size: length of the frame to be sent
|
||||
* @srcmac: source mac address
|
||||
* @dstmac: destination mac address
|
||||
*
|
||||
* Called with the fnic lock held.
|
||||
*/
|
||||
int fnic_send(struct fc_lport *lp, struct fc_frame *fp)
|
||||
static int
|
||||
fdls_send_fcoe_frame(struct fnic *fnic, void *frame, int frame_size,
|
||||
uint8_t *srcmac, uint8_t *dstmac)
|
||||
{
|
||||
struct fnic *fnic = lport_priv(lp);
|
||||
unsigned long flags;
|
||||
struct ethhdr *pethhdr;
|
||||
struct fcoe_hdr *pfcoe_hdr;
|
||||
struct fnic_frame_list *frame_elem;
|
||||
int len = frame_size;
|
||||
int ret;
|
||||
struct fc_frame_header *fchdr = (struct fc_frame_header *) (frame +
|
||||
FNIC_ETH_FCOE_HDRS_OFFSET);
|
||||
|
||||
if (fnic->in_remove) {
|
||||
dev_kfree_skb(fp_skb(fp));
|
||||
return -1;
|
||||
}
|
||||
pethhdr = (struct ethhdr *) frame;
|
||||
pethhdr->h_proto = cpu_to_be16(ETH_P_FCOE);
|
||||
|
||||
memcpy(pethhdr->h_source, srcmac, ETH_ALEN);
|
||||
memcpy(pethhdr->h_dest, dstmac, ETH_ALEN);
|
||||
|
||||
pfcoe_hdr = (struct fcoe_hdr *) (frame + sizeof(struct ethhdr));
|
||||
pfcoe_hdr->fcoe_sof = FC_SOF_I3;
|
||||
|
||||
/*
|
||||
* Queue frame if in a transitional state.
|
||||
* This occurs while registering the Port_ID / MAC address after FLOGI.
|
||||
*/
|
||||
spin_lock_irqsave(&fnic->fnic_lock, flags);
|
||||
if (fnic->state != FNIC_IN_FC_MODE && fnic->state != FNIC_IN_ETH_MODE) {
|
||||
skb_queue_tail(&fnic->tx_queue, fp_skb(fp));
|
||||
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
|
||||
if ((fnic->state != FNIC_IN_FC_MODE)
|
||||
&& (fnic->state != FNIC_IN_ETH_MODE)) {
|
||||
frame_elem = mempool_alloc(fnic->frame_elem_pool,
|
||||
GFP_ATOMIC | __GFP_ZERO);
|
||||
if (!frame_elem) {
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"Failed to allocate memory for frame elem");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
|
||||
"Queueing FC frame: sid/did/type/oxid = 0x%x/0x%x/0x%x/0x%x\n",
|
||||
ntoh24(fchdr->fh_s_id), ntoh24(fchdr->fh_d_id),
|
||||
fchdr->fh_type, FNIC_STD_GET_OX_ID(fchdr));
|
||||
|
||||
frame_elem->fp = frame;
|
||||
frame_elem->frame_len = len;
|
||||
list_add_tail(&frame_elem->links, &fnic->tx_queue);
|
||||
return 0;
|
||||
}
|
||||
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
|
||||
|
||||
return fnic_send_frame(fnic, fp);
|
||||
fnic_debug_dump_fc_frame(fnic, fchdr, frame_size, "Outgoing");
|
||||
|
||||
ret = fnic_send_frame(fnic, frame, len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void fnic_send_fcoe_frame(struct fnic_iport_s *iport, void *frame,
|
||||
int frame_size)
|
||||
{
|
||||
struct fnic *fnic = iport->fnic;
|
||||
uint8_t *dstmac, *srcmac;
|
||||
|
||||
/* If module unload is in-progress, don't send */
|
||||
if (fnic->in_remove)
|
||||
return;
|
||||
|
||||
if (iport->fabric.flags & FNIC_FDLS_FPMA_LEARNT) {
|
||||
srcmac = iport->fpma;
|
||||
dstmac = iport->fcfmac;
|
||||
} else {
|
||||
srcmac = iport->hwmac;
|
||||
dstmac = FCOE_ALL_FCF_MAC;
|
||||
}
|
||||
|
||||
fdls_send_fcoe_frame(fnic, frame, frame_size, srcmac, dstmac);
|
||||
}
|
||||
|
||||
int
|
||||
fnic_send_fip_frame(struct fnic_iport_s *iport, void *frame,
|
||||
int frame_size)
|
||||
{
|
||||
struct fnic *fnic = iport->fnic;
|
||||
|
||||
if (fnic->in_remove)
|
||||
return -1;
|
||||
|
||||
return fnic_send_frame(fnic, frame, frame_size);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1193,15 +1296,67 @@ int fnic_send(struct fc_lport *lp, struct fc_frame *fp)
|
|||
void fnic_flush_tx(struct work_struct *work)
|
||||
{
|
||||
struct fnic *fnic = container_of(work, struct fnic, flush_work);
|
||||
struct sk_buff *skb;
|
||||
struct fc_frame *fp;
|
||||
struct fnic_frame_list *cur_frame, *next;
|
||||
|
||||
while ((skb = skb_dequeue(&fnic->tx_queue))) {
|
||||
fp = (struct fc_frame *)skb;
|
||||
fnic_send_frame(fnic, fp);
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"Flush queued frames");
|
||||
|
||||
list_for_each_entry_safe(cur_frame, next, &fnic->tx_queue, links) {
|
||||
fp = cur_frame->fp;
|
||||
list_del(&cur_frame->links);
|
||||
fnic_send_frame(fnic, fp, cur_frame->frame_len);
|
||||
mempool_free(cur_frame, fnic->frame_elem_pool);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
fnic_fdls_register_portid(struct fnic_iport_s *iport, u32 port_id,
|
||||
void *fp)
|
||||
{
|
||||
struct fnic *fnic = iport->fnic;
|
||||
struct ethhdr *ethhdr;
|
||||
int ret;
|
||||
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"Setting port id: 0x%x fp: 0x%p fnic state: %d", port_id,
|
||||
fp, fnic->state);
|
||||
|
||||
if (fp) {
|
||||
ethhdr = (struct ethhdr *) fp;
|
||||
vnic_dev_add_addr(fnic->vdev, ethhdr->h_dest);
|
||||
}
|
||||
|
||||
/* Change state to reflect transition to FC mode */
|
||||
if (fnic->state == FNIC_IN_ETH_MODE || fnic->state == FNIC_IN_FC_MODE)
|
||||
fnic->state = FNIC_IN_ETH_TRANS_FC_MODE;
|
||||
else {
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"Unexpected fnic state while processing FLOGI response\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send FLOGI registration to firmware to set up FC mode.
|
||||
* The new address will be set up when registration completes.
|
||||
*/
|
||||
ret = fnic_flogi_reg_handler(fnic, port_id);
|
||||
if (ret < 0) {
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"FLOGI registration error ret: %d fnic state: %d\n",
|
||||
ret, fnic->state);
|
||||
if (fnic->state == FNIC_IN_ETH_TRANS_FC_MODE)
|
||||
fnic->state = FNIC_IN_ETH_MODE;
|
||||
|
||||
return -1;
|
||||
}
|
||||
iport->fabric.flags |= FNIC_FDLS_FPMA_LEARNT;
|
||||
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"FLOGI registration success\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* fnic_set_eth_mode() - put fnic into ethernet mode.
|
||||
* @fnic: fnic device
|
||||
|
@ -1240,6 +1395,17 @@ again:
|
|||
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
|
||||
}
|
||||
|
||||
void fnic_free_txq(struct list_head *head)
|
||||
{
|
||||
struct fnic_frame_list *cur_frame, *next;
|
||||
|
||||
list_for_each_entry_safe(cur_frame, next, head, links) {
|
||||
list_del(&cur_frame->links);
|
||||
kfree(cur_frame->fp);
|
||||
kfree(cur_frame);
|
||||
}
|
||||
}
|
||||
|
||||
static void fnic_wq_complete_frame_send(struct vnic_wq *wq,
|
||||
struct cq_desc *cq_desc,
|
||||
struct vnic_wq_buf *buf, void *opaque)
|
||||
|
@ -1319,88 +1485,3 @@ void fnic_fcoe_reset_vlans(struct fnic *fnic)
|
|||
spin_unlock_irqrestore(&fnic->vlans_lock, flags);
|
||||
}
|
||||
|
||||
void fnic_handle_fip_timer(struct fnic *fnic)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct fcoe_vlan *vlan;
|
||||
struct fnic_stats *fnic_stats = &fnic->fnic_stats;
|
||||
u64 sol_time;
|
||||
|
||||
spin_lock_irqsave(&fnic->fnic_lock, flags);
|
||||
if (fnic->stop_rx_link_events) {
|
||||
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
|
||||
return;
|
||||
}
|
||||
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
|
||||
|
||||
if (fnic->ctlr.mode == FIP_MODE_NON_FIP)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&fnic->vlans_lock, flags);
|
||||
if (list_empty(&fnic->vlans)) {
|
||||
spin_unlock_irqrestore(&fnic->vlans_lock, flags);
|
||||
/* no vlans available, try again */
|
||||
if (unlikely(fnic_log_level & FNIC_FCS_LOGGING))
|
||||
if (printk_ratelimit())
|
||||
shost_printk(KERN_DEBUG, fnic->lport->host,
|
||||
"Start VLAN Discovery\n");
|
||||
fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC);
|
||||
return;
|
||||
}
|
||||
|
||||
vlan = list_first_entry(&fnic->vlans, struct fcoe_vlan, list);
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
|
||||
"fip_timer: vlan %d state %d sol_count %d\n",
|
||||
vlan->vid, vlan->state, vlan->sol_count);
|
||||
switch (vlan->state) {
|
||||
case FIP_VLAN_USED:
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, fnic->fnic_num,
|
||||
"FIP VLAN is selected for FC transaction\n");
|
||||
spin_unlock_irqrestore(&fnic->vlans_lock, flags);
|
||||
break;
|
||||
case FIP_VLAN_FAILED:
|
||||
spin_unlock_irqrestore(&fnic->vlans_lock, flags);
|
||||
/* if all vlans are in failed state, restart vlan disc */
|
||||
if (unlikely(fnic_log_level & FNIC_FCS_LOGGING))
|
||||
if (printk_ratelimit())
|
||||
shost_printk(KERN_DEBUG, fnic->lport->host,
|
||||
"Start VLAN Discovery\n");
|
||||
fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC);
|
||||
break;
|
||||
case FIP_VLAN_SENT:
|
||||
if (vlan->sol_count >= FCOE_CTLR_MAX_SOL) {
|
||||
/*
|
||||
* no response on this vlan, remove from the list.
|
||||
* Try the next vlan
|
||||
*/
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"Dequeue this VLAN ID %d from list\n",
|
||||
vlan->vid);
|
||||
list_del(&vlan->list);
|
||||
kfree(vlan);
|
||||
vlan = NULL;
|
||||
if (list_empty(&fnic->vlans)) {
|
||||
/* we exhausted all vlans, restart vlan disc */
|
||||
spin_unlock_irqrestore(&fnic->vlans_lock,
|
||||
flags);
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, fnic->fnic_num,
|
||||
"fip_timer: vlan list empty, "
|
||||
"trigger vlan disc\n");
|
||||
fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC);
|
||||
return;
|
||||
}
|
||||
/* check the next vlan */
|
||||
vlan = list_first_entry(&fnic->vlans, struct fcoe_vlan,
|
||||
list);
|
||||
fnic->set_vlan(fnic, vlan->vid);
|
||||
vlan->state = FIP_VLAN_SENT; /* sent now */
|
||||
}
|
||||
spin_unlock_irqrestore(&fnic->vlans_lock, flags);
|
||||
atomic64_inc(&fnic_stats->vlan_stats.sol_expiry_count);
|
||||
vlan->sol_count++;
|
||||
sol_time = jiffies + msecs_to_jiffies
|
||||
(FCOE_CTLR_START_DELAY);
|
||||
mod_timer(&fnic->fip_timer, round_jiffies(sol_time));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -402,7 +402,6 @@ int fnic_send_fip_frame(struct fnic_iport_s *iport,
|
|||
void *frame, int frame_size);
|
||||
void fnic_fdls_learn_fcoe_macs(struct fnic_iport_s *iport, void *rx_frame,
|
||||
uint8_t *fcid);
|
||||
|
||||
void fnic_fdls_add_tport(struct fnic_iport_s *iport,
|
||||
struct fnic_tport_s *tport, unsigned long flags);
|
||||
void fnic_fdls_remove_tport(struct fnic_iport_s *iport,
|
||||
|
|
|
@ -55,15 +55,4 @@ struct fnic_io_req {
|
|||
unsigned int tag;
|
||||
struct scsi_cmnd *sc; /* midlayer's cmd pointer */
|
||||
};
|
||||
|
||||
enum fnic_port_speeds {
|
||||
DCEM_PORTSPEED_NONE = 0,
|
||||
DCEM_PORTSPEED_1G = 1000,
|
||||
DCEM_PORTSPEED_10G = 10000,
|
||||
DCEM_PORTSPEED_20G = 20000,
|
||||
DCEM_PORTSPEED_25G = 25000,
|
||||
DCEM_PORTSPEED_40G = 40000,
|
||||
DCEM_PORTSPEED_4x10G = 41000,
|
||||
DCEM_PORTSPEED_100G = 100000,
|
||||
};
|
||||
#endif /* _FNIC_IO_H_ */
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
#include "fnic_io.h"
|
||||
#include "fnic_fip.h"
|
||||
#include "fnic.h"
|
||||
#include "fnic_fdls.h"
|
||||
#include "fdls_fc.h"
|
||||
|
||||
#define PCI_DEVICE_ID_CISCO_FNIC 0x0045
|
||||
|
||||
|
@ -39,6 +41,8 @@
|
|||
|
||||
static struct kmem_cache *fnic_sgl_cache[FNIC_SGL_NUM_CACHES];
|
||||
static struct kmem_cache *fnic_io_req_cache;
|
||||
static struct kmem_cache *fdls_frame_cache;
|
||||
static struct kmem_cache *fdls_frame_elem_cache;
|
||||
static LIST_HEAD(fnic_list);
|
||||
static DEFINE_SPINLOCK(fnic_list_lock);
|
||||
static DEFINE_IDA(fnic_ida);
|
||||
|
@ -80,7 +84,6 @@ module_param(fnic_max_qdepth, uint, S_IRUGO|S_IWUSR);
|
|||
MODULE_PARM_DESC(fnic_max_qdepth, "Queue depth to report for each LUN");
|
||||
|
||||
static struct libfc_function_template fnic_transport_template = {
|
||||
.frame_send = fnic_send,
|
||||
.lport_set_port_id = fnic_set_port_id,
|
||||
.fcp_abort_io = fnic_empty_scsi_cleanup,
|
||||
.fcp_cleanup = fnic_empty_scsi_cleanup,
|
||||
|
@ -413,7 +416,7 @@ static void fnic_fip_notify_timer(struct timer_list *t)
|
|||
{
|
||||
struct fnic *fnic = from_timer(fnic, t, fip_timer);
|
||||
|
||||
fnic_handle_fip_timer(fnic);
|
||||
/* Placeholder function */
|
||||
}
|
||||
|
||||
static void fnic_notify_timer_start(struct fnic *fnic)
|
||||
|
@ -515,6 +518,8 @@ static int fnic_cleanup(struct fnic *fnic)
|
|||
vnic_intr_clean(&fnic->intr[i]);
|
||||
|
||||
mempool_destroy(fnic->io_req_pool);
|
||||
mempool_destroy(fnic->frame_pool);
|
||||
mempool_destroy(fnic->frame_elem_pool);
|
||||
for (i = 0; i < FNIC_SGL_NUM_CACHES; i++)
|
||||
mempool_destroy(fnic->io_sgl_pool[i]);
|
||||
|
||||
|
@ -787,6 +792,17 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
goto err_out_free_dflt_pool;
|
||||
fnic->io_sgl_pool[FNIC_SGL_CACHE_MAX] = pool;
|
||||
|
||||
pool = mempool_create_slab_pool(FDLS_MIN_FRAMES, fdls_frame_cache);
|
||||
if (!pool)
|
||||
goto err_out_fdls_frame_pool;
|
||||
fnic->frame_pool = pool;
|
||||
|
||||
pool = mempool_create_slab_pool(FDLS_MIN_FRAME_ELEM,
|
||||
fdls_frame_elem_cache);
|
||||
if (!pool)
|
||||
goto err_out_fdls_frame_elem_pool;
|
||||
fnic->frame_elem_pool = pool;
|
||||
|
||||
/* setup vlan config, hw inserts vlan header */
|
||||
fnic->vlan_hw_insert = 1;
|
||||
fnic->vlan_id = 0;
|
||||
|
@ -921,7 +937,7 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
INIT_WORK(&fnic->frame_work, fnic_handle_frame);
|
||||
INIT_WORK(&fnic->flush_work, fnic_flush_tx);
|
||||
skb_queue_head_init(&fnic->frame_queue);
|
||||
skb_queue_head_init(&fnic->tx_queue);
|
||||
INIT_LIST_HEAD(&fnic->tx_queue);
|
||||
|
||||
fc_fabric_login(lp);
|
||||
|
||||
|
@ -946,6 +962,10 @@ err_out_request_intr:
|
|||
vnic_rq_clean(&fnic->rq[i], fnic_free_rq_buf);
|
||||
err_out_rq_buf:
|
||||
vnic_dev_notify_unset(fnic->vdev);
|
||||
mempool_destroy(fnic->frame_elem_pool);
|
||||
err_out_fdls_frame_elem_pool:
|
||||
mempool_destroy(fnic->frame_pool);
|
||||
err_out_fdls_frame_pool:
|
||||
err_out_free_max_pool:
|
||||
mempool_destroy(fnic->io_sgl_pool[FNIC_SGL_CACHE_MAX]);
|
||||
err_out_free_dflt_pool:
|
||||
|
@ -985,6 +1005,14 @@ static void fnic_remove(struct pci_dev *pdev)
|
|||
unsigned long flags;
|
||||
int hwq;
|
||||
|
||||
/*
|
||||
* Sometimes when probe() fails and do not exit with an error code,
|
||||
* remove() gets called with 'drvdata' not set. Avoid a crash by
|
||||
* adding a defensive check.
|
||||
*/
|
||||
if (!fnic)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Mark state so that the workqueue thread stops forwarding
|
||||
* received frames and link events to the local port. ISR and
|
||||
|
@ -1004,7 +1032,7 @@ static void fnic_remove(struct pci_dev *pdev)
|
|||
*/
|
||||
flush_workqueue(fnic_event_queue);
|
||||
skb_queue_purge(&fnic->frame_queue);
|
||||
skb_queue_purge(&fnic->tx_queue);
|
||||
fnic_free_txq(&fnic->tx_queue);
|
||||
|
||||
if (fnic->config.flags & VFCF_FIP_CAPABLE) {
|
||||
del_timer_sync(&fnic->fip_timer);
|
||||
|
@ -1036,7 +1064,6 @@ static void fnic_remove(struct pci_dev *pdev)
|
|||
fnic_cleanup(fnic);
|
||||
|
||||
BUG_ON(!skb_queue_empty(&fnic->frame_queue));
|
||||
BUG_ON(!skb_queue_empty(&fnic->tx_queue));
|
||||
|
||||
spin_lock_irqsave(&fnic_list_lock, flags);
|
||||
list_del(&fnic->list);
|
||||
|
@ -1133,6 +1160,24 @@ static int __init fnic_init_module(void)
|
|||
goto err_create_fnic_ioreq_slab;
|
||||
}
|
||||
|
||||
fdls_frame_cache = kmem_cache_create("fdls_frames",
|
||||
FNIC_FCOE_FRAME_MAXSZ,
|
||||
0, SLAB_HWCACHE_ALIGN, NULL);
|
||||
if (!fdls_frame_cache) {
|
||||
pr_err("fnic fdls frame cache create failed\n");
|
||||
err = -ENOMEM;
|
||||
goto err_create_fdls_frame_cache;
|
||||
}
|
||||
|
||||
fdls_frame_elem_cache = kmem_cache_create("fdls_frame_elem",
|
||||
sizeof(struct fnic_frame_list),
|
||||
0, SLAB_HWCACHE_ALIGN, NULL);
|
||||
if (!fdls_frame_elem_cache) {
|
||||
pr_err("fnic fdls frame elem cache create failed\n");
|
||||
err = -ENOMEM;
|
||||
goto err_create_fdls_frame_cache_elem;
|
||||
}
|
||||
|
||||
fnic_event_queue =
|
||||
alloc_ordered_workqueue("%s", WQ_MEM_RECLAIM, "fnic_event_wq");
|
||||
if (!fnic_event_queue) {
|
||||
|
@ -1171,6 +1216,10 @@ err_fc_transport:
|
|||
err_create_fip_workq:
|
||||
destroy_workqueue(fnic_event_queue);
|
||||
err_create_fnic_workq:
|
||||
kmem_cache_destroy(fdls_frame_elem_cache);
|
||||
err_create_fdls_frame_cache_elem:
|
||||
kmem_cache_destroy(fdls_frame_cache);
|
||||
err_create_fdls_frame_cache:
|
||||
kmem_cache_destroy(fnic_io_req_cache);
|
||||
err_create_fnic_ioreq_slab:
|
||||
kmem_cache_destroy(fnic_sgl_cache[FNIC_SGL_CACHE_MAX]);
|
||||
|
@ -1192,6 +1241,7 @@ static void __exit fnic_cleanup_module(void)
|
|||
kmem_cache_destroy(fnic_sgl_cache[FNIC_SGL_CACHE_MAX]);
|
||||
kmem_cache_destroy(fnic_sgl_cache[FNIC_SGL_CACHE_DFLT]);
|
||||
kmem_cache_destroy(fnic_io_req_cache);
|
||||
kmem_cache_destroy(fdls_frame_cache);
|
||||
fc_release_transport(fnic_fc_transport);
|
||||
fnic_trace_free();
|
||||
fnic_fc_trace_free();
|
||||
|
|
|
@ -184,7 +184,7 @@ int fnic_fw_reset_handler(struct fnic *fnic)
|
|||
fnic_set_state_flags(fnic, FNIC_FLAGS_FWRESET);
|
||||
|
||||
skb_queue_purge(&fnic->frame_queue);
|
||||
skb_queue_purge(&fnic->tx_queue);
|
||||
fnic_free_txq(&fnic->tx_queue);
|
||||
|
||||
/* wait for io cmpl */
|
||||
while (atomic_read(&fnic->in_flight))
|
||||
|
@ -674,7 +674,7 @@ static int fnic_fcpio_fw_reset_cmpl_handler(struct fnic *fnic,
|
|||
*/
|
||||
if (fnic->remove_wait || ret) {
|
||||
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
|
||||
skb_queue_purge(&fnic->tx_queue);
|
||||
fnic_free_txq(&fnic->tx_queue);
|
||||
goto reset_cmpl_handler_end;
|
||||
}
|
||||
|
||||
|
@ -1717,7 +1717,7 @@ static bool fnic_rport_abort_io_iter(struct scsi_cmnd *sc, void *data)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void fnic_rport_exch_reset(struct fnic *fnic, u32 port_id)
|
||||
void fnic_rport_exch_reset(struct fnic *fnic, u32 port_id)
|
||||
{
|
||||
struct terminate_stats *term_stats = &fnic->fnic_stats.term_stats;
|
||||
struct fnic_rport_abort_io_iter_data iter_data = {
|
||||
|
|
Loading…
Add table
Reference in a new issue