Commit 881c1b3c authored by Krishna Gudipati's avatar Krishna Gudipati Committed by James Bottomley
Browse files

[SCSI] bfa: Add PowerPC support and enable PCIE AER handling.



- Added few missing endian swap changes to support BFA on PowerPC.
- Added PCIE AER support to BFA:
  a) Implemented the PCI error handler entry points.
  b) Made changes to FCS state machine to handle STOP event from the
	 PCI error detected entry point.
  c) Made changes to the IO Controller state machine to handle SUSPEND
     event from the PCI error detected entry point.
  d) Made changes to restart the BFA operations on a slot_reset completion.

Signed-off-by: default avatarKrishna Gudipati <kgudipat@brocade.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 6dca60a3
Loading
Loading
Loading
Loading
+4 −8
Original line number Diff line number Diff line
@@ -1022,7 +1022,7 @@ bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg)
{
	u8	*dm_kva = NULL;
	u64	dm_pa = 0;
	int	i, per_reqq_sz, per_rspq_sz, dbgsz;
	int	i, per_reqq_sz, per_rspq_sz;
	struct bfa_iocfc_s  *iocfc = &bfa->iocfc;
	struct bfa_mem_dma_s *ioc_dma = BFA_MEM_IOC_DMA(bfa);
	struct bfa_mem_dma_s *iocfc_dma = BFA_MEM_IOCFC_DMA(bfa);
@@ -1083,11 +1083,8 @@ bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg)
			BFA_CACHELINE_SZ);

	/* Claim IOCFC kva memory */
	dbgsz = (bfa_auto_recover) ? BFA_DBG_FWTRC_LEN : 0;
	if (dbgsz > 0) {
	bfa_ioc_debug_memclaim(&bfa->ioc, bfa_mem_kva_curp(iocfc));
		bfa_mem_kva_curp(iocfc) += dbgsz;
	}
	bfa_mem_kva_curp(iocfc) += BFA_DBG_FWTRC_LEN;
}

/*
@@ -1429,8 +1426,7 @@ bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
	bfa_mem_dma_setup(meminfo, iocfc_dma, dm_len);

	/* kva memory setup for IOCFC */
	bfa_mem_kva_setup(meminfo, iocfc_kva,
			((bfa_auto_recover) ? BFA_DBG_FWTRC_LEN : 0));
	bfa_mem_kva_setup(meminfo, iocfc_kva, BFA_DBG_FWTRC_LEN);
}

/*
+133 −0
Original line number Diff line number Diff line
@@ -118,6 +118,18 @@ bfa_fcs_update_cfg(struct bfa_fcs_s *fcs)
	port_cfg->pwwn = ioc->attr->pwwn;
}

/*
 * Stop FCS operations.
 */
void
bfa_fcs_stop(struct bfa_fcs_s *fcs)
{
	bfa_wc_init(&fcs->wc, bfa_fcs_exit_comp, fcs);
	bfa_wc_up(&fcs->wc);
	bfa_fcs_fabric_modstop(fcs);
	bfa_wc_wait(&fcs->wc);
}

/*
 * fcs pbc vport initialization
 */
@@ -213,6 +225,8 @@ static void bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric);
static void bfa_fcs_fabric_delay(void *cbarg);
static void bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric);
static void bfa_fcs_fabric_delete_comp(void *cbarg);
static void bfa_fcs_fabric_stop(struct bfa_fcs_fabric_s *fabric);
static void bfa_fcs_fabric_stop_comp(void *cbarg);
static void bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric,
				      struct fchs_s *fchs, u16 len);
static void bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,
@@ -250,6 +264,10 @@ static void bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric,
					   enum bfa_fcs_fabric_event event);
static void	bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,
					   enum bfa_fcs_fabric_event event);
static void	bfa_fcs_fabric_sm_stopping(struct bfa_fcs_fabric_s *fabric,
					   enum bfa_fcs_fabric_event event);
static void	bfa_fcs_fabric_sm_cleanup(struct bfa_fcs_fabric_s *fabric,
					  enum bfa_fcs_fabric_event event);
/*
 *   Beginning state before fabric creation.
 */
@@ -334,6 +352,11 @@ bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,
		bfa_fcs_fabric_delete(fabric);
		break;

	case BFA_FCS_FABRIC_SM_STOP:
		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_cleanup);
		bfa_fcs_fabric_stop(fabric);
		break;

	default:
		bfa_sm_fault(fabric->fcs, event);
	}
@@ -585,6 +608,11 @@ bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
		bfa_fcs_fabric_delete(fabric);
		break;

	case BFA_FCS_FABRIC_SM_STOP:
		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_stopping);
		bfa_fcs_fabric_stop(fabric);
		break;

	case BFA_FCS_FABRIC_SM_AUTH_FAILED:
		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);
		bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
@@ -682,7 +710,62 @@ bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,
	}
}

/*
 * Fabric is being stopped, awaiting vport stop completions.
 */
static void
bfa_fcs_fabric_sm_stopping(struct bfa_fcs_fabric_s *fabric,
			   enum bfa_fcs_fabric_event event)
{
	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
	bfa_trc(fabric->fcs, event);

	switch (event) {
	case BFA_FCS_FABRIC_SM_STOPCOMP:
		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_cleanup);
		bfa_sm_send_event(fabric->lps, BFA_LPS_SM_LOGOUT);
		break;

	case BFA_FCS_FABRIC_SM_LINK_UP:
		break;

	case BFA_FCS_FABRIC_SM_LINK_DOWN:
		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_cleanup);
		break;

	default:
		bfa_sm_fault(fabric->fcs, event);
	}
}

/*
 * Fabric is being stopped, cleanup without FLOGO
 */
static void
bfa_fcs_fabric_sm_cleanup(struct bfa_fcs_fabric_s *fabric,
			  enum bfa_fcs_fabric_event event)
{
	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
	bfa_trc(fabric->fcs, event);

	switch (event) {
	case BFA_FCS_FABRIC_SM_STOPCOMP:
	case BFA_FCS_FABRIC_SM_LOGOCOMP:
		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created);
		bfa_wc_down(&(fabric->fcs)->wc);
		break;

	case BFA_FCS_FABRIC_SM_LINK_DOWN:
		/*
		 * Ignore - can get this event if we get notified about IOC down
		 * before the fabric completion callbk is done.
		 */
		break;

	default:
		bfa_sm_fault(fabric->fcs, event);
	}
}

/*
 *  fcs_fabric_private fabric private functions
@@ -918,6 +1001,28 @@ bfa_fcs_fabric_delay(void *cbarg)
	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELAYED);
}

/*
 * Stop all vports and wait for vport stop completions.
 */
static void
bfa_fcs_fabric_stop(struct bfa_fcs_fabric_s *fabric)
{
	struct bfa_fcs_vport_s *vport;
	struct list_head	*qe, *qen;

	bfa_wc_init(&fabric->stop_wc, bfa_fcs_fabric_stop_comp, fabric);

	list_for_each_safe(qe, qen, &fabric->vport_q) {
		vport = (struct bfa_fcs_vport_s *) qe;
		bfa_wc_up(&fabric->stop_wc);
		bfa_fcs_vport_fcs_stop(vport);
	}

	bfa_wc_up(&fabric->stop_wc);
	bfa_fcs_lport_stop(&fabric->bport);
	bfa_wc_wait(&fabric->stop_wc);
}

/*
 * Computes operating BB_SCN value
 */
@@ -978,6 +1083,14 @@ bfa_fcs_fabric_delete_comp(void *cbarg)
	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELCOMP);
}

static void
bfa_fcs_fabric_stop_comp(void *cbarg)
{
	struct bfa_fcs_fabric_s *fabric = cbarg;

	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_STOPCOMP);
}

/*
 *  fcs_fabric_public fabric public functions
 */
@@ -1038,6 +1151,19 @@ bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs)
	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELETE);
}

/*
 * Fabric module stop -- stop FCS actions
 */
void
bfa_fcs_fabric_modstop(struct bfa_fcs_s *fcs)
{
	struct bfa_fcs_fabric_s *fabric;

	bfa_trc(fcs, 0);
	fabric = &fcs->fabric;
	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_STOP);
}

/*
 * Fabric module start -- kick starts FCS actions
 */
@@ -1387,6 +1513,13 @@ bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,
	}
}

void
bfa_cb_lps_flogo_comp(void *bfad, void *uarg)
{
	struct bfa_fcs_fabric_s *fabric = uarg;
	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LOGOCOMP);
}

/*
 *	Returns FCS vf structure for a given vf_id.
 *
+8 −0
Original line number Diff line number Diff line
@@ -205,6 +205,7 @@ struct bfa_fcs_fabric_s {
	struct bfa_lps_s	*lps;	/*  lport login services	*/
	u8	fabric_ip_addr[BFA_FCS_FABRIC_IPADDR_SZ];
					/*  attached fabric's ip addr  */
	struct bfa_wc_s stop_wc;	/*  wait counter for stop */
};

#define bfa_fcs_fabric_npiv_capable(__f)    ((__f)->is_npiv)
@@ -323,6 +324,7 @@ void bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport,
void            bfa_fcs_lport_online(struct bfa_fcs_lport_s *port);
void            bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port);
void            bfa_fcs_lport_delete(struct bfa_fcs_lport_s *port);
void		bfa_fcs_lport_stop(struct bfa_fcs_lport_s *port);
struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_pid(
		struct bfa_fcs_lport_s *port, u32 pid);
struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_old_pid(
@@ -387,6 +389,7 @@ void bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport);
void bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport);
void bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport);
void bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport);
void bfa_fcs_vport_fcs_stop(struct bfa_fcs_vport_s *vport);
void bfa_fcs_vport_stop_comp(struct bfa_fcs_vport_s *vport);

#define BFA_FCS_RPORT_DEF_DEL_TIMEOUT	90	/* in secs */
@@ -709,6 +712,9 @@ enum bfa_fcs_fabric_event {
	BFA_FCS_FABRIC_SM_DELCOMP       = 14,   /*  all vports deleted event */
	BFA_FCS_FABRIC_SM_LOOPBACK      = 15,   /*  Received our own FLOGI   */
	BFA_FCS_FABRIC_SM_START         = 16,   /*  from driver       */
	BFA_FCS_FABRIC_SM_STOP		= 17,	/*  Stop from driver	*/
	BFA_FCS_FABRIC_SM_STOPCOMP	= 18,	/*  Stop completion	*/
	BFA_FCS_FABRIC_SM_LOGOCOMP	= 19,	/*  FLOGO completion	*/
};

/*
@@ -748,6 +754,7 @@ void bfa_fcs_update_cfg(struct bfa_fcs_s *fcs);
void bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs,
			      struct bfa_fcs_driver_info_s *driver_info);
void bfa_fcs_exit(struct bfa_fcs_s *fcs);
void bfa_fcs_stop(struct bfa_fcs_s *fcs);

/*
 * bfa fcs vf public functions
@@ -778,6 +785,7 @@ void bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,
u16 bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric);
void bfa_fcs_uf_attach(struct bfa_fcs_s *fcs);
void bfa_fcs_port_attach(struct bfa_fcs_s *fcs);
void bfa_fcs_fabric_modstop(struct bfa_fcs_s *fcs);
void bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
			enum bfa_fcs_fabric_event event);
void bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric,
+28 −0
Original line number Diff line number Diff line
@@ -131,6 +131,8 @@ bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
		/* If vport - send completion call back */
		if (port->vport)
			bfa_fcs_vport_stop_comp(port->vport);
		else
			bfa_wc_down(&(port->fabric->stop_wc));
		break;

	case BFA_FCS_PORT_SM_OFFLINE:
@@ -166,6 +168,8 @@ bfa_fcs_lport_sm_online(
			/* If vport - send completion call back */
			if (port->vport)
				bfa_fcs_vport_stop_comp(port->vport);
			else
				bfa_wc_down(&(port->fabric->stop_wc));
		} else {
			bfa_sm_set_state(port, bfa_fcs_lport_sm_stopping);
			list_for_each_safe(qe, qen, &port->rport_q) {
@@ -222,6 +226,8 @@ bfa_fcs_lport_sm_offline(
			/* If vport - send completion call back */
			if (port->vport)
				bfa_fcs_vport_stop_comp(port->vport);
			else
				bfa_wc_down(&(port->fabric->stop_wc));
		} else {
			bfa_sm_set_state(port, bfa_fcs_lport_sm_stopping);
			list_for_each_safe(qe, qen, &port->rport_q) {
@@ -267,6 +273,8 @@ bfa_fcs_lport_sm_stopping(struct bfa_fcs_lport_s *port,
			/* If vport - send completion call back */
			if (port->vport)
				bfa_fcs_vport_stop_comp(port->vport);
			else
				bfa_wc_down(&(port->fabric->stop_wc));
		}
		break;

@@ -977,6 +985,16 @@ bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port)
	bfa_sm_send_event(port, BFA_FCS_PORT_SM_OFFLINE);
}

/*
 * Called by fabric for base port and by vport for virtual ports
 * when target mode driver is unloaded.
 */
void
bfa_fcs_lport_stop(struct bfa_fcs_lport_s *port)
{
	bfa_sm_send_event(port, BFA_FCS_PORT_SM_STOP);
}

/*
 * Called by fabric to delete base lport and associated resources.
 *
@@ -5884,6 +5902,16 @@ bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport)
{
	vport->vport_stats.fab_cleanup++;
}

/*
 * Stop notification from fabric SM. To be invoked from within FCS.
 */
void
bfa_fcs_vport_fcs_stop(struct bfa_fcs_vport_s *vport)
{
	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP);
}

/*
 * delete notification from fabric SM. To be invoked from within FCS.
 */
+17 −7
Original line number Diff line number Diff line
@@ -92,7 +92,6 @@ static void bfa_ioc_event_notify(struct bfa_ioc_s *ioc ,
				enum bfa_ioc_event_e event);
static void bfa_ioc_disable_comp(struct bfa_ioc_s *ioc);
static void bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc);
static void bfa_ioc_debug_save_ftrc(struct bfa_ioc_s *ioc);
static void bfa_ioc_fail_notify(struct bfa_ioc_s *ioc);
static void bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc);

@@ -599,8 +598,9 @@ bfa_ioc_sm_fail(struct bfa_ioc_s *ioc, enum ioc_event event)
		break;

	case IOC_E_HWERROR:
	case IOC_E_HWFAILED:
		/*
		 * HB failure notification, ignore.
		 * HB failure / HW error notification, ignore.
		 */
		break;
	default:
@@ -632,6 +632,10 @@ bfa_ioc_sm_hwfail(struct bfa_ioc_s *ioc, enum ioc_event event)
		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
		break;

	case IOC_E_HWERROR:
		/* Ignore - already in hwfail state */
		break;

	default:
		bfa_sm_fault(ioc, event);
	}
@@ -1455,7 +1459,7 @@ bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
		bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);

	for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) {
		if (fwhdr->md5sum[i] != drv_fwhdr->md5sum[i]) {
		if (fwhdr->md5sum[i] != cpu_to_le32(drv_fwhdr->md5sum[i])) {
			bfa_trc(ioc, i);
			bfa_trc(ioc, fwhdr->md5sum[i]);
			bfa_trc(ioc, drv_fwhdr->md5sum[i]);
@@ -1480,7 +1484,7 @@ bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc, u32 boot_env)
	drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
		bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);

	if (fwhdr.signature != drv_fwhdr->signature) {
	if (fwhdr.signature != cpu_to_le32(drv_fwhdr->signature)) {
		bfa_trc(ioc, fwhdr.signature);
		bfa_trc(ioc, drv_fwhdr->signature);
		return BFA_FALSE;
@@ -1704,7 +1708,7 @@ bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
		 * write smem
		 */
		bfa_mem_write(ioc->ioc_regs.smem_page_start, loff,
			      fwimg[BFA_IOC_FLASH_OFFSET_IN_CHUNK(i)]);
			cpu_to_le32(fwimg[BFA_IOC_FLASH_OFFSET_IN_CHUNK(i)]));

		loff += sizeof(u32);

@@ -2260,6 +2264,12 @@ bfa_ioc_disable(struct bfa_ioc_s *ioc)
	bfa_fsm_send_event(ioc, IOC_E_DISABLE);
}

void
bfa_ioc_suspend(struct bfa_ioc_s *ioc)
{
	ioc->dbg_fwsave_once = BFA_TRUE;
	bfa_fsm_send_event(ioc, IOC_E_HWERROR);
}

/*
 * Initialize memory for saving firmware trace. Driver must initialize
@@ -2269,7 +2279,7 @@ void
bfa_ioc_debug_memclaim(struct bfa_ioc_s *ioc, void *dbg_fwsave)
{
	ioc->dbg_fwsave	    = dbg_fwsave;
	ioc->dbg_fwsave_len = (ioc->iocpf.auto_recover) ? BFA_DBG_FWTRC_LEN : 0;
	ioc->dbg_fwsave_len = BFA_DBG_FWTRC_LEN;
}

/*
@@ -2856,7 +2866,7 @@ bfa_ioc_fw_stats_clear(struct bfa_ioc_s *ioc)
/*
 * Save firmware trace if configured.
 */
static void
void
bfa_ioc_debug_save_ftrc(struct bfa_ioc_s *ioc)
{
	int		tlen;
Loading