Netdev List
 help / color / mirror / Atom feed
* [PATCH 12/45] bna: Hardware Clock Setup
From: Rasesh Mody @ 2011-07-18  8:22 UTC (permalink / raw)
  To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>

Change details:
 - Clock values for Brocade 1860 hardware PLL initialization depends on
   asic mode.
 - Removed additional mode dependent PCI device ID definitions for 1860.
 - Pass asic generation, port modes and asic mode as part firmware boot
   parameters to firmware.

Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 drivers/net/bna/bfa_defs.h |    1 +
 drivers/net/bna/bfa_ioc.c  |   23 ++++++++++++++++-------
 drivers/net/bna/bfa_ioc.h  |    5 +++--
 drivers/net/bna/bfi.h      |   28 ++++++++++++++++++----------
 4 files changed, 38 insertions(+), 19 deletions(-)

diff --git a/drivers/net/bna/bfa_defs.h b/drivers/net/bna/bfa_defs.h
index 49b990c..fc9702c 100644
--- a/drivers/net/bna/bfa_defs.h
+++ b/drivers/net/bna/bfa_defs.h
@@ -240,6 +240,7 @@ struct bfa_mfg_block {
 
 enum {
 	BFA_PCI_DEVICE_ID_CT		= 0x14,
+	BFA_PCI_DEVICE_ID_CT2		= 0x22,
 };
 
 #define bfa_asic_id_ct(devid)			\
diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
index a31c0cc..b23d331 100644
--- a/drivers/net/bna/bfa_ioc.c
+++ b/drivers/net/bna/bfa_ioc.c
@@ -1567,10 +1567,10 @@ bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type,
 	/*
 	 * Set boot type, env and device mode at the end.
 	*/
-	asicmode = BFI_FWBOOT_ASICMODE(ioc->asic_gen, ioc->mode_p0,
-					ioc->mode_p1);
+	asicmode = BFI_FWBOOT_ASICMODE(ioc->asic_gen, ioc->asic_mode,
+					ioc->port0_mode, ioc->port1_mode);
 	writel(asicmode, ((ioc->ioc_regs.smem_page_start)
-			+ BFI_FWBOOT_ASICMODE_OFF));
+			+ BFI_FWBOOT_DEVMODE_OFF));
 	writel(boot_type, ((ioc->ioc_regs.smem_page_start)
 			+ (BFI_FWBOOT_TYPE_OFF)));
 	writel(boot_env, ((ioc->ioc_regs.smem_page_start)
@@ -1875,10 +1875,19 @@ bfa_nw_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev,
 	/**
 	 * Initialize IOC and device personality
 	 */
+	ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_FC;
+	ioc->asic_mode  = BFI_ASIC_MODE_FC;
+
 	switch (pcidev->device_id) {
 	case BFA_PCI_DEVICE_ID_CT:
 		ioc->asic_gen = BFI_ASIC_GEN_CT;
-		ioc->mode_p0 = ioc->mode_p1 = BFI_FWBOOT_DEVMOD_CNA;
+		ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_ETH;
+		ioc->asic_mode  = BFI_ASIC_MODE_ETH;
+		break;
+
+	case BFA_PCI_DEVICE_ID_CT2:
+		ioc->asic_gen = BFI_ASIC_GEN_CT2;
+		ioc->asic_mode  = BFI_ASIC_MODE_FC16;
 		break;
 
 	default:
@@ -2097,15 +2106,15 @@ bfa_ioc_get_adapter_attr(struct bfa_ioc *ioc,
 enum bfa_ioc_type
 bfa_nw_ioc_get_type(struct bfa_ioc *ioc)
 {
-	enum bfi_fwboot_devmode mode;
+	enum bfi_port_mode mode;
 
 	if (ioc->clscode == BFI_PCIFN_CLASS_ETH)
 		return BFA_IOC_TYPE_LL;
 
 	BUG_ON(!(ioc->clscode == BFI_PCIFN_CLASS_FC));
 
-	mode = (ioc->port_id == 0) ? ioc->mode_p0 : ioc->mode_p1;
-	return (mode == BFI_FWBOOT_DEVMOD_HBA)
+	mode = (ioc->port_id == 0) ? ioc->port0_mode : ioc->port1_mode;
+	return (mode == BFI_PORT_MODE_FC)
 		? BFA_IOC_TYPE_FC : BFA_IOC_TYPE_FCoE;
 }
 
diff --git a/drivers/net/bna/bfa_ioc.h b/drivers/net/bna/bfa_ioc.h
index 8ffdbea..11c7bd5 100644
--- a/drivers/net/bna/bfa_ioc.h
+++ b/drivers/net/bna/bfa_ioc.h
@@ -203,8 +203,9 @@ struct bfa_ioc {
 	struct bfa_iocpf	iocpf;
 	enum bfi_fwboot_env	boot_env;
 	enum bfi_asic_gen	asic_gen;
-	enum bfi_fwboot_devmode	mode_p0;
-	enum bfi_fwboot_devmode	mode_p1;
+	enum bfi_asic_mode	asic_mode;
+	enum bfi_port_mode	port0_mode;
+	enum bfi_port_mode	port1_mode;
 };
 
 struct bfa_ioc_hwif {
diff --git a/drivers/net/bna/bfi.h b/drivers/net/bna/bfi.h
index cd51edd..c855b44 100644
--- a/drivers/net/bna/bfi.h
+++ b/drivers/net/bna/bfi.h
@@ -203,6 +203,13 @@ enum bfi_asic_gen {
 	BFI_ASIC_GEN_CT2	= 3,	/* 16G FC or 10G CNA	*/
 };
 
+enum bfi_asic_mode {
+	BFI_ASIC_MODE_FC	= 1,	/* FC upto 8G speed		*/
+	BFI_ASIC_MODE_FC16	= 2,	/* FC upto 16G speed		*/
+	BFI_ASIC_MODE_ETH	= 3,	/* Ethernet ports		*/
+	BFI_ASIC_MODE_COMBO	= 4,	/* FC 16G and Ethernet 10G port	*/
+};
+
 enum bfi_ioc_h2i_msgs {
 	BFI_IOC_H2I_ENABLE_REQ		= 1,
 	BFI_IOC_H2I_DISABLE_REQ		= 2,
@@ -285,8 +292,9 @@ struct bfi_ioc_getattr_reply {
 struct bfi_ioc_image_hdr {
 	u32	signature;	/*!< constant signature */
 	u8	asic_gen;	/*!< asic generation */
-	u8	mode_p0;	/*!< device mode for port 0 */
-	u8	mode_p1;	/*!< device mode for port 1 */
+	u8	asic_mode;
+	u8	port0_mode;	/*!< device mode for port 0 */
+	u8	port1_mode;	/*!< device mode for port 1 */
 	u8	rsvd_a;
 	u32	exec;		/*!< exec vector	*/
 	u32	bootenv;	/*!< firmware boot env */
@@ -294,13 +302,14 @@ struct bfi_ioc_image_hdr {
 	u32	md5sum[BFI_IOC_MD5SUM_SZ];
 };
 
-#define BFI_FWBOOT_ASICMODE_OFF		4
+#define BFI_FWBOOT_DEVMODE_OFF		4
 #define BFI_FWBOOT_TYPE_OFF		8
 #define BFI_FWBOOT_ENV_OFF		12
-#define BFI_FWBOOT_ASICMODE(__asic_gen, __mode_p0, __mode_p1) \
+#define BFI_FWBOOT_ASICMODE(__asic_gen, __asic_mode, __p0_mode, __p1_mode) \
 	(((u32)(__asic_gen)) << 24 |	\
-	 ((u32)(__mode_p0)) << 16 |	\
-	 ((u32)(__mode_p0)) << 8)
+	 ((u32)(__asic_mode)) << 16 |	\
+	 ((u32)(__p0_mode)) << 8 |	\
+	 ((u32)(__p1_mode)))
 
 enum bfi_fwboot_type {
 	BFI_FWBOOT_TYPE_NORMAL	= 0,
@@ -314,10 +323,9 @@ enum bfi_fwboot_env {
 	BFI_FWBOOT_ENV_UEFI	= 2,
 };
 
-enum bfi_fwboot_devmode {
-	BFI_FWBOOT_DEVMOD_HBA	= 1,
-	BFI_FWBOOT_DEVMOD_CNA	= 2,
-	BFI_FWBOOT_DEVMOD_NIC	= 3,
+enum bfi_port_mode {
+	BFI_PORT_MODE_FC	= 1,
+	BFI_PORT_MODE_ETH	= 2,
 };
 
 /**
-- 
1.7.1


^ permalink raw reply related

* [PATCH 13/45] bna: IOC PLL changes and init cleanup
From: Rasesh Mody @ 2011-07-18  8:22 UTC (permalink / raw)
  To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>

Change details:
 - Asic initialization interface cleanup.
 - Added mode based initialization for 1860

Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 drivers/net/bna/bfa_ioc.c    |    8 +-
 drivers/net/bna/bfa_ioc.h    |    3 +
 drivers/net/bna/bfa_ioc_ct.c |  378 ++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 377 insertions(+), 12 deletions(-)

diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
index b23d331..d970a42 100644
--- a/drivers/net/bna/bfa_ioc.c
+++ b/drivers/net/bna/bfa_ioc.c
@@ -1894,7 +1894,13 @@ bfa_nw_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev,
 		BUG_ON(1);
 	}
 
-	bfa_nw_ioc_set_ct_hwif(ioc);
+	/**
+	 * Set asic specific interfaces.
+	 */
+	if (ioc->asic_gen == BFI_ASIC_GEN_CT)
+		bfa_nw_ioc_set_ct_hwif(ioc);
+	else
+		bfa_nw_ioc_set_ct2_hwif(ioc);
 
 	bfa_ioc_map_port(ioc);
 	bfa_ioc_reg_init(ioc);
diff --git a/drivers/net/bna/bfa_ioc.h b/drivers/net/bna/bfa_ioc.h
index 11c7bd5..c22c9c0 100644
--- a/drivers/net/bna/bfa_ioc.h
+++ b/drivers/net/bna/bfa_ioc.h
@@ -72,6 +72,7 @@ struct bfa_ioc_regs {
 	void __iomem *hfn_mbox;
 	void __iomem *lpu_mbox_cmd;
 	void __iomem *lpu_mbox;
+	void __iomem *lpu_read_stat;
 	void __iomem *pss_ctl_reg;
 	void __iomem *pss_err_status_reg;
 	void __iomem *app_pll_fast_ctl_reg;
@@ -223,6 +224,7 @@ struct bfa_ioc_hwif {
 	void		(*ioc_sync_leave)	(struct bfa_ioc *ioc);
 	void		(*ioc_sync_ack)		(struct bfa_ioc *ioc);
 	bool		(*ioc_sync_complete)	(struct bfa_ioc *ioc);
+	bool		(*ioc_lpu_read_stat)	(struct bfa_ioc *ioc);
 };
 
 #define bfa_ioc_pcifn(__ioc)		((__ioc)->pcidev.pci_func)
@@ -276,6 +278,7 @@ void bfa_nw_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc,
 			((__ioc)->ioc_hwif->ioc_ownership_reset(__ioc))
 
 void bfa_nw_ioc_set_ct_hwif(struct bfa_ioc *ioc);
+void bfa_nw_ioc_set_ct2_hwif(struct bfa_ioc *ioc);
 
 void bfa_nw_ioc_attach(struct bfa_ioc *ioc, void *bfa,
 		struct bfa_ioc_cbfn *cbfn);
diff --git a/drivers/net/bna/bfa_ioc_ct.c b/drivers/net/bna/bfa_ioc_ct.c
index 2daa1dd..3aa01dd 100644
--- a/drivers/net/bna/bfa_ioc_ct.c
+++ b/drivers/net/bna/bfa_ioc_ct.c
@@ -37,7 +37,9 @@
 static bool bfa_ioc_ct_firmware_lock(struct bfa_ioc *ioc);
 static void bfa_ioc_ct_firmware_unlock(struct bfa_ioc *ioc);
 static void bfa_ioc_ct_reg_init(struct bfa_ioc *ioc);
+static void bfa_ioc_ct2_reg_init(struct bfa_ioc *ioc);
 static void bfa_ioc_ct_map_port(struct bfa_ioc *ioc);
+static void bfa_ioc_ct2_map_port(struct bfa_ioc *ioc);
 static void bfa_ioc_ct_isr_mode_set(struct bfa_ioc *ioc, bool msix);
 static void bfa_ioc_ct_notify_fail(struct bfa_ioc *ioc);
 static void bfa_ioc_ct_ownership_reset(struct bfa_ioc *ioc);
@@ -47,8 +49,28 @@ static void bfa_ioc_ct_sync_leave(struct bfa_ioc *ioc);
 static void bfa_ioc_ct_sync_ack(struct bfa_ioc *ioc);
 static bool bfa_ioc_ct_sync_complete(struct bfa_ioc *ioc);
 static enum bfa_status bfa_ioc_ct_pll_init(void __iomem *rb, bool fcmode);
+static enum bfa_status bfa_ioc_ct2_pll_init(void __iomem *rb, bool fcmode);
+static bool bfa_ioc_ct2_lpu_read_stat(struct bfa_ioc *ioc);
 
 static struct bfa_ioc_hwif nw_hwif_ct;
+static struct bfa_ioc_hwif nw_hwif_ct2;
+
+/**
+ * Called from bfa_ioc_attach() to map asic specific calls.
+ */
+static void
+bfa_ioc_set_ctx_hwif(struct bfa_ioc *ioc, struct bfa_ioc_hwif *hwif)
+{
+	hwif->ioc_firmware_lock = bfa_ioc_ct_firmware_lock;
+	hwif->ioc_firmware_unlock = bfa_ioc_ct_firmware_unlock;
+	hwif->ioc_notify_fail = bfa_ioc_ct_notify_fail;
+	hwif->ioc_ownership_reset = bfa_ioc_ct_ownership_reset;
+	hwif->ioc_sync_start = bfa_ioc_ct_sync_start;
+	hwif->ioc_sync_join = bfa_ioc_ct_sync_join;
+	hwif->ioc_sync_leave = bfa_ioc_ct_sync_leave;
+	hwif->ioc_sync_ack = bfa_ioc_ct_sync_ack;
+	hwif->ioc_sync_complete = bfa_ioc_ct_sync_complete;
+}
 
 /**
  * Called from bfa_ioc_attach() to map asic specific calls.
@@ -56,24 +78,32 @@ static struct bfa_ioc_hwif nw_hwif_ct;
 void
 bfa_nw_ioc_set_ct_hwif(struct bfa_ioc *ioc)
 {
+	bfa_ioc_set_ctx_hwif(ioc, &nw_hwif_ct);
+
 	nw_hwif_ct.ioc_pll_init = bfa_ioc_ct_pll_init;
-	nw_hwif_ct.ioc_firmware_lock = bfa_ioc_ct_firmware_lock;
-	nw_hwif_ct.ioc_firmware_unlock = bfa_ioc_ct_firmware_unlock;
 	nw_hwif_ct.ioc_reg_init = bfa_ioc_ct_reg_init;
 	nw_hwif_ct.ioc_map_port = bfa_ioc_ct_map_port;
 	nw_hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set;
-	nw_hwif_ct.ioc_notify_fail = bfa_ioc_ct_notify_fail;
-	nw_hwif_ct.ioc_ownership_reset = bfa_ioc_ct_ownership_reset;
-	nw_hwif_ct.ioc_sync_start = bfa_ioc_ct_sync_start;
-	nw_hwif_ct.ioc_sync_join = bfa_ioc_ct_sync_join;
-	nw_hwif_ct.ioc_sync_leave = bfa_ioc_ct_sync_leave;
-	nw_hwif_ct.ioc_sync_ack = bfa_ioc_ct_sync_ack;
-	nw_hwif_ct.ioc_sync_complete = bfa_ioc_ct_sync_complete;
-
 	ioc->ioc_hwif = &nw_hwif_ct;
 }
 
 /**
+ * Called from bfa_ioc_attach() to map asic specific calls.
+ */
+void
+bfa_nw_ioc_set_ct2_hwif(struct bfa_ioc *ioc)
+{
+	bfa_ioc_set_ctx_hwif(ioc, &nw_hwif_ct2);
+
+	nw_hwif_ct2.ioc_pll_init = bfa_ioc_ct2_pll_init;
+	nw_hwif_ct2.ioc_reg_init = bfa_ioc_ct2_reg_init;
+	nw_hwif_ct2.ioc_map_port = bfa_ioc_ct2_map_port;
+	nw_hwif_ct2.ioc_lpu_read_stat = bfa_ioc_ct2_lpu_read_stat;
+	nw_hwif_ct2.ioc_isr_mode_set = NULL;
+	ioc->ioc_hwif = &nw_hwif_ct2;
+}
+
+/**
  * Return true if firmware of current driver matches the running firmware.
  */
 static bool
@@ -201,6 +231,16 @@ static struct { u32 hfn, lpu; } ct_p1reg[] = {
 	{ HOSTFN3_LPU1_CMD_STAT, LPU1_HOSTFN3_CMD_STAT }
 };
 
+static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn, hfn, lpu, lpu_read; }
+	ct2_reg[] = {
+	{ CT2_HOSTFN_LPU0_MBOX0, CT2_LPU0_HOSTFN_MBOX0, CT2_HOSTFN_PAGE_NUM,
+	  CT2_HOSTFN_LPU0_CMD_STAT, CT2_LPU0_HOSTFN_CMD_STAT,
+	  CT2_HOSTFN_LPU0_READ_STAT},
+	{ CT2_HOSTFN_LPU1_MBOX0, CT2_LPU1_HOSTFN_MBOX0, CT2_HOSTFN_PAGE_NUM,
+	  CT2_HOSTFN_LPU1_CMD_STAT, CT2_LPU1_HOSTFN_CMD_STAT,
+	  CT2_HOSTFN_LPU1_READ_STAT},
+};
+
 static void
 bfa_ioc_ct_reg_init(struct bfa_ioc *ioc)
 {
@@ -260,6 +300,64 @@ bfa_ioc_ct_reg_init(struct bfa_ioc *ioc)
 	ioc->ioc_regs.err_set = (rb + ERR_SET_REG);
 }
 
+static void
+bfa_ioc_ct2_reg_init(struct bfa_ioc *ioc)
+{
+	void __iomem *rb;
+	int		port = bfa_ioc_portid(ioc);
+
+	rb = bfa_ioc_bar0(ioc);
+
+	ioc->ioc_regs.hfn_mbox = rb + ct2_reg[port].hfn_mbox;
+	ioc->ioc_regs.lpu_mbox = rb + ct2_reg[port].lpu_mbox;
+	ioc->ioc_regs.host_page_num_fn = rb + ct2_reg[port].hfn_pgn;
+	ioc->ioc_regs.hfn_mbox_cmd = rb + ct2_reg[port].hfn;
+	ioc->ioc_regs.lpu_mbox_cmd = rb + ct2_reg[port].lpu;
+	ioc->ioc_regs.lpu_read_stat = rb + ct2_reg[port].lpu_read;
+
+	if (port == 0) {
+		ioc->ioc_regs.heartbeat = rb + CT2_BFA_IOC0_HBEAT_REG;
+		ioc->ioc_regs.ioc_fwstate = rb + CT2_BFA_IOC0_STATE_REG;
+		ioc->ioc_regs.alt_ioc_fwstate = rb + CT2_BFA_IOC1_STATE_REG;
+		ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P0;
+		ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P1;
+	} else {
+		ioc->ioc_regs.heartbeat = (rb + CT2_BFA_IOC1_HBEAT_REG);
+		ioc->ioc_regs.ioc_fwstate = (rb + CT2_BFA_IOC1_STATE_REG);
+		ioc->ioc_regs.alt_ioc_fwstate = rb + CT2_BFA_IOC0_STATE_REG;
+		ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P1;
+		ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P0;
+	}
+
+	/*
+	 * PSS control registers
+	 */
+	ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG);
+	ioc->ioc_regs.pss_err_status_reg = (rb + PSS_ERR_STATUS_REG);
+	ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + CT2_APP_PLL_LCLK_CTL_REG);
+	ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + CT2_APP_PLL_SCLK_CTL_REG);
+
+	/*
+	 * IOC semaphore registers and serialization
+	 */
+	ioc->ioc_regs.ioc_sem_reg = (rb + CT2_HOST_SEM0_REG);
+	ioc->ioc_regs.ioc_usage_sem_reg = (rb + CT2_HOST_SEM1_REG);
+	ioc->ioc_regs.ioc_init_sem_reg = (rb + CT2_HOST_SEM2_REG);
+	ioc->ioc_regs.ioc_usage_reg = (rb + CT2_BFA_FW_USE_COUNT);
+	ioc->ioc_regs.ioc_fail_sync = (rb + CT2_BFA_IOC_FAIL_SYNC);
+
+	/**
+	 * sram memory access
+	 */
+	ioc->ioc_regs.smem_page_start = (rb + PSS_SMEM_PAGE_START);
+	ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CT;
+
+	/*
+	 * err set reg : for notification of hb failure in fcmode
+	 */
+	ioc->ioc_regs.err_set = (rb + ERR_SET_REG);
+}
+
 /**
  * Initialize IOC to port mapping.
  */
@@ -280,6 +378,16 @@ bfa_ioc_ct_map_port(struct bfa_ioc *ioc)
 
 }
 
+static void
+bfa_ioc_ct2_map_port(struct bfa_ioc *ioc)
+{
+	void __iomem *rb = ioc->pcidev.pci_bar_kva;
+	u32	r32;
+
+	r32 = readl(rb + CT2_HOSTFN_PERSONALITY0);
+	ioc->port_id = ((r32 & __FC_LL_PORT_MAP__MK) >> __FC_LL_PORT_MAP__SH);
+}
+
 /**
  * Set interrupt mode for a function: INTX or MSIX
  */
@@ -297,7 +405,7 @@ bfa_ioc_ct_isr_mode_set(struct bfa_ioc *ioc, bool msix)
 	/**
 	 * If already in desired mode, do not change anything
 	 */
-	if (!msix && mode)
+	if ((!msix && mode) || (msix && !mode))
 		return;
 
 	if (msix)
@@ -311,6 +419,50 @@ bfa_ioc_ct_isr_mode_set(struct bfa_ioc *ioc, bool msix)
 	writel(r32, rb + FNC_PERS_REG);
 }
 
+static bool
+bfa_ioc_ct2_lpu_read_stat(struct bfa_ioc *ioc)
+{
+	u32 r32;
+
+	r32 = readl(ioc->ioc_regs.lpu_read_stat);
+	if (r32) {
+		writel(1, ioc->ioc_regs.lpu_read_stat);
+		return true;
+	}
+
+	return false;
+}
+
+/**
+ * MSI-X resource allocation for 1860 with no asic block
+ */
+#define HOSTFN_MSIX_DEFAULT		64
+#define HOSTFN_MSIX_VT_INDEX_MBOX_ERR	0x30138
+#define HOSTFN_MSIX_VT_OFST_NUMVT	0x3013c
+#define __MSIX_VT_NUMVT__MK		0x003ff800
+#define __MSIX_VT_NUMVT__SH		11
+#define __MSIX_VT_NUMVT_(_v)		((_v) << __MSIX_VT_NUMVT__SH)
+#define __MSIX_VT_OFST_			0x000007ff
+void
+bfa_ioc_ct2_poweron(struct bfa_ioc *ioc)
+{
+	void __iomem *rb = ioc->pcidev.pci_bar_kva;
+	u32 r32;
+
+	r32 = readl(rb + HOSTFN_MSIX_VT_OFST_NUMVT);
+	if (r32 & __MSIX_VT_NUMVT__MK) {
+		writel(r32 & __MSIX_VT_OFST_,
+			rb + HOSTFN_MSIX_VT_INDEX_MBOX_ERR);
+		return;
+	}
+
+	writel(__MSIX_VT_NUMVT_(HOSTFN_MSIX_DEFAULT - 1) |
+			HOSTFN_MSIX_DEFAULT * bfa_ioc_pcifn(ioc),
+			rb + HOSTFN_MSIX_VT_OFST_NUMVT);
+	writel(HOSTFN_MSIX_DEFAULT * bfa_ioc_pcifn(ioc),
+			rb + HOSTFN_MSIX_VT_INDEX_MBOX_ERR);
+}
+
 /**
  * Cleanup hw semaphore and usecnt registers
  */
@@ -504,3 +656,207 @@ bfa_ioc_ct_pll_init(void __iomem *rb, bool fcmode)
 	writel(0, (rb + MBIST_CTL_REG));
 	return BFA_STATUS_OK;
 }
+
+static void
+bfa_ioc_ct2_sclk_init(void __iomem *rb)
+{
+	u32 r32;
+
+	/*
+	 * put s_clk PLL and PLL FSM in reset
+	 */
+	r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG));
+	r32 &= ~(__APP_PLL_SCLK_ENABLE | __APP_PLL_SCLK_LRESETN);
+	r32 |= (__APP_PLL_SCLK_ENARST | __APP_PLL_SCLK_BYPASS |
+		__APP_PLL_SCLK_LOGIC_SOFT_RESET);
+	writel(r32, (rb + CT2_APP_PLL_SCLK_CTL_REG));
+
+	/*
+	 * Ignore mode and program for the max clock (which is FC16)
+	 * Firmware/NFC will do the PLL init appropiately
+	 */
+	r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG));
+	r32 &= ~(__APP_PLL_SCLK_REFCLK_SEL | __APP_PLL_SCLK_CLK_DIV2);
+	writel(r32, (rb + CT2_APP_PLL_SCLK_CTL_REG));
+
+	/*
+	 * while doing PLL init dont clock gate ethernet subsystem
+	 */
+	r32 = readl((rb + CT2_CHIP_MISC_PRG));
+	writel((r32 | __ETH_CLK_ENABLE_PORT0),
+				(rb + CT2_CHIP_MISC_PRG));
+
+	r32 = readl((rb + CT2_PCIE_MISC_REG));
+	writel((r32 | __ETH_CLK_ENABLE_PORT1),
+				(rb + CT2_PCIE_MISC_REG));
+
+	/*
+	 * set sclk value
+	 */
+	r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG));
+	r32 &= (__P_SCLK_PLL_LOCK | __APP_PLL_SCLK_REFCLK_SEL |
+		__APP_PLL_SCLK_CLK_DIV2);
+	writel(r32 | 0x1061731b, (rb + CT2_APP_PLL_SCLK_CTL_REG));
+
+	/*
+	 * poll for s_clk lock or delay 1ms
+	 */
+	udelay(1000);
+
+	/*
+	 * Dont do clock gating for ethernet subsystem, firmware/NFC will
+	 * do this appropriately
+	 */
+}
+
+static void
+bfa_ioc_ct2_lclk_init(void __iomem *rb)
+{
+	u32 r32;
+
+	/*
+	 * put l_clk PLL and PLL FSM in reset
+	 */
+	r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG));
+	r32 &= ~(__APP_PLL_LCLK_ENABLE | __APP_PLL_LCLK_LRESETN);
+	r32 |= (__APP_PLL_LCLK_ENARST | __APP_PLL_LCLK_BYPASS |
+		__APP_PLL_LCLK_LOGIC_SOFT_RESET);
+	writel(r32, (rb + CT2_APP_PLL_LCLK_CTL_REG));
+
+	/*
+	 * set LPU speed (set for FC16 which will work for other modes)
+	 */
+	r32 = readl((rb + CT2_CHIP_MISC_PRG));
+	writel(r32, (rb + CT2_CHIP_MISC_PRG));
+
+	/*
+	 * set LPU half speed (set for FC16 which will work for other modes)
+	 */
+	r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG));
+	writel(r32, (rb + CT2_APP_PLL_LCLK_CTL_REG));
+
+	/*
+	 * set lclk for mode (set for FC16)
+	 */
+	r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG));
+	r32 &= (__P_LCLK_PLL_LOCK | __APP_LPUCLK_HALFSPEED);
+	r32 |= 0x20c1731b;
+	writel(r32, (rb + CT2_APP_PLL_LCLK_CTL_REG));
+
+	/*
+	 * poll for s_clk lock or delay 1ms
+	 */
+	udelay(1000);
+}
+
+static void
+bfa_ioc_ct2_mem_init(void __iomem *rb)
+{
+	u32 r32;
+
+	r32 = readl((rb + PSS_CTL_REG));
+	r32 &= ~__PSS_LMEM_RESET;
+	writel(r32, (rb + PSS_CTL_REG));
+	udelay(1000);
+
+	writel(__EDRAM_BISTR_START, (rb + CT2_MBIST_CTL_REG));
+	udelay(1000);
+	writel(0, (rb + CT2_MBIST_CTL_REG));
+}
+
+static void
+bfa_ioc_ct2_mac_reset(void __iomem *rb)
+{
+	volatile u32 r32;
+
+	bfa_ioc_ct2_sclk_init(rb);
+	bfa_ioc_ct2_lclk_init(rb);
+
+	/*
+	 * release soft reset on s_clk & l_clk
+	 */
+	r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG));
+	writel((r32 & ~__APP_PLL_SCLK_LOGIC_SOFT_RESET),
+			(rb + CT2_APP_PLL_SCLK_CTL_REG));
+
+	/*
+	 * release soft reset on s_clk & l_clk
+	 */
+	r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG));
+	writel((r32 & ~__APP_PLL_LCLK_LOGIC_SOFT_RESET),
+			(rb + CT2_APP_PLL_LCLK_CTL_REG));
+
+	/* put port0, port1 MAC & AHB in reset */
+	writel((__CSI_MAC_RESET | __CSI_MAC_AHB_RESET),
+			(rb + CT2_CSI_MAC_CONTROL_REG(0)));
+	writel((__CSI_MAC_RESET | __CSI_MAC_AHB_RESET),
+			(rb + CT2_CSI_MAC_CONTROL_REG(1)));
+}
+
+#define CT2_NFC_MAX_DELAY       1000
+static enum bfa_status
+bfa_ioc_ct2_pll_init(void __iomem *rb, bool fcmode)
+{
+	volatile u32 wgn, r32;
+	int i;
+
+	/*
+	 * Initialize PLL if not already done by NFC
+	 */
+	wgn = readl(rb + CT2_WGN_STATUS);
+	if (!(wgn & __GLBL_PF_VF_CFG_RDY)) {
+		writel(__HALT_NFC_CONTROLLER, (rb + CT2_NFC_CSR_SET_REG));
+		for (i = 0; i < CT2_NFC_MAX_DELAY; i++) {
+			r32 = readl(rb + CT2_NFC_CSR_SET_REG);
+			if (r32 & __NFC_CONTROLLER_HALTED)
+				break;
+			udelay(1000);
+		}
+	}
+
+	/*
+	 * Mask the interrupts and clear any
+	 * pending interrupts left by BIOS/EFI
+	 */
+
+	writel(1, (rb + CT2_LPU0_HOSTFN_MBOX0_MSK));
+	writel(1, (rb + CT2_LPU1_HOSTFN_MBOX0_MSK));
+
+	r32 = readl((rb + CT2_LPU0_HOSTFN_CMD_STAT));
+	if (r32 == 1) {
+		writel(1, (rb + CT2_LPU0_HOSTFN_CMD_STAT));
+		readl((rb + CT2_LPU0_HOSTFN_CMD_STAT));
+	}
+	r32 = readl((rb + CT2_LPU1_HOSTFN_CMD_STAT));
+	if (r32 == 1) {
+		writel(1, (rb + CT2_LPU1_HOSTFN_CMD_STAT));
+		readl((rb + CT2_LPU1_HOSTFN_CMD_STAT));
+	}
+
+	bfa_ioc_ct2_mac_reset(rb);
+	bfa_ioc_ct2_sclk_init(rb);
+	bfa_ioc_ct2_lclk_init(rb);
+
+	/*
+	 * release soft reset on s_clk & l_clk
+	 */
+	r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG));
+	writel((r32 & ~__APP_PLL_LCLK_LOGIC_SOFT_RESET),
+			(rb + CT2_APP_PLL_SCLK_CTL_REG));
+
+	/*
+	 * Announce flash device presence, if flash was corrupted.
+	 */
+	if (wgn == (__WGN_READY | __GLBL_PF_VF_CFG_RDY)) {
+		r32 = readl((rb + PSS_GPIO_OUT_REG));
+		writel((r32 & ~1), (rb + PSS_GPIO_OUT_REG));
+		r32 = readl((rb + PSS_GPIO_OE_REG));
+		writel((r32 | 1), (rb + PSS_GPIO_OE_REG));
+	}
+
+	bfa_ioc_ct2_mem_init(rb);
+
+	writel(BFI_IOC_UNINIT, (rb + CT2_BFA_IOC0_STATE_REG));
+	writel(BFI_IOC_UNINIT, (rb + CT2_BFA_IOC1_STATE_REG));
+	return BFA_STATUS_OK;
+}
-- 
1.7.1


^ permalink raw reply related

* [PATCH 14/45] bna: Brocade 1860 Register and ASIC Mode Changes
From: Rasesh Mody @ 2011-07-18  8:22 UTC (permalink / raw)
  To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>

Chnage details:
 - Added 1860 specific register definitions
 - Setup 1860 registers used by IOC logic

Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 drivers/net/bna/bfa_ioc.h    |    5 +++--
 drivers/net/bna/bfa_ioc_ct.c |   19 +++++++++++--------
 2 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/drivers/net/bna/bfa_ioc.h b/drivers/net/bna/bfa_ioc.h
index c22c9c0..592a104 100644
--- a/drivers/net/bna/bfa_ioc.h
+++ b/drivers/net/bna/bfa_ioc.h
@@ -210,7 +210,8 @@ struct bfa_ioc {
 };
 
 struct bfa_ioc_hwif {
-	enum bfa_status (*ioc_pll_init) (void __iomem *rb, bool fcmode);
+	enum bfa_status (*ioc_pll_init) (void __iomem *rb,
+						enum bfi_asic_mode m);
 	bool		(*ioc_firmware_lock)	(struct bfa_ioc *ioc);
 	void		(*ioc_firmware_unlock)	(struct bfa_ioc *ioc);
 	void		(*ioc_reg_init)	(struct bfa_ioc *ioc);
@@ -270,7 +271,7 @@ void bfa_nw_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc,
 
 #define bfa_ioc_pll_init_asic(__ioc) \
 	((__ioc)->ioc_hwif->ioc_pll_init((__ioc)->pcidev.pci_bar_kva, \
-			   (__ioc)->fcmode))
+			   (__ioc)->asic_mode))
 
 #define	bfa_ioc_isr_mode_set(__ioc, __msix)			\
 			((__ioc)->ioc_hwif->ioc_isr_mode_set(__ioc, __msix))
diff --git a/drivers/net/bna/bfa_ioc_ct.c b/drivers/net/bna/bfa_ioc_ct.c
index 3aa01dd..a615c15 100644
--- a/drivers/net/bna/bfa_ioc_ct.c
+++ b/drivers/net/bna/bfa_ioc_ct.c
@@ -48,8 +48,10 @@ static void bfa_ioc_ct_sync_join(struct bfa_ioc *ioc);
 static void bfa_ioc_ct_sync_leave(struct bfa_ioc *ioc);
 static void bfa_ioc_ct_sync_ack(struct bfa_ioc *ioc);
 static bool bfa_ioc_ct_sync_complete(struct bfa_ioc *ioc);
-static enum bfa_status bfa_ioc_ct_pll_init(void __iomem *rb, bool fcmode);
-static enum bfa_status bfa_ioc_ct2_pll_init(void __iomem *rb, bool fcmode);
+static enum bfa_status bfa_ioc_ct_pll_init(void __iomem *rb,
+				enum bfi_asic_mode asic_mode);
+static enum bfa_status bfa_ioc_ct2_pll_init(void __iomem *rb,
+				enum bfi_asic_mode asic_mode);
 static bool bfa_ioc_ct2_lpu_read_stat(struct bfa_ioc *ioc);
 
 static struct bfa_ioc_hwif nw_hwif_ct;
@@ -204,7 +206,7 @@ bfa_ioc_ct_notify_fail(struct bfa_ioc *ioc)
 /**
  * Host to LPU mailbox message addresses
  */
-static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } iocreg_fnreg[] = {
+static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } ct_fnreg[] = {
 	{ HOSTFN0_LPU_MBOX0_0, LPU_HOSTFN0_MBOX0_0, HOST_PAGE_NUM_FN0 },
 	{ HOSTFN1_LPU_MBOX0_8, LPU_HOSTFN1_MBOX0_8, HOST_PAGE_NUM_FN1 },
 	{ HOSTFN2_LPU_MBOX0_0, LPU_HOSTFN2_MBOX0_0, HOST_PAGE_NUM_FN2 },
@@ -249,9 +251,9 @@ bfa_ioc_ct_reg_init(struct bfa_ioc *ioc)
 
 	rb = bfa_ioc_bar0(ioc);
 
-	ioc->ioc_regs.hfn_mbox = rb + iocreg_fnreg[pcifn].hfn_mbox;
-	ioc->ioc_regs.lpu_mbox = rb + iocreg_fnreg[pcifn].lpu_mbox;
-	ioc->ioc_regs.host_page_num_fn = rb + iocreg_fnreg[pcifn].hfn_pgn;
+	ioc->ioc_regs.hfn_mbox = rb + ct_fnreg[pcifn].hfn_mbox;
+	ioc->ioc_regs.lpu_mbox = rb + ct_fnreg[pcifn].lpu_mbox;
+	ioc->ioc_regs.host_page_num_fn = rb + ct_fnreg[pcifn].hfn_pgn;
 
 	if (ioc->port_id == 0) {
 		ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG;
@@ -582,9 +584,10 @@ bfa_ioc_ct_sync_complete(struct bfa_ioc *ioc)
 }
 
 static enum bfa_status
-bfa_ioc_ct_pll_init(void __iomem *rb, bool fcmode)
+bfa_ioc_ct_pll_init(void __iomem *rb, enum bfi_asic_mode asic_mode)
 {
 	u32	pll_sclk, pll_fclk, r32;
+	bool fcmode = (asic_mode == BFI_ASIC_MODE_FC);
 
 	pll_sclk = __APP_PLL_SCLK_LRESETN | __APP_PLL_SCLK_ENARST |
 		__APP_PLL_SCLK_RSEL200500 | __APP_PLL_SCLK_P0_1(3U) |
@@ -795,7 +798,7 @@ bfa_ioc_ct2_mac_reset(void __iomem *rb)
 
 #define CT2_NFC_MAX_DELAY       1000
 static enum bfa_status
-bfa_ioc_ct2_pll_init(void __iomem *rb, bool fcmode)
+bfa_ioc_ct2_pll_init(void __iomem *rb, enum bfi_asic_mode asic_mode)
 {
 	volatile u32 wgn, r32;
 	int i;
-- 
1.7.1


^ permalink raw reply related

* [PATCH 15/45] bna: Set MBOX MSIX Index to Zero
From: Rasesh Mody @ 2011-07-18  8:22 UTC (permalink / raw)
  To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>

Change details:
 - Modifying mbox irq alloc/free code to use MSIX index 0 for mailbox
 - Call register_netdev() with the bnad_conf_lock() not held.
 - setting interrupt type conditionally - MSI-X or INTx and not setting
   interrupt type invariably to INTx.

Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 drivers/net/bna/bnad.c |   17 +++++++++--------
 drivers/net/bna/bnad.h |    3 +++
 2 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c
index f696d3a..cd2b921 100644
--- a/drivers/net/bna/bnad.c
+++ b/drivers/net/bna/bnad.c
@@ -58,7 +58,7 @@ static const u8 bnad_bcast_addr[] =  {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 
 #define BNAD_GET_MBOX_IRQ(_bnad)				\
 	(((_bnad)->cfg_flags & BNAD_CF_MSIX) ?			\
-	 ((_bnad)->msix_table[(_bnad)->msix_num - 1].vector) :	\
+	 ((_bnad)->msix_table[BNAD_MAILBOX_MSIX_INDEX].vector) : \
 	 ((_bnad)->pcidev->irq))
 
 #define BNAD_FILL_UNMAPQ_MEM_REQ(_res_info, _num, _depth)	\
@@ -1216,17 +1216,17 @@ bnad_mbox_irq_alloc(struct bnad *bnad,
 	spin_lock_irqsave(&bnad->bna_lock, flags);
 	if (bnad->cfg_flags & BNAD_CF_MSIX) {
 		irq_handler = (irq_handler_t)bnad_msix_mbox_handler;
-		irq = bnad->msix_table[bnad->msix_num - 1].vector;
+		irq = bnad->msix_table[BNAD_MAILBOX_MSIX_INDEX].vector;
 		irq_flags = 0;
 		intr_info->intr_type = BNA_INTR_T_MSIX;
-		intr_info->idl[0].vector = bnad->msix_num - 1;
+		intr_info->idl[0].vector = BNAD_MAILBOX_MSIX_INDEX;
 	} else {
 		irq_handler = (irq_handler_t)bnad_isr;
 		irq = bnad->pcidev->irq;
 		irq_flags = IRQF_SHARED;
 		intr_info->intr_type = BNA_INTR_T_INTX;
-		/* intr_info->idl.vector = 0 ? */
 	}
+
 	spin_unlock_irqrestore(&bnad->bna_lock, flags);
 	sprintf(bnad->mbox_irq_name, "%s", BNAD_NAME);
 
@@ -1279,11 +1279,12 @@ bnad_txrx_irq_alloc(struct bnad *bnad, enum bnad_intr_source src,
 
 		switch (src) {
 		case BNAD_INTR_TX:
-			vector_start = txrx_id;
+			vector_start = BNAD_MAILBOX_MSIX_VECTORS + txrx_id;
 			break;
 
 		case BNAD_INTR_RX:
-			vector_start = bnad->num_tx * bnad->num_txq_per_tx +
+			vector_start = BNAD_MAILBOX_MSIX_VECTORS +
+					(bnad->num_tx * bnad->num_txq_per_tx) +
 					txrx_id;
 			break;
 
@@ -1304,11 +1305,11 @@ bnad_txrx_irq_alloc(struct bnad *bnad, enum bnad_intr_source src,
 
 		switch (src) {
 		case BNAD_INTR_TX:
-			intr_info->idl[0].vector = 0x1; /* Bit mask : Tx IB */
+			intr_info->idl[0].vector = BNAD_INTX_TX_IB_BITMASK;
 			break;
 
 		case BNAD_INTR_RX:
-			intr_info->idl[0].vector = 0x2; /* Bit mask : Rx IB */
+			intr_info->idl[0].vector = BNAD_INTX_RX_IB_BITMASK;
 			break;
 		}
 	}
diff --git a/drivers/net/bna/bnad.h b/drivers/net/bna/bnad.h
index 0928e68..6a161b0 100644
--- a/drivers/net/bna/bnad.h
+++ b/drivers/net/bna/bnad.h
@@ -68,7 +68,10 @@ struct bnad_rx_ctrl {
 
 #define BNAD_VERSION			"2.3.2.3"
 
+#define BNAD_MAILBOX_MSIX_INDEX		0
 #define BNAD_MAILBOX_MSIX_VECTORS	1
+#define BNAD_INTX_TX_IB_BITMASK		0x1
+#define BNAD_INTX_RX_IB_BITMASK		0x2
 
 #define BNAD_STATS_TIMER_FREQ		1000	/* in msecs */
 #define BNAD_DIM_TIMER_FREQ		1000	/* in msecs */
-- 
1.7.1


^ permalink raw reply related

* [PATCH 16/45] bna: IOC PCI Init & Enable Changes
From: Rasesh Mody @ 2011-07-18  8:22 UTC (permalink / raw)
  To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>

Change details:
 - Change to pass pci function class code rather than msg class
   code in pci init and ioc enablement functions

Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 drivers/net/bna/bfa_ioc.c |    6 +++---
 drivers/net/bna/bfa_ioc.h |    3 +--
 drivers/net/bna/bfi.h     |    8 +++++---
 3 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
index d970a42..c304212 100644
--- a/drivers/net/bna/bfa_ioc.c
+++ b/drivers/net/bna/bfa_ioc.c
@@ -1449,7 +1449,7 @@ bfa_ioc_send_enable(struct bfa_ioc *ioc)
 
 	bfi_h2i_set(enable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_ENABLE_REQ,
 		    bfa_ioc_portid(ioc));
-	enable_req.ioc_class = ioc->ioc_mc;
+	enable_req.clscode = htons(ioc->clscode);
 	do_gettimeofday(&tv);
 	enable_req.tv_sec = ntohl(tv.tv_sec);
 	bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req));
@@ -1867,9 +1867,9 @@ bfa_nw_ioc_detach(struct bfa_ioc *ioc)
  */
 void
 bfa_nw_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev,
-		 enum bfi_mclass mc)
+		 enum bfi_pcifn_class clscode)
 {
-	ioc->ioc_mc	= mc;
+	ioc->clscode	= clscode;
 	ioc->pcidev	= *pcidev;
 
 	/**
diff --git a/drivers/net/bna/bfa_ioc.h b/drivers/net/bna/bfa_ioc.h
index 592a104..46309e4 100644
--- a/drivers/net/bna/bfa_ioc.h
+++ b/drivers/net/bna/bfa_ioc.h
@@ -188,7 +188,6 @@ struct bfa_ioc {
 	int			dbg_fwsave_len;
 	bool			dbg_fwsave_once;
 	enum bfi_pcifn_class	clscode;
-	enum bfi_mclass		ioc_mc;
 	struct bfa_ioc_regs	ioc_regs;
 	struct bfa_ioc_drv_stats stats;
 	bool			fcmode;
@@ -286,7 +285,7 @@ void bfa_nw_ioc_attach(struct bfa_ioc *ioc, void *bfa,
 void bfa_nw_ioc_auto_recover(bool auto_recover);
 void bfa_nw_ioc_detach(struct bfa_ioc *ioc);
 void bfa_nw_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev,
-		enum bfi_mclass mc);
+		enum bfi_pcifn_class clscode);
 u32 bfa_nw_ioc_meminfo(void);
 void bfa_nw_ioc_mem_claim(struct bfa_ioc *ioc,  u8 *dm_kva, u64 dm_pa);
 void bfa_nw_ioc_enable(struct bfa_ioc *ioc);
diff --git a/drivers/net/bna/bfi.h b/drivers/net/bna/bfi.h
index c855b44..284c3f8 100644
--- a/drivers/net/bna/bfi.h
+++ b/drivers/net/bna/bfi.h
@@ -37,13 +37,15 @@ struct bfi_mhdr {
 	u8		msg_id;		/*!< msg opcode with in the class   */
 	union {
 		struct {
-			u8	rsvd;
+			u8	qid;
 			u8	lpu_id;	/*!< msg destination		    */
 		} h2i;
 		u16	i2htok;	/*!< token in msgs to host	    */
 	} mtag;
 };
 
+#define bfi_mhdr_2_qid(_mh)     ((_mh)->mtag.h2i.qid)
+
 #define bfi_h2i_set(_mh, _mc, _op, _lpuid) do {		\
 	(_mh).msg_class			= (_mc);		\
 	(_mh).msg_id			= (_op);		\
@@ -393,8 +395,8 @@ enum {
  */
 struct bfi_ioc_ctrl_req {
 	struct bfi_mhdr mh;
-	u8			ioc_class;
-	u8			rsvd[3];
+	u16			clscode;
+	u16			rsvd;
 	u32		tv_sec;
 };
 
-- 
1.7.1


^ permalink raw reply related

* [PATCH 17/45] bna: Mailbox Interface Changes and FW MBOX fix
From: Rasesh Mody @ 2011-07-18  8:22 UTC (permalink / raw)
  To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>

Change details:
 - Define Brocade 1850 specific interrupt status defines.
 - CT2 host mailbox interrupt now has 2 roles -- lpu-to-host event notification
   and host-to-lpu mailbox completion event
 - Defined asic specific mailbox interfaces.
 - New h/w mailbox interfaces take 8-bit FIDs and 2-bit port id for owner.
 - Cleaned up mailbox definitions and usage for new and old HW.
   Eliminated usage of ASIC ID.
 - MSI-X vector assignment and programming done by firmware.
 - Fixed host offsets for CPE/RME queue registers.
 - Enable Ethernet driver/mode.
 - Firmware mbox fixes.

Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 drivers/net/bna/bfa_defs.h |   10 +++++++---
 drivers/net/bna/bfa_ioc.c  |   29 +++++++++++++++++++----------
 drivers/net/bna/bfa_ioc.h  |    6 ++++--
 3 files changed, 30 insertions(+), 15 deletions(-)

diff --git a/drivers/net/bna/bfa_defs.h b/drivers/net/bna/bfa_defs.h
index fc9702c..f5909d0 100644
--- a/drivers/net/bna/bfa_defs.h
+++ b/drivers/net/bna/bfa_defs.h
@@ -243,8 +243,12 @@ enum {
 	BFA_PCI_DEVICE_ID_CT2		= 0x22,
 };
 
-#define bfa_asic_id_ct(devid)			\
-	((devid) == PCI_DEVICE_ID_BROCADE_CT ||	\
-	(devid) == PCI_DEVICE_ID_BROCADE_CT_FC)
+#define bfa_asic_id_ct(device)			\
+	((device) == PCI_DEVICE_ID_BROCADE_CT ||	\
+	 (device) == PCI_DEVICE_ID_BROCADE_CT_FC)
+#define bfa_asic_id_ct2(device)			\
+	((device) == BFA_PCI_DEVICE_ID_CT2) /* Add to pci_ids.h */
+#define bfa_asic_id_ctc(device)			\
+	(bfa_asic_id_ct(device) || bfa_asic_id_ct2(device))
 
 #endif /* __BFA_DEFS_H__ */
diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
index c304212..fcc9278 100644
--- a/drivers/net/bna/bfa_ioc.c
+++ b/drivers/net/bna/bfa_ioc.c
@@ -1731,8 +1731,6 @@ static void
 bfa_ioc_boot(struct bfa_ioc *ioc, enum bfi_fwboot_type boot_type,
 		enum bfi_fwboot_env boot_env)
 {
-	void __iomem *rb;
-
 	bfa_ioc_stats(ioc, ioc_boots);
 
 	if (bfa_ioc_pll_init(ioc) != BFA_STATUS_OK)
@@ -1741,13 +1739,12 @@ bfa_ioc_boot(struct bfa_ioc *ioc, enum bfi_fwboot_type boot_type,
 	/**
 	 * Initialize IOC state of all functions on a chip reset.
 	 */
-	rb = ioc->pcidev.pci_bar_kva;
 	if (boot_type == BFI_FWBOOT_TYPE_MEMTEST) {
-		writel(BFI_IOC_MEMTEST, (rb + BFA_IOC0_STATE_REG));
-		writel(BFI_IOC_MEMTEST, (rb + BFA_IOC1_STATE_REG));
+		writel(BFI_IOC_MEMTEST, ioc->ioc_regs.ioc_fwstate);
+		writel(BFI_IOC_MEMTEST, ioc->ioc_regs.alt_ioc_fwstate);
 	} else {
-		writel(BFI_IOC_INITING, (rb + BFA_IOC0_STATE_REG));
-		writel(BFI_IOC_INITING, (rb + BFA_IOC1_STATE_REG));
+		writel(BFI_IOC_INITING, ioc->ioc_regs.ioc_fwstate);
+		writel(BFI_IOC_INITING, ioc->ioc_regs.alt_ioc_fwstate);
 	}
 
 	bfa_ioc_msgflush(ioc);
@@ -1769,13 +1766,17 @@ bfa_nw_ioc_auto_recover(bool auto_recover)
 	bfa_nw_auto_recover = auto_recover;
 }
 
-static void
+static bool
 bfa_ioc_msgget(struct bfa_ioc *ioc, void *mbmsg)
 {
 	u32	*msgp = mbmsg;
 	u32	r32;
 	int		i;
 
+	r32 = readl(ioc->ioc_regs.lpu_mbox_cmd);
+	if ((r32 & 1) == 0)
+		return false;
+
 	/**
 	 * read the MBOX msg
 	 */
@@ -1791,6 +1792,8 @@ bfa_ioc_msgget(struct bfa_ioc *ioc, void *mbmsg)
 	 */
 	writel(1, ioc->ioc_regs.lpu_mbox_cmd);
 	readl(ioc->ioc_regs.lpu_mbox_cmd);
+
+	return true;
 }
 
 static void
@@ -1887,7 +1890,12 @@ bfa_nw_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev,
 
 	case BFA_PCI_DEVICE_ID_CT2:
 		ioc->asic_gen = BFI_ASIC_GEN_CT2;
-		ioc->asic_mode  = BFI_ASIC_MODE_FC16;
+		if (clscode == BFI_PCIFN_CLASS_FC)
+			ioc->asic_mode  = BFI_ASIC_MODE_FC16;
+		else {
+			ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_ETH;
+			ioc->asic_mode  = BFI_ASIC_MODE_ETH;
+		}
 		break;
 
 	default:
@@ -2019,7 +2027,8 @@ bfa_nw_ioc_mbox_isr(struct bfa_ioc *ioc)
 	struct bfi_mbmsg m;
 	int				mc;
 
-	bfa_ioc_msgget(ioc, &m);
+	if (!bfa_ioc_msgget(ioc, &m))
+		return;
 
 	/**
 	 * Treat IOC message class as special.
diff --git a/drivers/net/bna/bfa_ioc.h b/drivers/net/bna/bfa_ioc.h
index 46309e4..95358a2 100644
--- a/drivers/net/bna/bfa_ioc.h
+++ b/drivers/net/bna/bfa_ioc.h
@@ -272,8 +272,10 @@ void bfa_nw_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc,
 	((__ioc)->ioc_hwif->ioc_pll_init((__ioc)->pcidev.pci_bar_kva, \
 			   (__ioc)->asic_mode))
 
-#define	bfa_ioc_isr_mode_set(__ioc, __msix)			\
-			((__ioc)->ioc_hwif->ioc_isr_mode_set(__ioc, __msix))
+#define	bfa_ioc_isr_mode_set(__ioc, __msix) do {			\
+	if ((__ioc)->ioc_hwif->ioc_isr_mode_set)			\
+		((__ioc)->ioc_hwif->ioc_isr_mode_set(__ioc, __msix));	\
+} while (0)
 #define	bfa_ioc_ownership_reset(__ioc)				\
 			((__ioc)->ioc_hwif->ioc_ownership_reset(__ioc))
 
-- 
1.7.1


^ permalink raw reply related

* [PATCH 18/45] bna: Implement Polling Mechanism for FW Ready
From: Rasesh Mody @ 2011-07-18  8:22 UTC (permalink / raw)
  To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>

Change details:
 - A poll mechanism replaces the current interrupt based FW READY method.
 - The timer based poll routine in IOC will query the ioc_fwstate register
   to see if there is a state change in FW, and sends the READY event.
 - Removed infrastructure needed to support mbox READY event from fw as well as
   IOC code.

Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 drivers/net/bna/bfa_ioc.c |  117 +++++++++++++++-----------------------------
 drivers/net/bna/bfa_ioc.h |    5 +-
 drivers/net/bna/bfi.h     |   11 +----
 3 files changed, 45 insertions(+), 88 deletions(-)

diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
index fcc9278..df26a8a 100644
--- a/drivers/net/bna/bfa_ioc.c
+++ b/drivers/net/bna/bfa_ioc.c
@@ -61,6 +61,7 @@ static bool bfa_nw_auto_recover = true;
 static void bfa_ioc_hw_sem_get(struct bfa_ioc *ioc);
 static void bfa_ioc_hw_sem_get_cancel(struct bfa_ioc *ioc);
 static void bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force);
+static void bfa_ioc_poll_fwinit(struct bfa_ioc *ioc);
 static void bfa_ioc_send_enable(struct bfa_ioc *ioc);
 static void bfa_ioc_send_disable(struct bfa_ioc *ioc);
 static void bfa_ioc_send_getattr(struct bfa_ioc *ioc);
@@ -77,7 +78,6 @@ static void bfa_ioc_lpu_stop(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_disabled(struct bfa_ioc *ioc);
-static void bfa_ioc_pf_initfailed(struct bfa_ioc *ioc);
 static void bfa_ioc_pf_failed(struct bfa_ioc *ioc);
 static void bfa_ioc_pf_fwmismatch(struct bfa_ioc *ioc);
 static void bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type,
@@ -107,11 +107,10 @@ enum ioc_event {
 	IOC_E_ENABLED		= 5,	/*!< f/w enabled		*/
 	IOC_E_FWRSP_GETATTR	= 6,	/*!< IOC get attribute response	*/
 	IOC_E_DISABLED		= 7,	/*!< f/w disabled		*/
-	IOC_E_INITFAILED	= 8,	/*!< failure notice by iocpf sm	*/
-	IOC_E_PFAILED		= 9,	/*!< failure notice by iocpf sm	*/
-	IOC_E_HBFAIL		= 10,	/*!< heartbeat failure		*/
-	IOC_E_HWERROR		= 11,	/*!< hardware error interrupt	*/
-	IOC_E_TIMEOUT		= 12,	/*!< timeout			*/
+	IOC_E_PFAILED		= 8,	/*!< failure notice by iocpf sm	*/
+	IOC_E_HBFAIL		= 9,	/*!< heartbeat failure		*/
+	IOC_E_HWERROR		= 10,	/*!< hardware error interrupt	*/
+	IOC_E_TIMEOUT		= 11,	/*!< timeout			*/
 };
 
 bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc, enum ioc_event);
@@ -299,7 +298,7 @@ bfa_ioc_sm_enabling(struct bfa_ioc *ioc, enum ioc_event event)
 		/* !!! fall through !!! */
 	case IOC_E_HWERROR:
 		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
 		if (event != IOC_E_PFAILED)
 			bfa_iocpf_initfail(ioc);
 		break;
@@ -351,7 +350,7 @@ bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event)
 		/* fall through */
 	case IOC_E_TIMEOUT:
 		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
 		if (event != IOC_E_PFAILED)
 			bfa_iocpf_getattrfail(ioc);
 		break;
@@ -492,14 +491,11 @@ bfa_ioc_sm_fail_retry(struct bfa_ioc *ioc, enum ioc_event event)
 		 * Initialization retry failed.
 		 */
 		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
 		if (event != IOC_E_PFAILED)
 			bfa_iocpf_initfail(ioc);
 		break;
 
-	case IOC_E_INITFAILED:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
-		break;
-
 	case IOC_E_ENABLE:
 		break;
 
@@ -561,7 +557,7 @@ bfa_ioc_sm_fail(struct bfa_ioc *ioc, enum ioc_event event)
 static void
 bfa_iocpf_sm_reset_entry(struct bfa_iocpf *iocpf)
 {
-	iocpf->retry_count = 0;
+	iocpf->fw_mismatch_notified = false;
 	iocpf->auto_recover = bfa_nw_auto_recover;
 }
 
@@ -605,7 +601,6 @@ bfa_iocpf_sm_fwcheck(struct bfa_iocpf *iocpf, enum iocpf_event event)
 	case IOCPF_E_SEMLOCKED:
 		if (bfa_ioc_firmware_lock(ioc)) {
 			if (bfa_ioc_sync_start(ioc)) {
-				iocpf->retry_count = 0;
 				bfa_ioc_sync_join(ioc);
 				bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
 			} else {
@@ -643,10 +638,10 @@ static void
 bfa_iocpf_sm_mismatch_entry(struct bfa_iocpf *iocpf)
 {
 	/* Call only the first time sm enters fwmismatch state. */
-	if (iocpf->retry_count == 0)
+	if (iocpf->fw_mismatch_notified == false)
 		bfa_ioc_pf_fwmismatch(iocpf->ioc);
 
-	iocpf->retry_count++;
+	iocpf->fw_mismatch_notified = true;
 	mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies +
 		msecs_to_jiffies(BFA_IOC_TOV));
 }
@@ -722,8 +717,7 @@ bfa_iocpf_sm_semwait(struct bfa_iocpf *iocpf, enum iocpf_event event)
 static void
 bfa_iocpf_sm_hwinit_entry(struct bfa_iocpf *iocpf)
 {
-	mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies +
-		msecs_to_jiffies(BFA_IOC_TOV));
+	iocpf->poll_time = 0;
 	bfa_ioc_reset(iocpf->ioc, 0);
 }
 
@@ -738,20 +732,12 @@ bfa_iocpf_sm_hwinit(struct bfa_iocpf *iocpf, enum iocpf_event event)
 
 	switch (event) {
 	case IOCPF_E_FWREADY:
-		del_timer(&ioc->iocpf_timer);
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_enabling);
 		break;
 
-	case IOCPF_E_INITFAIL:
-		del_timer(&ioc->iocpf_timer);
-		/*
-		 * !!! fall through !!!
-		 */
-
 	case IOCPF_E_TIMEOUT:
 		bfa_nw_ioc_hw_sem_release(ioc);
-		if (event == IOCPF_E_TIMEOUT)
-			bfa_ioc_pf_failed(ioc);
+		bfa_ioc_pf_failed(ioc);
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
 		break;
 
@@ -772,6 +758,7 @@ bfa_iocpf_sm_enabling_entry(struct bfa_iocpf *iocpf)
 {
 	mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies +
 		msecs_to_jiffies(BFA_IOC_TOV));
+	iocpf->ioc->cbfn->reset_cbfn(iocpf->ioc->bfa);
 	bfa_ioc_send_enable(iocpf->ioc);
 }
 
@@ -809,21 +796,11 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf *iocpf, enum iocpf_event event)
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
 		break;
 
-	case IOCPF_E_FWREADY:
-		bfa_ioc_send_enable(ioc);
-		break;
-
 	default:
 		bfa_sm_fault(event);
 	}
 }
 
-static bool
-bfa_nw_ioc_is_operational(struct bfa_ioc *ioc)
-{
-	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op);
-}
-
 static void
 bfa_iocpf_sm_ready_entry(struct bfa_iocpf *iocpf)
 {
@@ -833,8 +810,6 @@ bfa_iocpf_sm_ready_entry(struct bfa_iocpf *iocpf)
 static void
 bfa_iocpf_sm_ready(struct bfa_iocpf *iocpf, enum iocpf_event event)
 {
-	struct bfa_ioc *ioc = iocpf->ioc;
-
 	switch (event) {
 	case IOCPF_E_DISABLE:
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
@@ -848,14 +823,6 @@ bfa_iocpf_sm_ready(struct bfa_iocpf *iocpf, enum iocpf_event event)
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync);
 		break;
 
-	case IOCPF_E_FWREADY:
-		bfa_ioc_pf_failed(ioc);
-		if (bfa_nw_ioc_is_operational(ioc))
-			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync);
-		else
-			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
-		break;
-
 	default:
 		bfa_sm_fault(event);
 	}
@@ -879,7 +846,6 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf *iocpf, enum iocpf_event event)
 
 	switch (event) {
 	case IOCPF_E_FWRSP_DISABLE:
-	case IOCPF_E_FWREADY:
 		del_timer(&ioc->iocpf_timer);
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
 		break;
@@ -948,7 +914,6 @@ bfa_iocpf_sm_disabled(struct bfa_iocpf *iocpf, enum iocpf_event event)
 
 	switch (event) {
 	case IOCPF_E_ENABLE:
-		iocpf->retry_count = 0;
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
 		break;
 
@@ -979,20 +944,10 @@ bfa_iocpf_sm_initfail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
 	switch (event) {
 	case IOCPF_E_SEMLOCKED:
 		bfa_ioc_notify_fail(ioc);
-		bfa_ioc_sync_ack(ioc);
-		iocpf->retry_count++;
-		if (iocpf->retry_count >= BFA_IOC_HWINIT_MAX) {
-			bfa_ioc_sync_leave(ioc);
-			bfa_nw_ioc_hw_sem_release(ioc);
-			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
-		} else {
-			if (bfa_ioc_sync_complete(ioc))
-				bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
-			else {
-				bfa_nw_ioc_hw_sem_release(ioc);
-				bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
-			}
-		}
+		bfa_ioc_sync_leave(ioc);
+		writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
+		bfa_nw_ioc_hw_sem_release(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
 		break;
 
 	case IOCPF_E_DISABLE:
@@ -1017,7 +972,6 @@ bfa_iocpf_sm_initfail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
 static void
 bfa_iocpf_sm_initfail_entry(struct bfa_iocpf *iocpf)
 {
-	bfa_ioc_pf_initfailed(iocpf->ioc);
 }
 
 /**
@@ -1068,11 +1022,11 @@ bfa_iocpf_sm_fail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
 
 	switch (event) {
 	case IOCPF_E_SEMLOCKED:
-		iocpf->retry_count = 0;
 		bfa_ioc_sync_ack(ioc);
 		bfa_ioc_notify_fail(ioc);
 		if (!iocpf->auto_recover) {
 			bfa_ioc_sync_leave(ioc);
+			writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
 			bfa_nw_ioc_hw_sem_release(ioc);
 			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
 		} else {
@@ -1383,7 +1337,7 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)
 	 * just wait for an initialization completion interrupt.
 	 */
 	if (ioc_fwstate == BFI_IOC_INITING) {
-		ioc->cbfn->reset_cbfn(ioc->bfa);
+		bfa_ioc_poll_fwinit(ioc);
 		return;
 	}
 
@@ -1397,7 +1351,6 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)
 		 * be flushed. Otherwise MSI-X interrupts are not delivered.
 		 */
 		bfa_ioc_msgflush(ioc);
-		ioc->cbfn->reset_cbfn(ioc->bfa);
 		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY);
 		return;
 	}
@@ -1681,12 +1634,6 @@ bfa_ioc_pf_disabled(struct bfa_ioc *ioc)
 }
 
 static void
-bfa_ioc_pf_initfailed(struct bfa_ioc *ioc)
-{
-	bfa_fsm_send_event(ioc, IOC_E_INITFAILED);
-}
-
-static void
 bfa_ioc_pf_failed(struct bfa_ioc *ioc)
 {
 	bfa_fsm_send_event(ioc, IOC_E_PFAILED);
@@ -1755,6 +1702,7 @@ bfa_ioc_boot(struct bfa_ioc *ioc, enum bfi_fwboot_type boot_type,
 	 */
 	ioc->cbfn->reset_cbfn(ioc->bfa);
 	bfa_ioc_lpu_start(ioc);
+	bfa_ioc_poll_fwinit(ioc);
 }
 
 /**
@@ -1810,10 +1758,6 @@ bfa_ioc_isr(struct bfa_ioc *ioc, struct bfi_mbmsg *m)
 	case BFI_IOC_I2H_HBEAT:
 		break;
 
-	case BFI_IOC_I2H_READY_EVENT:
-		bfa_fsm_send_event(iocpf, IOCPF_E_FWREADY);
-		break;
-
 	case BFI_IOC_I2H_ENABLE_REPLY:
 		bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_ENABLE);
 		break;
@@ -2341,3 +2285,22 @@ bfa_nw_iocpf_sem_timeout(void *ioc_arg)
 
 	bfa_ioc_hw_sem_get(ioc);
 }
+
+static void
+bfa_ioc_poll_fwinit(struct bfa_ioc *ioc)
+{
+	u32 fwstate = readl(ioc->ioc_regs.ioc_fwstate);
+
+	if (fwstate == BFI_IOC_DISABLED) {
+		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY);
+		return;
+	}
+
+	if (ioc->iocpf.poll_time >= BFA_IOC_TOV) {
+		bfa_nw_iocpf_timeout(ioc);
+	} else {
+		ioc->iocpf.poll_time += BFA_IOC_POLL_TOV;
+		mod_timer(&ioc->ioc_timer, jiffies +
+			msecs_to_jiffies(BFA_IOC_POLL_TOV));
+	}
+}
diff --git a/drivers/net/bna/bfa_ioc.h b/drivers/net/bna/bfa_ioc.h
index 95358a2..bcc9acc 100644
--- a/drivers/net/bna/bfa_ioc.h
+++ b/drivers/net/bna/bfa_ioc.h
@@ -26,7 +26,7 @@
 #define BFA_IOC_TOV		3000	/* msecs */
 #define BFA_IOC_HWSEM_TOV	500	/* msecs */
 #define BFA_IOC_HB_TOV		500	/* msecs */
-#define BFA_IOC_HWINIT_MAX	5
+#define BFA_IOC_POLL_TOV	200	/* msecs */
 
 /**
  * PCI device information required by IOC
@@ -170,8 +170,9 @@ struct bfa_ioc_hbfail_notify {
 struct bfa_iocpf {
 	bfa_fsm_t		fsm;
 	struct bfa_ioc		*ioc;
-	u32			retry_count;
+	bool			fw_mismatch_notified;
 	bool			auto_recover;
+	u32			poll_time;
 };
 
 struct bfa_ioc {
diff --git a/drivers/net/bna/bfi.h b/drivers/net/bna/bfi.h
index 284c3f8..d95eeb2 100644
--- a/drivers/net/bna/bfi.h
+++ b/drivers/net/bna/bfi.h
@@ -224,8 +224,7 @@ enum bfi_ioc_i2h_msgs {
 	BFI_IOC_I2H_ENABLE_REPLY	= BFA_I2HM(1),
 	BFI_IOC_I2H_DISABLE_REPLY	= BFA_I2HM(2),
 	BFI_IOC_I2H_GETATTR_REPLY	= BFA_I2HM(3),
-	BFI_IOC_I2H_READY_EVENT		= BFA_I2HM(4),
-	BFI_IOC_I2H_HBEAT		= BFA_I2HM(5),
+	BFI_IOC_I2H_HBEAT		= BFA_I2HM(4),
 };
 
 /**
@@ -333,12 +332,6 @@ enum bfi_port_mode {
 /**
  *  BFI_IOC_I2H_READY_EVENT message
  */
-struct bfi_ioc_rdy_event {
-	struct bfi_mhdr mh;		/*!< common msg header */
-	u8			init_status;	/*!< init event status */
-	u8			rsvd[3];
-};
-
 struct bfi_ioc_hbeat {
 	struct bfi_mhdr mh;		/*!< common msg header		*/
 	u32	   hb_count;	/*!< current heart beat count	*/
@@ -426,7 +419,7 @@ union bfi_ioc_h2i_msg_u {
  */
 union bfi_ioc_i2h_msg_u {
 	struct bfi_mhdr mh;
-	struct bfi_ioc_rdy_event rdy_event;
+	struct bfi_ioc_ctrl_reply fw_event;
 	u32			mboxmsg[BFI_IOC_MSGSZ];
 };
 
-- 
1.7.1


^ permalink raw reply related

* [PATCH 19/45] bna: HW Type Check Fix
From: Rasesh Mody @ 2011-07-18  8:22 UTC (permalink / raw)
  To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>

Change detils:
 - The macro bfa_ioc_is_cna() will return true  if IOC type is BFA_IOC_TYPE_FCoE
   or BFA_IOC_TYPE_LL

Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 drivers/net/bna/bfa_ioc.h |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/net/bna/bfa_ioc.h b/drivers/net/bna/bfa_ioc.h
index bcc9acc..07e1a9d 100644
--- a/drivers/net/bna/bfa_ioc.h
+++ b/drivers/net/bna/bfa_ioc.h
@@ -234,7 +234,8 @@ struct bfa_ioc_hwif {
 #define bfa_ioc_portid(__ioc)		((__ioc)->port_id)
 #define bfa_ioc_asic_gen(__ioc)		((__ioc)->asic_gen)
 #define bfa_ioc_is_cna(__ioc)		\
-	(bfa_nw_ioc_get_type(ioc) == BFA_IOC_TYPE_FCoE)
+	((bfa_nw_ioc_get_type(ioc) == BFA_IOC_TYPE_FCoE) ||	\
+	 (bfa_nw_ioc_get_type(ioc) == BFA_IOC_TYPE_LL))
 #define bfa_ioc_fetch_stats(__ioc, __stats) \
 		(((__stats)->drv_stats) = (__ioc)->stats)
 #define bfa_ioc_clr_stats(__ioc)	\
-- 
1.7.1


^ permalink raw reply related

* [PATCH 20/45] bna: MBOX IRQ Sync Vector Num Fix
From: Rasesh Mody @ 2011-07-18  8:22 UTC (permalink / raw)
  To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>

Change details:
 - Fixed the vector number used for syncing MBox IRQ

Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 drivers/net/bna/bnad.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c
index cd2b921..076f398 100644
--- a/drivers/net/bna/bnad.c
+++ b/drivers/net/bna/bnad.c
@@ -2180,7 +2180,7 @@ bnad_mbox_irq_sync(struct bnad *bnad)
 
 	spin_lock_irqsave(&bnad->bna_lock, flags);
 	if (bnad->cfg_flags & BNAD_CF_MSIX)
-		irq = bnad->msix_table[bnad->msix_num - 1].vector;
+		irq = bnad->msix_table[BNAD_MAILBOX_MSIX_INDEX].vector;
 	else
 		irq = bnad->pcidev->irq;
 	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-- 
1.7.1


^ permalink raw reply related

* [PATCH 21/45] bna: Remove Reset Call Back
From: Rasesh Mody @ 2011-07-18  8:22 UTC (permalink / raw)
  To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>

Change details:
 - Remove call to reset_cbfn() from bfa_ioc_boot().
 - Call bfa_ioc_fail_notify() to notify other modules/driver after setting IOC
   sm state to fail_retry/fail.

Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 drivers/net/bna/bfa_ioc.c |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
index df26a8a..3e38cbb 100644
--- a/drivers/net/bna/bfa_ioc.c
+++ b/drivers/net/bna/bfa_ioc.c
@@ -392,12 +392,13 @@ bfa_ioc_sm_op(struct bfa_ioc *ioc, enum ioc_event event)
 		bfa_ioc_hb_stop(ioc);
 		/* !!! fall through !!! */
 	case IOC_E_HBFAIL:
-		bfa_ioc_fail_notify(ioc);
 		if (ioc->iocpf.auto_recover)
 			bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
 		else
 			bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
 
+		bfa_ioc_fail_notify(ioc);
+
 		if (event != IOC_E_PFAILED)
 			bfa_iocpf_fail(ioc);
 		break;
@@ -758,6 +759,9 @@ bfa_iocpf_sm_enabling_entry(struct bfa_iocpf *iocpf)
 {
 	mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies +
 		msecs_to_jiffies(BFA_IOC_TOV));
+	/**
+	 * Enable Interrupts before sending fw IOC ENABLE cmd.
+	 */
 	iocpf->ioc->cbfn->reset_cbfn(iocpf->ioc->bfa);
 	bfa_ioc_send_enable(iocpf->ioc);
 }
@@ -1697,10 +1701,6 @@ bfa_ioc_boot(struct bfa_ioc *ioc, enum bfi_fwboot_type boot_type,
 	bfa_ioc_msgflush(ioc);
 	bfa_ioc_download_fw(ioc, boot_type, boot_env);
 
-	/**
-	 * Enable interrupts just before starting LPU
-	 */
-	ioc->cbfn->reset_cbfn(ioc->bfa);
 	bfa_ioc_lpu_start(ioc);
 	bfa_ioc_poll_fwinit(ioc);
 }
-- 
1.7.1


^ permalink raw reply related

* [PATCH 22/45] bna: Capability Map and MFG Block Changes for New HW
From: Rasesh Mody @ 2011-07-18  8:22 UTC (permalink / raw)
  To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>

Change details:
 - Added capability map and generic model name scheme for manufacturing block.
 - Updated the mfginfo command to handle old h/w alongside new one.
 - Changed firmware code to reduce card types for 1860 cards and derived card
   model from card type, capability fields and initial capability.
 - Removed explicit set/get fcmode. Now this is based on PCI device properties.

Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 drivers/net/bna/bfa_defs.h          |   20 +++++++---
 drivers/net/bna/bfa_defs_mfg_comm.h |   72 ++++++++++++++++++++++++++---------
 drivers/net/bna/bfa_ioc.c           |    5 +-
 3 files changed, 71 insertions(+), 26 deletions(-)

diff --git a/drivers/net/bna/bfa_defs.h b/drivers/net/bna/bfa_defs.h
index f5909d0..e89830f 100644
--- a/drivers/net/bna/bfa_defs.h
+++ b/drivers/net/bna/bfa_defs.h
@@ -220,15 +220,23 @@ struct bfa_mfg_block {
 	u8		rsv[2];
 	char		supplier_id[STRSZ(BFA_MFG_SUPPLIER_ID_SIZE)];
 	char		supplier_partnum[STRSZ(BFA_MFG_SUPPLIER_PARTNUM_SIZE)];
-	char
-		supplier_serialnum[STRSZ(BFA_MFG_SUPPLIER_SERIALNUM_SIZE)];
-	char
-		supplier_revision[STRSZ(BFA_MFG_SUPPLIER_REVISION_SIZE)];
+	char	supplier_serialnum[STRSZ(BFA_MFG_SUPPLIER_SERIALNUM_SIZE)];
+	char	supplier_revision[STRSZ(BFA_MFG_SUPPLIER_REVISION_SIZE)];
 	mac_t		mfg_mac;	/*!< mac address */
 	u8		num_mac;	/*!< number of mac addresses */
 	u8		rsv2;
-	u32	mfg_type;	/*!< card type */
-	u8		rsv3[108];
+	u32		card_type;	/*!< card type */
+	char		cap_nic;	/*!< capability nic */
+	char		cap_cna;	/*!< capability cna */
+	char		cap_hba;	/*!< capability hba */
+	char		cap_fc16g;	/*!< capability fc 16g */
+	char		cap_sriov;	/*!< capability sriov */
+	char		cap_mezz;	/*!< capability mezz */
+	u8		rsv3;
+	u8		mfg_nports;	/*!< number of ports */
+	char		media[8];	/*!< xfi/xaui */
+	char		initial_mode[8];/*!< initial mode: hba/cna/nic */
+	u8		rsv4[84];
 	u8		md5_chksum[BFA_MFG_CHKSUM_SIZE]; /*!< md5 checksum */
 };
 
diff --git a/drivers/net/bna/bfa_defs_mfg_comm.h b/drivers/net/bna/bfa_defs_mfg_comm.h
index 885ef3a..2f00813 100644
--- a/drivers/net/bna/bfa_defs_mfg_comm.h
+++ b/drivers/net/bna/bfa_defs_mfg_comm.h
@@ -19,11 +19,12 @@
 #define __BFA_DEFS_MFG_COMM_H__
 
 #include "cna.h"
+#include "bfa_defs.h"
 
 /**
  * Manufacturing block version
  */
-#define BFA_MFG_VERSION				2
+#define BFA_MFG_VERSION				3
 #define BFA_MFG_VERSION_UNINIT			0xFF
 
 /**
@@ -60,20 +61,17 @@ enum {
 	BFA_MFG_TYPE_ASTRA    = 807,	 /*!< Astra mezz card		*/
 	BFA_MFG_TYPE_LIGHTNING_P0 = 902, /*!< Lightning mezz card - old	*/
 	BFA_MFG_TYPE_LIGHTNING = 1741,	 /*!< Lightning mezz card	*/
+	BFA_MFG_TYPE_PROWLER_F = 1560,	 /*!< Prowler FC only cards	*/
+	BFA_MFG_TYPE_PROWLER_N = 1410,	 /*!< Prowler NIC only cards	*/
+	BFA_MFG_TYPE_PROWLER_C = 1710,	 /*!< Prowler CNA only cards	*/
+	BFA_MFG_TYPE_PROWLER_D = 1860,	 /*!< Prowler Dual cards	*/
+	BFA_MFG_TYPE_CHINOOK   = 1867,	 /*!< Chinook cards		*/
 	BFA_MFG_TYPE_INVALID = 0,	 /*!< Invalid card type		*/
 };
 
 #pragma pack(1)
 
 /**
- * Check if 1-port card
- */
-#define bfa_mfg_is_1port(type) (( \
-	(type) == BFA_MFG_TYPE_FC8P1 || \
-	(type) == BFA_MFG_TYPE_FC4P1 || \
-	(type) == BFA_MFG_TYPE_CNA10P1))
-
-/**
  * Check if Mezz card
  */
 #define bfa_mfg_is_mezz(type) (( \
@@ -81,7 +79,8 @@ enum {
 	(type) == BFA_MFG_TYPE_WANCHESE || \
 	(type) == BFA_MFG_TYPE_ASTRA || \
 	(type) == BFA_MFG_TYPE_LIGHTNING_P0 || \
-	(type) == BFA_MFG_TYPE_LIGHTNING))
+	(type) == BFA_MFG_TYPE_LIGHTNING || \
+	(type) == BFA_MFG_TYPE_CHINOOK))
 
 /**
  * Check if card type valid
@@ -93,14 +92,16 @@ enum {
 	(type) == BFA_MFG_TYPE_FC4P1 || \
 	(type) == BFA_MFG_TYPE_CNA10P2 || \
 	(type) == BFA_MFG_TYPE_CNA10P1 || \
+	(type) == BFA_MFG_TYPE_PROWLER_F || \
+	(type) == BFA_MFG_TYPE_PROWLER_N || \
+	(type) == BFA_MFG_TYPE_PROWLER_C || \
+	(type) == BFA_MFG_TYPE_PROWLER_D || \
 	bfa_mfg_is_mezz(type)))
 
-#define bfa_mfg_adapter_prop_init_flash(card_type, prop)	\
+#define bfa_mfg_adapter_prop_init_flash_cb(mfgblk, prop)	\
 do {								\
-	switch ((card_type)) {					\
+	switch ((mfgblk)->card_type) {				\
 	case BFA_MFG_TYPE_FC8P2:				\
-	case BFA_MFG_TYPE_JAYHAWK:				\
-	case BFA_MFG_TYPE_ASTRA:				\
 		(prop) = BFI_ADAPTER_SETP(NPORTS, 2) |		\
 			BFI_ADAPTER_SETP(SPEED, 8);		\
 		break;						\
@@ -116,22 +117,57 @@ do {								\
 		(prop) = BFI_ADAPTER_SETP(NPORTS, 1) |		\
 			BFI_ADAPTER_SETP(SPEED, 4);		\
 		break;						\
+	default:						\
+		(prop) = BFI_ADAPTER_UNSUPP;			\
+	}							\
+} while (0)
+
+#define bfa_mfg_adapter_prop_init_flash_ct(mfgblk, prop)	\
+do {								\
+	switch ((mfgblk)->card_type) {				\
+	case BFA_MFG_TYPE_JAYHAWK:				\
+	case BFA_MFG_TYPE_ASTRA:				\
+		(prop) = BFI_ADAPTER_SETP(NPORTS, 2) |		\
+			BFI_ADAPTER_SETP(SPEED, 8);		\
+		break;						\
 	case BFA_MFG_TYPE_CNA10P2:				\
 	case BFA_MFG_TYPE_WANCHESE:				\
 	case BFA_MFG_TYPE_LIGHTNING_P0:				\
 	case BFA_MFG_TYPE_LIGHTNING:				\
-		(prop) = BFI_ADAPTER_SETP(NPORTS, 2);		\
-		(prop) |= BFI_ADAPTER_SETP(SPEED, 10);		\
+		(prop) = BFI_ADAPTER_SETP(NPORTS, 2) |		\
+			BFI_ADAPTER_SETP(SPEED, 10);		\
 		break;						\
 	case BFA_MFG_TYPE_CNA10P1:				\
-		(prop) = BFI_ADAPTER_SETP(NPORTS, 1);		\
-		(prop) |= BFI_ADAPTER_SETP(SPEED, 10);		\
+		(prop) = BFI_ADAPTER_SETP(NPORTS, 1) |		\
+			BFI_ADAPTER_SETP(SPEED, 10);		\
 		break;						\
 	default:						\
 		(prop) = BFI_ADAPTER_UNSUPP;			\
 	}							\
 } while (0)
 
+#define bfa_mfg_adapter_prop_init_flash_ct2(mfgblk, prop)	\
+do {								\
+	int sp, np = (mfgblk)->mfg_nports;			\
+	switch ((mfgblk)->card_type) {				\
+	case BFA_MFG_TYPE_PROWLER_F:				\
+	case BFA_MFG_TYPE_CHINOOK:				\
+		sp = 16;					\
+		break;						\
+	case BFA_MFG_TYPE_PROWLER_N:				\
+	case BFA_MFG_TYPE_PROWLER_C:				\
+		sp = 10;					\
+		break;						\
+	case BFA_MFG_TYPE_PROWLER_D:				\
+		sp = 16;					\
+		break;						\
+	default:						\
+		sp = 16;				\
+	}							\
+	(prop) = BFI_ADAPTER_SETP(NPORTS, np) |			\
+		BFI_ADAPTER_SETP(SPEED, sp);			\
+} while (0)
+
 enum {
 	CB_GPIO_TTV	= (1),		/*!< TTV debug capable cards	*/
 	CB_GPIO_FC8P2   = (2),		/*!< 8G 2port FC card		*/
diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
index 3e38cbb..33776da 100644
--- a/drivers/net/bna/bfa_ioc.c
+++ b/drivers/net/bna/bfa_ioc.c
@@ -1834,9 +1834,10 @@ bfa_nw_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev,
 
 	case BFA_PCI_DEVICE_ID_CT2:
 		ioc->asic_gen = BFI_ASIC_GEN_CT2;
-		if (clscode == BFI_PCIFN_CLASS_FC)
+		if (clscode == BFI_PCIFN_CLASS_FC) {
 			ioc->asic_mode  = BFI_ASIC_MODE_FC16;
-		else {
+			ioc->fcmode = true;
+		} else {
 			ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_ETH;
 			ioc->asic_mode  = BFI_ASIC_MODE_ETH;
 		}
-- 
1.7.1


^ permalink raw reply related

* [PATCH 23/45] bna: Added Defines for Multi TXQ Support
From: Rasesh Mody @ 2011-07-18  8:22 UTC (permalink / raw)
  To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>

Chnage details:
 - Added new Macros - bna_prio_allow(), bna_iscsi_prio(), bna_default_nw_prio(),
   bna_is_iscsi_over_cee(), bna_is_prio_reconfig()
 - Construction of priority indirection table to be used by bnad to direct
   packets into TxQs
 - Making available valid priority map, iscsi priority, default priority
   and priority indirection table to bnad through macros
 - Set/reset prio_reconfigured when txq reconfigured/not reconfigured

Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 drivers/net/bna/bna.h |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/drivers/net/bna/bna.h b/drivers/net/bna/bna.h
index b342bdb..518f3dd 100644
--- a/drivers/net/bna/bna.h
+++ b/drivers/net/bna/bna.h
@@ -32,6 +32,7 @@ extern u32 bna_napi_dim_vector[][BNA_BIAS_T_MAX];
 #define BNA_MESSAGE_SIZE		256
 
 #define bna_is_small_rxq(_id) ((_id) & 0x1)
+#define bna_is_header_rxq(_id) bna_is_small_rxq(_id)
 
 #define BNA_MAC_IS_EQUAL(_mac1, _mac2)					\
 	(!memcmp((_mac1), (_mac2), sizeof(mac_t)))
@@ -351,6 +352,16 @@ do {									\
 	}								\
 } while (0)
 
+#define bna_prio_allowed(_bna, _prio) ((_bna)->tx_mod.prio_map & (1 << _prio))
+
+#define bna_iscsi_prio(_bna) ((_bna)->tx_mod.iscsi_prio)
+
+#define bna_default_prio(_bna) ((_bna)->tx_mod.default_prio)
+
+#define bna_is_iscsi_over_cee(_bna) ((_bna)->tx_mod.iscsi_over_cee)
+
+#define bna_is_prio_reconfig(_bna) ((_bna)->tx_mod.prio_reconfigured)
+
 /**
  *
  *  Inline functions
-- 
1.7.1


^ permalink raw reply related

* [PATCH 24/45] bna: Mboxq Flush When Ioc Disabled
From: Rasesh Mody @ 2011-07-18  8:22 UTC (permalink / raw)
  To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>

Change details:
 - If there is a command pending in the mailbox, bfa_ioc_mbox_queue() enqueues
   the mailbox command to a pending command queue. Entries in this queue are
   not flushed when IOC is disabled. As a result, when IOC is re-enabled again,
   the stale entries in the pending command queue are posted to the mailbox.
   When these mailbox commands are processed by the FW and responses are sent,
   unexpected  events are received by other modules' FSMs (f.e. bfa_msgq) which
   have not posted any mailbox commands after IOC was enabled.
 - Flush the pending mailbox command queue when IOC is disabled. Rename
   bfa_ioc_mbox_hbfail to bfa_ioc_mbox_flush. Call bfa_ioc_mbox_flush
   from bfa_iocpf_sm_disabled_entry()

Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 drivers/net/bna/bfa_ioc.c |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
index 33776da..a38f5cd 100644
--- a/drivers/net/bna/bfa_ioc.c
+++ b/drivers/net/bna/bfa_ioc.c
@@ -69,7 +69,7 @@ static void bfa_ioc_hb_monitor(struct bfa_ioc *ioc);
 static void bfa_ioc_hb_stop(struct bfa_ioc *ioc);
 static void bfa_ioc_reset(struct bfa_ioc *ioc, bool force);
 static void bfa_ioc_mbox_poll(struct bfa_ioc *ioc);
-static void bfa_ioc_mbox_hbfail(struct bfa_ioc *ioc);
+static void bfa_ioc_mbox_flush(struct bfa_ioc *ioc);
 static void bfa_ioc_recover(struct bfa_ioc *ioc);
 static void bfa_ioc_check_attr_wwns(struct bfa_ioc *ioc);
 static void bfa_ioc_event_notify(struct bfa_ioc *, enum bfa_ioc_event);
@@ -908,6 +908,7 @@ bfa_iocpf_sm_disabling_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
 static void
 bfa_iocpf_sm_disabled_entry(struct bfa_iocpf *iocpf)
 {
+	bfa_ioc_mbox_flush(iocpf->ioc);
 	bfa_ioc_pf_disabled(iocpf->ioc);
 }
 
@@ -1012,7 +1013,7 @@ bfa_iocpf_sm_fail_sync_entry(struct bfa_iocpf *iocpf)
 	/**
 	 * Flush any queued up mailbox requests.
 	 */
-	bfa_ioc_mbox_hbfail(iocpf->ioc);
+	bfa_ioc_mbox_flush(iocpf->ioc);
 	bfa_ioc_hw_sem_get(iocpf->ioc);
 }
 
@@ -1606,7 +1607,7 @@ bfa_ioc_mbox_poll(struct bfa_ioc *ioc)
  * Cleanup any pending requests.
  */
 static void
-bfa_ioc_mbox_hbfail(struct bfa_ioc *ioc)
+bfa_ioc_mbox_flush(struct bfa_ioc *ioc)
 {
 	struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
 	struct bfa_mbox_cmd *cmd;
-- 
1.7.1


^ permalink raw reply related

* [PATCH 25/45] bna: Move FW Init to HW Init and Disable Hang Unmapped Fix
From: Rasesh Mody @ 2011-07-18  8:22 UTC (permalink / raw)
  To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>

Change details:
 - Move the bfa_ioc_poll_fwinit() function call out of bfa_ioc_boot() and put
   it inside the caller of bfa_ioc_boot(), which is bfa_ioc_hwinit()
 - Diag memtest call bfa_ioc_boot() to download memtest specific fw code.
   Inside bfa_ioc_boot(), it called bfa_ioc_poll_fwinit() which start a timer,
   with a timeout duration much shorter than the memtest timer. As a result,
   this poll timer expired, and cause the assert. But eventually, the
   memtest complete successfully.
 - Handle the case where PCI mapping goes away when IOCPF state machine is
   waiting for semaphore.

Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 drivers/net/bna/bfa_defs.h |    1 +
 drivers/net/bna/bfa_ioc.c  |   91 ++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 89 insertions(+), 3 deletions(-)

diff --git a/drivers/net/bna/bfa_defs.h b/drivers/net/bna/bfa_defs.h
index e89830f..621d50b 100644
--- a/drivers/net/bna/bfa_defs.h
+++ b/drivers/net/bna/bfa_defs.h
@@ -124,6 +124,7 @@ enum bfa_ioc_state {
 	BFA_IOC_DISABLED	= 10,	/*!< IOC is disabled */
 	BFA_IOC_FWMISMATCH	= 11,	/*!< IOC f/w different from drivers */
 	BFA_IOC_ENABLING	= 12,	/*!< IOC is being enabled */
+	BFA_IOC_HWFAIL		= 13,	/*!< PCI mapping doesn't exist */
 };
 
 /**
diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
index a38f5cd..216d0d1 100644
--- a/drivers/net/bna/bfa_ioc.c
+++ b/drivers/net/bna/bfa_ioc.c
@@ -79,6 +79,7 @@ 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_disabled(struct bfa_ioc *ioc);
 static void bfa_ioc_pf_failed(struct bfa_ioc *ioc);
+static void bfa_ioc_pf_hwfailed(struct bfa_ioc *ioc);
 static void bfa_ioc_pf_fwmismatch(struct bfa_ioc *ioc);
 static void bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type,
 			 u32 boot_param);
@@ -111,6 +112,7 @@ enum ioc_event {
 	IOC_E_HBFAIL		= 9,	/*!< heartbeat failure		*/
 	IOC_E_HWERROR		= 10,	/*!< hardware error interrupt	*/
 	IOC_E_TIMEOUT		= 11,	/*!< timeout			*/
+	IOC_E_HWFAILED		= 12,	/*!< PCI mapping failure notice	*/
 };
 
 bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc, enum ioc_event);
@@ -122,6 +124,7 @@ bfa_fsm_state_decl(bfa_ioc, fail_retry, struct bfa_ioc, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, hwfail, struct bfa_ioc, enum ioc_event);
 
 static struct bfa_sm_table ioc_sm_table[] = {
 	{BFA_SM(bfa_ioc_sm_uninit), BFA_IOC_UNINIT},
@@ -133,6 +136,7 @@ static struct bfa_sm_table ioc_sm_table[] = {
 	{BFA_SM(bfa_ioc_sm_fail), BFA_IOC_FAIL},
 	{BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING},
 	{BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED},
+	{BFA_SM(bfa_ioc_sm_hwfail), BFA_IOC_HWFAIL},
 };
 
 /**
@@ -164,6 +168,7 @@ enum iocpf_event {
 	IOCPF_E_GETATTRFAIL	= 9,	/*!< init fail notice by ioc sm	*/
 	IOCPF_E_SEMLOCKED	= 10,   /*!< h/w semaphore is locked	*/
 	IOCPF_E_TIMEOUT		= 11,   /*!< f/w response timeout	*/
+	IOCPF_E_SEM_ERROR	= 12,   /*!< h/w sem mapping error	*/
 };
 
 /**
@@ -303,6 +308,11 @@ bfa_ioc_sm_enabling(struct bfa_ioc *ioc, enum ioc_event event)
 			bfa_iocpf_initfail(ioc);
 		break;
 
+	case IOC_E_HWFAILED:
+		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);
+		break;
+
 	case IOC_E_DISABLE:
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
 		break;
@@ -434,6 +444,11 @@ bfa_ioc_sm_disabling(struct bfa_ioc *ioc, enum ioc_event event)
 		bfa_iocpf_fail(ioc);
 		break;
 
+	case IOC_E_HWFAILED:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);
+		bfa_ioc_disable_comp(ioc);
+		break;
+
 	default:
 		bfa_sm_fault(event);
 	}
@@ -497,6 +512,11 @@ bfa_ioc_sm_fail_retry(struct bfa_ioc *ioc, enum ioc_event event)
 			bfa_iocpf_initfail(ioc);
 		break;
 
+	case IOC_E_HWFAILED:
+		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);
+		break;
+
 	case IOC_E_ENABLE:
 		break;
 
@@ -548,6 +568,36 @@ bfa_ioc_sm_fail(struct bfa_ioc *ioc, enum ioc_event event)
 	}
 }
 
+static void
+bfa_ioc_sm_hwfail_entry(struct bfa_ioc *ioc)
+{
+}
+
+/**
+ * IOC failure.
+ */
+static void
+bfa_ioc_sm_hwfail(struct bfa_ioc *ioc, enum ioc_event event)
+{
+	switch (event) {
+
+	case IOC_E_ENABLE:
+		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+		break;
+
+	case IOC_E_DISABLE:
+		ioc->cbfn->disable_cbfn(ioc->bfa);
+		break;
+
+	case IOC_E_DETACH:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
+		break;
+
+	default:
+		bfa_sm_fault(event);
+	}
+}
+
 /**
  * IOCPF State Machine
  */
@@ -616,6 +666,11 @@ bfa_iocpf_sm_fwcheck(struct bfa_iocpf *iocpf, enum iocpf_event event)
 		}
 		break;
 
+	case IOCPF_E_SEM_ERROR:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+		bfa_ioc_pf_hwfailed(ioc);
+		break;
+
 	case IOCPF_E_DISABLE:
 		bfa_ioc_hw_sem_get_cancel(ioc);
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
@@ -705,6 +760,11 @@ bfa_iocpf_sm_semwait(struct bfa_iocpf *iocpf, enum iocpf_event event)
 		}
 		break;
 
+	case IOCPF_E_SEM_ERROR:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+		bfa_ioc_pf_hwfailed(ioc);
+		break;
+
 	case IOCPF_E_DISABLE:
 		bfa_ioc_hw_sem_get_cancel(ioc);
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
@@ -894,6 +954,11 @@ bfa_iocpf_sm_disabling_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
 		break;
 
+	case IOCPF_E_SEM_ERROR:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+		bfa_ioc_pf_hwfailed(ioc);
+		break;
+
 	case IOCPF_E_FAIL:
 		break;
 
@@ -955,6 +1020,11 @@ bfa_iocpf_sm_initfail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
 		break;
 
+	case IOCPF_E_SEM_ERROR:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+		bfa_ioc_pf_hwfailed(ioc);
+		break;
+
 	case IOCPF_E_DISABLE:
 		bfa_ioc_hw_sem_get_cancel(ioc);
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
@@ -1044,6 +1114,11 @@ bfa_iocpf_sm_fail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
 		}
 		break;
 
+	case IOCPF_E_SEM_ERROR:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+		bfa_ioc_pf_hwfailed(ioc);
+		break;
+
 	case IOCPF_E_DISABLE:
 		bfa_ioc_hw_sem_get_cancel(ioc);
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
@@ -1143,7 +1218,11 @@ bfa_ioc_hw_sem_get(struct bfa_ioc *ioc)
 	 * will return 1. Semaphore is released by writing 1 to the register
 	 */
 	r32 = readl(ioc->ioc_regs.ioc_sem_reg);
-	if (r32 == 0) {
+	if (r32 == ~0) {
+		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEM_ERROR);
+		return;
+	}
+	if (!(r32 & 1)) {
 		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEMLOCKED);
 		return;
 	}
@@ -1334,6 +1413,7 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)
 
 	if (!fwvalid) {
 		bfa_ioc_boot(ioc, BFI_FWBOOT_TYPE_NORMAL, boot_env);
+		bfa_ioc_poll_fwinit(ioc);
 		return;
 	}
 
@@ -1364,6 +1444,7 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)
 	 * Initialize the h/w for any other states.
 	 */
 	bfa_ioc_boot(ioc, BFI_FWBOOT_TYPE_NORMAL, boot_env);
+	bfa_ioc_poll_fwinit(ioc);
 }
 
 void
@@ -1645,6 +1726,12 @@ bfa_ioc_pf_failed(struct bfa_ioc *ioc)
 }
 
 static void
+bfa_ioc_pf_hwfailed(struct bfa_ioc *ioc)
+{
+	bfa_fsm_send_event(ioc, IOC_E_HWFAILED);
+}
+
+static void
 bfa_ioc_pf_fwmismatch(struct bfa_ioc *ioc)
 {
 	/**
@@ -1701,9 +1788,7 @@ bfa_ioc_boot(struct bfa_ioc *ioc, enum bfi_fwboot_type boot_type,
 
 	bfa_ioc_msgflush(ioc);
 	bfa_ioc_download_fw(ioc, boot_type, boot_env);
-
 	bfa_ioc_lpu_start(ioc);
-	bfa_ioc_poll_fwinit(ioc);
 }
 
 /**
-- 
1.7.1


^ permalink raw reply related

* [PATCH 26/45] bna: Ethfn LPU DMA Read Fix
From: Rasesh Mody @ 2011-07-18  8:22 UTC (permalink / raw)
  To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>

Change details:
 - In new HW, LPU cannot perform DMA read from host memory for PFs with
   Ethernet functionality. As a result, BFI_ENET command processing (which
   uses the msgq implementation and relies on LPU doing DMA read from host
   memoty) will not work
 - To fix this, msgq sends mailbox message to Host to request data from a
   specified memory area, Host copies the data from specifies memory area
   to mailbox and notifies the LPU, LPU upon receiving all fragments of
   data, continues processing Enet commands
 - Host processes LPU mailbox read status interrupt and schedules mailbox
   poll routine. Host implements handler for BFI_MSGQ_I2H_CMDQ_COPY_REQ
   message and uses BFI_MSGQ_H2I_CMDQ_COPY_RSP message to send data to LPU.
   Msgq module in FW implements mailbox based cmdq read routine

Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 drivers/net/bna/bfa_ioc.c |   30 ++++++++++++++++++------------
 drivers/net/bna/bfa_ioc.h |    5 +++++
 2 files changed, 23 insertions(+), 12 deletions(-)

diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
index 216d0d1..beb63f9 100644
--- a/drivers/net/bna/bfa_ioc.c
+++ b/drivers/net/bna/bfa_ioc.c
@@ -2058,22 +2058,28 @@ bfa_nw_ioc_mbox_isr(struct bfa_ioc *ioc)
 	struct bfi_mbmsg m;
 	int				mc;
 
-	if (!bfa_ioc_msgget(ioc, &m))
-		return;
+	if (bfa_ioc_msgget(ioc, &m)) {
+		/**
+		 * Treat IOC message class as special.
+		 */
+		mc = m.mh.msg_class;
+		if (mc == BFI_MC_IOC) {
+			bfa_ioc_isr(ioc, &m);
+			return;
+		}
 
-	/**
-	 * Treat IOC message class as special.
-	 */
-	mc = m.mh.msg_class;
-	if (mc == BFI_MC_IOC) {
-		bfa_ioc_isr(ioc, &m);
-		return;
+		if ((mc >= BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL))
+			return;
+
+		mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m);
 	}
 
-	if ((mc >= BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL))
-		return;
+	bfa_ioc_lpu_read_stat(ioc);
 
-	mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m);
+	/**
+	 * Try to send pending mailbox commands
+	 */
+	bfa_ioc_mbox_poll(ioc);
 }
 
 void
diff --git a/drivers/net/bna/bfa_ioc.h b/drivers/net/bna/bfa_ioc.h
index 07e1a9d..a9f24e2 100644
--- a/drivers/net/bna/bfa_ioc.h
+++ b/drivers/net/bna/bfa_ioc.h
@@ -281,6 +281,11 @@ void bfa_nw_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc,
 #define	bfa_ioc_ownership_reset(__ioc)				\
 			((__ioc)->ioc_hwif->ioc_ownership_reset(__ioc))
 
+#define bfa_ioc_lpu_read_stat(__ioc) do {				\
+		if ((__ioc)->ioc_hwif->ioc_lpu_read_stat)		\
+			((__ioc)->ioc_hwif->ioc_lpu_read_stat(__ioc));	\
+} while (0)
+
 void bfa_nw_ioc_set_ct_hwif(struct bfa_ioc *ioc);
 void bfa_nw_ioc_set_ct2_hwif(struct bfa_ioc *ioc);
 
-- 
1.7.1


^ permalink raw reply related

* [PATCH 27/45] bna: IOC Event Name Change
From: Rasesh Mody @ 2011-07-18  8:22 UTC (permalink / raw)
  To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>

Change details:
 - Changed event name IOC_E_PFAILED to IOC_E_PFFAILED

Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 drivers/net/bna/bfa_ioc.c |   20 ++++++++++----------
 1 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
index beb63f9..2dd19d2 100644
--- a/drivers/net/bna/bfa_ioc.c
+++ b/drivers/net/bna/bfa_ioc.c
@@ -108,7 +108,7 @@ enum ioc_event {
 	IOC_E_ENABLED		= 5,	/*!< f/w enabled		*/
 	IOC_E_FWRSP_GETATTR	= 6,	/*!< IOC get attribute response	*/
 	IOC_E_DISABLED		= 7,	/*!< f/w disabled		*/
-	IOC_E_PFAILED		= 8,	/*!< failure notice by iocpf sm	*/
+	IOC_E_PFFAILED		= 8,	/*!< failure notice by iocpf sm	*/
 	IOC_E_HBFAIL		= 9,	/*!< heartbeat failure		*/
 	IOC_E_HWERROR		= 10,	/*!< hardware error interrupt	*/
 	IOC_E_TIMEOUT		= 11,	/*!< timeout			*/
@@ -299,12 +299,12 @@ bfa_ioc_sm_enabling(struct bfa_ioc *ioc, enum ioc_event event)
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
 		break;
 
-	case IOC_E_PFAILED:
+	case IOC_E_PFFAILED:
 		/* !!! fall through !!! */
 	case IOC_E_HWERROR:
 		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
-		if (event != IOC_E_PFAILED)
+		if (event != IOC_E_PFFAILED)
 			bfa_iocpf_initfail(ioc);
 		break;
 
@@ -354,14 +354,14 @@ bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event)
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
 		break;
 
-	case IOC_E_PFAILED:
+	case IOC_E_PFFAILED:
 	case IOC_E_HWERROR:
 		del_timer(&ioc->ioc_timer);
 		/* fall through */
 	case IOC_E_TIMEOUT:
 		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
-		if (event != IOC_E_PFAILED)
+		if (event != IOC_E_PFFAILED)
 			bfa_iocpf_getattrfail(ioc);
 		break;
 
@@ -397,7 +397,7 @@ bfa_ioc_sm_op(struct bfa_ioc *ioc, enum ioc_event event)
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
 		break;
 
-	case IOC_E_PFAILED:
+	case IOC_E_PFFAILED:
 	case IOC_E_HWERROR:
 		bfa_ioc_hb_stop(ioc);
 		/* !!! fall through !!! */
@@ -409,7 +409,7 @@ bfa_ioc_sm_op(struct bfa_ioc *ioc, enum ioc_event event)
 
 		bfa_ioc_fail_notify(ioc);
 
-		if (event != IOC_E_PFAILED)
+		if (event != IOC_E_PFFAILED)
 			bfa_iocpf_fail(ioc);
 		break;
 
@@ -501,14 +501,14 @@ bfa_ioc_sm_fail_retry(struct bfa_ioc *ioc, enum ioc_event event)
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
 		break;
 
-	case IOC_E_PFAILED:
+	case IOC_E_PFFAILED:
 	case IOC_E_HWERROR:
 		/**
 		 * Initialization retry failed.
 		 */
 		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
-		if (event != IOC_E_PFAILED)
+		if (event != IOC_E_PFFAILED)
 			bfa_iocpf_initfail(ioc);
 		break;
 
@@ -1722,7 +1722,7 @@ bfa_ioc_pf_disabled(struct bfa_ioc *ioc)
 static void
 bfa_ioc_pf_failed(struct bfa_ioc *ioc)
 {
-	bfa_fsm_send_event(ioc, IOC_E_PFAILED);
+	bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
 }
 
 static void
-- 
1.7.1


^ permalink raw reply related

* [PATCH 28/45] bna: Add New IOC event
From: Rasesh Mody @ 2011-07-18  8:22 UTC (permalink / raw)
  To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>

Change details:
 - ACQ_ADDR IOC state and its state machine implementation.
 - The changes related to FAA enable/disable/query in firmware

Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 drivers/net/bna/bfa_defs.h        |    1 +
 drivers/net/bna/bfa_defs_status.h |    9 +++++
 drivers/net/bna/bfa_ioc.c         |   69 ++++++++++++++++++++++++++++++++++++-
 drivers/net/bna/bfi.h             |    1 +
 4 files changed, 79 insertions(+), 1 deletions(-)

diff --git a/drivers/net/bna/bfa_defs.h b/drivers/net/bna/bfa_defs.h
index 621d50b..e7dd91f 100644
--- a/drivers/net/bna/bfa_defs.h
+++ b/drivers/net/bna/bfa_defs.h
@@ -125,6 +125,7 @@ enum bfa_ioc_state {
 	BFA_IOC_FWMISMATCH	= 11,	/*!< IOC f/w different from drivers */
 	BFA_IOC_ENABLING	= 12,	/*!< IOC is being enabled */
 	BFA_IOC_HWFAIL		= 13,	/*!< PCI mapping doesn't exist */
+	BFA_IOC_ACQ_ADDR	= 14,	/*!< Acquiring addr from fabric */
 };
 
 /**
diff --git a/drivers/net/bna/bfa_defs_status.h b/drivers/net/bna/bfa_defs_status.h
index 7c5fe6c..bf7f87a 100644
--- a/drivers/net/bna/bfa_defs_status.h
+++ b/drivers/net/bna/bfa_defs_status.h
@@ -205,6 +205,15 @@ enum bfa_status {
 	BFA_STATUS_BOOT_CODE_TIMEDOUT = 177,
 	BFA_STATUS_NO_VPORT_LOCK = 178,
 	BFA_STATUS_VPORT_NO_CNFG = 179,
+	BFA_STATUS_FEATURE_NOT_SUPPORTED = 180,
+	BFA_STATUS_ENTRY_EXISTS = 181,
+	BFA_STATUS_ENTRY_NOT_EXISTS = 182,
+	BFA_STATUS_NO_CHANGE = 183,
+	BFA_STATUS_DISABLED = 184,
+	BFA_STATUS_FAA_ENABLED = 185,
+	BFA_STATUS_FAA_DISABLED = 186,
+	BFA_STATUS_FAA_ACQUIRED = 187,
+	BFA_STATUS_FAA_ACQ_ADDR = 188,
 	BFA_STATUS_MAX_VAL
 };
 
diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
index 2dd19d2..2130b5a 100644
--- a/drivers/net/bna/bfa_ioc.c
+++ b/drivers/net/bna/bfa_ioc.c
@@ -113,6 +113,7 @@ enum ioc_event {
 	IOC_E_HWERROR		= 10,	/*!< hardware error interrupt	*/
 	IOC_E_TIMEOUT		= 11,	/*!< timeout			*/
 	IOC_E_HWFAILED		= 12,	/*!< PCI mapping failure notice	*/
+	IOC_E_FWRSP_ACQ_ADDR	= 13,	/*!< Acquiring address		*/
 };
 
 bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc, enum ioc_event);
@@ -125,6 +126,7 @@ bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, hwfail, struct bfa_ioc, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, acq_addr, struct bfa_ioc, enum ioc_event);
 
 static struct bfa_sm_table ioc_sm_table[] = {
 	{BFA_SM(bfa_ioc_sm_uninit), BFA_IOC_UNINIT},
@@ -137,6 +139,7 @@ static struct bfa_sm_table ioc_sm_table[] = {
 	{BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING},
 	{BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED},
 	{BFA_SM(bfa_ioc_sm_hwfail), BFA_IOC_HWFAIL},
+	{BFA_SM(bfa_ioc_sm_acq_addr), BFA_IOC_ACQ_ADDR},
 };
 
 /**
@@ -351,9 +354,17 @@ bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event)
 	case IOC_E_FWRSP_GETATTR:
 		del_timer(&ioc->ioc_timer);
 		bfa_ioc_check_attr_wwns(ioc);
+		bfa_ioc_hb_monitor(ioc);
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
 		break;
 
+	case IOC_E_FWRSP_ACQ_ADDR:
+		del_timer(&ioc->ioc_timer);
+		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_FAA_ACQ_ADDR);
+		bfa_ioc_hb_monitor(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_acq_addr);
+		break;
+
 	case IOC_E_PFFAILED:
 	case IOC_E_HWERROR:
 		del_timer(&ioc->ioc_timer);
@@ -378,11 +389,54 @@ bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event)
 	}
 }
 
+/**
+ * Acquiring address from fabric (entry function)
+ */
+static void
+bfa_ioc_sm_acq_addr_entry(struct bfa_ioc *ioc)
+{
+}
+
+/**
+ * Acquiring address from the fabric
+ */
+static void
+bfa_ioc_sm_acq_addr(struct bfa_ioc *ioc, enum ioc_event event)
+{
+	switch (event) {
+	case IOC_E_FWRSP_GETATTR:
+		bfa_ioc_check_attr_wwns(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
+		break;
+
+	case IOC_E_PFFAILED:
+	case IOC_E_HWERROR:
+		bfa_ioc_hb_stop(ioc);
+	case IOC_E_HBFAIL:
+		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
+		if (event != IOC_E_PFFAILED)
+			bfa_iocpf_getattrfail(ioc);
+		break;
+
+	case IOC_E_DISABLE:
+		bfa_ioc_hb_stop(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
+		break;
+
+	case IOC_E_ENABLE:
+		break;
+
+	default:
+		bfa_sm_fault(event);
+	}
+}
+
 static void
 bfa_ioc_sm_op_entry(struct bfa_ioc *ioc)
 {
 	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);
-	bfa_ioc_hb_monitor(ioc);
+	bfa_ioc_event_notify(ioc, BFA_IOC_E_ENABLED);
 }
 
 static void
@@ -1639,6 +1693,15 @@ bfa_ioc_getattr_reply(struct bfa_ioc *ioc)
 }
 
 /**
+ * Response from f/w that IOC attributes are not ready
+ */
+static void
+bfa_ioc_acq_addr_reply(struct bfa_ioc *ioc)
+{
+	bfa_fsm_send_event(ioc, IOC_E_FWRSP_ACQ_ADDR);
+}
+
+/**
  * Attach time initialization of mbox logic.
  */
 static void
@@ -1856,6 +1919,10 @@ bfa_ioc_isr(struct bfa_ioc *ioc, struct bfi_mbmsg *m)
 		bfa_ioc_getattr_reply(ioc);
 		break;
 
+	case BFI_IOC_I2H_ACQ_ADDR_REPLY:
+		bfa_ioc_acq_addr_reply(ioc);
+		break;
+
 	default:
 		BUG_ON(1);
 	}
diff --git a/drivers/net/bna/bfi.h b/drivers/net/bna/bfi.h
index d95eeb2..8d238a7 100644
--- a/drivers/net/bna/bfi.h
+++ b/drivers/net/bna/bfi.h
@@ -225,6 +225,7 @@ enum bfi_ioc_i2h_msgs {
 	BFI_IOC_I2H_DISABLE_REPLY	= BFA_I2HM(2),
 	BFI_IOC_I2H_GETATTR_REPLY	= BFA_I2HM(3),
 	BFI_IOC_I2H_HBEAT		= BFA_I2HM(4),
+	BFI_IOC_I2H_ACQ_ADDR_REPLY	= BFA_I2HM(5),
 };
 
 /**
-- 
1.7.1


^ permalink raw reply related

* [PATCH 29/45] bna: Add Sub-System Device ID Info
From: Rasesh Mody @ 2011-07-18  8:22 UTC (permalink / raw)
  To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>

Change details:
 - 1860 has CNA personality with SSID 22 for PCI functions.
 - Preserve the same SSID numbering so that FCoE drivers claim adapters with
   no-asic block (default personality).

Can we get this out?

Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 drivers/net/bna/bfa_defs.h |   10 ++++++++++
 drivers/net/bna/bfa_ioc.c  |    3 ++-
 drivers/net/bna/bfa_ioc.h  |    1 +
 3 files changed, 13 insertions(+), 1 deletions(-)

diff --git a/drivers/net/bna/bfa_defs.h b/drivers/net/bna/bfa_defs.h
index e7dd91f..3e5d096 100644
--- a/drivers/net/bna/bfa_defs.h
+++ b/drivers/net/bna/bfa_defs.h
@@ -261,4 +261,14 @@ enum {
 #define bfa_asic_id_ctc(device)			\
 	(bfa_asic_id_ct(device) || bfa_asic_id_ct2(device))
 
+/**
+ * PCI sub-system device and vendor ID information
+ */
+enum {
+	BFA_PCI_FCOE_SSDEVICE_ID	= 0x14,
+	BFA_PCI_CT2_SSID_FCoE		= 0x22,
+	BFA_PCI_CT2_SSID_ETH		= 0x23,
+	BFA_PCI_CT2_SSID_FC		= 0x24,
+};
+
 #endif /* __BFA_DEFS_H__ */
diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
index 2130b5a..78cdc2b 100644
--- a/drivers/net/bna/bfa_ioc.c
+++ b/drivers/net/bna/bfa_ioc.c
@@ -1987,7 +1987,8 @@ bfa_nw_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev,
 
 	case BFA_PCI_DEVICE_ID_CT2:
 		ioc->asic_gen = BFI_ASIC_GEN_CT2;
-		if (clscode == BFI_PCIFN_CLASS_FC) {
+		if (clscode == BFI_PCIFN_CLASS_FC &&
+			pcidev->ssid == BFA_PCI_CT2_SSID_FC) {
 			ioc->asic_mode  = BFI_ASIC_MODE_FC16;
 			ioc->fcmode = true;
 		} else {
diff --git a/drivers/net/bna/bfa_ioc.h b/drivers/net/bna/bfa_ioc.h
index a9f24e2..0f7dba1 100644
--- a/drivers/net/bna/bfa_ioc.h
+++ b/drivers/net/bna/bfa_ioc.h
@@ -35,6 +35,7 @@ struct bfa_pcidev {
 	int	pci_slot;
 	u8	pci_func;
 	u16	device_id;
+	u16	ssid;
 	void	__iomem *pci_bar_kva;
 };
 
-- 
1.7.1


^ permalink raw reply related

* [PATCH 30/45] bna: Add HW Semaphore Unlock Logic
From: Rasesh Mody @ 2011-07-18  8:22 UTC (permalink / raw)
  To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>

Change details:
 - Added logic to unlock hw semaphore if the previos FW boot was from boot
   code (flash based) and the current FW initialization attempt is from OS
   driver.

Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 drivers/net/bna/bfa_ioc.c |   25 +++++++++++++++++++++++++
 1 files changed, 25 insertions(+), 0 deletions(-)

diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
index 78cdc2b..940c94a 100644
--- a/drivers/net/bna/bfa_ioc.c
+++ b/drivers/net/bna/bfa_ioc.c
@@ -58,6 +58,7 @@ static bool bfa_nw_auto_recover = true;
 /*
  * forward declarations
  */
+static void bfa_ioc_hw_sem_init(struct bfa_ioc *ioc);
 static void bfa_ioc_hw_sem_get(struct bfa_ioc *ioc);
 static void bfa_ioc_hw_sem_get_cancel(struct bfa_ioc *ioc);
 static void bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force);
@@ -691,6 +692,7 @@ bfa_iocpf_sm_reset(struct bfa_iocpf *iocpf, enum iocpf_event event)
 static void
 bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf *iocpf)
 {
+	bfa_ioc_hw_sem_init(iocpf->ioc);
 	bfa_ioc_hw_sem_get(iocpf->ioc);
 }
 
@@ -1263,6 +1265,29 @@ bfa_nw_ioc_sem_release(void __iomem *sem_reg)
 }
 
 static void
+bfa_ioc_hw_sem_init(struct bfa_ioc *ioc)
+{
+	struct bfi_ioc_image_hdr fwhdr;
+	u32 fwstate = readl(ioc->ioc_regs.ioc_fwstate);
+
+	if (fwstate == BFI_IOC_UNINIT)
+		return;
+
+	bfa_nw_ioc_fwver_get(ioc, &fwhdr);
+
+	if (swab32(fwhdr.exec) == BFI_FWBOOT_TYPE_NORMAL)
+		return;
+
+	writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
+
+	/*
+	 * Try to lock and then unlock the semaphore.
+	 */
+	readl(ioc->ioc_regs.ioc_sem_reg);
+	writel(1, ioc->ioc_regs.ioc_sem_reg);
+}
+
+static void
 bfa_ioc_hw_sem_get(struct bfa_ioc *ioc)
 {
 	u32	r32;
-- 
1.7.1


^ permalink raw reply related

* [PATCH 31/45] bna: Configuration changes
From: Rasesh Mody @ 2011-07-18  8:22 UTC (permalink / raw)
  To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>

Change details:
bnad.c:
 - Set number of Tx and Rx queues bassed on underlying hardware.
 - Take VLAN header into account for MTU calculation
 - Default to INTx mode when pci_enable_msix() fails.
 - Set a bit in Rx poll routine, check and wait for that bit to be cleared
   in the cleanup routine before proceeding.
bnad.h:
 - Define separate macros for maximum and supported numbers of Tx and Rx
   queues based on underlying hardware
bna.h:
 - Define a macro to access the supported attributes for underlying hardware

Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 drivers/net/bna/bna.h  |    4 ++
 drivers/net/bna/bnad.c |  136 ++++++++++++++++++++++++++++++-----------------
 drivers/net/bna/bnad.h |   23 ++++++---
 3 files changed, 107 insertions(+), 56 deletions(-)

diff --git a/drivers/net/bna/bna.h b/drivers/net/bna/bna.h
index 518f3dd..66725d3 100644
--- a/drivers/net/bna/bna.h
+++ b/drivers/net/bna/bna.h
@@ -362,6 +362,8 @@ do {									\
 
 #define bna_is_prio_reconfig(_bna) ((_bna)->tx_mod.prio_reconfigured)
 
+#define bna_attr(_bna) (&(_bna)->ioceth.attr)
+
 /**
  *
  *  Inline functions
@@ -403,6 +405,8 @@ void bna_init(struct bna *bna, struct bnad *bnad,
 			struct bna_res_info *res_info);
 void bna_mod_init(struct bna *bna, struct bna_res_info *res_info);
 void bna_uninit(struct bna *bna);
+int bna_num_txq_set(struct bna *bna, int num_txq);
+int bna_num_rxp_set(struct bna *bna, int num_rxp);
 void bna_stats_get(struct bna *bna);
 void bna_get_perm_mac(struct bna *bna, u8 *mac);
 void bna_hw_stats_get(struct bna *bna);
diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c
index 076f398..684ff91 100644
--- a/drivers/net/bna/bnad.c
+++ b/drivers/net/bna/bnad.c
@@ -441,9 +441,17 @@ bnad_poll_cq(struct bnad *bnad, struct bna_ccb *ccb, int budget)
 	struct sk_buff *skb;
 	u32 flags, unmap_cons;
 	struct bna_pkt_rate *pkt_rt = &ccb->pkt_rate;
+	struct bnad_rx_ctrl *rx_ctrl = (struct bnad_rx_ctrl *)(ccb->ctrl);
+
+	preempt_disable();
+
+	set_bit(BNAD_FP_IN_RX_PATH, &rx_ctrl->flags);
 
-	if (!test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags))
+	if (!test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags)) {
+		clear_bit(BNAD_FP_IN_RX_PATH, &rx_ctrl->flags);
+		preempt_enable();
 		return 0;
+	}
 
 	prefetch(bnad->netdev);
 	BNA_CQ_QPGE_PTR_GET(ccb->producer_index, ccb->sw_qpt, cmpl,
@@ -551,6 +559,10 @@ next:
 			bna_ib_ack(ccb->i_dbell, 0);
 	}
 
+	clear_bit(BNAD_FP_IN_RX_PATH, &rx_ctrl->flags);
+
+	preempt_enable();
+
 	return packets;
 }
 
@@ -1259,7 +1271,7 @@ bnad_txrx_irq_free(struct bnad *bnad, struct bna_intr_info *intr_info)
 /* Allocates Interrupt Descriptor List for MSIX/INT-X vectors */
 static int
 bnad_txrx_irq_alloc(struct bnad *bnad, enum bnad_intr_source src,
-		    uint txrx_id, struct bna_intr_info *intr_info)
+		    u32 txrx_id, struct bna_intr_info *intr_info)
 {
 	int i, vector_start = 0;
 	u32 cfg_flags;
@@ -1342,7 +1354,7 @@ bnad_tx_msix_unregister(struct bnad *bnad, struct bnad_tx_info *tx_info,
  */
 static int
 bnad_tx_msix_register(struct bnad *bnad, struct bnad_tx_info *tx_info,
-			uint tx_id, int num_txqs)
+			u32 tx_id, int num_txqs)
 {
 	int i;
 	int err;
@@ -1395,7 +1407,7 @@ bnad_rx_msix_unregister(struct bnad *bnad, struct bnad_rx_info *rx_info,
  */
 static int
 bnad_rx_msix_register(struct bnad *bnad, struct bnad_rx_info *rx_info,
-			uint rx_id, int num_rxps)
+			u32 rx_id, int num_rxps)
 {
 	int i;
 	int err;
@@ -1439,7 +1451,7 @@ bnad_tx_res_free(struct bnad *bnad, struct bna_res_info *res_info)
 /* Allocates memory and interrupt resources for Tx object */
 static int
 bnad_tx_res_alloc(struct bnad *bnad, struct bna_res_info *res_info,
-		  uint tx_id)
+		  u32 tx_id)
 {
 	int i, err = 0;
 
@@ -1733,7 +1745,7 @@ bnad_napi_disable(struct bnad *bnad, u32 rx_id)
 
 /* Should be held with conf_lock held */
 void
-bnad_cleanup_tx(struct bnad *bnad, uint tx_id)
+bnad_cleanup_tx(struct bnad *bnad, u32 tx_id)
 {
 	struct bnad_tx_info *tx_info = &bnad->tx_info[tx_id];
 	struct bna_res_info *res_info = &bnad->tx_res_info[tx_id].res_info[0];
@@ -1757,6 +1769,7 @@ bnad_cleanup_tx(struct bnad *bnad, uint tx_id)
 	spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
 	tx_info->tx = NULL;
+	tx_info->tx_id = 0;
 
 	if (0 == tx_id)
 		tasklet_kill(&bnad->tx_free_tasklet);
@@ -1766,7 +1779,7 @@ bnad_cleanup_tx(struct bnad *bnad, uint tx_id)
 
 /* Should be held with conf_lock held */
 int
-bnad_setup_tx(struct bnad *bnad, uint tx_id)
+bnad_setup_tx(struct bnad *bnad, u32 tx_id)
 {
 	int err;
 	struct bnad_tx_info *tx_info = &bnad->tx_info[tx_id];
@@ -1778,6 +1791,8 @@ bnad_setup_tx(struct bnad *bnad, uint tx_id)
 	struct bna_tx *tx;
 	unsigned long flags;
 
+	tx_info->tx_id = tx_id;
+
 	/* Initialize the Tx object configuration */
 	tx_config->num_txq = bnad->num_txq_per_tx;
 	tx_config->txq_depth = bnad->txq_depth;
@@ -1869,7 +1884,7 @@ bnad_init_rx_config(struct bnad *bnad, struct bna_rx_config *rx_config)
 
 /* Called with mutex_lock(&bnad->conf_mutex) held */
 void
-bnad_cleanup_rx(struct bnad *bnad, uint rx_id)
+bnad_cleanup_rx(struct bnad *bnad, u32 rx_id)
 {
 	struct bnad_rx_info *rx_info = &bnad->rx_info[rx_id];
 	struct bna_rx_config *rx_config = &bnad->rx_config[rx_id];
@@ -1912,7 +1927,7 @@ bnad_cleanup_rx(struct bnad *bnad, uint rx_id)
 
 /* Called with mutex_lock(&bnad->conf_mutex) held */
 int
-bnad_setup_rx(struct bnad *bnad, uint rx_id)
+bnad_setup_rx(struct bnad *bnad, u32 rx_id)
 {
 	int err;
 	struct bnad_rx_info *rx_info = &bnad->rx_info[rx_id];
@@ -1924,6 +1939,8 @@ bnad_setup_rx(struct bnad *bnad, uint rx_id)
 	struct bna_rx *rx;
 	unsigned long flags;
 
+	rx_info->rx_id = rx_id;
+
 	/* Initialize the Rx object configuration */
 	bnad_init_rx_config(bnad, rx_config);
 
@@ -2138,7 +2155,7 @@ void
 bnad_netdev_hwstats_fill(struct bnad *bnad, struct rtnl_link_stats64 *stats)
 {
 	struct bfi_enet_stats_mac *mac_stats;
-	u64 bmap;
+	u32 bmap;
 	int i;
 
 	mac_stats = &bnad->stats.bna_stats->hw_stats.mac_stats;
@@ -2253,7 +2270,7 @@ bnad_q_num_init(struct bnad *bnad)
 	bnad->num_rx = 1;
 	bnad->num_tx = 1;
 	bnad->num_rxp_per_rx = rxps;
-	bnad->num_txq_per_tx = BNAD_TXQ_NUM;
+	bnad->num_txq_per_tx = BNAD_MAX_TXQ_PER_TX;
 }
 
 /*
@@ -2263,7 +2280,7 @@ bnad_q_num_init(struct bnad *bnad)
  * Called with bnad->bna_lock held b'cos of cfg_flags access
  */
 static void
-bnad_q_num_adjust(struct bnad *bnad, int msix_vectors)
+bnad_q_num_adjust(struct bnad *bnad, int msix_vectors, int temp)
 {
 	bnad->num_txq_per_tx = 1;
 	if ((msix_vectors >= (bnad->num_tx * bnad->num_txq_per_tx)  +
@@ -2317,12 +2334,12 @@ bnad_ioceth_enable(struct bnad *bnad)
 
 /* Free BNA resources */
 static void
-bnad_res_free(struct bnad *bnad)
+bnad_res_free(struct bnad *bnad, struct bna_res_info *res_info,
+		u32 res_val_max)
 {
 	int i;
-	struct bna_res_info *res_info = &bnad->res_info[0];
 
-	for (i = 0; i < BNA_RES_T_MAX; i++) {
+	for (i = 0; i < res_val_max; i++) {
 		if (res_info[i].res_type == BNA_RES_T_MEM)
 			bnad_mem_free(bnad, &res_info[i].res_u.mem_info);
 		else
@@ -2332,10 +2349,10 @@ bnad_res_free(struct bnad *bnad)
 
 /* Allocates memory and interrupt resources for BNA */
 static int
-bnad_res_alloc(struct bnad *bnad)
+bnad_res_alloc(struct bnad *bnad, struct bna_res_info *res_info,
+		u32 res_val_max)
 {
 	int i, err;
-	struct bna_res_info *res_info = &bnad->res_info[0];
 
 	for (i = 0; i < BNA_RES_T_MAX; i++) {
 		if (res_info[i].res_type == BNA_RES_T_MEM)
@@ -2349,7 +2366,7 @@ bnad_res_alloc(struct bnad *bnad)
 	return 0;
 
 err_return:
-	bnad_res_free(bnad);
+	bnad_res_free(bnad, res_info, res_val_max);
 	return err;
 }
 
@@ -2385,7 +2402,7 @@ bnad_enable_msix(struct bnad *bnad)
 
 		spin_lock_irqsave(&bnad->bna_lock, flags);
 		/* ret = #of vectors that we got */
-		bnad_q_num_adjust(bnad, ret);
+		bnad_q_num_adjust(bnad, ret, 0);
 		spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
 		bnad->msix_num = (bnad->num_tx * bnad->num_txq_per_tx)
@@ -2393,6 +2410,9 @@ bnad_enable_msix(struct bnad *bnad)
 			* bnad->num_rxp_per_rx) +
 			 BNAD_MAILBOX_MSIX_VECTORS;
 
+		if (bnad->msix_num > ret)
+			goto intx_mode;
+
 		/* Try once more with adjusted numbers */
 		/* If this fails, fall back to INTx */
 		ret = pci_enable_msix(bnad->pcidev, bnad->msix_table,
@@ -2402,6 +2422,9 @@ bnad_enable_msix(struct bnad *bnad)
 
 	} else if (ret < 0)
 		goto intx_mode;
+
+	pci_intx(bnad->pcidev, 0);
+
 	return;
 
 intx_mode:
@@ -2460,7 +2483,7 @@ bnad_open(struct net_device *netdev)
 	pause_config.tx_pause = 0;
 	pause_config.rx_pause = 0;
 
-	mtu = ETH_HLEN + bnad->netdev->mtu + ETH_FCS_LEN;
+	mtu = ETH_HLEN + VLAN_HLEN + bnad->netdev->mtu + ETH_FCS_LEN;
 
 	spin_lock_irqsave(&bnad->bna_lock, flags);
 	bna_enet_mtu_set(&bnad->bna.enet, mtu, NULL);
@@ -2534,16 +2557,15 @@ static netdev_tx_t
 bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 {
 	struct bnad *bnad = netdev_priv(netdev);
+	u32 txq_id = 0;
+	struct bna_tcb *tcb = bnad->tx_info[0].tcb[txq_id];
 
 	u16		txq_prod, vlan_tag = 0;
 	u32		unmap_prod, wis, wis_used, wi_range;
 	u32		vectors, vect_id, i, acked;
-	u32		tx_id;
 	int			err;
 
-	struct bnad_tx_info *tx_info;
-	struct bna_tcb *tcb;
-	struct bnad_unmap_q *unmap_q;
+	struct bnad_unmap_q *unmap_q = tcb->unmap_q;
 	dma_addr_t		dma_addr;
 	struct bna_txq_entry *txqent;
 	u16	flags;
@@ -2554,15 +2576,9 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 		return NETDEV_TX_OK;
 	}
 
-	tx_id = 0;
-
-	tx_info = &bnad->tx_info[tx_id];
-	tcb = tx_info->tcb[tx_id];
-	unmap_q = tcb->unmap_q;
-
 	/*
 	 * Takes care of the Tx that is scheduled between clearing the flag
-	 * and the netif_stop_queue() call.
+	 * and the netif_stop_all_queue() call.
 	 */
 	if (unlikely(!test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))) {
 		dev_kfree_skb(skb);
@@ -2576,9 +2592,8 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 	}
 	wis = BNA_TXQ_WI_NEEDED(vectors);	/* 4 vectors per work item */
 	acked = 0;
-	if (unlikely
-	    (wis > BNA_QE_FREE_CNT(tcb, tcb->q_depth) ||
-	     vectors > BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth))) {
+	if (unlikely(wis > BNA_QE_FREE_CNT(tcb, tcb->q_depth) ||
+			vectors > BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth))) {
 		if ((u16) (*tcb->hw_consumer_index) !=
 		    tcb->consumer_index &&
 		    !test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags)) {
@@ -3190,12 +3205,15 @@ bnad_pci_probe(struct pci_dev *pdev,
 	 */
 	netdev = alloc_etherdev(sizeof(struct bnad));
 	if (!netdev) {
-		dev_err(&pdev->dev, "alloc_etherdev failed\n");
+		dev_err(&pdev->dev, "netdev allocation failed\n");
 		err = -ENOMEM;
 		return err;
 	}
 	bnad = netdev_priv(netdev);
 
+	bnad_lock_init(bnad);
+
+	mutex_lock(&bnad->conf_mutex);
 	/*
 	 * PCI initialization
 	 *	Output : using_dac = 1 for 64 bit DMA
@@ -3205,7 +3223,6 @@ bnad_pci_probe(struct pci_dev *pdev,
 	if (err)
 		goto free_netdev;
 
-	bnad_lock_init(bnad);
 	/*
 	 * Initialize bnad structure
 	 * Setup relation between pci_dev & netdev
@@ -3214,6 +3231,7 @@ bnad_pci_probe(struct pci_dev *pdev,
 	err = bnad_init(bnad, pdev, netdev);
 	if (err)
 		goto pci_uninit;
+
 	/* Initialize netdev structure, set up ethtool ops */
 	bnad_netdev_init(bnad, using_dac);
 
@@ -3223,10 +3241,12 @@ bnad_pci_probe(struct pci_dev *pdev,
 	bnad_enable_msix(bnad);
 
 	/* Get resource requirement form bna */
+	spin_lock_irqsave(&bnad->bna_lock, flags);
 	bna_res_req(&bnad->res_info[0]);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
 	/* Allocate resources from bna */
-	err = bnad_res_alloc(bnad);
+	err = bnad_res_alloc(bnad, &bnad->res_info[0], BNA_RES_T_MAX);
 	if (err)
 		goto free_netdev;
 
@@ -3238,8 +3258,6 @@ bnad_pci_probe(struct pci_dev *pdev,
 	pcidev_info.device_id = bnad->pcidev->device;
 	pcidev_info.pci_bar_kva = bnad->bar0;
 
-	mutex_lock(&bnad->conf_mutex);
-
 	spin_lock_irqsave(&bnad->bna_lock, flags);
 	bna_init(bna, bnad, &pcidev_info, &bnad->res_info[0]);
 	spin_unlock_irqrestore(&bnad->bna_lock, flags);
@@ -3262,10 +3280,32 @@ bnad_pci_probe(struct pci_dev *pdev,
 
 	/*
 	 * Start the chip
-	 * Don't care even if err != 0, bna state machine will
-	 * deal with it
+	 * If the call back comes with error, we bail out.
+	 * This is a catastrophic error.
 	 */
 	err = bnad_ioceth_enable(bnad);
+	if (err)
+		goto disable_device;
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	if (bna_num_txq_set(bna, BNAD_NUM_TXQ + 1) ||
+		bna_num_rxp_set(bna, BNAD_NUM_RXP + 1)) {
+		bnad_q_num_adjust(bnad, bna_attr(bna)->num_txq - 1,
+			bna_attr(bna)->num_rxp - 1);
+		if (bna_num_txq_set(bna, BNAD_NUM_TXQ + 1) ||
+			bna_num_rxp_set(bna, BNAD_NUM_RXP + 1))
+			err = -EIO;
+	}
+	bna_mod_res_req(&bnad->bna, &bnad->mod_res_info[0]);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	err = bnad_res_alloc(bnad, &bnad->mod_res_info[0], BNA_MOD_RES_T_MAX);
+	if (err)
+		goto disable_device;
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	bna_mod_init(&bnad->bna, &bnad->mod_res_info[0]);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
 	/* Get the burnt-in mac */
 	spin_lock_irqsave(&bnad->bna_lock, flags);
@@ -3273,19 +3313,17 @@ bnad_pci_probe(struct pci_dev *pdev,
 	bnad_set_netdev_perm_addr(bnad);
 	spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
-	mutex_unlock(&bnad->conf_mutex);
-
 	/* Finally, reguister with net_device layer */
 	err = register_netdev(netdev);
 	if (err) {
 		pr_err("BNA : Registering with netdev failed\n");
 		goto disable_device;
 	}
+	mutex_unlock(&bnad->conf_mutex);
 
 	return 0;
 
 disable_device:
-	mutex_lock(&bnad->conf_mutex);
 	bnad_ioceth_disable(bnad);
 	del_timer_sync(&bnad->bna.ioceth.ioc.ioc_timer);
 	del_timer_sync(&bnad->bna.ioceth.ioc.sem_timer);
@@ -3293,9 +3331,8 @@ disable_device:
 	spin_lock_irqsave(&bnad->bna_lock, flags);
 	bna_uninit(bna);
 	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-	mutex_unlock(&bnad->conf_mutex);
-
-	bnad_res_free(bnad);
+	bnad_res_free(bnad, &bnad->mod_res_info[0], BNA_MOD_RES_T_MAX);
+	bnad_res_free(bnad, &bnad->res_info[0], BNA_RES_T_MAX);
 	bnad_disable_msix(bnad);
 pci_uninit:
 	bnad_pci_uninit(pdev);
@@ -3331,11 +3368,12 @@ bnad_pci_remove(struct pci_dev *pdev)
 	spin_lock_irqsave(&bnad->bna_lock, flags);
 	bna_uninit(bna);
 	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-	mutex_unlock(&bnad->conf_mutex);
 
-	bnad_res_free(bnad);
+	bnad_res_free(bnad, &bnad->mod_res_info[0], BNA_MOD_RES_T_MAX);
+	bnad_res_free(bnad, &bnad->res_info[0], BNA_RES_T_MAX);
 	bnad_disable_msix(bnad);
 	bnad_pci_uninit(pdev);
+	mutex_unlock(&bnad->conf_mutex);
 	bnad_lock_uninit(bnad);
 	bnad_uninit(bnad);
 	free_netdev(netdev);
diff --git a/drivers/net/bna/bnad.h b/drivers/net/bna/bnad.h
index 6a161b0..41ade02 100644
--- a/drivers/net/bna/bnad.h
+++ b/drivers/net/bna/bnad.h
@@ -38,12 +38,11 @@
 #define BNAD_RXQ_DEPTH		2048
 
 #define BNAD_MAX_TX		1
-#define BNAD_MAX_TXQ_PER_TX	8	/* 8 priority queues */
-#define BNAD_TXQ_NUM		1
+#define BNAD_MAX_TXQ_PER_TX	8
 
 #define BNAD_MAX_RX		1
 #define BNAD_MAX_RXP_PER_RX	16
-#define BNAD_MAX_RXQ_PER_RXP    2
+#define BNAD_MAX_RXQ_PER_RXP	2
 
 /*
  * Control structure pointed to ccb->ctrl, which
@@ -95,6 +94,13 @@ struct bnad_rx_ctrl {
 #define BNAD_RXQ_REFILL			0
 #define BNAD_RXQ_STARTED		1
 
+/* Resource limits */
+#define BNAD_MAX_TXQ			(BNAD_MAX_TX * BNAD_MAX_TXQ_PER_TX)
+#define BNAD_MAX_RXP			(BNAD_MAX_RX * BNAD_MAX_RXP_PER_RX)
+
+#define BNAD_NUM_TXQ			(bnad->num_tx * bnad->num_txq_per_tx)
+#define BNAD_NUM_RXP			(bnad->num_rx * bnad->num_rxp_per_rx)
+
 /*
  * DATA STRUCTURES
  */
@@ -179,12 +185,14 @@ struct bnad_rx_res_info {
 struct bnad_tx_info {
 	struct bna_tx *tx; /* 1:1 between tx_info & tx */
 	struct bna_tcb *tcb[BNAD_MAX_TXQ_PER_TX];
+	u32 tx_id;
 } ____cacheline_aligned;
 
 struct bnad_rx_info {
 	struct bna_rx *rx; /* 1:1 between rx_info & rx */
 
 	struct bnad_rx_ctrl rx_ctrl[BNAD_MAX_RXP_PER_RX];
+	u32 rx_id;
 } ____cacheline_aligned;
 
 /* Unmap queues for Tx / Rx cleanup */
@@ -274,6 +282,7 @@ struct bnad {
 
 	/* Control path resources, memory & irq */
 	struct bna_res_info res_info[BNA_RES_T_MAX];
+	struct bna_res_info mod_res_info[BNA_MOD_RES_T_MAX];
 	struct bnad_tx_res_info tx_res_info[BNAD_MAX_TX];
 	struct bnad_rx_res_info rx_res_info[BNAD_MAX_RX];
 
@@ -311,10 +320,10 @@ extern void bnad_set_ethtool_ops(struct net_device *netdev);
 extern void bnad_tx_coalescing_timeo_set(struct bnad *bnad);
 extern void bnad_rx_coalescing_timeo_set(struct bnad *bnad);
 
-extern int bnad_setup_rx(struct bnad *bnad, uint rx_id);
-extern int bnad_setup_tx(struct bnad *bnad, uint tx_id);
-extern void bnad_cleanup_tx(struct bnad *bnad, uint tx_id);
-extern void bnad_cleanup_rx(struct bnad *bnad, uint rx_id);
+extern int bnad_setup_rx(struct bnad *bnad, u32 rx_id);
+extern int bnad_setup_tx(struct bnad *bnad, u32 tx_id);
+extern void bnad_cleanup_tx(struct bnad *bnad, u32 tx_id);
+extern void bnad_cleanup_rx(struct bnad *bnad, u32 rx_id);
 
 /* Timer start/stop protos */
 extern void bnad_dim_timer_start(struct bnad *bnad);
-- 
1.7.1


^ permalink raw reply related

* [PATCH 32/45] bna: TxRx Coalesce Settings Fix and Reorg PCI Probe Failure
From: Rasesh Mody @ 2011-07-18  8:22 UTC (permalink / raw)
  To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>

Change details:
 - The TX and Rx coalesce settings are programmed in steps of 5 us. The value
   that are not divisible by 5 are rounded to the next lower number. This was
   causing the value os 1 to 4 to be rounded to 0, which is an invalid setting.
 - When creating Rx and Tx object, we are currently assigning the default
   values of Rx and Tx coalescing_timeo. If these values are changed in
   the driver to a different value, the change is lost during such
   operations as MTU change. In order to avoid that, pass the configured
   value of coalescing_timeo before Rx and Tx object creation.
 - Fix bnad_tx_coalescing_timeo_set() so it applies to all the Tx objects.
 - Fix uninitialization path in case of pci_probe failure.
 - Added/Removed flags.

Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 drivers/net/bna/bnad.c |   46 ++++++++++++++++++++++++++++++----------------
 drivers/net/bna/bnad.h |    9 +++++----
 2 files changed, 35 insertions(+), 20 deletions(-)

diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c
index 684ff91..6d1b82b 100644
--- a/drivers/net/bna/bnad.c
+++ b/drivers/net/bna/bnad.c
@@ -1797,6 +1797,7 @@ bnad_setup_tx(struct bnad *bnad, u32 tx_id)
 	tx_config->num_txq = bnad->num_txq_per_tx;
 	tx_config->txq_depth = bnad->txq_depth;
 	tx_config->tx_type = BNA_TX_T_REGULAR;
+	tx_config->coalescing_timeo = bnad->tx_coalescing_timeo;
 
 	/* Initialize the tx event handlers */
 	tx_cbfn.tcb_setup_cbfn = bnad_cb_tcb_setup;
@@ -1857,6 +1858,7 @@ bnad_init_rx_config(struct bnad *bnad, struct bna_rx_config *rx_config)
 {
 	rx_config->rx_type = BNA_RX_T_REGULAR;
 	rx_config->num_paths = bnad->num_rxp_per_rx;
+	rx_config->coalescing_timeo = bnad->rx_coalescing_timeo;
 
 	if (bnad->num_rxp_per_rx > 1) {
 		rx_config->rss_status = BNA_STATUS_T_ENABLED;
@@ -2017,12 +2019,15 @@ void
 bnad_tx_coalescing_timeo_set(struct bnad *bnad)
 {
 	struct bnad_tx_info *tx_info;
+	int i;
 
-	tx_info = &bnad->tx_info[0];
-	if (!tx_info->tx)
-		return;
-
-	bna_tx_coalescing_timeo_set(tx_info->tx, bnad->tx_coalescing_timeo);
+	for (i = 0; i < bnad->num_tx; i++) {
+		tx_info = &bnad->tx_info[i];
+		if (!tx_info->tx)
+			continue;
+		bna_tx_coalescing_timeo_set(tx_info->tx,
+				bnad->tx_coalescing_timeo);
+	}
 }
 
 /* Called with conf_lock & bnad->bna_lock held */
@@ -2726,7 +2731,7 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 
 	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
 		struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
-		u32		size = frag->size;
+		u16		size = frag->size;
 
 		if (++vect_id == BFI_TX_MAX_VECTORS_PER_WI) {
 			vect_id = 0;
@@ -3248,7 +3253,7 @@ bnad_pci_probe(struct pci_dev *pdev,
 	/* Allocate resources from bna */
 	err = bnad_res_alloc(bnad, &bnad->res_info[0], BNA_RES_T_MAX);
 	if (err)
-		goto free_netdev;
+		goto drv_uninit;
 
 	bna = &bnad->bna;
 
@@ -3284,8 +3289,11 @@ bnad_pci_probe(struct pci_dev *pdev,
 	 * This is a catastrophic error.
 	 */
 	err = bnad_ioceth_enable(bnad);
-	if (err)
-		goto disable_device;
+	if (err) {
+		pr_err("BNA: Initialization failed err=%d\n",
+		       err);
+		goto probe_success;
+	}
 
 	spin_lock_irqsave(&bnad->bna_lock, flags);
 	if (bna_num_txq_set(bna, BNAD_NUM_TXQ + 1) ||
@@ -3301,7 +3309,7 @@ bnad_pci_probe(struct pci_dev *pdev,
 
 	err = bnad_res_alloc(bnad, &bnad->mod_res_info[0], BNA_MOD_RES_T_MAX);
 	if (err)
-		goto disable_device;
+		goto disable_ioceth;
 
 	spin_lock_irqsave(&bnad->bna_lock, flags);
 	bna_mod_init(&bnad->bna, &bnad->mod_res_info[0]);
@@ -3317,13 +3325,17 @@ bnad_pci_probe(struct pci_dev *pdev,
 	err = register_netdev(netdev);
 	if (err) {
 		pr_err("BNA : Registering with netdev failed\n");
-		goto disable_device;
+		goto probe_uninit;
 	}
-	mutex_unlock(&bnad->conf_mutex);
+	set_bit(BNAD_RF_NETDEV_REGISTERED, &bnad->run_flags);
 
+probe_success:
+	mutex_unlock(&bnad->conf_mutex);
 	return 0;
 
-disable_device:
+probe_uninit:
+	bnad_res_free(bnad, &bnad->mod_res_info[0], BNA_MOD_RES_T_MAX);
+disable_ioceth:
 	bnad_ioceth_disable(bnad);
 	del_timer_sync(&bnad->bna.ioceth.ioc.ioc_timer);
 	del_timer_sync(&bnad->bna.ioceth.ioc.sem_timer);
@@ -3331,13 +3343,14 @@ disable_device:
 	spin_lock_irqsave(&bnad->bna_lock, flags);
 	bna_uninit(bna);
 	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-	bnad_res_free(bnad, &bnad->mod_res_info[0], BNA_MOD_RES_T_MAX);
 	bnad_res_free(bnad, &bnad->res_info[0], BNA_RES_T_MAX);
+drv_uninit:
 	bnad_disable_msix(bnad);
+	bnad_uninit(bnad);
 pci_uninit:
 	bnad_pci_uninit(pdev);
+	mutex_unlock(&bnad->conf_mutex);
 	bnad_lock_uninit(bnad);
-	bnad_uninit(bnad);
 free_netdev:
 	free_netdev(netdev);
 	return err;
@@ -3358,7 +3371,8 @@ bnad_pci_remove(struct pci_dev *pdev)
 	bnad = netdev_priv(netdev);
 	bna = &bnad->bna;
 
-	unregister_netdev(netdev);
+	if (test_and_clear_bit(BNAD_RF_NETDEV_REGISTERED, &bnad->run_flags))
+		unregister_netdev(netdev);
 
 	mutex_lock(&bnad->conf_mutex);
 	bnad_ioceth_disable(bnad);
diff --git a/drivers/net/bna/bnad.h b/drivers/net/bna/bnad.h
index 41ade02..c25e6e2 100644
--- a/drivers/net/bna/bnad.h
+++ b/drivers/net/bna/bnad.h
@@ -218,13 +218,14 @@ struct bnad_unmap_q {
 /* Defines for run_flags bit-mask */
 /* Set, tested & cleared using xxx_bit() functions */
 /* Values indicated bit positions */
-#define	BNAD_RF_CEE_RUNNING		1
+#define BNAD_RF_CEE_RUNNING		0
+#define BNAD_RF_MTU_SET		1
 #define BNAD_RF_MBOX_IRQ_DISABLED	2
-#define BNAD_RF_RX_STARTED		3
+#define BNAD_RF_NETDEV_REGISTERED	3
 #define BNAD_RF_DIM_TIMER_RUNNING	4
 #define BNAD_RF_STATS_TIMER_RUNNING	5
-#define BNAD_RF_TX_SHUTDOWN_DELAYED	6
-#define BNAD_RF_RX_SHUTDOWN_DELAYED	7
+#define BNAD_RF_TX_PRIO_SET		6
+
 
 /* Define for Fast Path flags */
 /* Defined as bit positions */
-- 
1.7.1


^ permalink raw reply related

* [PATCH 33/45] bna: Device Init Fix
From: Rasesh Mody @ 2011-07-18  8:22 UTC (permalink / raw)
  To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>

Change details:
 - Do not return probe failure when device initialization fails so that the
   driver stays loaded and the hardware is accessible for debugging.

Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 drivers/net/bna/bnad.c |   10 +++++++---
 1 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c
index 6d1b82b..2b716ed 100644
--- a/drivers/net/bna/bnad.c
+++ b/drivers/net/bna/bnad.c
@@ -3308,19 +3308,21 @@ bnad_pci_probe(struct pci_dev *pdev,
 	spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
 	err = bnad_res_alloc(bnad, &bnad->mod_res_info[0], BNA_MOD_RES_T_MAX);
-	if (err)
+	if (err) {
+		err = -EIO;
 		goto disable_ioceth;
+	}
 
 	spin_lock_irqsave(&bnad->bna_lock, flags);
 	bna_mod_init(&bnad->bna, &bnad->mod_res_info[0]);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
 	/* Get the burnt-in mac */
-	spin_lock_irqsave(&bnad->bna_lock, flags);
 	bna_enet_perm_mac_get(&bna->enet, &bnad->perm_addr);
 	bnad_set_netdev_perm_addr(bnad);
 	spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
+	mutex_unlock(&bnad->conf_mutex);
+
 	/* Finally, reguister with net_device layer */
 	err = register_netdev(netdev);
 	if (err) {
@@ -3329,6 +3331,8 @@ bnad_pci_probe(struct pci_dev *pdev,
 	}
 	set_bit(BNAD_RF_NETDEV_REGISTERED, &bnad->run_flags);
 
+	return 0;
+
 probe_success:
 	mutex_unlock(&bnad->conf_mutex);
 	return 0;
-- 
1.7.1


^ permalink raw reply related

* [PATCH 34/45] bna: Add Multiple Tx Queue Support
From: Rasesh Mody @ 2011-07-18  8:22 UTC (permalink / raw)
  To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>

Change details:
 - Added support for multipe Tx queues with a separate iSCSI Tx queue based
   on the default value of iSCSI port number. The feature is supported based
   on the underlying hardware and enabled for DCB (CEE) mode only.
 - Allocate multiple TxQ resource in netdev
 - Implement bnad_tx_select_queue() which enables the correct selection of
   TxQ Id (and tcb). This function is called either by the kernel to channel
   packets to the right TxQ
 - Implement bnad_iscsi_tcb_get() and BNAD_IS_ISCSI_PKT() for iSCSI packet
   inspection and retrieval of tcb corresponding to the iSCSI priority.

Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 drivers/net/bna/bna_types.h |    2 +
 drivers/net/bna/bnad.c      |  146 ++++++++++++++++++++++++++++++++++---------
 drivers/net/bna/bnad.h      |    9 +++
 3 files changed, 127 insertions(+), 30 deletions(-)

diff --git a/drivers/net/bna/bna_types.h b/drivers/net/bna/bna_types.h
index a4f71c0..7f037db 100644
--- a/drivers/net/bna/bna_types.h
+++ b/drivers/net/bna/bna_types.h
@@ -329,6 +329,7 @@ struct bna_attr {
 	int			num_ucmac;
 	int			num_mcmac;
 	int			max_rit_size;
+	int			max_ets_groups;
 };
 
 /**
@@ -578,6 +579,7 @@ struct bna_tx_mod {
 	int			iscsi_over_cee;
 	int			iscsi_prio;
 	int			prio_reconfigured;
+	void			*prio_indirection[BFI_TX_MAX_PRIO];
 
 	u32			rid_mask;
 
diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c
index 2b716ed..8ca1b60 100644
--- a/drivers/net/bna/bnad.c
+++ b/drivers/net/bna/bnad.c
@@ -194,8 +194,6 @@ bnad_free_txbufs(struct bnad *bnad,
 	while (wis) {
 		skb = unmap_array[unmap_cons].skb;
 
-		unmap_array[unmap_cons].skb = NULL;
-
 		sent_packets++;
 		sent_bytes += skb->len;
 		wis -= BNA_TXQ_WI_NEEDED(1 + skb_shinfo(skb)->nr_frags);
@@ -245,7 +243,7 @@ bnad_tx_free_tasklet(unsigned long bnad_ptr)
 {
 	struct bnad *bnad = (struct bnad *)bnad_ptr;
 	struct bna_tcb *tcb;
-	u32		acked = 0;
+	u32		acked = 0, txq_id;
 	int			i, j;
 
 	for (i = 0; i < bnad->num_tx; i++) {
@@ -264,14 +262,20 @@ bnad_tx_free_tasklet(unsigned long bnad_ptr)
 				smp_mb__before_clear_bit();
 				clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
 			}
+			/*
+			 * Check again, because this bit can be set from another
+			 * context. This is not lock protected.
+			 */
 			if (unlikely(!test_bit(BNAD_TXQ_TX_STARTED,
 						&tcb->flags)))
 				continue;
-			if (netif_queue_stopped(bnad->netdev)) {
+			txq_id = tcb->id;
+			if (__netif_subqueue_stopped(bnad->netdev, txq_id)) {
 				if (acked && netif_carrier_ok(bnad->netdev) &&
 					BNA_QE_FREE_CNT(tcb, tcb->q_depth) >=
 						BNAD_NETIF_WAKE_THRESHOLD) {
-					netif_wake_queue(bnad->netdev);
+					netif_wake_subqueue(bnad->netdev,
+									txq_id);
 					/* TODO */
 					/* Counters for individual TxQs? */
 					BNAD_UPDATE_CTR(bnad,
@@ -286,19 +290,21 @@ static u32
 bnad_tx(struct bnad *bnad, struct bna_tcb *tcb)
 {
 	struct net_device *netdev = bnad->netdev;
-	u32 sent = 0;
+	u32 sent = 0, txq_id;
 
 	if (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags))
 		return 0;
 
 	sent = bnad_free_txbufs(bnad, tcb);
 	if (sent) {
-		if (netif_queue_stopped(netdev) &&
+		txq_id = tcb->id;
+
+		if (__netif_subqueue_stopped(netdev, txq_id) &&
 		    netif_carrier_ok(netdev) &&
 		    BNA_QE_FREE_CNT(tcb, tcb->q_depth) >=
 				    BNAD_NETIF_WAKE_THRESHOLD) {
 			if (test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)) {
-				netif_wake_queue(netdev);
+				netif_wake_subqueue(netdev, txq_id);
 				BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
 			}
 		}
@@ -850,7 +856,9 @@ bnad_cb_tcb_setup(struct bnad *bnad, struct bna_tcb *tcb)
 			(struct bnad_tx_info *)tcb->txq->tx->priv;
 	struct bnad_unmap_q *unmap_q = tcb->unmap_q;
 
+	tcb->priv = tcb;
 	tx_info->tcb[tcb->id] = tcb;
+
 	unmap_q->producer_index = 0;
 	unmap_q->consumer_index = 0;
 	unmap_q->q_depth = BNAD_TX_UNMAPQ_DEPTH;
@@ -875,6 +883,7 @@ bnad_cb_tcb_destroy(struct bnad *bnad, struct bna_tcb *tcb)
 	clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
 
 	tx_info->tcb[tcb->id] = NULL;
+	tcb->priv = NULL;
 }
 
 static void
@@ -1777,6 +1786,29 @@ bnad_cleanup_tx(struct bnad *bnad, u32 tx_id)
 	bnad_tx_res_free(bnad, res_info);
 }
 
+/*
+ * Sets up bnad->num_tx depending on the current value (already
+ * adjusted based on MSIX vectors available and ETS support in
+ * the chip
+ */
+static void
+bnad_num_txq_set(struct bnad *bnad)
+{
+	struct bna *bna	= &bnad->bna;
+	struct bna_attr	attr;
+	unsigned long		flags;
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	attr = bna->ioceth.attr;
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	if (attr.max_ets_groups < BFI_TX_MAX_PRIO)
+		bnad->num_txq_per_tx = 1;
+	else
+		bnad->num_txq_per_tx = min((u32)attr.max_ets_groups,
+					(u32)bnad->num_txq_per_tx);
+}
+
 /* Should be held with conf_lock held */
 int
 bnad_setup_tx(struct bnad *bnad, u32 tx_id)
@@ -1793,6 +1825,8 @@ bnad_setup_tx(struct bnad *bnad, u32 tx_id)
 
 	tx_info->tx_id = tx_id;
 
+	bnad_num_txq_set(bnad);
+
 	/* Initialize the Tx object configuration */
 	tx_config->num_txq = bnad->num_txq_per_tx;
 	tx_config->txq_depth = bnad->txq_depth;
@@ -2264,38 +2298,45 @@ bnad_tso_prepare(struct bnad *bnad, struct sk_buff *skb)
 static void
 bnad_q_num_init(struct bnad *bnad)
 {
-	int rxps;
+	int rxps = min((u32)num_online_cpus(),
+			(u32)(BNAD_MAX_RXP_PER_RX));
 
-	rxps = min((uint)num_online_cpus(),
-			(uint)(BNAD_MAX_RX * BNAD_MAX_RXP_PER_RX));
+	BNA_TO_POWER_OF_2(rxps);
 
 	if (!(bnad->cfg_flags & BNAD_CF_MSIX))
 		rxps = 1;	/* INTx */
 
-	bnad->num_rx = 1;
-	bnad->num_tx = 1;
+	bnad->num_rx = BNAD_MAX_RX;
+	bnad->num_tx = BNAD_MAX_TX;
 	bnad->num_rxp_per_rx = rxps;
 	bnad->num_txq_per_tx = BNAD_MAX_TXQ_PER_TX;
 }
 
 /*
- * Adjusts the Q numbers, given a number of msix vectors
+ * Adjusts the Q numbers, given a number of max possible queues.
  * Give preference to RSS as opposed to Tx priority Queues,
  * in such a case, just use 1 Tx Q
  * Called with bnad->bna_lock held b'cos of cfg_flags access
  */
 static void
-bnad_q_num_adjust(struct bnad *bnad, int msix_vectors, int temp)
+bnad_q_num_adjust(struct bnad *bnad, int max_txq, int max_rxq)
 {
-	bnad->num_txq_per_tx = 1;
-	if ((msix_vectors >= (bnad->num_tx * bnad->num_txq_per_tx)  +
-	     bnad_rxqs_per_cq + BNAD_MAILBOX_MSIX_VECTORS) &&
-	    (bnad->cfg_flags & BNAD_CF_MSIX)) {
-		bnad->num_rxp_per_rx = msix_vectors -
-			(bnad->num_tx * bnad->num_txq_per_tx) -
-			BNAD_MAILBOX_MSIX_VECTORS;
-	} else
-		bnad->num_rxp_per_rx = 1;
+	if (!(bnad->cfg_flags & BNAD_CF_MSIX)) {
+		bnad->num_tx = bnad->num_txq_per_tx = 1;
+		bnad->num_rx = bnad->num_rxp_per_rx = 1;
+		return;
+	}
+
+	if (max_txq < BNAD_NUM_TXQ) {
+		bnad->num_txq_per_tx = 1;
+		bnad->num_tx = 1;
+	}
+
+	bnad->num_rx = 1;
+	bnad->num_rxp_per_rx = min((u32)(min((u32)num_online_cpus(),
+					(u32)(BNAD_MAX_RXP_PER_RX))),
+					(u32)max_rxq);
+	BNA_TO_POWER_OF_2(bnad->num_rxp_per_rx);
 }
 
 /* Enable / disable ioceth */
@@ -2359,7 +2400,7 @@ bnad_res_alloc(struct bnad *bnad, struct bna_res_info *res_info,
 {
 	int i, err;
 
-	for (i = 0; i < BNA_RES_T_MAX; i++) {
+	for (i = 0; i < res_val_max; i++) {
 		if (res_info[i].res_type == BNA_RES_T_MEM)
 			err = bnad_mem_alloc(bnad, &res_info[i].res_u.mem_info);
 		else
@@ -2433,7 +2474,6 @@ bnad_enable_msix(struct bnad *bnad)
 	return;
 
 intx_mode:
-
 	kfree(bnad->msix_table);
 	bnad->msix_table = NULL;
 	bnad->msix_num = 0;
@@ -2608,7 +2648,7 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 			smp_mb__before_clear_bit();
 			clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
 		} else {
-			netif_stop_queue(netdev);
+			netif_stop_subqueue(netdev, txq_id);
 			BNAD_UPDATE_CTR(bnad, netif_queue_stop);
 		}
 
@@ -2624,7 +2664,7 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 			BNAD_UPDATE_CTR(bnad, netif_queue_stop);
 			return NETDEV_TX_BUSY;
 		} else {
-			netif_wake_queue(netdev);
+			netif_wake_subqueue(netdev, txq_id);
 			BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
 		}
 	}
@@ -2649,7 +2689,8 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 	}
 	if (test_bit(BNAD_RF_CEE_RUNNING, &bnad->run_flags)) {
 		vlan_tag =
-			(tcb->priority & 0x7) << 13 | (vlan_tag & 0x1fff);
+			((tcb->priority & 0x7) << VLAN_PRIO_SHIFT)
+							| (vlan_tag & 0x1fff);
 		flags |= (BNA_TXQ_WI_CF_INS_PRIO | BNA_TXQ_WI_CF_INS_VLAN);
 	}
 
@@ -2796,6 +2837,50 @@ bnad_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
 	return stats;
 }
 
+static bool bnad_is_iscsi(struct sk_buff *skb)
+{
+	u16		proto = 0;
+	struct tcphdr		*th;
+
+	if (skb->protocol == htons(ETH_P_IP))
+		proto = ip_hdr(skb)->protocol;
+	else if (skb->protocol == htons(ETH_P_IPV6))
+		/* nexthdr may not be TCP immediately. */
+		proto = ipv6_hdr(skb)->nexthdr;
+	if (proto == IPPROTO_TCP) {
+		th = tcp_hdr(skb);
+		if (BNAD_IS_ISCSI_PKT(th))
+			return true;
+	}
+
+	return false;
+}
+
+static u16
+bnad_tx_select_queue(struct net_device *netdev, struct sk_buff *skb)
+{
+	struct bnad *bnad =  netdev_priv(netdev);
+	struct bna *bna = &bnad->bna;
+	u8	prio = 0;
+
+	if (bnad->num_txq_per_tx < BFI_TX_MAX_PRIO)
+		prio = 0;
+	else if (bna_is_iscsi_over_cee(&bnad->bna) && bnad_is_iscsi(skb))
+		prio = bna_iscsi_prio(bna);
+	else if (vlan_tx_tag_present(skb)) {
+		u8 pkt_vlan_prio = 0;
+		u16 pkt_vlan_tag = 0;
+		pkt_vlan_tag = (u16)vlan_tx_tag_get(skb);
+		pkt_vlan_prio = (pkt_vlan_tag & VLAN_PRIO_MASK)
+					>> VLAN_PRIO_SHIFT;
+		prio = bna_prio_allowed(bna, pkt_vlan_prio) ?
+			pkt_vlan_prio : bna_default_prio(bna);
+	} else
+		prio = bna_default_prio(bna);
+
+	return (u16)prio;
+}
+
 static void
 bnad_set_rx_mode(struct net_device *netdev)
 {
@@ -3011,6 +3096,7 @@ bnad_netpoll(struct net_device *netdev)
 static const struct net_device_ops bnad_netdev_ops = {
 	.ndo_open		= bnad_open,
 	.ndo_stop		= bnad_stop,
+	.ndo_select_queue	= bnad_tx_select_queue,
 	.ndo_start_xmit		= bnad_start_xmit,
 	.ndo_get_stats64		= bnad_get_stats64,
 	.ndo_set_rx_mode	= bnad_set_rx_mode,
@@ -3208,7 +3294,7 @@ bnad_pci_probe(struct pci_dev *pdev,
 	 * Allocates sizeof(struct net_device + struct bnad)
 	 * bnad = netdev->priv
 	 */
-	netdev = alloc_etherdev(sizeof(struct bnad));
+	netdev = alloc_etherdev_mq(sizeof(struct bnad), BNAD_MAX_TXQ);
 	if (!netdev) {
 		dev_err(&pdev->dev, "netdev allocation failed\n");
 		err = -ENOMEM;
diff --git a/drivers/net/bna/bnad.h b/drivers/net/bna/bnad.h
index c25e6e2..1b87b27 100644
--- a/drivers/net/bna/bnad.h
+++ b/drivers/net/bna/bnad.h
@@ -231,6 +231,15 @@ struct bnad_unmap_q {
 /* Defined as bit positions */
 #define BNAD_FP_IN_RX_PATH	      0
 
+/*
+ * Deep Inspection : Checks if packet is ISCSI based on
+ * standard iSCSI port
+ */
+#define BNAD_TCP_ISCSI_PORT 3260
+#define BNAD_IS_ISCSI_PKT(_tch)				\
+(((_tch)->source == ntohs(BNAD_TCP_ISCSI_PORT)) ||	\
+	((_tch)->dest == ntohs(BNAD_TCP_ISCSI_PORT)))
+
 struct bnad {
 	struct net_device	*netdev;
 
-- 
1.7.1


^ permalink raw reply related

* [PATCH 35/45] bna: Change TxQ Select Logic and Interrupt Handling
From: Rasesh Mody @ 2011-07-18  8:22 UTC (permalink / raw)
  To: davem, netdev; +Cc: adapter_linux_open_src_team, dradovan, Rasesh Mody
In-Reply-To: <1310977385-5268-1-git-send-email-rmody@brocade.com>

Change details:
 - Simplify the TxQ selection logic:
   Macro BNAD_TXQ_ID_GET() calls bnad_tx_select_queue(), which returns priority.
   While only a few packets during transition could have wrong priority, all
   will be associated with a valid non-NULL tcb.
 - Add bnad pointer to rx_ctrl structure, so that bnad can be accessed directly
   from rx_ctrl in the NAPI poll routines, even if ccb is NULL
 - Fix the order of init / uninit in Tx / Rx setup / teardown path:
   Kill bnad tx free tasklet ahead of call to bna_tx_destroy().
   Call NAPI disable only aftet call to Rx free_irq(). This makes sure Rx
   interrupt does not schedule a poll when NAPI is already disabled.

Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 drivers/net/bna/bnad.c |   70 +++++++++++++++++++++++++++++++----------------
 drivers/net/bna/bnad.h |    1 +
 2 files changed, 47 insertions(+), 24 deletions(-)

diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c
index 8ca1b60..3f9ddbf 100644
--- a/drivers/net/bna/bnad.c
+++ b/drivers/net/bna/bnad.c
@@ -554,16 +554,11 @@ next:
 
 	BNA_QE_INDX_ADD(ccb->producer_index, wis, ccb->q_depth);
 
-	if (likely(ccb)) {
-		if (likely(test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags)))
-			bna_ib_ack(ccb->i_dbell, packets);
-		bnad_refill_rxq(bnad, ccb->rcb[0]);
-		if (ccb->rcb[1])
-			bnad_refill_rxq(bnad, ccb->rcb[1]);
-	} else {
-		if (likely(test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags)))
-			bna_ib_ack(ccb->i_dbell, 0);
-	}
+	if (likely(test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags)))
+		bna_ib_ack(ccb->i_dbell, packets);
+	bnad_refill_rxq(bnad, ccb->rcb[0]);
+	if (ccb->rcb[1])
+		bnad_refill_rxq(bnad, ccb->rcb[1]);
 
 	clear_bit(BNAD_FP_IN_RX_PATH, &rx_ctrl->flags);
 
@@ -613,7 +608,8 @@ bnad_msix_rx(int irq, void *data)
 	struct bna_ccb *ccb = (struct bna_ccb *)data;
 	struct bnad *bnad = ccb->bnad;
 
-	bnad_netif_rx_schedule_poll(bnad, ccb);
+	if (ccb)
+		bnad_netif_rx_schedule_poll(bnad, ccb);
 
 	return IRQ_HANDLED;
 }
@@ -652,6 +648,7 @@ bnad_isr(int irq, void *data)
 	struct bnad *bnad = (struct bnad *)data;
 	struct bnad_rx_info *rx_info;
 	struct bnad_rx_ctrl *rx_ctrl;
+	struct bna_tcb *tcb = NULL;
 
 	if (unlikely(test_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags)))
 		return IRQ_NONE;
@@ -674,8 +671,11 @@ bnad_isr(int irq, void *data)
 	/* Process data interrupts */
 	/* Tx processing */
 	for (i = 0; i < bnad->num_tx; i++) {
-		for (j = 0; j < bnad->num_txq_per_tx; j++)
-			bnad_tx(bnad, bnad->tx_info[i].tcb[j]);
+		for (j = 0; j < bnad->num_txq_per_tx; j++) {
+			tcb = bnad->tx_info[i].tcb[j];
+			if (tcb && test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))
+				bnad_tx(bnad, bnad->tx_info[i].tcb[j]);
+		}
 	}
 	/* Rx processing */
 	for (i = 0; i < bnad->num_rx; i++) {
@@ -1773,6 +1773,9 @@ bnad_cleanup_tx(struct bnad *bnad, u32 tx_id)
 		bnad_tx_msix_unregister(bnad, tx_info,
 			bnad->num_txq_per_tx);
 
+	if (0 == tx_id)
+		tasklet_kill(&bnad->tx_free_tasklet);
+
 	spin_lock_irqsave(&bnad->bna_lock, flags);
 	bna_tx_destroy(tx_info->tx);
 	spin_unlock_irqrestore(&bnad->bna_lock, flags);
@@ -1780,9 +1783,6 @@ bnad_cleanup_tx(struct bnad *bnad, u32 tx_id)
 	tx_info->tx = NULL;
 	tx_info->tx_id = 0;
 
-	if (0 == tx_id)
-		tasklet_kill(&bnad->tx_free_tasklet);
-
 	bnad_tx_res_free(bnad, res_info);
 }
 
@@ -1918,6 +1918,16 @@ bnad_init_rx_config(struct bnad *bnad, struct bna_rx_config *rx_config)
 	rx_config->vlan_strip_status = BNA_STATUS_T_ENABLED;
 }
 
+static void
+bnad_rx_ctrl_init(struct bnad *bnad, u32 rx_id)
+{
+	struct bnad_rx_info *rx_info = &bnad->rx_info[rx_id];
+	int i;
+
+	for (i = 0; i < bnad->num_rxp_per_rx; i++)
+		rx_info->rx_ctrl[i].bnad = bnad;
+}
+
 /* Called with mutex_lock(&bnad->conf_mutex) held */
 void
 bnad_cleanup_rx(struct bnad *bnad, u32 rx_id)
@@ -1941,8 +1951,6 @@ bnad_cleanup_rx(struct bnad *bnad, u32 rx_id)
 			del_timer_sync(&bnad->dim_timer);
 	}
 
-	bnad_napi_disable(bnad, rx_id);
-
 	init_completion(&bnad->bnad_completions.rx_comp);
 	spin_lock_irqsave(&bnad->bna_lock, flags);
 	bna_rx_disable(rx_info->rx, BNA_HARD_CLEANUP, bnad_cb_rx_disabled);
@@ -1952,6 +1960,8 @@ bnad_cleanup_rx(struct bnad *bnad, u32 rx_id)
 	if (rx_info->rx_ctrl[0].ccb->intr_type == BNA_INTR_T_MSIX)
 		bnad_rx_msix_unregister(bnad, rx_info, rx_config->num_paths);
 
+	bnad_napi_disable(bnad, rx_id);
+
 	spin_lock_irqsave(&bnad->bna_lock, flags);
 	bna_rx_destroy(rx_info->rx);
 	spin_unlock_irqrestore(&bnad->bna_lock, flags);
@@ -2005,6 +2015,8 @@ bnad_setup_rx(struct bnad *bnad, u32 rx_id)
 	if (err)
 		return err;
 
+	bnad_rx_ctrl_init(bnad, rx_id);
+
 	/* Ask BNA to create one Rx object, supplying required resources */
 	spin_lock_irqsave(&bnad->bna_lock, flags);
 	rx = bna_rx_create(&bnad->bna, bnad, rx_config, &rx_cbfn, res_info,
@@ -2014,6 +2026,9 @@ bnad_setup_rx(struct bnad *bnad, u32 rx_id)
 		goto err_return;
 	rx_info->rx = rx;
 
+	/* Enable NAPI */
+	bnad_napi_enable(bnad, rx_id);
+
 	/* Register ISR for the Rx object */
 	if (intr_info->intr_type == BNA_INTR_T_MSIX) {
 		err = bnad_rx_msix_register(bnad, rx_info, rx_id,
@@ -2022,9 +2037,6 @@ bnad_setup_rx(struct bnad *bnad, u32 rx_id)
 			goto err_return;
 	}
 
-	/* Enable NAPI */
-	bnad_napi_enable(bnad, rx_id);
-
 	spin_lock_irqsave(&bnad->bna_lock, flags);
 	if (0 == rx_id) {
 		/* Set up Dynamic Interrupt Moderation Vector */
@@ -2602,15 +2614,15 @@ static netdev_tx_t
 bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 {
 	struct bnad *bnad = netdev_priv(netdev);
-	u32 txq_id = 0;
-	struct bna_tcb *tcb = bnad->tx_info[0].tcb[txq_id];
+	struct bna_tcb *tcb = NULL;
+	u32 txq_id;
+	struct bnad_unmap_q *unmap_q;
 
 	u16		txq_prod, vlan_tag = 0;
 	u32		unmap_prod, wis, wis_used, wi_range;
 	u32		vectors, vect_id, i, acked;
 	int			err;
 
-	struct bnad_unmap_q *unmap_q = tcb->unmap_q;
 	dma_addr_t		dma_addr;
 	struct bna_txq_entry *txqent;
 	u16	flags;
@@ -2621,6 +2633,16 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 		return NETDEV_TX_OK;
 	}
 
+	txq_id = skb_get_queue_mapping(skb);
+
+	tcb = bnad->tx_info[0].tcb[txq_id];
+
+	if (unlikely(!tcb)) {
+		dev_kfree_skb(skb);
+		return NETDEV_TX_OK;
+	}
+
+	unmap_q = tcb->unmap_q;
 	/*
 	 * Takes care of the Tx that is scheduled between clearing the flag
 	 * and the netif_stop_all_queue() call.
diff --git a/drivers/net/bna/bnad.h b/drivers/net/bna/bnad.h
index 1b87b27..4f9da1c 100644
--- a/drivers/net/bna/bnad.h
+++ b/drivers/net/bna/bnad.h
@@ -51,6 +51,7 @@
  */
 struct bnad_rx_ctrl {
 	struct bna_ccb *ccb;
+	struct bnad *bnad;
 	unsigned long  flags;
 	struct napi_struct	napi;
 };
-- 
1.7.1


^ permalink raw reply related

* [PATCH 0/4] More work towards neigh-less dsts.
From: David Miller @ 2011-07-18  8:24 UTC (permalink / raw)
  To: netdev


This continues the effort to divorce neighbour from dst_entry as
much as possible.

When we remove the routing cache, route entries will be fully generic
and not specific to any particular keyed destination.  Therefore we'll
need to lookup neigh entries dynamically, and quickly, at packet
output time.

To that end, this series:

1) Passes an explicit neighbour to packet out neigh_ops.

2) Abstracts all dst->neighbour behind helpers to ease the
   transition process.

3) Adds a new dst_ops entry, ->neigh_lookup(), to provide a transition
   scheme for dst->neighbour uses outside of the packet output path.

The next set of patches after this one will deal with all of
the dst_get_neighbour() code paths, converting them over to
dst_neigh_lookup()/neigh_release() sequences.

Then there will be a little bit of fiddling around in decnet since
it's usage of dst->neighbour is still too tight in the packet output
path.

Finally, we can kill dst->neighbour and do RCU neigh lookups in the
packet output paths for all the protocols using the neighbour cache
(ipv4, ipv6, decnet).

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox