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>