diff options
Diffstat (limited to 'drivers/net/ipa')
-rw-r--r-- | drivers/net/ipa/ipa_data-sdm845.c | 1 | ||||
-rw-r--r-- | drivers/net/ipa/ipa_data.h | 6 | ||||
-rw-r--r-- | drivers/net/ipa/ipa_endpoint.c | 85 |
3 files changed, 49 insertions, 43 deletions
diff --git a/drivers/net/ipa/ipa_data-sdm845.c b/drivers/net/ipa/ipa_data-sdm845.c index f7ba85717edf..52d4b84e0dac 100644 --- a/drivers/net/ipa/ipa_data-sdm845.c +++ b/drivers/net/ipa/ipa_data-sdm845.c @@ -74,7 +74,6 @@ static const struct ipa_gsi_endpoint_data ipa_gsi_endpoint_data[] = { .tx = { .status_endpoint = IPA_ENDPOINT_MODEM_AP_RX, - .delay = true, }, }, }, diff --git a/drivers/net/ipa/ipa_data.h b/drivers/net/ipa/ipa_data.h index 16dfd74717b1..7fc1058a5ca9 100644 --- a/drivers/net/ipa/ipa_data.h +++ b/drivers/net/ipa/ipa_data.h @@ -80,18 +80,12 @@ struct gsi_channel_data { /** * struct ipa_endpoint_tx_data - configuration data for TX endpoints * @status_endpoint: endpoint to which status elements are sent - * @delay: whether endpoint starts in delay mode - * - * Delay mode prevents a TX endpoint from transmitting anything, even if - * commands have been presented to the hardware. Once the endpoint exits - * delay mode, queued transfer commands are sent. * * The @status_endpoint is only valid if the endpoint's @status_enable * flag is set. */ struct ipa_endpoint_tx_data { enum ipa_endpoint_name status_endpoint; - bool delay; }; /** diff --git a/drivers/net/ipa/ipa_endpoint.c b/drivers/net/ipa/ipa_endpoint.c index db82ae48e402..dec1dc8618ed 100644 --- a/drivers/net/ipa/ipa_endpoint.c +++ b/drivers/net/ipa/ipa_endpoint.c @@ -284,25 +284,52 @@ static struct gsi_trans *ipa_endpoint_trans_alloc(struct ipa_endpoint *endpoint, /* suspend_delay represents suspend for RX, delay for TX endpoints. * Note that suspend is not supported starting with IPA v4.0. */ -static int +static bool ipa_endpoint_init_ctrl(struct ipa_endpoint *endpoint, bool suspend_delay) { u32 offset = IPA_REG_ENDP_INIT_CTRL_N_OFFSET(endpoint->endpoint_id); struct ipa *ipa = endpoint->ipa; + bool state; u32 mask; u32 val; - /* assert(ipa->version == IPA_VERSION_3_5_1 */ + /* Suspend is not supported for IPA v4.0+. Delay doesn't work + * correctly on IPA v4.2. + * + * if (endpoint->toward_ipa) + * assert(ipa->version != IPA_VERSION_4.2); + * else + * assert(ipa->version == IPA_VERSION_3_5_1); + */ mask = endpoint->toward_ipa ? ENDP_DELAY_FMASK : ENDP_SUSPEND_FMASK; val = ioread32(ipa->reg_virt + offset); - if (suspend_delay == !!(val & mask)) - return -EALREADY; /* Already set to desired state */ + /* Don't bother if it's already in the requested state */ + state = !!(val & mask); + if (suspend_delay != state) { + val ^= mask; + iowrite32(val, ipa->reg_virt + offset); + } - val ^= mask; - iowrite32(val, ipa->reg_virt + offset); + return state; +} - return 0; +/* We currently don't care what the previous state was for delay mode */ +static void +ipa_endpoint_program_delay(struct ipa_endpoint *endpoint, bool enable) +{ + /* assert(endpoint->toward_ipa); */ + + (void)ipa_endpoint_init_ctrl(endpoint, enable); +} + +/* Returns previous suspend state (true means it was enabled) */ +static bool +ipa_endpoint_program_suspend(struct ipa_endpoint *endpoint, bool enable) +{ + /* assert(!endpoint->toward_ipa); */ + + return ipa_endpoint_init_ctrl(endpoint, enable); } /* Enable or disable delay or suspend mode on all modem endpoints */ @@ -311,7 +338,7 @@ void ipa_endpoint_modem_pause_all(struct ipa *ipa, bool enable) bool support_suspend; u32 endpoint_id; - /* DELAY mode doesn't work right on IPA v4.2 */ + /* DELAY mode doesn't work correctly on IPA v4.2 */ if (ipa->version == IPA_VERSION_4_2) return; @@ -325,8 +352,10 @@ void ipa_endpoint_modem_pause_all(struct ipa *ipa, bool enable) continue; /* Set TX delay mode, or for IPA v3.5.1 RX suspend mode */ - if (endpoint->toward_ipa || support_suspend) - (void)ipa_endpoint_init_ctrl(endpoint, enable); + if (endpoint->toward_ipa) + ipa_endpoint_program_delay(endpoint, enable); + else if (support_suspend) + (void)ipa_endpoint_program_suspend(endpoint, enable); } } @@ -1133,8 +1162,8 @@ static int ipa_endpoint_reset_rx_aggr(struct ipa_endpoint *endpoint) { struct device *dev = &endpoint->ipa->pdev->dev; struct ipa *ipa = endpoint->ipa; - bool endpoint_suspended = false; struct gsi *gsi = &ipa->gsi; + bool suspended = false; dma_addr_t addr; bool legacy; u32 retries; @@ -1164,8 +1193,7 @@ static int ipa_endpoint_reset_rx_aggr(struct ipa_endpoint *endpoint) /* Make sure the channel isn't suspended */ if (endpoint->ipa->version == IPA_VERSION_3_5_1) - if (!ipa_endpoint_init_ctrl(endpoint, false)) - endpoint_suspended = true; + suspended = ipa_endpoint_program_suspend(endpoint, false); /* Start channel and do a 1 byte read */ ret = gsi_channel_start(gsi, endpoint->channel_id); @@ -1210,8 +1238,8 @@ static int ipa_endpoint_reset_rx_aggr(struct ipa_endpoint *endpoint) err_endpoint_stop: ipa_endpoint_stop(endpoint); out_suspend_again: - if (endpoint_suspended) - (void)ipa_endpoint_init_ctrl(endpoint, true); + if (suspended) + (void)ipa_endpoint_program_suspend(endpoint, true); dma_unmap_single(dev, addr, len, DMA_FROM_DEVICE); out_kfree: kfree(virt); @@ -1312,31 +1340,16 @@ int ipa_endpoint_stop(struct ipa_endpoint *endpoint) static void ipa_endpoint_program(struct ipa_endpoint *endpoint) { - struct device *dev = &endpoint->ipa->pdev->dev; - int ret; - if (endpoint->toward_ipa) { - bool delay_mode = endpoint->data->tx.delay; - - ret = ipa_endpoint_init_ctrl(endpoint, delay_mode); - /* Endpoint is expected to not be in delay mode */ - if (!ret != delay_mode) { - dev_warn(dev, - "TX endpoint %u was %sin delay mode\n", - endpoint->endpoint_id, - delay_mode ? "already " : ""); - } + if (endpoint->ipa->version != IPA_VERSION_4_2) + ipa_endpoint_program_delay(endpoint, false); ipa_endpoint_init_hdr_ext(endpoint); ipa_endpoint_init_aggr(endpoint); ipa_endpoint_init_deaggr(endpoint); ipa_endpoint_init_seq(endpoint); } else { - if (endpoint->ipa->version == IPA_VERSION_3_5_1) { - if (!ipa_endpoint_init_ctrl(endpoint, false)) - dev_warn(dev, - "RX endpoint %u was suspended\n", - endpoint->endpoint_id); - } + if (endpoint->ipa->version == IPA_VERSION_3_5_1) + (void)ipa_endpoint_program_suspend(endpoint, false); ipa_endpoint_init_hdr_ext(endpoint); ipa_endpoint_init_aggr(endpoint); } @@ -1448,7 +1461,7 @@ void ipa_endpoint_suspend_one(struct ipa_endpoint *endpoint) * aggregation frame, then simulating the arrival of such * an interrupt. */ - WARN_ON(ipa_endpoint_init_ctrl(endpoint, true)); + (void)ipa_endpoint_program_suspend(endpoint, true); ipa_endpoint_suspend_aggr(endpoint); } @@ -1471,7 +1484,7 @@ void ipa_endpoint_resume_one(struct ipa_endpoint *endpoint) /* IPA v3.5.1 doesn't use channel start for resume */ start_channel = endpoint->ipa->version != IPA_VERSION_3_5_1; if (!endpoint->toward_ipa && !start_channel) - WARN_ON(ipa_endpoint_init_ctrl(endpoint, false)); + (void)ipa_endpoint_program_suspend(endpoint, false); ret = gsi_channel_resume(gsi, endpoint->channel_id, start_channel); if (ret) |