Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 1 Jul 2012 13:43:31 +0000 (UTC)
From:      Navdeep Parhar <np@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org
Subject:   svn commit: r237925 - in stable/9/sys: dev/cxgb dev/cxgbe dev/cxgbe/common dev/cxgbe/firmware dev/cxgbe/tom modules/cxgbe/if_cxgbe
Message-ID:  <201207011343.q61DhVuI005167@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: np
Date: Sun Jul  1 13:43:30 2012
New Revision: 237925
URL: http://svn.freebsd.org/changeset/base/237925

Log:
  MFC r237832, r237436, r237439, r237463, r237512, r237587, r237799,
  r237819, r237831.
  
  r237832:
  cxgb(4): IPv6 rx/tx hw checksum, IPv6 TSO and LRO too.
  
  r237436:
  cxgbe(4): update to firmware interface 1.5.2.0; updates to shared code.
  
  r237439:
  Do not read registers with read side effects while performing a register
  dump for cxgbetool.
  
  r237463:
  Do not allocate extra vectors when adapter is not TOE
  capable (or toecaps have been disallowed by the user).
  
  r237512:
  Better way to determine the status page length and rx pad boundary.
  
  r237587:
  Allow cxgbe(4) running within a VM to attach to its devices that have been
  exported via PCI passthrough.
  
  r237799:
  cxgbe(4): support for IPv6 hardware checksumming (rx and tx).
  
  r237819:
  cxgbe(4): support for IPv6 TSO and LRO.
  
  r237831:
  - Assign (don't OR) the CSUM_XXX bits to csum_flags in the rx checksum code.
  - Fix TSO/TSO4 mixup.
  - Add IFCAP_LINKSTATE to the available/enabled capabilities.

Modified:
  stable/9/sys/dev/cxgb/cxgb_adapter.h
  stable/9/sys/dev/cxgb/cxgb_main.c
  stable/9/sys/dev/cxgb/cxgb_sge.c
  stable/9/sys/dev/cxgbe/adapter.h
  stable/9/sys/dev/cxgbe/common/common.h
  stable/9/sys/dev/cxgbe/common/t4_hw.c
  stable/9/sys/dev/cxgbe/common/t4_msg.h
  stable/9/sys/dev/cxgbe/firmware/t4fw_cfg.txt
  stable/9/sys/dev/cxgbe/firmware/t4fw_cfg_uwire.txt
  stable/9/sys/dev/cxgbe/firmware/t4fw_interface.h
  stable/9/sys/dev/cxgbe/osdep.h
  stable/9/sys/dev/cxgbe/t4_l2t.c
  stable/9/sys/dev/cxgbe/t4_main.c
  stable/9/sys/dev/cxgbe/t4_sge.c
  stable/9/sys/dev/cxgbe/tom/t4_cpl_io.c
  stable/9/sys/modules/cxgbe/if_cxgbe/Makefile
Directory Properties:
  stable/9/sys/   (props changed)
  stable/9/sys/dev/   (props changed)
  stable/9/sys/modules/   (props changed)

Modified: stable/9/sys/dev/cxgb/cxgb_adapter.h
==============================================================================
--- stable/9/sys/dev/cxgb/cxgb_adapter.h	Sun Jul  1 12:59:00 2012	(r237924)
+++ stable/9/sys/dev/cxgb/cxgb_adapter.h	Sun Jul  1 13:43:30 2012	(r237925)
@@ -80,6 +80,15 @@ extern int cxgb_debug;
 #define MTX_DESTROY mtx_destroy
 #endif
 
+#ifndef IFCAP_HWCSUM_IPV6
+#define IFCAP_HWCSUM_IPV6 0
+#define CSUM_TCP_IPV6 0
+#define CSUM_UDP_IPV6 0
+#define IFCAP_TXCSUM_IPV6 0
+#define IFCAP_RXCSUM_IPV6 0
+#define CSUM_DATA_VALID_IPV6 0
+#endif
+
 enum {
 	LF_NO = 0,
 	LF_MAYBE,
@@ -264,15 +273,6 @@ struct sge_txq {
 	struct sg_ent  txq_sgl[TX_MAX_SEGS / 2 + 1];
 };
      	
-
-enum {
-	SGE_PSTAT_TSO,              /* # of TSO requests */
-	SGE_PSTAT_RX_CSUM_GOOD,     /* # of successful RX csum offloads */
-	SGE_PSTAT_TX_CSUM,          /* # of TX checksum offloads */
-	SGE_PSTAT_VLANEX,           /* # of VLAN tag extractions */
-	SGE_PSTAT_VLANINS,          /* # of VLAN tag insertions */
-};
-
 #define SGE_PSTAT_MAX (SGE_PSTAT_VLANINS+1)
 
 #define QS_EXITING              0x1
@@ -287,7 +287,6 @@ struct sge_qset {
 	struct lro_state        lro;
 	struct sge_txq		txq[SGE_TXQ_PER_SET];
 	uint32_t                txq_stopped;       /* which Tx queues are stopped */
-	uint64_t                port_stats[SGE_PSTAT_MAX];
 	struct port_info        *port;
 	struct adapter          *adap;
 	int                     idx; /* qset # */
@@ -537,7 +536,7 @@ int t3_sge_reset_adapter(adapter_t *);
 int t3_sge_init_port(struct port_info *);
 void t3_free_tx_desc(struct sge_qset *qs, int n, int qid);
 
-void t3_rx_eth(struct adapter *adap, struct sge_rspq *rq, struct mbuf *m, int ethpad);
+void t3_rx_eth(struct adapter *adap, struct mbuf *m, int ethpad);
 
 void t3_add_attach_sysctls(adapter_t *sc);
 void t3_add_configured_sysctls(adapter_t *sc);

Modified: stable/9/sys/dev/cxgb/cxgb_main.c
==============================================================================
--- stable/9/sys/dev/cxgb/cxgb_main.c	Sun Jul  1 12:59:00 2012	(r237924)
+++ stable/9/sys/dev/cxgb/cxgb_main.c	Sun Jul  1 13:43:30 2012	(r237925)
@@ -986,7 +986,7 @@ cxgb_makedev(struct port_info *pi)
 
 #define CXGB_CAP (IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU | IFCAP_HWCSUM | \
     IFCAP_VLAN_HWCSUM | IFCAP_TSO | IFCAP_JUMBO_MTU | IFCAP_LRO | \
-    IFCAP_VLAN_HWTSO | IFCAP_LINKSTATE)
+    IFCAP_VLAN_HWTSO | IFCAP_LINKSTATE | IFCAP_HWCSUM_IPV6)
 #define CXGB_CAP_ENABLE CXGB_CAP
 
 static int
@@ -1027,7 +1027,8 @@ cxgb_port_attach(device_t dev)
 		ifp->if_capabilities |= IFCAP_TOE4;
 #endif
 	ifp->if_capenable = CXGB_CAP_ENABLE;
-	ifp->if_hwassist = CSUM_TCP | CSUM_UDP | CSUM_IP | CSUM_TSO;
+	ifp->if_hwassist = CSUM_TCP | CSUM_UDP | CSUM_IP | CSUM_TSO |
+	    CSUM_UDP_IPV6 | CSUM_TCP_IPV6;
 
 	/*
 	 * Disable TSO on 4-port - it isn't supported by the firmware.
@@ -1950,31 +1951,52 @@ fail:
 			ifp->if_capenable ^= IFCAP_TXCSUM;
 			ifp->if_hwassist ^= (CSUM_TCP | CSUM_UDP | CSUM_IP);
 
-			if (IFCAP_TSO & ifp->if_capenable &&
+			if (IFCAP_TSO4 & ifp->if_capenable &&
 			    !(IFCAP_TXCSUM & ifp->if_capenable)) {
-				ifp->if_capenable &= ~IFCAP_TSO;
-				ifp->if_hwassist &= ~CSUM_TSO;
+				ifp->if_capenable &= ~IFCAP_TSO4;
 				if_printf(ifp,
-				    "tso disabled due to -txcsum.\n");
+				    "tso4 disabled due to -txcsum.\n");
+			}
+		}
+		if (mask & IFCAP_TXCSUM_IPV6) {
+			ifp->if_capenable ^= IFCAP_TXCSUM_IPV6;
+			ifp->if_hwassist ^= (CSUM_UDP_IPV6 | CSUM_TCP_IPV6);
+
+			if (IFCAP_TSO6 & ifp->if_capenable &&
+			    !(IFCAP_TXCSUM_IPV6 & ifp->if_capenable)) {
+				ifp->if_capenable &= ~IFCAP_TSO6;
+				if_printf(ifp,
+				    "tso6 disabled due to -txcsum6.\n");
 			}
 		}
 		if (mask & IFCAP_RXCSUM)
 			ifp->if_capenable ^= IFCAP_RXCSUM;
-		if (mask & IFCAP_TSO) {
-			ifp->if_capenable ^= IFCAP_TSO;
+		if (mask & IFCAP_RXCSUM_IPV6)
+			ifp->if_capenable ^= IFCAP_RXCSUM_IPV6;
 
-			if (IFCAP_TSO & ifp->if_capenable) {
-				if (IFCAP_TXCSUM & ifp->if_capenable)
-					ifp->if_hwassist |= CSUM_TSO;
-				else {
-					ifp->if_capenable &= ~IFCAP_TSO;
-					ifp->if_hwassist &= ~CSUM_TSO;
-					if_printf(ifp,
-					    "enable txcsum first.\n");
-					error = EAGAIN;
-				}
-			} else
-				ifp->if_hwassist &= ~CSUM_TSO;
+		/*
+		 * Note that we leave CSUM_TSO alone (it is always set).  The
+		 * kernel takes both IFCAP_TSOx and CSUM_TSO into account before
+		 * sending a TSO request our way, so it's sufficient to toggle
+		 * IFCAP_TSOx only.
+		 */
+		if (mask & IFCAP_TSO4) {
+			if (!(IFCAP_TSO4 & ifp->if_capenable) &&
+			    !(IFCAP_TXCSUM & ifp->if_capenable)) {
+				if_printf(ifp, "enable txcsum first.\n");
+				error = EAGAIN;
+				goto fail;
+			}
+			ifp->if_capenable ^= IFCAP_TSO4;
+		}
+		if (mask & IFCAP_TSO6) {
+			if (!(IFCAP_TSO6 & ifp->if_capenable) &&
+			    !(IFCAP_TXCSUM_IPV6 & ifp->if_capenable)) {
+				if_printf(ifp, "enable txcsum6 first.\n");
+				error = EAGAIN;
+				goto fail;
+			}
+			ifp->if_capenable ^= IFCAP_TSO6;
 		}
 		if (mask & IFCAP_LRO) {
 			ifp->if_capenable ^= IFCAP_LRO;

Modified: stable/9/sys/dev/cxgb/cxgb_sge.c
==============================================================================
--- stable/9/sys/dev/cxgb/cxgb_sge.c	Sun Jul  1 12:59:00 2012	(r237924)
+++ stable/9/sys/dev/cxgb/cxgb_sge.c	Sun Jul  1 13:43:30 2012	(r237925)
@@ -1432,7 +1432,8 @@ t3_encap(struct sge_qset *qs, struct mbu
 			cntrl |= V_TXPKT_OPCODE(CPL_TX_PKT);
 			if (__predict_false(!(cflags & CSUM_IP)))
 				cntrl |= F_TXPKT_IPCSUM_DIS;
-			if (__predict_false(!(cflags & (CSUM_TCP | CSUM_UDP))))
+			if (__predict_false(!(cflags & (CSUM_TCP | CSUM_UDP |
+			    CSUM_UDP_IPV6 | CSUM_TCP_IPV6))))
 				cntrl |= F_TXPKT_L4CSUM_DIS;
 
 			hflit[0] = htonl(cntrl);
@@ -1547,7 +1548,8 @@ t3_encap(struct sge_qset *qs, struct mbu
 		cntrl |= V_TXPKT_OPCODE(CPL_TX_PKT);
 		if (__predict_false(!(m0->m_pkthdr.csum_flags & CSUM_IP)))
 			cntrl |= F_TXPKT_IPCSUM_DIS;
-		if (__predict_false(!(m0->m_pkthdr.csum_flags & (CSUM_TCP | CSUM_UDP))))
+		if (__predict_false(!(m0->m_pkthdr.csum_flags & (CSUM_TCP |
+		    CSUM_UDP | CSUM_UDP_IPV6 | CSUM_TCP_IPV6))))
 			cntrl |= F_TXPKT_L4CSUM_DIS;
 		cpl->cntrl = htonl(cntrl);
 		cpl->len = htonl(mlen | 0x80000000);
@@ -2620,20 +2622,12 @@ err:	
  * will also be taken into account here.
  */
 void
-t3_rx_eth(struct adapter *adap, struct sge_rspq *rq, struct mbuf *m, int ethpad)
+t3_rx_eth(struct adapter *adap, struct mbuf *m, int ethpad)
 {
 	struct cpl_rx_pkt *cpl = (struct cpl_rx_pkt *)(mtod(m, uint8_t *) + ethpad);
 	struct port_info *pi = &adap->port[adap->rxpkt_map[cpl->iff]];
 	struct ifnet *ifp = pi->ifp;
 	
-	if ((ifp->if_capenable & IFCAP_RXCSUM) && !cpl->fragment &&
-	    cpl->csum_valid && cpl->csum == 0xffff) {
-		m->m_pkthdr.csum_flags = (CSUM_IP_CHECKED|CSUM_IP_VALID);
-		rspq_to_qset(rq)->port_stats[SGE_PSTAT_RX_CSUM_GOOD]++;
-		m->m_pkthdr.csum_flags = (CSUM_IP_CHECKED|CSUM_IP_VALID|CSUM_DATA_VALID|CSUM_PSEUDO_HDR);
-		m->m_pkthdr.csum_data = 0xffff;
-	}
-
 	if (cpl->vlan_valid) {
 		m->m_pkthdr.ether_vtag = ntohs(cpl->vlan);
 		m->m_flags |= M_VLANTAG;
@@ -2647,6 +2641,30 @@ t3_rx_eth(struct adapter *adap, struct s
 	m->m_pkthdr.len -= (sizeof(*cpl) + ethpad);
 	m->m_len -= (sizeof(*cpl) + ethpad);
 	m->m_data += (sizeof(*cpl) + ethpad);
+
+	if (!cpl->fragment && cpl->csum_valid && cpl->csum == 0xffff) {
+		struct ether_header *eh = mtod(m, void *);
+		uint16_t eh_type;
+
+		if (eh->ether_type == htons(ETHERTYPE_VLAN)) {
+			struct ether_vlan_header *evh = mtod(m, void *);
+
+			eh_type = evh->evl_proto;
+		} else
+			eh_type = eh->ether_type;
+
+		if (ifp->if_capenable & IFCAP_RXCSUM &&
+		    eh_type == htons(ETHERTYPE_IP)) {
+			m->m_pkthdr.csum_flags = (CSUM_IP_CHECKED |
+			    CSUM_IP_VALID | CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
+			m->m_pkthdr.csum_data = 0xffff;
+		} else if (ifp->if_capenable & IFCAP_RXCSUM_IPV6 &&
+		    eh_type == htons(ETHERTYPE_IPV6)) {
+			m->m_pkthdr.csum_flags = (CSUM_DATA_VALID_IPV6 |
+			    CSUM_PSEUDO_HDR);
+			m->m_pkthdr.csum_data = 0xffff;
+		}
+	}
 }
 
 /**
@@ -2913,7 +2931,7 @@ process_responses(adapter_t *adap, struc
 		} else if (eth && eop) {
 			struct mbuf *m = mh->mh_head;
 
-			t3_rx_eth(adap, rspq, m, ethpad);
+			t3_rx_eth(adap, m, ethpad);
 
 			/*
 			 * The T304 sends incoming packets on any qset.  If LRO

Modified: stable/9/sys/dev/cxgbe/adapter.h
==============================================================================
--- stable/9/sys/dev/cxgbe/adapter.h	Sun Jul  1 12:59:00 2012	(r237924)
+++ stable/9/sys/dev/cxgbe/adapter.h	Sun Jul  1 13:43:30 2012	(r237925)
@@ -56,6 +56,15 @@ MALLOC_DECLARE(M_CXGBE);
 #define CXGBE_UNIMPLEMENTED(s) \
     panic("%s (%s, line %d) not implemented yet.", s, __FILE__, __LINE__)
 
+#ifndef IFCAP_HWCSUM_IPV6
+#define IFCAP_HWCSUM_IPV6 0
+#define CSUM_TCP_IPV6 0
+#define CSUM_UDP_IPV6 0
+#define IFCAP_TXCSUM_IPV6 0
+#define IFCAP_RXCSUM_IPV6 0
+#define CSUM_DATA_VALID_IPV6 0
+#endif
+
 #if defined(__i386__) || defined(__amd64__)
 static __inline void
 prefetch(void *x)
@@ -391,7 +400,7 @@ struct sge_txq {
 	/* stats for common events first */
 
 	uint64_t txcsum;	/* # of times hardware assisted with checksum */
-	uint64_t tso_wrs;	/* # of IPv4 TSO work requests */
+	uint64_t tso_wrs;	/* # of TSO work requests */
 	uint64_t vlan_insertion;/* # of times VLAN tag was inserted */
 	uint64_t imm_wrs;	/* # of work requests with immediate data */
 	uint64_t sgl_wrs;	/* # of work requests with direct SGL */
@@ -411,7 +420,7 @@ struct sge_rxq {
 	struct sge_fl fl;	/* MUST follow iq */
 
 	struct ifnet *ifp;	/* the interface this rxq belongs to */
-#ifdef INET
+#if defined(INET) || defined(INET6)
 	struct lro_ctrl lro;	/* LRO state */
 #endif
 

Modified: stable/9/sys/dev/cxgbe/common/common.h
==============================================================================
--- stable/9/sys/dev/cxgbe/common/common.h	Sun Jul  1 12:59:00 2012	(r237924)
+++ stable/9/sys/dev/cxgbe/common/common.h	Sun Jul  1 13:43:30 2012	(r237925)
@@ -38,6 +38,8 @@ enum {
 	SERNUM_LEN     = 24,    /* Serial # length */
 	EC_LEN         = 16,    /* E/C length */
 	ID_LEN         = 16,    /* ID length */
+	PN_LEN         = 16,    /* Part Number length */
+	MACADDR_LEN    = 12,    /* MAC Address length */
 };
 
 enum { MEM_EDC0, MEM_EDC1, MEM_MC };
@@ -62,8 +64,8 @@ enum {
 };
 
 #define FW_VERSION_MAJOR 1
-#define FW_VERSION_MINOR 4
-#define FW_VERSION_MICRO 16
+#define FW_VERSION_MINOR 5
+#define FW_VERSION_MICRO 2
 
 struct port_stats {
 	u64 tx_octets;            /* total # of octets in good frames */
@@ -219,6 +221,8 @@ struct vpd_params {
 	u8 ec[EC_LEN + 1];
 	u8 sn[SERNUM_LEN + 1];
 	u8 id[ID_LEN + 1];
+	u8 pn[PN_LEN + 1];
+	u8 na[MACADDR_LEN + 1];
 };
 
 struct pci_params {
@@ -356,6 +360,8 @@ void t4_write_indirect(struct adapter *a
 		       unsigned int data_reg, const u32 *vals,
 		       unsigned int nregs, unsigned int start_idx);
 
+u32 t4_hw_pci_read_cfg4(adapter_t *adapter, int reg);
+
 struct fw_filter_wr;
 
 void t4_intr_enable(struct adapter *adapter);
@@ -374,7 +380,7 @@ int t4_seeprom_wp(struct adapter *adapte
 int t4_read_flash(struct adapter *adapter, unsigned int addr, unsigned int nwords,
 		  u32 *data, int byte_oriented);
 int t4_load_fw(struct adapter *adapter, const u8 *fw_data, unsigned int size);
-int t4_load_boot(struct adapter *adap, const u8 *boot_data,
+int t4_load_boot(struct adapter *adap, u8 *boot_data,
                  unsigned int boot_addr, unsigned int size);
 unsigned int t4_flash_cfg_addr(struct adapter *adapter);
 int t4_load_cfg(struct adapter *adapter, const u8 *cfg_data, unsigned int size);
@@ -431,6 +437,9 @@ int t4_mem_read(struct adapter *adap, in
 		__be32 *data);
 
 void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p);
+void t4_get_port_stats_offset(struct adapter *adap, int idx,
+		struct port_stats *stats,
+		struct port_stats *offset);
 void t4_get_lb_stats(struct adapter *adap, int idx, struct lb_port_stats *p);
 void t4_clr_port_stats(struct adapter *adap, int idx);
 
@@ -472,6 +481,10 @@ int t4_fw_hello(struct adapter *adap, un
 		enum dev_master master, enum dev_state *state);
 int t4_fw_bye(struct adapter *adap, unsigned int mbox);
 int t4_fw_reset(struct adapter *adap, unsigned int mbox, int reset);
+int t4_fw_halt(struct adapter *adap, unsigned int mbox, int force);
+int t4_fw_restart(struct adapter *adap, unsigned int mbox, int reset);
+int t4_fw_upgrade(struct adapter *adap, unsigned int mbox,
+		  const u8 *fw_data, unsigned int size, int force);
 int t4_fw_initialize(struct adapter *adap, unsigned int mbox);
 int t4_query_params(struct adapter *adap, unsigned int mbox, unsigned int pf,
 		    unsigned int vf, unsigned int nparams, const u32 *params,
@@ -484,6 +497,10 @@ int t4_cfg_pfvf(struct adapter *adap, un
 		unsigned int rxqi, unsigned int rxq, unsigned int tc,
 		unsigned int vi, unsigned int cmask, unsigned int pmask,
 		unsigned int exactf, unsigned int rcaps, unsigned int wxcaps);
+int t4_alloc_vi_func(struct adapter *adap, unsigned int mbox,
+		     unsigned int port, unsigned int pf, unsigned int vf,
+		     unsigned int nmac, u8 *mac, unsigned int *rss_size,
+		     unsigned int portfunc, unsigned int idstype);
 int t4_alloc_vi(struct adapter *adap, unsigned int mbox, unsigned int port,
 		unsigned int pf, unsigned int vf, unsigned int nmac, u8 *mac,
 		unsigned int *rss_size);
@@ -524,5 +541,10 @@ int t4_sge_ctxt_rd(struct adapter *adap,
 		   enum ctxt_type ctype, u32 *data);
 int t4_sge_ctxt_rd_bd(struct adapter *adap, unsigned int cid, enum ctxt_type ctype,
 		      u32 *data);
+int t4_sge_ctxt_flush(struct adapter *adap, unsigned int mbox);
 int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl);
+int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox, u32 addr, u32 val);
+int t4_config_scheduler(struct adapter *adapter, int mode, int level, int pktsize,
+                        int sched_class, int port, int rate, int unit,
+			int weight, int minrate, int maxrate);
 #endif /* __CHELSIO_COMMON_H */

Modified: stable/9/sys/dev/cxgbe/common/t4_hw.c
==============================================================================
--- stable/9/sys/dev/cxgbe/common/t4_hw.c	Sun Jul  1 12:59:00 2012	(r237924)
+++ stable/9/sys/dev/cxgbe/common/t4_hw.c	Sun Jul  1 13:43:30 2012	(r237925)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2011 Chelsio Communications, Inc.
+ * Copyright (c) 2012 Chelsio Communications, Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -135,6 +135,20 @@ void t4_write_indirect(struct adapter *a
 }
 
 /*
+ * Read a 32-bit PCI Configuration Space register via the PCI-E backdoor
+ * mechanism.  This guarantees that we get the real value even if we're
+ * operating within a Virtual Machine and the Hypervisor is trapping our
+ * Configuration Space accesses.
+ */
+u32 t4_hw_pci_read_cfg4(adapter_t *adap, int reg)
+{
+	t4_write_reg(adap, A_PCIE_CFG_SPACE_REQ,
+		     F_ENABLE | F_LOCALCFG | V_FUNCTION(adap->pf) |
+		     V_REGISTER(reg));
+	return t4_read_reg(adap, A_PCIE_CFG_SPACE_DATA);
+}
+
+/*
  * Get the reply to a mailbox command and store it in @rpl in big-endian order.
  */
 static void get_mbox_rpl(struct adapter *adap, __be64 *rpl, int nflit,
@@ -196,7 +210,6 @@ int t4_wr_mbox_meat(struct adapter *adap
 	u64 res;
 	int i, ms, delay_idx;
 	const __be64 *p = cmd;
-
 	u32 data_reg = PF_REG(mbox, A_CIM_PF_MAILBOX_DATA);
 	u32 ctl_reg = PF_REG(mbox, A_CIM_PF_MAILBOX_CTRL);
 
@@ -283,7 +296,7 @@ int t4_mc_read(struct adapter *adap, u32
 #define MC_DATA(i) MC_BIST_STATUS_REG(A_MC_BIST_STATUS_RDATA, i)
 
 	for (i = 15; i >= 0; i--)
-		*data++ = htonl(t4_read_reg(adap, MC_DATA(i)));
+		*data++ = ntohl(t4_read_reg(adap, MC_DATA(i)));
 	if (ecc)
 		*ecc = t4_read_reg64(adap, MC_DATA(16));
 #undef MC_DATA
@@ -321,7 +334,7 @@ int t4_edc_read(struct adapter *adap, in
 #define EDC_DATA(i) (EDC_BIST_STATUS_REG(A_EDC_BIST_STATUS_RDATA, i) + idx)
 
 	for (i = 15; i >= 0; i--)
-		*data++ = htonl(t4_read_reg(adap, EDC_DATA(i)));
+		*data++ = ntohl(t4_read_reg(adap, EDC_DATA(i)));
 	if (ecc)
 		*ecc = t4_read_reg64(adap, EDC_DATA(16));
 #undef EDC_DATA
@@ -566,7 +579,7 @@ static int get_vpd_keyword_val(const str
 static int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
 {
 	int i, ret, addr;
-	int ec, sn;
+	int ec, sn, pn, na;
 	u8 vpd[VPD_LEN], csum;
 	const struct t4_vpd_hdr *v;
 
@@ -602,6 +615,8 @@ static int get_vpd_params(struct adapter
 	}
 	FIND_VPD_KW(ec, "EC");
 	FIND_VPD_KW(sn, "SN");
+	FIND_VPD_KW(pn, "PN");
+	FIND_VPD_KW(na, "NA");
 #undef FIND_VPD_KW
 
 	memcpy(p->id, v->id_data, ID_LEN);
@@ -611,6 +626,10 @@ static int get_vpd_params(struct adapter
 	i = vpd[sn - VPD_INFO_FLD_HDR_SIZE + 2];
 	memcpy(p->sn, vpd + sn, min(i, SERNUM_LEN));
 	strstrip(p->sn);
+	memcpy(p->pn, vpd + pn, min(i, PN_LEN));
+	strstrip((char *)p->pn);
+	memcpy(p->na, vpd + na, min(i, MACADDR_LEN));
+	strstrip((char *)p->na);
 
 	return 0;
 }
@@ -954,7 +973,7 @@ int t4_load_cfg(struct adapter *adap, co
 	if (ret || size == 0)
 		goto out;
 
-        /* this will write to the flash up to SF_PAGE_SIZE at a time */
+	/* this will write to the flash up to SF_PAGE_SIZE at a time */
 	for (i = 0; i< size; i+= SF_PAGE_SIZE) {
 		if ( (size - i) <  SF_PAGE_SIZE) 
 			n = size - i;
@@ -1056,42 +1075,209 @@ out:
 	return ret;
 }
 
-/* BIOS boot header */
-typedef struct boot_header_s {
-	u8	signature[2];	/* signature */
-	u8	length;		/* image length (include header) */
-	u8	offset[4];	/* initialization vector */
-	u8	reserved[19];	/* reserved */
-	u8	exheader[2];	/* offset to expansion header */
-} boot_header_t;
+/* BIOS boot headers */
+typedef struct pci_expansion_rom_header {
+	u8	signature[2]; /* ROM Signature. Should be 0xaa55 */
+	u8	reserved[22]; /* Reserved per processor Architecture data */
+	u8	pcir_offset[2]; /* Offset to PCI Data Structure */
+} pci_exp_rom_header_t; /* PCI_EXPANSION_ROM_HEADER */
+
+/* Legacy PCI Expansion ROM Header */
+typedef struct legacy_pci_expansion_rom_header {
+	u8	signature[2]; /* ROM Signature. Should be 0xaa55 */
+	u8	size512; /* Current Image Size in units of 512 bytes */
+	u8	initentry_point[4];
+	u8	cksum; /* Checksum computed on the entire Image */
+	u8	reserved[16]; /* Reserved */
+	u8	pcir_offset[2]; /* Offset to PCI Data Struture */
+} legacy_pci_exp_rom_header_t; /* LEGACY_PCI_EXPANSION_ROM_HEADER */
+
+/* EFI PCI Expansion ROM Header */
+typedef struct efi_pci_expansion_rom_header {
+	u8	signature[2]; // ROM signature. The value 0xaa55
+	u8	initialization_size[2]; /* Units 512. Includes this header */
+	u8	efi_signature[4]; /* Signature from EFI image header. 0x0EF1 */
+	u8	efi_subsystem[2]; /* Subsystem value for EFI image header */
+	u8	efi_machine_type[2]; /* Machine type from EFI image header */
+	u8	compression_type[2]; /* Compression type. */
+		/* 
+		 * Compression type definition
+		 * 0x0: uncompressed
+		 * 0x1: Compressed
+		 * 0x2-0xFFFF: Reserved
+		 */
+	u8	reserved[8]; /* Reserved */
+	u8	efi_image_header_offset[2]; /* Offset to EFI Image */
+	u8	pcir_offset[2]; /* Offset to PCI Data Structure */
+} efi_pci_exp_rom_header_t; /* EFI PCI Expansion ROM Header */
+
+/* PCI Data Structure Format */
+typedef struct pcir_data_structure { /* PCI Data Structure */
+	u8	signature[4]; /* Signature. The string "PCIR" */
+	u8	vendor_id[2]; /* Vendor Identification */
+	u8	device_id[2]; /* Device Identification */
+	u8	vital_product[2]; /* Pointer to Vital Product Data */
+	u8	length[2]; /* PCIR Data Structure Length */
+	u8	revision; /* PCIR Data Structure Revision */
+	u8	class_code[3]; /* Class Code */
+	u8	image_length[2]; /* Image Length. Multiple of 512B */
+	u8	code_revision[2]; /* Revision Level of Code/Data */
+	u8	code_type; /* Code Type. */
+		/*
+		 * PCI Expansion ROM Code Types
+		 * 0x00: Intel IA-32, PC-AT compatible. Legacy
+		 * 0x01: Open Firmware standard for PCI. FCODE
+		 * 0x02: Hewlett-Packard PA RISC. HP reserved
+		 * 0x03: EFI Image. EFI
+		 * 0x04-0xFF: Reserved.
+		 */
+	u8	indicator; /* Indicator. Identifies the last image in the ROM */
+	u8	reserved[2]; /* Reserved */
+} pcir_data_t; /* PCI__DATA_STRUCTURE */
 
+/* BOOT constants */
 enum {
 	BOOT_FLASH_BOOT_ADDR = 0x0,/* start address of boot image in flash */
 	BOOT_SIGNATURE = 0xaa55,   /* signature of BIOS boot ROM */
 	BOOT_SIZE_INC = 512,       /* image size measured in 512B chunks */
-	BOOT_MIN_SIZE = sizeof(boot_header_t), /* at least basic header */
-	BOOT_MAX_SIZE = 1024*BOOT_SIZE_INC /* 1 byte * length increment  */
+	BOOT_MIN_SIZE = sizeof(pci_exp_rom_header_t), /* basic header */
+	BOOT_MAX_SIZE = 1024*BOOT_SIZE_INC, /* 1 byte * length increment  */
+	VENDOR_ID = 0x1425, /* Vendor ID */
+	PCIR_SIGNATURE = 0x52494350 /* PCIR signature */
 };
 
 /*
+ *	modify_device_id - Modifies the device ID of the Boot BIOS image 
+ *	@adatper: the device ID to write.
+ *	@boot_data: the boot image to modify.
+ *
+ *	Write the supplied device ID to the boot BIOS image.
+ */
+static void modify_device_id(int device_id, u8 *boot_data)
+{
+	legacy_pci_exp_rom_header_t *header;
+	pcir_data_t *pcir_header;
+	u32 cur_header = 0;
+
+	/*
+	 * Loop through all chained images and change the device ID's
+	 */
+	while (1) {
+		header = (legacy_pci_exp_rom_header_t *) &boot_data[cur_header];
+		pcir_header = (pcir_data_t *) &boot_data[cur_header +
+		    le16_to_cpu(*(u16*)header->pcir_offset)];
+
+		/*
+		 * Only modify the Device ID if code type is Legacy or HP.
+		 * 0x00: Okay to modify
+		 * 0x01: FCODE. Do not be modify
+		 * 0x03: Okay to modify
+		 * 0x04-0xFF: Do not modify
+		 */
+		if (pcir_header->code_type == 0x00) {
+			u8 csum = 0;
+			int i;
+
+			/*
+			 * Modify Device ID to match current adatper
+			 */
+			*(u16*) pcir_header->device_id = device_id;
+
+			/*
+			 * Set checksum temporarily to 0.
+			 * We will recalculate it later.
+			 */
+			header->cksum = 0x0;
+
+			/*
+			 * Calculate and update checksum
+			 */
+			for (i = 0; i < (header->size512 * 512); i++)
+				csum += (u8)boot_data[cur_header + i];
+
+			/*
+			 * Invert summed value to create the checksum
+			 * Writing new checksum value directly to the boot data
+			 */
+			boot_data[cur_header + 7] = -csum;
+
+		} else if (pcir_header->code_type == 0x03) {
+
+			/*
+			 * Modify Device ID to match current adatper
+			 */
+			*(u16*) pcir_header->device_id = device_id;
+
+		}
+
+
+		/*
+		 * Check indicator element to identify if this is the last
+		 * image in the ROM.
+		 */
+		if (pcir_header->indicator & 0x80)
+			break;
+
+		/*
+		 * Move header pointer up to the next image in the ROM.
+		 */
+		cur_header += header->size512 * 512;
+	}
+}
+
+/*
  *	t4_load_boot - download boot flash
  *	@adapter: the adapter
  *	@boot_data: the boot image to write
+ *	@boot_addr: offset in flash to write boot_data
  *	@size: image size
  *
  *	Write the supplied boot image to the card's serial flash.
  *	The boot image has the following sections: a 28-byte header and the
  *	boot image.
  */
-int t4_load_boot(struct adapter *adap, const u8 *boot_data, 
+int t4_load_boot(struct adapter *adap, u8 *boot_data, 
 		 unsigned int boot_addr, unsigned int size)
 {
+	pci_exp_rom_header_t *header;
+	int pcir_offset ;
+	pcir_data_t *pcir_header;
 	int ret, addr;
+	uint16_t device_id;
 	unsigned int i;
 	unsigned int boot_sector = boot_addr * 1024;
 	unsigned int sf_sec_size = adap->params.sf_size / adap->params.sf_nsec;
 
 	/*
+	 * Make sure the boot image does not encroach on the firmware region
+	 */
+	if ((boot_sector + size) >> 16 > FLASH_FW_START_SEC) {
+		CH_ERR(adap, "boot image encroaching on firmware region\n");
+		return -EFBIG;
+	}
+
+	/*
+	 * Number of sectors spanned
+	 */
+	i = DIV_ROUND_UP(size ? size : FLASH_BOOTCFG_MAX_SIZE,
+			sf_sec_size);
+	ret = t4_flash_erase_sectors(adap, boot_sector >> 16,
+				     (boot_sector >> 16) + i - 1);
+
+	/*
+	 * If size == 0 then we're simply erasing the FLASH sectors associated
+	 * with the on-adapter option ROM file
+	 */
+	if (ret || (size == 0))
+		goto out;
+
+	/* Get boot header */
+	header = (pci_exp_rom_header_t *)boot_data;
+	pcir_offset = le16_to_cpu(*(u16 *)header->pcir_offset);
+	/* PCIR Data Structure */
+	pcir_header = (pcir_data_t *) &boot_data[pcir_offset];
+
+	/*
 	 * Perform some primitive sanity testing to avoid accidentally
 	 * writing garbage over the boot sectors.  We ought to check for
 	 * more but it's not worth it for now ...
@@ -1102,18 +1288,46 @@ int t4_load_boot(struct adapter *adap, c
 	}
 
 	/*
-	 * Make sure the boot image does not encroach on the firmware region
+	 * Check BOOT ROM header signature
 	 */
-	if ((boot_sector + size) >> 16 > FLASH_FW_START_SEC) {
-		CH_ERR(adap, "boot image encroaching on firmware region\n");
-		return -EFBIG;
+	if (le16_to_cpu(*(u16*)header->signature) != BOOT_SIGNATURE ) {
+		CH_ERR(adap, "Boot image missing signature\n");
+		return -EINVAL;
 	}
 
-	i = DIV_ROUND_UP(size, sf_sec_size);        /* # of sectors spanned */
-	ret = t4_flash_erase_sectors(adap, boot_sector >> 16, 
-				     (boot_sector >> 16) + i - 1);
-	if (ret)
-		goto out;
+	/*
+	 * Check PCI header signature
+	 */
+	if (le32_to_cpu(*(u32*)pcir_header->signature) != PCIR_SIGNATURE) {
+		CH_ERR(adap, "PCI header missing signature\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Check Vendor ID matches Chelsio ID
+	 */
+	if (le16_to_cpu(*(u16*)pcir_header->vendor_id) != VENDOR_ID) {
+		CH_ERR(adap, "Vendor ID missing signature\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Retrieve adapter's device ID
+	 */
+	t4_os_pci_read_cfg2(adap, PCI_DEVICE_ID, &device_id);
+	/* Want to deal with PF 0 so I strip off PF 4 indicator */
+	device_id = (device_id & 0xff) | 0x4000;
+
+	/*
+	 * Check PCIE Device ID
+	 */
+	if (le16_to_cpu(*(u16*)pcir_header->device_id) != device_id) {
+		/*
+		 * Change the device ID in the Boot BIOS image to match
+		 * the Device ID of the current adapter.
+		 */
+		modify_device_id(device_id, boot_data);
+	}
 
 	/*
 	 * Skip over the first SF_PAGE_SIZE worth of data and write it after
@@ -3206,7 +3420,11 @@ void t4_get_chan_txrate(struct adapter *
  *	@enable: whether to enable or disable the filter
  *
  *	Configures one of the tracing filters available in HW.  If @enable is
- *	%0 @tp is not examined and may be %NULL.
+ *	%0 @tp is not examined and may be %NULL. The user is responsible to
+ *	set the single/multiple trace mode by writing to A_MPS_TRC_CFG register
+ *	by using "cxgbtool iface reg reg_addr=val" command. See t4_sniffer/
+ *	docs/readme.txt for a complete description of how to setup traceing on
+ *	T4.
  */
 int t4_set_trace_filter(struct adapter *adap, const struct trace_params *tp, int idx,
 			int enable)
@@ -3217,45 +3435,45 @@ int t4_set_trace_filter(struct adapter *
 
 	if (!enable) {
 		t4_write_reg(adap, A_MPS_TRC_FILTER_MATCH_CTL_A + ofst, 0);
-		goto out;
+		return 0;
 	}
 
-	if (tp->port > 11 || tp->invert > 1 || tp->skip_len > M_TFLENGTH ||
-	    tp->skip_ofst > M_TFOFFSET || tp->min_len > M_TFMINPKTSIZE ||
-	    tp->snap_len > 9600 || (idx && tp->snap_len > 256))
-		return -EINVAL;
-
-	if (tp->snap_len > 256) {            /* must be tracer 0 */
-		if ((t4_read_reg(adap, A_MPS_TRC_FILTER_MATCH_CTL_A + 4) |
-		     t4_read_reg(adap, A_MPS_TRC_FILTER_MATCH_CTL_A + 8) |
-		     t4_read_reg(adap, A_MPS_TRC_FILTER_MATCH_CTL_A + 12)) &
-		    F_TFEN)
-			return -EINVAL;  /* other tracers are enabled */
+	/*
+	 * TODO - After T4 data book is updated, specify the exact
+	 * section below.
+	 *
+	 * See T4 data book - MPS section for a complete description 
+	 * of the below if..else handling of A_MPS_TRC_CFG register 
+	 * value.
+	 */ 
+	cfg = t4_read_reg(adap, A_MPS_TRC_CFG);
+	if (cfg & F_TRCMULTIFILTER) {
+		/*
+		 * If multiple tracers are enabled, then maximum
+		 * capture size is 2.5KB (FIFO size of a single channel)
+		 * minus 2 flits for CPL_TRACE_PKT header.
+		 */
+		if (tp->snap_len > ((10 * 1024 / 4) - (2 * 8)))
+			return -EINVAL;		
+	}
+	else {
+		/*
+		 * If multiple tracers are disabled, to avoid deadlocks 
+		 * maximum packet capture size of 9600 bytes is recommended.
+		 * Also in this mode, only trace0 can be enabled and running.
+		 */
 		multitrc = 0;
-	} else if (idx) {
-		i = t4_read_reg(adap, A_MPS_TRC_FILTER_MATCH_CTL_B);
-		if (G_TFCAPTUREMAX(i) > 256 &&
-		    (t4_read_reg(adap, A_MPS_TRC_FILTER_MATCH_CTL_A) & F_TFEN))
+		if (tp->snap_len > 9600 || idx)
 			return -EINVAL;
 	}
 
+	if (tp->port > 11 || tp->invert > 1 || tp->skip_len > M_TFLENGTH ||
+	    tp->skip_ofst > M_TFOFFSET || tp->min_len > M_TFMINPKTSIZE)
+		return -EINVAL;
+
 	/* stop the tracer we'll be changing */
 	t4_write_reg(adap, A_MPS_TRC_FILTER_MATCH_CTL_A + ofst, 0);
 
-	/* disable tracing globally if running in the wrong single/multi mode */
-	cfg = t4_read_reg(adap, A_MPS_TRC_CFG);
-	if ((cfg & F_TRCEN) && multitrc != (cfg & F_TRCMULTIFILTER)) {
-		t4_write_reg(adap, A_MPS_TRC_CFG, cfg ^ F_TRCEN);
-		t4_read_reg(adap, A_MPS_TRC_CFG);                  /* flush */
-		msleep(1);
-		if (!(t4_read_reg(adap, A_MPS_TRC_CFG) & F_TRCFIFOEMPTY))
-			return -ETIMEDOUT;
-	}
-	/*
-	 * At this point either the tracing is enabled and in the right mode or
-	 * disabled.
-	 */
-
 	idx *= (A_MPS_TRC_FILTER1_MATCH - A_MPS_TRC_FILTER0_MATCH);
 	data_reg = A_MPS_TRC_FILTER0_MATCH + idx;
 	mask_reg = A_MPS_TRC_FILTER0_DONT_CARE + idx;
@@ -3271,9 +3489,6 @@ int t4_set_trace_filter(struct adapter *
 		     V_TFOFFSET(tp->skip_ofst) | V_TFLENGTH(tp->skip_len) |
 		     V_TFPORT(tp->port) | F_TFEN | V_TFINVERTMATCH(tp->invert));
 
-	cfg &= ~F_TRCMULTIFILTER;
-	t4_write_reg(adap, A_MPS_TRC_CFG, cfg | F_TRCEN | multitrc);
-out:	t4_read_reg(adap, A_MPS_TRC_CFG);  /* flush */
 	return 0;
 }
 
@@ -3373,6 +3588,28 @@ static unsigned int get_mps_bg_map(struc
 }
 
 /**
+ *      t4_get_port_stats_offset - collect port stats relative to a previous
+ *                                 snapshot
+ *      @adap: The adapter
+ *      @idx: The port
+ *      @stats: Current stats to fill
+ *      @offset: Previous stats snapshot
+ */
+void t4_get_port_stats_offset(struct adapter *adap, int idx,
+		struct port_stats *stats,
+		struct port_stats *offset)
+{
+	u64 *s, *o;
+	int i;
+
+	t4_get_port_stats(adap, idx, stats);
+	for (i = 0, s = (u64 *)stats, o = (u64 *)offset ;
+			i < (sizeof(struct port_stats)/sizeof(u64)) ;
+			i++, s++, o++)
+		*s -= *o;
+}
+
+/**
  *	t4_get_port_stats - collect port statistics
  *	@adap: the adapter
  *	@idx: the port index
@@ -3633,6 +3870,20 @@ void t4_mk_filtdelwr(unsigned int ftid, 
 	(var).retval_len16 = htonl(FW_LEN16(var)); \
 } while (0)
 
+int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox, u32 addr, u32 val)
+{
+	struct fw_ldst_cmd c;
+
+	memset(&c, 0, sizeof(c));
+	c.op_to_addrspace = htonl(V_FW_CMD_OP(FW_LDST_CMD) | F_FW_CMD_REQUEST |
+		F_FW_CMD_WRITE | V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_FIRMWARE));
+	c.cycles_to_len16 = htonl(FW_LEN16(c));
+	c.u.addrval.addr = htonl(addr);
+	c.u.addrval.val = htonl(val);
+
+	return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
+}
+
 /**
  *	t4_mdio_rd - read a PHY register through MDIO
  *	@adap: the adapter
@@ -3693,6 +3944,30 @@ int t4_mdio_wr(struct adapter *adap, uns
 }
 
 /**
+ *	t4_sge_ctxt_flush - flush the SGE context cache
+ *	@adap: the adapter
+ *	@mbox: mailbox to use for the FW command
+ *
+ *	Issues a FW command through the given mailbox to flush the
+ *	SGE context cache.
+ */
+int t4_sge_ctxt_flush(struct adapter *adap, unsigned int mbox)
+{
+	int ret;
+	struct fw_ldst_cmd c;
+
+	memset(&c, 0, sizeof(c));
+	c.op_to_addrspace = htonl(V_FW_CMD_OP(FW_LDST_CMD) | F_FW_CMD_REQUEST |
+			F_FW_CMD_READ |
+			V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_SGE_EGRC));
+	c.cycles_to_len16 = htonl(FW_LEN16(c));
+	c.u.idctxt.msg_ctxtflush = htonl(F_FW_LDST_CMD_CTXTFLUSH);
+
+	ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
+	return ret;
+}
+
+/**
  *	t4_sge_ctxt_rd - read an SGE context through FW
  *	@adap: the adapter
  *	@mbox: mailbox to use for the FW command
@@ -3764,9 +4039,10 @@ int t4_sge_ctxt_rd_bd(struct adapter *ad
  *	@mbox: mailbox to use for the FW command
  *	@evt_mbox: mailbox to receive async FW events
  *	@master: specifies the caller's willingness to be the device master
- *	@state: returns the current device state
+ *	@state: returns the current device state (if non-NULL)
  *
- *	Issues a command to establish communication with FW.
+ *	Issues a command to establish communication with FW.  Returns either
+ *	an error (negative integer) or the mailbox of the Master PF.
  */
 int t4_fw_hello(struct adapter *adap, unsigned int mbox, unsigned int evt_mbox,
 		enum dev_master master, enum dev_state *state)
@@ -3918,6 +4194,175 @@ int t4_fw_reset(struct adapter *adap, un
 }
 
 /**
+ *	t4_fw_halt - issue a reset/halt to FW and put uP into RESET
+ *	@adap: the adapter
+ *	@mbox: mailbox to use for the FW RESET command (if desired)
+ *	@force: force uP into RESET even if FW RESET command fails
+ *
+ *	Issues a RESET command to firmware (if desired) with a HALT indication
+ *	and then puts the microprocessor into RESET state.  The RESET command
+ *	will only be issued if a legitimate mailbox is provided (mbox <=
+ *	M_PCIE_FW_MASTER).
+ *
+ *	This is generally used in order for the host to safely manipulate the
+ *	adapter without fear of conflicting with whatever the firmware might
+ *	be doing.  The only way out of this state is to RESTART the firmware
+ *	...
+ */
+int t4_fw_halt(struct adapter *adap, unsigned int mbox, int force)
+{
+	int ret = 0;
+
+	/*
+	 * If a legitimate mailbox is provided, issue a RESET command
+	 * with a HALT indication.
+	 */
+	if (mbox <= M_PCIE_FW_MASTER) {
+		struct fw_reset_cmd c;
+
+		memset(&c, 0, sizeof(c));
+		INIT_CMD(c, RESET, WRITE);
+		c.val = htonl(F_PIORST | F_PIORSTMODE);
+		c.halt_pkd = htonl(F_FW_RESET_CMD_HALT);
+		ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
+	}
+
+	/*
+	 * Normally we won't complete the operation if the firmware RESET
+	 * command fails but if our caller insists we'll go ahead and put the
+	 * uP into RESET.  This can be useful if the firmware is hung or even
+	 * missing ...  We'll have to take the risk of putting the uP into
+	 * RESET without the cooperation of firmware in that case.
+	 *
+	 * We also force the firmware's HALT flag to be on in case we bypassed
+	 * the firmware RESET command above or we're dealing with old firmware
+	 * which doesn't have the HALT capability.  This will serve as a flag
+	 * for the incoming firmware to know that it's coming out of a HALT
+	 * rather than a RESET ... if it's new enough to understand that ...
+	 */
+	if (ret == 0 || force) {
+		t4_set_reg_field(adap, A_CIM_BOOT_CFG, F_UPCRST, F_UPCRST);
+		t4_set_reg_field(adap, A_PCIE_FW, F_PCIE_FW_HALT, F_PCIE_FW_HALT);
+	}
+
+	/*
+	 * And we always return the result of the firmware RESET command
+	 * even when we force the uP into RESET ...
+	 */
+	return ret;
+}
+
+/**
+ *	t4_fw_restart - restart the firmware by taking the uP out of RESET
+ *	@adap: the adapter
+ *	@reset: if we want to do a RESET to restart things
+ *
+ *	Restart firmware previously halted by t4_fw_halt().  On successful
+ *	return the previous PF Master remains as the new PF Master and there
+ *	is no need to issue a new HELLO command, etc.
+ *
+ *	We do this in two ways:
+ *
+ *	 1. If we're dealing with newer firmware we'll simply want to take
+ *	    the chip's microprocessor out of RESET.  This will cause the
+ *	    firmware to start up from its start vector.  And then we'll loop
+ *	    until the firmware indicates it's started again (PCIE_FW.HALT
+ *	    reset to 0) or we timeout.
+ *
+ *	 2. If we're dealing with older firmware then we'll need to RESET
+ *	    the chip since older firmware won't recognize the PCIE_FW.HALT

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201207011343.q61DhVuI005167>