diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ipa/gsi.c | 20 | ||||
-rw-r--r-- | drivers/net/ipa/gsi.h | 2 | ||||
-rw-r--r-- | drivers/net/ipa/gsi_reg.h | 2 |
3 files changed, 19 insertions, 5 deletions
diff --git a/drivers/net/ipa/gsi.c b/drivers/net/ipa/gsi.c index ee4893c60beb..bc981043cc80 100644 --- a/drivers/net/ipa/gsi.c +++ b/drivers/net/ipa/gsi.c @@ -93,6 +93,7 @@ #define GSI_CHANNEL_STOP_RETRIES 10 #define GSI_CHANNEL_MODEM_HALT_RETRIES 10 +#define GSI_CHANNEL_MODEM_FLOW_RETRIES 5 /* disable flow control only */ #define GSI_MHI_EVENT_ID_START 10 /* 1st reserved event id */ #define GSI_MHI_EVENT_ID_END 16 /* Last reserved event id */ @@ -1649,7 +1650,8 @@ static void gsi_channel_teardown_one(struct gsi *gsi, u32 channel_id) * issue the command and wait for it to complete. */ static int gsi_generic_command(struct gsi *gsi, u32 channel_id, - enum gsi_generic_cmd_opcode opcode) + enum gsi_generic_cmd_opcode opcode, + u8 params) { bool timeout; u32 val; @@ -1675,6 +1677,7 @@ static int gsi_generic_command(struct gsi *gsi, u32 channel_id, val = u32_encode_bits(opcode, GENERIC_OPCODE_FMASK); val |= u32_encode_bits(channel_id, GENERIC_CHID_FMASK); val |= u32_encode_bits(GSI_EE_MODEM, GENERIC_EE_FMASK); + val |= u32_encode_bits(params, GENERIC_PARAMS_FMASK); timeout = !gsi_command(gsi, GSI_GENERIC_CMD_OFFSET, val); @@ -1693,7 +1696,7 @@ static int gsi_generic_command(struct gsi *gsi, u32 channel_id, static int gsi_modem_channel_alloc(struct gsi *gsi, u32 channel_id) { return gsi_generic_command(gsi, channel_id, - GSI_GENERIC_ALLOCATE_CHANNEL); + GSI_GENERIC_ALLOCATE_CHANNEL, 0); } static void gsi_modem_channel_halt(struct gsi *gsi, u32 channel_id) @@ -1703,7 +1706,7 @@ static void gsi_modem_channel_halt(struct gsi *gsi, u32 channel_id) do ret = gsi_generic_command(gsi, channel_id, - GSI_GENERIC_HALT_CHANNEL); + GSI_GENERIC_HALT_CHANNEL, 0); while (ret == -EAGAIN && retries--); if (ret) @@ -1715,13 +1718,22 @@ static void gsi_modem_channel_halt(struct gsi *gsi, u32 channel_id) void gsi_modem_channel_flow_control(struct gsi *gsi, u32 channel_id, bool enable) { + u32 retries = 0; u32 command; int ret; command = enable ? GSI_GENERIC_ENABLE_FLOW_CONTROL : GSI_GENERIC_DISABLE_FLOW_CONTROL; + /* Disabling flow control on IPA v4.11+ can return -EAGAIN if enable + * is underway. In this case we need to retry the command. + */ + if (!enable && gsi->version >= IPA_VERSION_4_11) + retries = GSI_CHANNEL_MODEM_FLOW_RETRIES; + + do + ret = gsi_generic_command(gsi, channel_id, command, 0); + while (ret == -EAGAIN && retries--); - ret = gsi_generic_command(gsi, channel_id, command); if (ret) dev_err(gsi->dev, "error %d %sabling mode channel %u flow control\n", diff --git a/drivers/net/ipa/gsi.h b/drivers/net/ipa/gsi.h index 1af6266683e2..9cc657658811 100644 --- a/drivers/net/ipa/gsi.h +++ b/drivers/net/ipa/gsi.h @@ -101,7 +101,7 @@ enum gsi_channel_state { GSI_CHANNEL_STATE_STARTED = 0x2, GSI_CHANNEL_STATE_STOPPED = 0x3, GSI_CHANNEL_STATE_STOP_IN_PROC = 0x4, - GSI_CHANNEL_STATE_FLOW_CONTROLLED = 0x5, /* IPA v4.2+ */ + GSI_CHANNEL_STATE_FLOW_CONTROLLED = 0x5, /* IPA v4.2-v4.9 */ GSI_CHANNEL_STATE_ERROR = 0xf, }; diff --git a/drivers/net/ipa/gsi_reg.h b/drivers/net/ipa/gsi_reg.h index 4ab23998b348..8906f4381032 100644 --- a/drivers/net/ipa/gsi_reg.h +++ b/drivers/net/ipa/gsi_reg.h @@ -313,6 +313,7 @@ enum gsi_evt_cmd_opcode { #define GENERIC_OPCODE_FMASK GENMASK(4, 0) #define GENERIC_CHID_FMASK GENMASK(9, 5) #define GENERIC_EE_FMASK GENMASK(13, 10) +#define GENERIC_PARAMS_FMASK GENMASK(31, 24) /* IPA v4.11+ */ /** enum gsi_generic_cmd_opcode - GENERIC_OPCODE field values in GENERIC_CMD */ enum gsi_generic_cmd_opcode { @@ -320,6 +321,7 @@ enum gsi_generic_cmd_opcode { GSI_GENERIC_ALLOCATE_CHANNEL = 0x2, GSI_GENERIC_ENABLE_FLOW_CONTROL = 0x3, /* IPA v4.2+ */ GSI_GENERIC_DISABLE_FLOW_CONTROL = 0x4, /* IPA v4.2+ */ + GSI_GENERIC_QUERY_FLOW_CONTROL = 0x5, /* IPA v4.11+ */ }; /* The next register is present for IPA v3.5.1 and above */ |