Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next
[linux-2.6-microblaze.git] / drivers / net / ipa / ipa_endpoint.c
index b40b711..9f4be98 100644 (file)
@@ -37,7 +37,7 @@
 #define IPA_ENDPOINT_QMAP_METADATA_MASK                0x000000ff /* host byte order */
 
 #define IPA_ENDPOINT_RESET_AGGR_RETRY_MAX      3
-#define IPA_AGGR_TIME_LIMIT_DEFAULT            500     /* microseconds */
+#define IPA_AGGR_TIME_LIMIT                    500     /* microseconds */
 
 /** enum ipa_status_opcode - status element opcode hardware values */
 enum ipa_status_opcode {
@@ -74,31 +74,6 @@ struct ipa_status {
 
 #ifdef IPA_VALIDATE
 
-static void ipa_endpoint_validate_build(void)
-{
-       /* The aggregation byte limit defines the point at which an
-        * aggregation window will close.  It is programmed into the
-        * IPA hardware as a number of KB.  We don't use "hard byte
-        * limit" aggregation, which means that we need to supply
-        * enough space in a receive buffer to hold a complete MTU
-        * plus normal skb overhead *after* that aggregation byte
-        * limit has been crossed.
-        *
-        * This check just ensures we don't define a receive buffer
-        * size that would exceed what we can represent in the field
-        * that is used to program its size.
-        */
-       BUILD_BUG_ON(IPA_RX_BUFFER_SIZE >
-                    field_max(AGGR_BYTE_LIMIT_FMASK) * SZ_1K +
-                    IPA_MTU + IPA_RX_BUFFER_OVERHEAD);
-
-       /* I honestly don't know where this requirement comes from.  But
-        * it holds, and if we someday need to loosen the constraint we
-        * can try to track it down.
-        */
-       BUILD_BUG_ON(sizeof(struct ipa_status) % 4);
-}
-
 static bool ipa_endpoint_data_valid_one(struct ipa *ipa, u32 count,
                            const struct ipa_gsi_endpoint_data *all_data,
                            const struct ipa_gsi_endpoint_data *data)
@@ -180,14 +155,24 @@ static bool ipa_endpoint_data_valid_one(struct ipa *ipa, u32 count,
        return true;
 }
 
+static u32 aggr_byte_limit_max(enum ipa_version version)
+{
+       if (version < IPA_VERSION_4_5)
+               return field_max(aggr_byte_limit_fmask(true));
+
+       return field_max(aggr_byte_limit_fmask(false));
+}
+
 static bool ipa_endpoint_data_valid(struct ipa *ipa, u32 count,
                                    const struct ipa_gsi_endpoint_data *data)
 {
        const struct ipa_gsi_endpoint_data *dp = data;
        struct device *dev = &ipa->pdev->dev;
        enum ipa_endpoint_name name;
+       u32 limit;
 
-       ipa_endpoint_validate_build();
+       /* Not sure where this constraint come from... */
+       BUILD_BUG_ON(sizeof(struct ipa_status) % 4);
 
        if (count > IPA_ENDPOINT_COUNT) {
                dev_err(dev, "too many endpoints specified (%u > %u)\n",
@@ -195,6 +180,26 @@ static bool ipa_endpoint_data_valid(struct ipa *ipa, u32 count,
                return false;
        }
 
+       /* The aggregation byte limit defines the point at which an
+        * aggregation window will close.  It is programmed into the
+        * IPA hardware as a number of KB.  We don't use "hard byte
+        * limit" aggregation, which means that we need to supply
+        * enough space in a receive buffer to hold a complete MTU
+        * plus normal skb overhead *after* that aggregation byte
+        * limit has been crossed.
+        *
+        * This check ensures we don't define a receive buffer size
+        * that would exceed what we can represent in the field that
+        * is used to program its size.
+        */
+       limit = aggr_byte_limit_max(ipa->version) * SZ_1K;
+       limit += IPA_MTU + IPA_RX_BUFFER_OVERHEAD;
+       if (limit < IPA_RX_BUFFER_SIZE) {
+               dev_err(dev, "buffer size too big for aggregation (%u > %u)\n",
+                       IPA_RX_BUFFER_SIZE, limit);
+               return false;
+       }
+
        /* Make sure needed endpoints have defined data */
        if (ipa_gsi_endpoint_data_empty(&data[IPA_ENDPOINT_AP_COMMAND_TX])) {
                dev_err(dev, "command TX endpoint not defined\n");
@@ -485,28 +490,34 @@ static void ipa_endpoint_init_cfg(struct ipa_endpoint *endpoint)
 static void ipa_endpoint_init_hdr(struct ipa_endpoint *endpoint)
 {
        u32 offset = IPA_REG_ENDP_INIT_HDR_N_OFFSET(endpoint->endpoint_id);
+       struct ipa *ipa = endpoint->ipa;
        u32 val = 0;
 
        if (endpoint->data->qmap) {
                size_t header_size = sizeof(struct rmnet_map_header);
+               enum ipa_version version = ipa->version;
 
                /* We might supply a checksum header after the QMAP header */
                if (endpoint->toward_ipa && endpoint->data->checksum)
                        header_size += sizeof(struct rmnet_map_ul_csum_header);
-               val |= u32_encode_bits(header_size, HDR_LEN_FMASK);
+               val |= ipa_header_size_encoded(version, header_size);
 
                /* Define how to fill fields in a received QMAP header */
                if (!endpoint->toward_ipa) {
-                       u32 off;        /* Field offset within header */
+                       u32 offset;     /* Field offset within header */
 
                        /* Where IPA will write the metadata value */
-                       off = offsetof(struct rmnet_map_header, mux_id);
-                       val |= u32_encode_bits(off, HDR_OFST_METADATA_FMASK);
+                       offset = offsetof(struct rmnet_map_header, mux_id);
+                       val |= ipa_metadata_offset_encoded(version, offset);
 
                        /* Where IPA will write the length */
-                       off = offsetof(struct rmnet_map_header, pkt_len);
+                       offset = offsetof(struct rmnet_map_header, pkt_len);
+                       /* Upper bits are stored in HDR_EXT with IPA v4.5 */
+                       if (version == IPA_VERSION_4_5)
+                               offset &= field_mask(HDR_OFST_PKT_SIZE_FMASK);
+
                        val |= HDR_OFST_PKT_SIZE_VALID_FMASK;
-                       val |= u32_encode_bits(off, HDR_OFST_PKT_SIZE_FMASK);
+                       val |= u32_encode_bits(offset, HDR_OFST_PKT_SIZE_FMASK);
                }
                /* For QMAP TX, metadata offset is 0 (modem assumes this) */
                val |= HDR_OFST_METADATA_VALID_FMASK;
@@ -514,16 +525,17 @@ static void ipa_endpoint_init_hdr(struct ipa_endpoint *endpoint)
                /* HDR_ADDITIONAL_CONST_LEN is 0; (RX only) */
                /* HDR_A5_MUX is 0 */
                /* HDR_LEN_INC_DEAGG_HDR is 0 */
-               /* HDR_METADATA_REG_VALID is 0 (TX only) */
+               /* HDR_METADATA_REG_VALID is 0 (TX only, version < v4.5) */
        }
 
-       iowrite32(val, endpoint->ipa->reg_virt + offset);
+       iowrite32(val, ipa->reg_virt + offset);
 }
 
 static void ipa_endpoint_init_hdr_ext(struct ipa_endpoint *endpoint)
 {
        u32 offset = IPA_REG_ENDP_INIT_HDR_EXT_N_OFFSET(endpoint->endpoint_id);
        u32 pad_align = endpoint->data->rx.pad_align;
+       struct ipa *ipa = endpoint->ipa;
        u32 val = 0;
 
        val |= HDR_ENDIANNESS_FMASK;            /* big endian */
@@ -545,10 +557,24 @@ static void ipa_endpoint_init_hdr_ext(struct ipa_endpoint *endpoint)
        if (!endpoint->toward_ipa)
                val |= u32_encode_bits(pad_align, HDR_PAD_TO_ALIGNMENT_FMASK);
 
-       iowrite32(val, endpoint->ipa->reg_virt + offset);
+       /* IPA v4.5 adds some most-significant bits to a few fields,
+        * two of which are defined in the HDR (not HDR_EXT) register.
+        */
+       if (ipa->version == IPA_VERSION_4_5) {
+               /* HDR_TOTAL_LEN_OR_PAD_OFFSET is 0, so MSB is 0 */
+               if (endpoint->data->qmap && !endpoint->toward_ipa) {
+                       u32 offset;
+
+                       offset = offsetof(struct rmnet_map_header, pkt_len);
+                       offset >>= hweight32(HDR_OFST_PKT_SIZE_FMASK);
+                       val |= u32_encode_bits(offset,
+                                              HDR_OFST_PKT_SIZE_MSB_FMASK);
+                       /* HDR_ADDITIONAL_CONST_LEN is 0 so MSB is 0 */
+               }
+       }
+       iowrite32(val, ipa->reg_virt + offset);
 }
 
-
 static void ipa_endpoint_init_hdr_metadata_mask(struct ipa_endpoint *endpoint)
 {
        u32 endpoint_id = endpoint->endpoint_id;
@@ -603,29 +629,84 @@ static u32 ipa_aggr_size_kb(u32 rx_buffer_size)
        return rx_buffer_size / SZ_1K;
 }
 
+/* Encoded values for AGGR endpoint register fields */
+static u32 aggr_byte_limit_encoded(enum ipa_version version, u32 limit)
+{
+       if (version < IPA_VERSION_4_5)
+               return u32_encode_bits(limit, aggr_byte_limit_fmask(true));
+
+       return u32_encode_bits(limit, aggr_byte_limit_fmask(false));
+}
+
+/* Encode the aggregation timer limit (microseconds) based on IPA version */
+static u32 aggr_time_limit_encoded(enum ipa_version version, u32 limit)
+{
+       u32 gran_sel;
+       u32 fmask;
+       u32 val;
+
+       if (version < IPA_VERSION_4_5) {
+               /* We set aggregation granularity in ipa_hardware_config() */
+               limit = DIV_ROUND_CLOSEST(limit, IPA_AGGR_GRANULARITY);
+
+               return u32_encode_bits(limit, aggr_time_limit_fmask(true));
+       }
+
+       /* IPA v4.5 expresses the time limit using Qtime.  The AP has
+        * pulse generators 0 and 1 available, which were configured
+        * in ipa_qtime_config() to have granularity 100 usec and
+        * 1 msec, respectively.  Use pulse generator 0 if possible,
+        * otherwise fall back to pulse generator 1.
+        */
+       fmask = aggr_time_limit_fmask(false);
+       val = DIV_ROUND_CLOSEST(limit, 100);
+       if (val > field_max(fmask)) {
+               /* Have to use pulse generator 1 (millisecond granularity) */
+               gran_sel = AGGR_GRAN_SEL_FMASK;
+               val = DIV_ROUND_CLOSEST(limit, 1000);
+       } else {
+               /* We can use pulse generator 0 (100 usec granularity) */
+               gran_sel = 0;
+       }
+
+       return gran_sel | u32_encode_bits(val, fmask);
+}
+
+static u32 aggr_sw_eof_active_encoded(enum ipa_version version, bool enabled)
+{
+       u32 val = enabled ? 1 : 0;
+
+       if (version < IPA_VERSION_4_5)
+               return u32_encode_bits(val, aggr_sw_eof_active_fmask(true));
+
+       return u32_encode_bits(val, aggr_sw_eof_active_fmask(false));
+}
+
 static void ipa_endpoint_init_aggr(struct ipa_endpoint *endpoint)
 {
        u32 offset = IPA_REG_ENDP_INIT_AGGR_N_OFFSET(endpoint->endpoint_id);
+       enum ipa_version version = endpoint->ipa->version;
        u32 val = 0;
 
        if (endpoint->data->aggregation) {
                if (!endpoint->toward_ipa) {
+                       bool close_eof;
                        u32 limit;
 
                        val |= u32_encode_bits(IPA_ENABLE_AGGR, AGGR_EN_FMASK);
                        val |= u32_encode_bits(IPA_GENERIC, AGGR_TYPE_FMASK);
 
                        limit = ipa_aggr_size_kb(IPA_RX_BUFFER_SIZE);
-                       val |= u32_encode_bits(limit, AGGR_BYTE_LIMIT_FMASK);
+                       val |= aggr_byte_limit_encoded(version, limit);
 
-                       limit = IPA_AGGR_TIME_LIMIT_DEFAULT;
-                       limit = DIV_ROUND_CLOSEST(limit, IPA_AGGR_GRANULARITY);
-                       val |= u32_encode_bits(limit, AGGR_TIME_LIMIT_FMASK);
+                       limit = IPA_AGGR_TIME_LIMIT;
+                       val |= aggr_time_limit_encoded(version, limit);
 
                        /* AGGR_PKT_LIMIT is 0 (unlimited) */
 
-                       if (endpoint->data->rx.aggr_close_eof)
-                               val |= AGGR_SW_EOF_ACTIVE_FMASK;
+                       close_eof = endpoint->data->rx.aggr_close_eof;
+                       val |= aggr_sw_eof_active_encoded(version, close_eof);
+
                        /* AGGR_HARD_BYTE_LIMIT_ENABLE is 0 */
                } else {
                        val |= u32_encode_bits(IPA_ENABLE_DEAGGR,
@@ -634,6 +715,7 @@ static void ipa_endpoint_init_aggr(struct ipa_endpoint *endpoint)
                        /* other fields ignored */
                }
                /* AGGR_FORCE_CLOSE is 0 */
+               /* AGGR_GRAN_SEL is 0 for IPA v4.5 */
        } else {
                val |= u32_encode_bits(IPA_BYPASS_AGGR, AGGR_EN_FMASK);
                /* other fields ignored */
@@ -642,12 +724,45 @@ static void ipa_endpoint_init_aggr(struct ipa_endpoint *endpoint)
        iowrite32(val, endpoint->ipa->reg_virt + offset);
 }
 
-/* The head-of-line blocking timer is defined as a tick count, where each
- * tick represents 128 cycles of the IPA core clock.  Return the value
- * that should be written to that register that represents the timeout
- * period provided.
+/* Return the Qtime-based head-of-line blocking timer value that
+ * represents the given number of microseconds.  The result
+ * includes both the timer value and the selected timer granularity.
  */
-static u32 ipa_reg_init_hol_block_timer_val(struct ipa *ipa, u32 microseconds)
+static u32 hol_block_timer_qtime_val(struct ipa *ipa, u32 microseconds)
+{
+       u32 gran_sel;
+       u32 val;
+
+       /* IPA v4.5 expresses time limits using Qtime.  The AP has
+        * pulse generators 0 and 1 available, which were configured
+        * in ipa_qtime_config() to have granularity 100 usec and
+        * 1 msec, respectively.  Use pulse generator 0 if possible,
+        * otherwise fall back to pulse generator 1.
+        */
+       val = DIV_ROUND_CLOSEST(microseconds, 100);
+       if (val > field_max(TIME_LIMIT_FMASK)) {
+               /* Have to use pulse generator 1 (millisecond granularity) */
+               gran_sel = GRAN_SEL_FMASK;
+               val = DIV_ROUND_CLOSEST(microseconds, 1000);
+       } else {
+               /* We can use pulse generator 0 (100 usec granularity) */
+               gran_sel = 0;
+       }
+
+       return gran_sel | u32_encode_bits(val, TIME_LIMIT_FMASK);
+}
+
+/* The head-of-line blocking timer is defined as a tick count.  For
+ * IPA version 4.5 the tick count is based on the Qtimer, which is
+ * derived from the 19.2 MHz SoC XO clock.  For older IPA versions
+ * each tick represents 128 cycles of the IPA core clock.
+ *
+ * Return the encoded value that should be written to that register
+ * that represents the timeout period provided.  For IPA v4.2 this
+ * encodes a base and scale value, while for earlier versions the
+ * value is a simple tick count.
+ */
+static u32 hol_block_timer_val(struct ipa *ipa, u32 microseconds)
 {
        u32 width;
        u32 scale;
@@ -659,14 +774,17 @@ static u32 ipa_reg_init_hol_block_timer_val(struct ipa *ipa, u32 microseconds)
        if (!microseconds)
                return 0;       /* Nothing to compute if timer period is 0 */
 
+       if (ipa->version == IPA_VERSION_4_5)
+               return hol_block_timer_qtime_val(ipa, microseconds);
+
        /* Use 64 bit arithmetic to avoid overflow... */
        rate = ipa_clock_rate(ipa);
        ticks = DIV_ROUND_CLOSEST(microseconds * rate, 128 * USEC_PER_SEC);
        /* ...but we still need to fit into a 32-bit register */
        WARN_ON(ticks > U32_MAX);
 
-       /* IPA v3.5.1 just records the tick count */
-       if (ipa->version == IPA_VERSION_3_5_1)
+       /* IPA v3.5.1 through v4.1 just record the tick count */
+       if (ipa->version < IPA_VERSION_4_2)
                return (u32)ticks;
 
        /* For IPA v4.2, the tick count is represented by base and
@@ -704,7 +822,7 @@ static void ipa_endpoint_init_hol_block_timer(struct ipa_endpoint *endpoint,
        u32 val;
 
        offset = IPA_REG_ENDP_INIT_HOL_BLOCK_TIMER_N_OFFSET(endpoint_id);
-       val = ipa_reg_init_hol_block_timer_val(ipa, microseconds);
+       val = hol_block_timer_val(ipa, microseconds);
        iowrite32(val, ipa->reg_virt + offset);
 }
 
@@ -751,6 +869,16 @@ static void ipa_endpoint_init_deaggr(struct ipa_endpoint *endpoint)
        iowrite32(val, endpoint->ipa->reg_virt + offset);
 }
 
+static void ipa_endpoint_init_rsrc_grp(struct ipa_endpoint *endpoint)
+{
+       u32 offset = IPA_REG_ENDP_INIT_RSRC_GRP_N_OFFSET(endpoint->endpoint_id);
+       struct ipa *ipa = endpoint->ipa;
+       u32 val;
+
+       val = rsrc_grp_encoded(ipa->version, endpoint->data->resource_group);
+       iowrite32(val, ipa->reg_virt + offset);
+}
+
 static void ipa_endpoint_init_seq(struct ipa_endpoint *endpoint)
 {
        u32 offset = IPA_REG_ENDP_INIT_SEQ_N_OFFSET(endpoint->endpoint_id);
@@ -834,9 +962,10 @@ static void ipa_endpoint_status(struct ipa_endpoint *endpoint)
                        val |= u32_encode_bits(status_endpoint_id,
                                               STATUS_ENDP_FMASK);
                }
-               /* STATUS_LOCATION is 0 (status element precedes packet) */
-               /* The next field is present for IPA v4.0 and above */
-               /* STATUS_PKT_SUPPRESS_FMASK is 0 */
+               /* STATUS_LOCATION is 0, meaning status element precedes
+                * packet (not present for IPA v4.5)
+                */
+               /* STATUS_PKT_SUPPRESS_FMASK is 0 (not present for v3.5.1) */
        }
 
        iowrite32(val, ipa->reg_virt + offset);
@@ -1207,7 +1336,6 @@ static int ipa_endpoint_reset_rx_aggr(struct ipa_endpoint *endpoint)
        struct gsi *gsi = &ipa->gsi;
        bool suspended = false;
        dma_addr_t addr;
-       bool legacy;
        u32 retries;
        u32 len = 1;
        void *virt;
@@ -1269,8 +1397,7 @@ static int ipa_endpoint_reset_rx_aggr(struct ipa_endpoint *endpoint)
         * complete the channel reset sequence.  Finish by suspending the
         * channel again (if necessary).
         */
-       legacy = ipa->version == IPA_VERSION_3_5_1;
-       gsi_channel_reset(gsi, endpoint->channel_id, legacy);
+       gsi_channel_reset(gsi, endpoint->channel_id, true);
 
        msleep(1);
 
@@ -1293,21 +1420,19 @@ static void ipa_endpoint_reset(struct ipa_endpoint *endpoint)
        u32 channel_id = endpoint->channel_id;
        struct ipa *ipa = endpoint->ipa;
        bool special;
-       bool legacy;
        int ret = 0;
 
        /* On IPA v3.5.1, if an RX endpoint is reset while aggregation
         * is active, we need to handle things specially to recover.
         * All other cases just need to reset the underlying GSI channel.
-        *
-        * IPA v3.5.1 enables the doorbell engine.  Newer versions do not.
         */
-       legacy = ipa->version == IPA_VERSION_3_5_1;
-       special = !endpoint->toward_ipa && endpoint->data->aggregation;
+       special = ipa->version == IPA_VERSION_3_5_1 &&
+                       !endpoint->toward_ipa &&
+                       endpoint->data->aggregation;
        if (special && ipa_endpoint_aggr_active(endpoint))
                ret = ipa_endpoint_reset_rx_aggr(endpoint);
        else
-               gsi_channel_reset(&ipa->gsi, channel_id, legacy);
+               gsi_channel_reset(&ipa->gsi, channel_id, true);
 
        if (ret)
                dev_err(&ipa->pdev->dev,
@@ -1328,6 +1453,7 @@ static void ipa_endpoint_program(struct ipa_endpoint *endpoint)
        ipa_endpoint_init_mode(endpoint);
        ipa_endpoint_init_aggr(endpoint);
        ipa_endpoint_init_deaggr(endpoint);
+       ipa_endpoint_init_rsrc_grp(endpoint);
        ipa_endpoint_init_seq(endpoint);
        ipa_endpoint_status(endpoint);
 }
@@ -1538,8 +1664,8 @@ int ipa_endpoint_config(struct ipa *ipa)
        val = ioread32(ipa->reg_virt + IPA_REG_FLAVOR_0_OFFSET);
 
        /* Our RX is an IPA producer */
-       rx_base = u32_get_bits(val, BAM_PROD_LOWEST_FMASK);
-       max = rx_base + u32_get_bits(val, BAM_MAX_PROD_PIPES_FMASK);
+       rx_base = u32_get_bits(val, IPA_PROD_LOWEST_FMASK);
+       max = rx_base + u32_get_bits(val, IPA_MAX_PROD_PIPES_FMASK);
        if (max > IPA_ENDPOINT_MAX) {
                dev_err(dev, "too many endpoints (%u > %u)\n",
                        max, IPA_ENDPOINT_MAX);
@@ -1548,7 +1674,7 @@ int ipa_endpoint_config(struct ipa *ipa)
        rx_mask = GENMASK(max - 1, rx_base);
 
        /* Our TX is an IPA consumer */
-       max = u32_get_bits(val, BAM_MAX_CONS_PIPES_FMASK);
+       max = u32_get_bits(val, IPA_MAX_CONS_PIPES_FMASK);
        tx_mask = GENMASK(max - 1, 0);
 
        ipa->available = rx_mask | tx_mask;