From owner-svn-src-head@FreeBSD.ORG Fri Jun 22 07:51:15 2012 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id A39181065676; Fri, 22 Jun 2012 07:51:15 +0000 (UTC) (envelope-from np@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 8BD818FC21; Fri, 22 Jun 2012 07:51:15 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q5M7pFEw064767; Fri, 22 Jun 2012 07:51:15 GMT (envelope-from np@svn.freebsd.org) Received: (from np@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q5M7pF0k064763; Fri, 22 Jun 2012 07:51:15 GMT (envelope-from np@svn.freebsd.org) Message-Id: <201206220751.q5M7pF0k064763@svn.freebsd.org> From: Navdeep Parhar Date: Fri, 22 Jun 2012 07:51:15 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r237436 - in head/sys/dev/cxgbe: . common firmware tom X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 22 Jun 2012 07:51:15 -0000 Author: np Date: Fri Jun 22 07:51:15 2012 New Revision: 237436 URL: http://svn.freebsd.org/changeset/base/237436 Log: cxgbe(4): update to firmware interface 1.5.2.0; updates to shared code. Modified: head/sys/dev/cxgbe/common/common.h head/sys/dev/cxgbe/common/t4_hw.c head/sys/dev/cxgbe/common/t4_msg.h head/sys/dev/cxgbe/firmware/t4fw_cfg.txt head/sys/dev/cxgbe/firmware/t4fw_cfg_uwire.txt head/sys/dev/cxgbe/firmware/t4fw_interface.h head/sys/dev/cxgbe/osdep.h head/sys/dev/cxgbe/t4_sge.c head/sys/dev/cxgbe/tom/t4_cpl_io.c Modified: head/sys/dev/cxgbe/common/common.h ============================================================================== --- head/sys/dev/cxgbe/common/common.h Fri Jun 22 07:16:29 2012 (r237435) +++ head/sys/dev/cxgbe/common/common.h Fri Jun 22 07:51:15 2012 (r237436) @@ -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: head/sys/dev/cxgbe/common/t4_hw.c ============================================================================== --- head/sys/dev/cxgbe/common/t4_hw.c Fri Jun 22 07:16:29 2012 (r237435) +++ head/sys/dev/cxgbe/common/t4_hw.c Fri Jun 22 07:51:15 2012 (r237436) @@ -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 + * flag and automatically RESET itself on startup. + */ +int t4_fw_restart(struct adapter *adap, unsigned int mbox, int reset) +{ + if (reset) { + /* + * Since we're directing the RESET instead of the firmware + * doing it automatically, we need to clear the PCIE_FW.HALT + * bit. + */ + t4_set_reg_field(adap, A_PCIE_FW, F_PCIE_FW_HALT, 0); + + /* + * If we've been given a valid mailbox, first try to get the + * firmware to do the RESET. If that works, great and we can + * return success. Otherwise, if we haven't been given a + * valid mailbox or the RESET command failed, fall back to + * hitting the chip with a hammer. + */ + if (mbox <= M_PCIE_FW_MASTER) { + t4_set_reg_field(adap, A_CIM_BOOT_CFG, F_UPCRST, 0); + msleep(100); + if (t4_fw_reset(adap, mbox, + F_PIORST | F_PIORSTMODE) == 0) + return 0; + } + + t4_write_reg(adap, A_PL_RST, F_PIORST | F_PIORSTMODE); + msleep(2000); + } else { + int ms; + + t4_set_reg_field(adap, A_CIM_BOOT_CFG, F_UPCRST, 0); + for (ms = 0; ms < FW_CMD_MAX_TIMEOUT; ) { + if (!(t4_read_reg(adap, A_PCIE_FW) & F_PCIE_FW_HALT)) + return FW_SUCCESS; + msleep(100); + ms += 100; + } + return -ETIMEDOUT; + } + return 0; +} + +/** + * t4_fw_upgrade - perform all of the steps necessary to upgrade FW + * @adap: the adapter + * @mbox: mailbox to use for the FW RESET command (if desired) + * @fw_data: the firmware image to write + * @size: image size + * @force: force upgrade even if firmware doesn't cooperate + * + * Perform all of the steps necessary for upgrading an adapter's + * firmware image. Normally this requires the cooperation of the + * existing firmware in order to halt all existing activities + * but if an invalid mailbox token is passed in we skip that step + * (though we'll still put the adapter microprocessor into RESET in + * that case). + * + * On successful return the new firmware will have been loaded and + * the adapter will have been fully RESET losing all previous setup + * state. On unsuccessful return the adapter may be completely hosed ... + * positive errno indicates that the adapter is ~probably~ intact, a + * negative errno indicates that things are looking bad ... + */ +int t4_fw_upgrade(struct adapter *adap, unsigned int mbox, + const u8 *fw_data, unsigned int size, int force) +{ + const struct fw_hdr *fw_hdr = (const struct fw_hdr *)fw_data; + int reset, ret; + + ret = t4_fw_halt(adap, mbox, force); + if (ret < 0 && !force) + return ret; + + ret = t4_load_fw(adap, fw_data, size); + if (ret < 0) + return ret; + + /* + * Older versions of the firmware don't understand the new + * PCIE_FW.HALT flag and so won't know to perform a RESET when they + * restart. So for newly loaded older firmware we'll have to do the + * RESET for it so it starts up on a clean slate. We can tell if + * the newly loaded firmware will handle this right by checking + * its header flags to see if it advertises the capability. + */ + reset = ((ntohl(fw_hdr->flags) & FW_HDR_FLAGS_RESET_HALT) == 0); + return t4_fw_restart(adap, mbox, reset); +} + +/** * t4_fw_initialize - ask FW to initialize the device * @adap: the adapter * @mbox: mailbox to use for the FW command @@ -4059,7 +4504,7 @@ int t4_cfg_pfvf(struct adapter *adap, un } /** - * t4_alloc_vi - allocate a virtual interface + * t4_alloc_vi_func - allocate a virtual interface * @adap: the adapter * @mbox: mailbox to use for the FW command * @port: physical port associated with the VI @@ -4068,6 +4513,8 @@ int t4_cfg_pfvf(struct adapter *adap, un * @nmac: number of MAC addresses needed (1 to 5) * @mac: the MAC addresses of the VI * @rss_size: size of RSS table slice associated with this VI + * @portfunc: which Port Application Function MAC Address is desired + * @idstype: Intrusion Detection Type * * Allocates a virtual interface for the given physical port. If @mac is * not %NULL it contains the MAC addresses of the VI as assigned by FW. @@ -4075,9 +4522,10 @@ int t4_cfg_pfvf(struct adapter *adap, un * stored consecutively so the space needed is @nmac * 6 bytes. * Returns a negative error number or the non-negative VI id. */ -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) +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 ret; struct fw_vi_cmd c; @@ -4087,6 +4535,8 @@ int t4_alloc_vi(struct adapter *adap, un F_FW_CMD_WRITE | F_FW_CMD_EXEC | V_FW_VI_CMD_PFN(pf) | V_FW_VI_CMD_VFN(vf)); c.alloc_to_len16 = htonl(F_FW_VI_CMD_ALLOC | FW_LEN16(c)); + c.type_to_viid = htons(V_FW_VI_CMD_TYPE(idstype) | + V_FW_VI_CMD_FUNC(portfunc)); c.portid_pkd = V_FW_VI_CMD_PORTID(port); c.nmac = nmac - 1; @@ -4109,7 +4559,30 @@ int t4_alloc_vi(struct adapter *adap, un } if (rss_size) *rss_size = G_FW_VI_CMD_RSSSIZE(ntohs(c.rsssize_pkd)); - return G_FW_VI_CMD_VIID(ntohs(c.type_to_viid)); + return G_FW_VI_CMD_VIID(htons(c.type_to_viid)); +} + +/** + * t4_alloc_vi - allocate an [Ethernet Function] virtual interface + * @adap: the adapter + * @mbox: mailbox to use for the FW command + * @port: physical port associated with the VI + * @pf: the PF owning the VI + * @vf: the VF owning the VI + * @nmac: number of MAC addresses needed (1 to 5) + * @mac: the MAC addresses of the VI + * @rss_size: size of RSS table slice associated with this VI + * + * backwards compatible and convieniance routine to allocate a Virtual + * Interface with a Ethernet Port Application Function and Intrustion + * Detection System disabled. + */ +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) +{ + return t4_alloc_vi_func(adap, mbox, port, pf, vf, nmac, mac, rss_size, + FW_VI_FUNC_ETH, 0); } /** @@ -4214,7 +4687,7 @@ int t4_alloc_mac_filt(struct adapter *ad unsigned int nfilters = 0; unsigned int rem = naddr; - if (naddr > FW_CLS_TCAM_NUM_ENTRIES) + if (naddr > NUM_MPS_CLS_SRAM_L_INSTANCES) return -EINVAL; for (offset = 0; offset < naddr ; /**/) { @@ -4255,10 +4728,10 @@ int t4_alloc_mac_filt(struct adapter *ad u16 index = G_FW_VI_MAC_CMD_IDX(ntohs(p->valid_to_idx)); if (idx) - idx[offset+i] = (index >= FW_CLS_TCAM_NUM_ENTRIES + idx[offset+i] = (index >= NUM_MPS_CLS_SRAM_L_INSTANCES ? 0xffff : index); - if (index < FW_CLS_TCAM_NUM_ENTRIES) + if (index < NUM_MPS_CLS_SRAM_L_INSTANCES) nfilters++; else if (hash) *hash |= (1ULL << hash_mac_addr(addr[offset+i])); @@ -4319,7 +4792,7 @@ int t4_change_mac(struct adapter *adap, ret = t4_wr_mbox_ns(adap, mbox, &c, sizeof(c), &c); if (ret == 0) { ret = G_FW_VI_MAC_CMD_IDX(ntohs(p->valid_to_idx)); - if (ret >= FW_CLS_TCAM_NUM_ENTRIES) + if (ret >= NUM_MPS_CLS_SRAM_L_INSTANCES) ret = -ENOMEM; } return ret; @@ -4540,10 +5013,12 @@ int t4_ofld_eq_free(struct adapter *adap int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl) { u8 opcode = *(const u8 *)rpl; + const struct fw_port_cmd *p = (const void *)rpl; + unsigned int action = G_FW_PORT_CMD_ACTION(ntohl(p->action_to_len16)); - if (opcode == FW_PORT_CMD) { /* link/module state change message */ + if (opcode == FW_PORT_CMD && action == FW_PORT_ACTION_GET_PORT_INFO) { + /* link/module state change message */ int speed = 0, fc = 0, i; - const struct fw_port_cmd *p = (const void *)rpl; int chan = G_FW_PORT_CMD_PORTID(ntohl(p->op_to_portid)); struct port_info *pi = NULL; struct link_config *lc; @@ -4580,6 +5055,10 @@ int t4_handle_fw_rpl(struct adapter *ada pi->mod_type = mod; t4_os_portmod_changed(adap, i); } + } else { + CH_WARN_RATELIMIT(adap, + "Unknown firmware reply 0x%x (0x%x)\n", opcode, action); + return -EINVAL; } return 0; } @@ -4706,6 +5185,11 @@ int __devinit t4_prep_adapter(struct ada get_pci_mode(adapter, &adapter->params.pci); adapter->params.rev = t4_read_reg(adapter, A_PL_REV); + /* T4A1 chip is no longer supported */ + if (adapter->params.rev == 1) { + CH_ALERT(adapter, "T4 rev 1 chip is no longer supported\n"); + return -EINVAL; + } adapter->params.pci.vpd_cap_addr = t4_os_find_pci_capability(adapter, PCI_CAP_ID_VPD); @@ -4717,9 +5201,11 @@ int __devinit t4_prep_adapter(struct ada if (ret < 0) return ret; - if (t4_read_reg(adapter, A_SGE_PC0_REQ_BIST_CMD) != 0xffffffff) { + if (t4_read_reg(adapter, A_PCIE_REVISION) != 0) { + /* FPGA */ adapter->params.cim_la_size = 2 * CIMLA_SIZE; } else { + /* ASIC */ adapter->params.cim_la_size = CIMLA_SIZE; } @@ -4783,3 +5269,43 @@ int __devinit t4_port_init(struct port_i return 0; } + +int t4_config_scheduler(struct adapter *adapter, int mode, int level, + int pktsize, int sched_class, int port, int unit, + int rate, int weight, int minrate, int maxrate) +{ + struct fw_sched_cmd cmd, rpl; + + if (rate < 0 || unit < 0) + return -EINVAL; *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***