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 ***
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to