Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7afc5dbd authored by Krishna Gudipati's avatar Krishna Gudipati Committed by David S. Miller
Browse files

bna: Add debugfs interface.



Change details:
	- Add debugfs support to obtain firmware trace, saved firmware trace on
	  an IOC crash, driver info and read/write to registers.

	- debugfs hierarchy:
	  bna/pci_dev:<pci_name>
	  where the pci_name corresponds to the one under /sys/bus/pci/drivers/bna

	- Following are the new debugfs entries added:
	  fwtrc: collect current firmware trace.
	  fwsave: collect last saved fw trace as a result of firmware crash.
	  regwr: write one word to chip register
	  regrd: read one or more words from chip register.
	  drvinfo: collect the driver information.

Signed-off-by: default avatarKrishna Gudipati <kgudipat@brocade.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 72a9730b
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -5,7 +5,7 @@


obj-$(CONFIG_BNA) += bna.o
obj-$(CONFIG_BNA) += bna.o


bna-objs := bnad.o bnad_ethtool.o bna_enet.o bna_tx_rx.o
bna-objs := bnad.o bnad_ethtool.o bnad_debugfs.o bna_enet.o bna_tx_rx.o
bna-objs += bfa_msgq.o bfa_ioc.o bfa_ioc_ct.o bfa_cee.o
bna-objs += bfa_msgq.o bfa_ioc.o bfa_ioc_ct.o bfa_cee.o
bna-objs += cna_fwimg.o
bna-objs += cna_fwimg.o


+35 −0
Original line number Original line Diff line number Diff line
@@ -184,6 +184,41 @@ bfa_nw_cee_mem_claim(struct bfa_cee *cee, u8 *dma_kva, u64 dma_pa)
		(dma_kva + bfa_cee_attr_meminfo());
		(dma_kva + bfa_cee_attr_meminfo());
}
}


/**
 * bfa_cee_get_attr()
 *
 * @brief	Send the request to the f/w to fetch CEE attributes.
 *
 * @param[in]	Pointer to the CEE module data structure.
 *
 * @return	Status
 */
enum bfa_status
bfa_nw_cee_get_attr(struct bfa_cee *cee, struct bfa_cee_attr *attr,
		    bfa_cee_get_attr_cbfn_t cbfn, void *cbarg)
{
	struct bfi_cee_get_req *cmd;

	BUG_ON(!((cee != NULL) && (cee->ioc != NULL)));
	if (!bfa_nw_ioc_is_operational(cee->ioc))
		return BFA_STATUS_IOC_FAILURE;

	if (cee->get_attr_pending == true)
		return  BFA_STATUS_DEVBUSY;

	cee->get_attr_pending = true;
	cmd = (struct bfi_cee_get_req *) cee->get_cfg_mb.msg;
	cee->attr = attr;
	cee->cbfn.get_attr_cbfn = cbfn;
	cee->cbfn.get_attr_cbarg = cbarg;
	bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_CFG_REQ,
		    bfa_ioc_portid(cee->ioc));
	bfa_dma_be_addr_set(cmd->dma_addr, cee->attr_dma.pa);
	bfa_nw_ioc_mbox_queue(cee->ioc, &cee->get_cfg_mb, NULL, NULL);

	return BFA_STATUS_OK;
}

/**
/**
 * bfa_cee_isrs()
 * bfa_cee_isrs()
 *
 *
+3 −1
Original line number Original line Diff line number Diff line
@@ -59,5 +59,7 @@ u32 bfa_nw_cee_meminfo(void);
void bfa_nw_cee_mem_claim(struct bfa_cee *cee, u8 *dma_kva,
void bfa_nw_cee_mem_claim(struct bfa_cee *cee, u8 *dma_kva,
	u64 dma_pa);
	u64 dma_pa);
void bfa_nw_cee_attach(struct bfa_cee *cee, struct bfa_ioc *ioc, void *dev);
void bfa_nw_cee_attach(struct bfa_cee *cee, struct bfa_ioc *ioc, void *dev);

enum bfa_status bfa_nw_cee_get_attr(struct bfa_cee *cee,
				struct bfa_cee_attr *attr,
				bfa_cee_get_attr_cbfn_t cbfn, void *cbarg);
#endif /* __BFA_CEE_H__ */
#endif /* __BFA_CEE_H__ */
+121 −0
Original line number Original line Diff line number Diff line
@@ -74,6 +74,7 @@ static void bfa_ioc_check_attr_wwns(struct bfa_ioc *ioc);
static void bfa_ioc_event_notify(struct bfa_ioc *, enum bfa_ioc_event);
static void bfa_ioc_event_notify(struct bfa_ioc *, enum bfa_ioc_event);
static void bfa_ioc_disable_comp(struct bfa_ioc *ioc);
static void bfa_ioc_disable_comp(struct bfa_ioc *ioc);
static void bfa_ioc_lpu_stop(struct bfa_ioc *ioc);
static void bfa_ioc_lpu_stop(struct bfa_ioc *ioc);
static void bfa_nw_ioc_debug_save_ftrc(struct bfa_ioc *ioc);
static void bfa_ioc_fail_notify(struct bfa_ioc *ioc);
static void bfa_ioc_fail_notify(struct bfa_ioc *ioc);
static void bfa_ioc_pf_enabled(struct bfa_ioc *ioc);
static void bfa_ioc_pf_enabled(struct bfa_ioc *ioc);
static void bfa_ioc_pf_disabled(struct bfa_ioc *ioc);
static void bfa_ioc_pf_disabled(struct bfa_ioc *ioc);
@@ -997,6 +998,7 @@ bfa_iocpf_sm_disabled(struct bfa_iocpf *iocpf, enum iocpf_event event)
static void
static void
bfa_iocpf_sm_initfail_sync_entry(struct bfa_iocpf *iocpf)
bfa_iocpf_sm_initfail_sync_entry(struct bfa_iocpf *iocpf)
{
{
	bfa_nw_ioc_debug_save_ftrc(iocpf->ioc);
	bfa_ioc_hw_sem_get(iocpf->ioc);
	bfa_ioc_hw_sem_get(iocpf->ioc);
}
}


@@ -1743,6 +1745,114 @@ bfa_ioc_mbox_flush(struct bfa_ioc *ioc)
		bfa_q_deq(&mod->cmd_q, &cmd);
		bfa_q_deq(&mod->cmd_q, &cmd);
}
}


/**
 * Read data from SMEM to host through PCI memmap
 *
 * @param[in]  ioc     memory for IOC
 * @param[in]  tbuf    app memory to store data from smem
 * @param[in]  soff    smem offset
 * @param[in]  sz      size of smem in bytes
 */
static int
bfa_nw_ioc_smem_read(struct bfa_ioc *ioc, void *tbuf, u32 soff, u32 sz)
{
	u32 pgnum, loff, r32;
	int i, len;
	u32 *buf = tbuf;

	pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, soff);
	loff = PSS_SMEM_PGOFF(soff);

	/*
	 *  Hold semaphore to serialize pll init and fwtrc.
	*/
	if (bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg) == 0)
		return 1;

	writel(pgnum, ioc->ioc_regs.host_page_num_fn);

	len = sz/sizeof(u32);
	for (i = 0; i < len; i++) {
		r32 = swab32(readl((loff) + (ioc->ioc_regs.smem_page_start)));
		buf[i] = be32_to_cpu(r32);
		loff += sizeof(u32);

		/**
		 * handle page offset wrap around
		 */
		loff = PSS_SMEM_PGOFF(loff);
		if (loff == 0) {
			pgnum++;
			writel(pgnum, ioc->ioc_regs.host_page_num_fn);
		}
	}

	writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0),
	       ioc->ioc_regs.host_page_num_fn);

	/*
	 * release semaphore
	 */
	readl(ioc->ioc_regs.ioc_init_sem_reg);
	writel(1, ioc->ioc_regs.ioc_init_sem_reg);
	return 0;
}

/**
 * Retrieve saved firmware trace from a prior IOC failure.
 */
int
bfa_nw_ioc_debug_fwtrc(struct bfa_ioc *ioc, void *trcdata, int *trclen)
{
	u32 loff = BFI_IOC_TRC_OFF + BNA_DBG_FWTRC_LEN * ioc->port_id;
	int tlen, status = 0;

	tlen = *trclen;
	if (tlen > BNA_DBG_FWTRC_LEN)
		tlen = BNA_DBG_FWTRC_LEN;

	status = bfa_nw_ioc_smem_read(ioc, trcdata, loff, tlen);
	*trclen = tlen;
	return status;
}

/**
 * Save firmware trace if configured.
 */
static void
bfa_nw_ioc_debug_save_ftrc(struct bfa_ioc *ioc)
{
	int tlen;

	if (ioc->dbg_fwsave_once) {
		ioc->dbg_fwsave_once = 0;
		if (ioc->dbg_fwsave_len) {
			tlen = ioc->dbg_fwsave_len;
			bfa_nw_ioc_debug_fwtrc(ioc, ioc->dbg_fwsave, &tlen);
		}
	}
}

/**
 * Retrieve saved firmware trace from a prior IOC failure.
 */
int
bfa_nw_ioc_debug_fwsave(struct bfa_ioc *ioc, void *trcdata, int *trclen)
{
	int tlen;

	if (ioc->dbg_fwsave_len == 0)
		return BFA_STATUS_ENOFSAVE;

	tlen = *trclen;
	if (tlen > ioc->dbg_fwsave_len)
		tlen = ioc->dbg_fwsave_len;

	memcpy(trcdata, ioc->dbg_fwsave, tlen);
	*trclen = tlen;
	return BFA_STATUS_OK;
}

static void
static void
bfa_ioc_fail_notify(struct bfa_ioc *ioc)
bfa_ioc_fail_notify(struct bfa_ioc *ioc)
{
{
@@ -1751,6 +1861,7 @@ bfa_ioc_fail_notify(struct bfa_ioc *ioc)
	 */
	 */
	ioc->cbfn->hbfail_cbfn(ioc->bfa);
	ioc->cbfn->hbfail_cbfn(ioc->bfa);
	bfa_ioc_event_notify(ioc, BFA_IOC_E_FAILED);
	bfa_ioc_event_notify(ioc, BFA_IOC_E_FAILED);
	bfa_nw_ioc_debug_save_ftrc(ioc);
}
}


/**
/**
@@ -2058,6 +2169,16 @@ bfa_nw_ioc_disable(struct bfa_ioc *ioc)
	bfa_fsm_send_event(ioc, IOC_E_DISABLE);
	bfa_fsm_send_event(ioc, IOC_E_DISABLE);
}
}


/**
 * Initialize memory for saving firmware trace.
 */
void
bfa_nw_ioc_debug_memclaim(struct bfa_ioc *ioc, void *dbg_fwsave)
{
	ioc->dbg_fwsave = dbg_fwsave;
	ioc->dbg_fwsave_len = ioc->iocpf.auto_recover ? BNA_DBG_FWTRC_LEN : 0;
}

static u32
static u32
bfa_ioc_smem_pgnum(struct bfa_ioc *ioc, u32 fmaddr)
bfa_ioc_smem_pgnum(struct bfa_ioc *ioc, u32 fmaddr)
{
{
+6 −0
Original line number Original line Diff line number Diff line
@@ -27,6 +27,8 @@
#define BFA_IOC_HWSEM_TOV	500	/* msecs */
#define BFA_IOC_HWSEM_TOV	500	/* msecs */
#define BFA_IOC_HB_TOV		500	/* msecs */
#define BFA_IOC_HB_TOV		500	/* msecs */
#define BFA_IOC_POLL_TOV	200	/* msecs */
#define BFA_IOC_POLL_TOV	200	/* msecs */
#define BNA_DBG_FWTRC_LEN      (BFI_IOC_TRC_ENTS * BFI_IOC_TRC_ENT_SZ + \
				BFI_IOC_TRC_HDR_SZ)


/**
/**
 * PCI device information required by IOC
 * PCI device information required by IOC
@@ -306,6 +308,7 @@ void bfa_nw_ioc_disable(struct bfa_ioc *ioc);


void bfa_nw_ioc_error_isr(struct bfa_ioc *ioc);
void bfa_nw_ioc_error_isr(struct bfa_ioc *ioc);
bool bfa_nw_ioc_is_disabled(struct bfa_ioc *ioc);
bool bfa_nw_ioc_is_disabled(struct bfa_ioc *ioc);
bool bfa_nw_ioc_is_operational(struct bfa_ioc *ioc);
void bfa_nw_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr);
void bfa_nw_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr);
void bfa_nw_ioc_notify_register(struct bfa_ioc *ioc,
void bfa_nw_ioc_notify_register(struct bfa_ioc *ioc,
	struct bfa_ioc_notify *notify);
	struct bfa_ioc_notify *notify);
@@ -317,6 +320,9 @@ void bfa_nw_ioc_fwver_get(struct bfa_ioc *ioc,
bool bfa_nw_ioc_fwver_cmp(struct bfa_ioc *ioc,
bool bfa_nw_ioc_fwver_cmp(struct bfa_ioc *ioc,
			struct bfi_ioc_image_hdr *fwhdr);
			struct bfi_ioc_image_hdr *fwhdr);
mac_t bfa_nw_ioc_get_mac(struct bfa_ioc *ioc);
mac_t bfa_nw_ioc_get_mac(struct bfa_ioc *ioc);
void bfa_nw_ioc_debug_memclaim(struct bfa_ioc *ioc, void *dbg_fwsave);
int bfa_nw_ioc_debug_fwtrc(struct bfa_ioc *ioc, void *trcdata, int *trclen);
int bfa_nw_ioc_debug_fwsave(struct bfa_ioc *ioc, void *trcdata, int *trclen);


/*
/*
 * Timeout APIs
 * Timeout APIs
Loading