net/cxgbe: support flow API for matching all packets on VF
[dpdk.git] / drivers / net / cxgbe / base / t4_hw.c
index 628b280..48b6d77 100644 (file)
@@ -246,7 +246,7 @@ static void get_mbox_rpl(struct adapter *adap, __be64 *rpl, int nflit,
                         u32 mbox_addr)
 {
        for ( ; nflit; nflit--, mbox_addr += 8)
-               *rpl++ = htobe64(t4_read_reg64(adap, mbox_addr));
+               *rpl++ = cpu_to_be64(t4_read_reg64(adap, mbox_addr));
 }
 
 /*
@@ -335,7 +335,7 @@ int t4_wr_mbox_meat_timeout(struct adapter *adap, int mbox,
                return -EINVAL;
        }
 
-       bzero(p, size);
+       memset(p, 0, size);
        memcpy(p, (const __be64 *)cmd, size);
 
        /*
@@ -4017,7 +4017,8 @@ int t4_set_params(struct adapter *adap, unsigned int mbox, unsigned int pf,
 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)
+                    unsigned int portfunc, unsigned int idstype,
+                    u8 *vivld, u8 *vin)
 {
        int ret;
        struct fw_vi_cmd c;
@@ -4055,6 +4056,10 @@ int t4_alloc_vi_func(struct adapter *adap, unsigned int mbox,
        }
        if (rss_size)
                *rss_size = G_FW_VI_CMD_RSSSIZE(be16_to_cpu(c.norss_rsssize));
+       if (vivld)
+               *vivld = G_FW_VI_CMD_VFVLD(be32_to_cpu(c.alloc_to_len16));
+       if (vin)
+               *vin = G_FW_VI_CMD_VIN(be32_to_cpu(c.alloc_to_len16));
        return G_FW_VI_CMD_VIID(cpu_to_be16(c.type_to_viid));
 }
 
@@ -4075,10 +4080,10 @@ int t4_alloc_vi_func(struct adapter *adap, unsigned int mbox,
  */
 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)
+               unsigned int *rss_size, u8 *vivld, u8 *vin)
 {
        return t4_alloc_vi_func(adap, mbox, port, pf, vf, nmac, mac, rss_size,
-                               FW_VI_FUNC_ETH, 0);
+                               FW_VI_FUNC_ETH, 0, vivld, vin);
 }
 
 /**
@@ -4161,6 +4166,112 @@ int t4_set_rxmode(struct adapter *adap, unsigned int mbox, unsigned int viid,
                return t4vf_wr_mbox(adap, &c, sizeof(c), NULL);
 }
 
+/**
+ *     t4_alloc_raw_mac_filt - Adds a raw mac entry in mps tcam
+ *     @adap: the adapter
+ *     @viid: the VI id
+ *     @mac: the MAC address
+ *     @mask: the mask
+ *     @idx: index at which to add this entry
+ *     @port_id: the port index
+ *     @lookup_type: MAC address for inner (1) or outer (0) header
+ *     @sleep_ok: call is allowed to sleep
+ *
+ *     Adds the mac entry at the specified index using raw mac interface.
+ *
+ *     Returns a negative error number or the allocated index for this mac.
+ */
+int t4_alloc_raw_mac_filt(struct adapter *adap, unsigned int viid,
+                         const u8 *addr, const u8 *mask, unsigned int idx,
+                         u8 lookup_type, u8 port_id, bool sleep_ok)
+{
+       int ret = 0;
+       struct fw_vi_mac_cmd c;
+       struct fw_vi_mac_raw *p = &c.u.raw;
+       u32 val;
+
+       memset(&c, 0, sizeof(c));
+       c.op_to_viid = cpu_to_be32(V_FW_CMD_OP(FW_VI_MAC_CMD) |
+                                  F_FW_CMD_REQUEST | F_FW_CMD_WRITE |
+                                  V_FW_VI_MAC_CMD_VIID(viid));
+       val = V_FW_CMD_LEN16(1) |
+             V_FW_VI_MAC_CMD_ENTRY_TYPE(FW_VI_MAC_TYPE_RAW);
+       c.freemacs_to_len16 = cpu_to_be32(val);
+
+       /* Specify that this is an inner mac address */
+       p->raw_idx_pkd = cpu_to_be32(V_FW_VI_MAC_CMD_RAW_IDX(idx));
+
+       /* Lookup Type. Outer header: 0, Inner header: 1 */
+       p->data0_pkd = cpu_to_be32(V_DATALKPTYPE(lookup_type) |
+                                  V_DATAPORTNUM(port_id));
+       /* Lookup mask and port mask */
+       p->data0m_pkd = cpu_to_be64(V_DATALKPTYPE(M_DATALKPTYPE) |
+                                   V_DATAPORTNUM(M_DATAPORTNUM));
+
+       /* Copy the address and the mask */
+       memcpy((u8 *)&p->data1[0] + 2, addr, ETHER_ADDR_LEN);
+       memcpy((u8 *)&p->data1m[0] + 2, mask, ETHER_ADDR_LEN);
+
+       ret = t4_wr_mbox_meat(adap, adap->mbox, &c, sizeof(c), &c, sleep_ok);
+       if (ret == 0) {
+               ret = G_FW_VI_MAC_CMD_RAW_IDX(be32_to_cpu(p->raw_idx_pkd));
+               if (ret != (int)idx)
+                       ret = -ENOMEM;
+       }
+
+       return ret;
+}
+
+/**
+ *     t4_free_raw_mac_filt - Frees a raw mac entry in mps tcam
+ *     @adap: the adapter
+ *     @viid: the VI id
+ *     @addr: the MAC address
+ *     @mask: the mask
+ *     @idx: index of the entry in mps tcam
+ *     @lookup_type: MAC address for inner (1) or outer (0) header
+ *     @port_id: the port index
+ *     @sleep_ok: call is allowed to sleep
+ *
+ *     Removes the mac entry at the specified index using raw mac interface.
+ *
+ *     Returns a negative error number on failure.
+ */
+int t4_free_raw_mac_filt(struct adapter *adap, unsigned int viid,
+                        const u8 *addr, const u8 *mask, unsigned int idx,
+                        u8 lookup_type, u8 port_id, bool sleep_ok)
+{
+       struct fw_vi_mac_cmd c;
+       struct fw_vi_mac_raw *p = &c.u.raw;
+       u32 raw;
+
+       memset(&c, 0, sizeof(c));
+       c.op_to_viid = cpu_to_be32(V_FW_CMD_OP(FW_VI_MAC_CMD) |
+                                  F_FW_CMD_REQUEST | F_FW_CMD_WRITE |
+                                  V_FW_CMD_EXEC(0) |
+                                  V_FW_VI_MAC_CMD_VIID(viid));
+       raw = V_FW_VI_MAC_CMD_ENTRY_TYPE(FW_VI_MAC_TYPE_RAW);
+       c.freemacs_to_len16 = cpu_to_be32(V_FW_VI_MAC_CMD_FREEMACS(0U) |
+                                         raw |
+                                         V_FW_CMD_LEN16(1));
+
+       p->raw_idx_pkd = cpu_to_be32(V_FW_VI_MAC_CMD_RAW_IDX(idx) |
+                                    FW_VI_MAC_ID_BASED_FREE);
+
+       /* Lookup Type. Outer header: 0, Inner header: 1 */
+       p->data0_pkd = cpu_to_be32(V_DATALKPTYPE(lookup_type) |
+                                  V_DATAPORTNUM(port_id));
+       /* Lookup mask and port mask */
+       p->data0m_pkd = cpu_to_be64(V_DATALKPTYPE(M_DATALKPTYPE) |
+                                   V_DATAPORTNUM(M_DATAPORTNUM));
+
+       /* Copy the address and the mask */
+       memcpy((u8 *)&p->data1[0] + 2, addr, ETHER_ADDR_LEN);
+       memcpy((u8 *)&p->data1m[0] + 2, mask, ETHER_ADDR_LEN);
+
+       return t4_wr_mbox_meat(adap, adap->mbox, &c, sizeof(c), &c, sleep_ok);
+}
+
 /**
  * t4_change_mac - modifies the exact-match filter for a MAC address
  * @adap: the adapter
@@ -4681,9 +4792,8 @@ struct flash_desc {
 int t4_get_flash_params(struct adapter *adapter)
 {
        /*
-        * Table for non-Numonix supported flash parts.  Numonix parts are left
-        * to the preexisting well-tested code.  All flash parts have 64KB
-        * sectors.
+        * Table for non-standard supported Flash parts.  Note, all Flash
+        * parts must have 64KB sectors.
         */
        static struct flash_desc supported_flash[] = {
                { 0x00150201, 4 << 20 },       /* Spansion 4MB S25FL032P */
@@ -4692,7 +4802,7 @@ int t4_get_flash_params(struct adapter *adapter)
        int ret;
        u32 flashid = 0;
        unsigned int part, manufacturer;
-       unsigned int density, size;
+       unsigned int density, size = 0;
 
        /**
         * Issue a Read ID Command to the Flash part.  We decode supported
@@ -4707,6 +4817,9 @@ int t4_get_flash_params(struct adapter *adapter)
        if (ret < 0)
                return ret;
 
+       /**
+        * Check to see if it's one of our non-standard supported Flash parts.
+        */
        for (part = 0; part < ARRAY_SIZE(supported_flash); part++) {
                if (supported_flash[part].vendor_and_model_id == flashid) {
                        adapter->params.sf_size =
@@ -4717,6 +4830,15 @@ int t4_get_flash_params(struct adapter *adapter)
                }
        }
 
+       /**
+        * Decode Flash part size.  The code below looks repetative with
+        * common encodings, but that's not guaranteed in the JEDEC
+        * specification for the Read JADEC ID command.  The only thing that
+        * we're guaranteed by the JADEC specification is where the
+        * Manufacturer ID is in the returned result.  After that each
+        * Manufacturer ~could~ encode things completely differently.
+        * Note, all Flash parts must have 64KB sectors.
+        */
        manufacturer = flashid & 0xff;
        switch (manufacturer) {
        case 0x20: { /* Micron/Numonix */
@@ -4753,21 +4875,81 @@ int t4_get_flash_params(struct adapter *adapter)
                case 0x22:
                        size = 1 << 28; /* 256MB */
                        break;
-               default:
-                       dev_err(adapter, "Micron Flash Part has bad size, ID = %#x, Density code = %#x\n",
-                               flashid, density);
-                       return -EINVAL;
                }
+               break;
+       }
 
-               adapter->params.sf_size = size;
-               adapter->params.sf_nsec = size / SF_SEC_SIZE;
+       case 0x9d: { /* ISSI -- Integrated Silicon Solution, Inc. */
+               /**
+                * This Density -> Size decoding table is taken from ISSI
+                * Data Sheets.
+                */
+               density = (flashid >> 16) & 0xff;
+               switch (density) {
+               case 0x16:
+                       size = 1 << 25; /* 32MB */
+                       break;
+               case 0x17:
+                       size = 1 << 26; /* 64MB */
+                       break;
+               }
                break;
        }
-       default:
-               dev_err(adapter, "Unsupported Flash Part, ID = %#x\n", flashid);
-               return -EINVAL;
+
+       case 0xc2: { /* Macronix */
+               /**
+                * This Density -> Size decoding table is taken from Macronix
+                * Data Sheets.
+                */
+               density = (flashid >> 16) & 0xff;
+               switch (density) {
+               case 0x17:
+                       size = 1 << 23; /* 8MB */
+                       break;
+               case 0x18:
+                       size = 1 << 24; /* 16MB */
+                       break;
+               }
+               break;
        }
 
+       case 0xef: { /* Winbond */
+               /**
+                * This Density -> Size decoding table is taken from Winbond
+                * Data Sheets.
+                */
+               density = (flashid >> 16) & 0xff;
+               switch (density) {
+               case 0x17:
+                       size = 1 << 23; /* 8MB */
+                       break;
+               case 0x18:
+                       size = 1 << 24; /* 16MB */
+                       break;
+               }
+               break;
+       }
+       }
+
+       /* If we didn't recognize the FLASH part, that's no real issue: the
+        * Hardware/Software contract says that Hardware will _*ALWAYS*_
+        * use a FLASH part which is at least 4MB in size and has 64KB
+        * sectors.  The unrecognized FLASH part is likely to be much larger
+        * than 4MB, but that's all we really need.
+        */
+       if (size == 0) {
+               dev_warn(adapter,
+                        "Unknown Flash Part, ID = %#x, assuming 4MB\n",
+                        flashid);
+               size = 1 << 22;
+       }
+
+       /**
+        * Store decoded Flash size and fall through into vetting code.
+        */
+       adapter->params.sf_size = size;
+       adapter->params.sf_nsec = size / SF_SEC_SIZE;
+
 found:
        /*
         * We should reject adapters with FLASHes which are too small. So, emit
@@ -5074,13 +5256,9 @@ int t4_init_tp_params(struct adapter *adap)
                                                               F_PROTOCOL);
        adap->params.tp.ethertype_shift = t4_filter_field_shift(adap,
                                                                F_ETHERTYPE);
-
-       /*
-        * If TP_INGRESS_CONFIG.VNID == 0, then TP_VLAN_PRI_MAP.VNIC_ID
-        * represents the presense of an Outer VLAN instead of a VNIC ID.
-        */
-       if ((adap->params.tp.ingress_config & F_VNIC) == 0)
-               adap->params.tp.vnic_shift = -1;
+       adap->params.tp.macmatch_shift = t4_filter_field_shift(adap,
+                                                              F_MACMATCH);
+       adap->params.tp.tos_shift = t4_filter_field_shift(adap, F_TOS);
 
        v = t4_read_reg(adap, LE_3_DB_HASH_MASK_GEN_IPV4_T6_A);
        adap->params.tp.hash_filter_mask = v;
@@ -5173,6 +5351,7 @@ int t4_port_init(struct adapter *adap, int mbox, int pf, int vf)
        fw_port_cap32_t pcaps, acaps;
        enum fw_port_type port_type;
        struct fw_port_cmd cmd;
+       u8 vivld = 0, vin = 0;
        int ret, i, j = 0;
        int mdio_addr;
        u32 action;
@@ -5244,7 +5423,8 @@ int t4_port_init(struct adapter *adap, int mbox, int pf, int vf)
                        acaps = be32_to_cpu(cmd.u.info32.acaps32);
                }
 
-               ret = t4_alloc_vi(adap, mbox, j, pf, vf, 1, addr, &rss_size);
+               ret = t4_alloc_vi(adap, mbox, j, pf, vf, 1, addr, &rss_size,
+                                 &vivld, &vin);
                if (ret < 0)
                        return ret;
 
@@ -5253,6 +5433,18 @@ int t4_port_init(struct adapter *adap, int mbox, int pf, int vf)
                pi->rss_size = rss_size;
                t4_os_set_hw_addr(adap, i, addr);
 
+               /* If fw supports returning the VIN as part of FW_VI_CMD,
+                * save the returned values.
+                */
+               if (adap->params.viid_smt_extn_support) {
+                       pi->vivld = vivld;
+                       pi->vin = vin;
+               } else {
+                       /* Retrieve the values from VIID */
+                       pi->vivld = G_FW_VIID_VIVLD(pi->viid);
+                       pi->vin =  G_FW_VIID_VIN(pi->viid);
+               }
+
                pi->port_type = port_type;
                pi->mdio_addr = mdio_addr;
                pi->mod_type = FW_PORT_MOD_TYPE_NA;