Skip to content

Commit 1f52d7b

Browse files
mchetankumardavem330
authored andcommitted
net: wwan: iosm: Enable M.2 7360 WWAN card support
This patch enables Intel M.2 7360 WWAN card support on IOSM Driver. Control path implementation is a reuse whereas data path implementation it uses a different protocol called as MUX Aggregation. The major portion of this patch covers the MUX Aggregation protocol implementation used for IP traffic communication. For M.2 7360 WWAN card, driver exposes 2 wwan AT ports for control communication. The user space application or the modem manager to use wwan AT port for data path establishment. During probe, driver reads the mux protocol device capability register to know the mux protocol version supported by device. Base on which the right mux protocol is initialized for data path communication. An overview of an Aggregation Protocol 1> An IP packet is encapsulated with 16 octet padding header to form a Datagram & the start offset of the Datagram is indexed into Datagram Header (DH). 2> Multiple such Datagrams are composed & the start offset of each DH is indexed into Datagram Table Header (DTH). 3> The Datagram Table (DT) is IP session specific & table_length item in DTH holds the number of composed datagram pertaining to that particular IP session. 4> And finally the offset of first DTH is indexed into DBH (Datagram Block Header). So in TX/RX flow Datagram Block (Datagram Block Header + Payload)is exchanged between driver & device. Signed-off-by: M Chetan Kumar <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent f126ec9 commit 1f52d7b

File tree

10 files changed

+1033
-78
lines changed

10 files changed

+1033
-78
lines changed

drivers/net/wwan/iosm/iosm_ipc_imem.c

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,17 +114,35 @@ ipc_imem_fast_update_timer_cb(struct hrtimer *hr_timer)
114114
return HRTIMER_NORESTART;
115115
}
116116

117+
static int ipc_imem_tq_adb_timer_cb(struct iosm_imem *ipc_imem, int arg,
118+
void *msg, size_t size)
119+
{
120+
ipc_mux_ul_adb_finish(ipc_imem->mux);
121+
return 0;
122+
}
123+
124+
static enum hrtimer_restart
125+
ipc_imem_adb_timer_cb(struct hrtimer *hr_timer)
126+
{
127+
struct iosm_imem *ipc_imem =
128+
container_of(hr_timer, struct iosm_imem, adb_timer);
129+
130+
ipc_task_queue_send_task(ipc_imem, ipc_imem_tq_adb_timer_cb, 0,
131+
NULL, 0, false);
132+
return HRTIMER_NORESTART;
133+
}
134+
117135
static int ipc_imem_setup_cp_mux_cap_init(struct iosm_imem *ipc_imem,
118136
struct ipc_mux_config *cfg)
119137
{
120138
ipc_mmio_update_cp_capability(ipc_imem->mmio);
121139

122-
if (!ipc_imem->mmio->has_mux_lite) {
140+
if (ipc_imem->mmio->mux_protocol == MUX_UNKNOWN) {
123141
dev_err(ipc_imem->dev, "Failed to get Mux capability.");
124142
return -EINVAL;
125143
}
126144

127-
cfg->protocol = MUX_LITE;
145+
cfg->protocol = ipc_imem->mmio->mux_protocol;
128146

129147
cfg->ul_flow = (ipc_imem->mmio->has_ul_flow_credit == 1) ?
130148
MUX_UL_ON_CREDITS :
@@ -153,6 +171,10 @@ void ipc_imem_msg_send_feature_set(struct iosm_imem *ipc_imem,
153171
IPC_MSG_PREP_FEATURE_SET, &prep_args);
154172
}
155173

174+
/**
175+
* ipc_imem_td_update_timer_start - Starts the TD Update Timer if not started.
176+
* @ipc_imem: Pointer to imem data-struct
177+
*/
156178
void ipc_imem_td_update_timer_start(struct iosm_imem *ipc_imem)
157179
{
158180
/* Use the TD update timer only in the runtime phase */
@@ -179,6 +201,21 @@ void ipc_imem_hrtimer_stop(struct hrtimer *hr_timer)
179201
hrtimer_cancel(hr_timer);
180202
}
181203

204+
/**
205+
* ipc_imem_adb_timer_start - Starts the adb Timer if not starting.
206+
* @ipc_imem: Pointer to imem data-struct
207+
*/
208+
void ipc_imem_adb_timer_start(struct iosm_imem *ipc_imem)
209+
{
210+
if (!hrtimer_active(&ipc_imem->adb_timer)) {
211+
ipc_imem->hrtimer_period =
212+
ktime_set(0, IOSM_AGGR_MUX_ADB_FINISH_TIMEOUT_NSEC);
213+
hrtimer_start(&ipc_imem->adb_timer,
214+
ipc_imem->hrtimer_period,
215+
HRTIMER_MODE_REL);
216+
}
217+
}
218+
182219
bool ipc_imem_ul_write_td(struct iosm_imem *ipc_imem)
183220
{
184221
struct ipc_mem_channel *channel;
@@ -550,6 +587,11 @@ static void ipc_imem_run_state_worker(struct work_struct *instance)
550587
while (ctrl_chl_idx < IPC_MEM_MAX_CHANNELS) {
551588
if (!ipc_chnl_cfg_get(&chnl_cfg_port, ctrl_chl_idx)) {
552589
ipc_imem->ipc_port[ctrl_chl_idx] = NULL;
590+
if (ipc_imem->pcie->pci->device == INTEL_CP_DEVICE_7360_ID &&
591+
chnl_cfg_port.wwan_port_type == WWAN_PORT_MBIM) {
592+
ctrl_chl_idx++;
593+
continue;
594+
}
553595
if (chnl_cfg_port.wwan_port_type != WWAN_PORT_UNKNOWN) {
554596
ipc_imem_channel_init(ipc_imem, IPC_CTYPE_CTRL,
555597
chnl_cfg_port,
@@ -680,8 +722,11 @@ static void ipc_imem_handle_irq(struct iosm_imem *ipc_imem, int irq)
680722
}
681723

682724
/* Try to generate new ADB or ADGH. */
683-
if (ipc_mux_ul_data_encode(ipc_imem->mux))
725+
if (ipc_mux_ul_data_encode(ipc_imem->mux)) {
684726
ipc_imem_td_update_timer_start(ipc_imem);
727+
if (ipc_imem->mux->protocol == MUX_AGGREGATION)
728+
ipc_imem_adb_timer_start(ipc_imem);
729+
}
685730

686731
/* Continue the send procedure with accumulated SIO or NETIF packets.
687732
* Reset the debounce flags.
@@ -1330,6 +1375,9 @@ struct iosm_imem *ipc_imem_init(struct iosm_pcie *pcie, unsigned int device_id,
13301375
HRTIMER_MODE_REL);
13311376
ipc_imem->td_alloc_timer.function = ipc_imem_td_alloc_timer_cb;
13321377

1378+
hrtimer_init(&ipc_imem->adb_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
1379+
ipc_imem->adb_timer.function = ipc_imem_adb_timer_cb;
1380+
13331381
if (ipc_imem_config(ipc_imem)) {
13341382
dev_err(ipc_imem->dev, "failed to initialize the imem");
13351383
goto imem_config_fail;

drivers/net/wwan/iosm/iosm_ipc_imem.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ enum ipc_phase {
317317
* @tdupdate_timer: Delay the TD update doorbell.
318318
* @fast_update_timer: forced head pointer update delay timer.
319319
* @td_alloc_timer: Timer for DL pipe TD allocation retry
320+
* @adb_timer: Timer for finishing the ADB.
320321
* @rom_exit_code: Mapped boot rom exit code.
321322
* @enter_runtime: 1 means the transition to runtime phase was
322323
* executed.
@@ -364,6 +365,7 @@ struct iosm_imem {
364365
struct hrtimer tdupdate_timer;
365366
struct hrtimer fast_update_timer;
366367
struct hrtimer td_alloc_timer;
368+
struct hrtimer adb_timer;
367369
enum rom_exit_code rom_exit_code;
368370
u32 enter_runtime;
369371
struct completion ul_pend_sem;
@@ -593,4 +595,7 @@ void ipc_imem_channel_init(struct iosm_imem *ipc_imem, enum ipc_ctype ctype,
593595
* Returns: 0 on success, -1 on failure
594596
*/
595597
int ipc_imem_devlink_trigger_chip_info(struct iosm_imem *ipc_imem);
598+
599+
void ipc_imem_adb_timer_start(struct iosm_imem *ipc_imem);
600+
596601
#endif

drivers/net/wwan/iosm/iosm_ipc_mmio.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <linux/slab.h>
1111

1212
#include "iosm_ipc_mmio.h"
13+
#include "iosm_ipc_mux.h"
1314

1415
/* Definition of MMIO offsets
1516
* note that MMIO_CI offsets are relative to end of chip info structure
@@ -71,8 +72,9 @@ void ipc_mmio_update_cp_capability(struct iosm_mmio *ipc_mmio)
7172
ver = ipc_mmio_get_cp_version(ipc_mmio);
7273
cp_cap = ioread32(ipc_mmio->base + ipc_mmio->offset.cp_capability);
7374

74-
ipc_mmio->has_mux_lite = (ver >= IOSM_CP_VERSION) &&
75-
!(cp_cap & DL_AGGR) && !(cp_cap & UL_AGGR);
75+
ipc_mmio->mux_protocol = ((ver >= IOSM_CP_VERSION) && (cp_cap &
76+
(UL_AGGR | DL_AGGR))) ? MUX_AGGREGATION
77+
: MUX_LITE;
7678

7779
ipc_mmio->has_ul_flow_credit =
7880
(ver >= IOSM_CP_VERSION) && (cp_cap & UL_FLOW_CREDIT);

drivers/net/wwan/iosm/iosm_ipc_mmio.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ struct mmio_offset {
7272
* @context_info_addr: Physical base address of context info structure
7373
* @chip_info_version: Version of chip info structure
7474
* @chip_info_size: Size of chip info structure
75-
* @has_mux_lite: It doesn't support mux aggergation
75+
* @mux_protocol: mux protocol
7676
* @has_ul_flow_credit: Ul flow credit support
7777
* @has_slp_no_prot: Device sleep no protocol support
7878
* @has_mcr_support: Usage of mcr support
@@ -84,8 +84,8 @@ struct iosm_mmio {
8484
phys_addr_t context_info_addr;
8585
unsigned int chip_info_version;
8686
unsigned int chip_info_size;
87-
u8 has_mux_lite:1,
88-
has_ul_flow_credit:1,
87+
u32 mux_protocol;
88+
u8 has_ul_flow_credit:1,
8989
has_slp_no_prot:1,
9090
has_mcr_support:1;
9191
};

drivers/net/wwan/iosm/iosm_ipc_mux.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,9 +279,10 @@ struct iosm_mux *ipc_mux_init(struct ipc_mux_config *mux_cfg,
279279
struct iosm_imem *imem)
280280
{
281281
struct iosm_mux *ipc_mux = kzalloc(sizeof(*ipc_mux), GFP_KERNEL);
282-
int i, ul_tds, ul_td_size;
282+
int i, j, ul_tds, ul_td_size;
283283
struct sk_buff_head *free_list;
284284
struct sk_buff *skb;
285+
int qlt_size;
285286

286287
if (!ipc_mux)
287288
return NULL;
@@ -321,6 +322,24 @@ struct iosm_mux *ipc_mux_init(struct ipc_mux_config *mux_cfg,
321322
ipc_mux->channel_id = -1;
322323
ipc_mux->channel = NULL;
323324

325+
if (ipc_mux->protocol != MUX_LITE) {
326+
qlt_size = offsetof(struct mux_qlth, ql) +
327+
MUX_QUEUE_LEVEL * sizeof(struct mux_qlth_ql);
328+
329+
for (i = 0; i < IPC_MEM_MUX_IP_SESSION_ENTRIES; i++) {
330+
ipc_mux->ul_adb.pp_qlt[i] = kzalloc(qlt_size,
331+
GFP_ATOMIC);
332+
if (!ipc_mux->ul_adb.pp_qlt[i]) {
333+
for (j = i - 1; j >= 0; j--)
334+
kfree(ipc_mux->ul_adb.pp_qlt[j]);
335+
return NULL;
336+
}
337+
}
338+
339+
ul_td_size = IPC_MEM_MAX_UL_ADB_BUF_SIZE;
340+
ul_tds = IPC_MEM_MAX_TDS_MUX_AGGR_UL;
341+
}
342+
324343
/* Allocate the list of UL ADB. */
325344
for (i = 0; i < ul_tds; i++) {
326345
dma_addr_t mapping;

drivers/net/wwan/iosm/iosm_ipc_mux.h

Lines changed: 118 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@
88

99
#include "iosm_ipc_protocol.h"
1010

11-
/* Size of the buffer for the IP MUX data buffer. */
12-
#define IPC_MEM_MAX_DL_MUX_BUF_SIZE (16 * 1024)
13-
#define IPC_MEM_MAX_UL_ADB_BUF_SIZE IPC_MEM_MAX_DL_MUX_BUF_SIZE
11+
#define IPC_MEM_MAX_UL_DG_ENTRIES 100
12+
#define IPC_MEM_MAX_TDS_MUX_AGGR_UL 60
13+
14+
#define IPC_MEM_MAX_ADB_BUF_SIZE (16 * 1024)
15+
#define IPC_MEM_MAX_UL_ADB_BUF_SIZE IPC_MEM_MAX_ADB_BUF_SIZE
16+
#define IPC_MEM_MAX_DL_ADB_BUF_SIZE IPC_MEM_MAX_ADB_BUF_SIZE
1417

1518
/* Size of the buffer for the IP MUX Lite data buffer. */
1619
#define IPC_MEM_MAX_DL_MUX_LITE_BUF_SIZE (2 * 1024)
@@ -167,6 +170,7 @@ enum mux_state {
167170
enum ipc_mux_protocol {
168171
MUX_UNKNOWN,
169172
MUX_LITE,
173+
MUX_AGGREGATION,
170174
};
171175

172176
/* Supported UL data transfer methods. */
@@ -192,24 +196,111 @@ struct mux_session {
192196
flush:1; /* flush net interface ? */
193197
};
194198

195-
/* State of a single UL data block. */
199+
/**
200+
* struct mux_adth_dg - Structure of the datagram in the Aggregated Datagram
201+
* Table Header.
202+
* @datagram_index : Index (in bytes) to the k-th datagram in the table.
203+
* Index shall count from the start of the block including
204+
* the 16-byte header. This value shall be non-zero.
205+
* @datagram_length: Length of the k-th datagram including the head padding.
206+
* This value shall be non-zero.
207+
* @service_class: Service class identifier for the datagram.
208+
* @reserved: Reserved bytes. Set to zero
209+
*/
210+
struct mux_adth_dg {
211+
__le32 datagram_index;
212+
__le16 datagram_length;
213+
u8 service_class;
214+
u8 reserved;
215+
};
216+
217+
/**
218+
* struct mux_qlth_ql - Structure of the queue level in the Aggregated
219+
* Datagram Queue Level Table Header.
220+
* @nr_of_bytes: Number of bytes available to transmit in the queue.
221+
*/
222+
struct mux_qlth_ql {
223+
__le32 nr_of_bytes;
224+
};
225+
226+
/**
227+
* struct mux_qlth - Structure of Aggregated Datagram Queue Level Table
228+
* Header.
229+
* @signature: Signature of the Queue Level Table Header
230+
* Value: 0x48544C51 (ASCII characters: 'Q' 'L' 'T' 'H')
231+
* @table_length: Length (in bytes) of the datagram table. This length
232+
* shall include the queue level table header size.
233+
* Minimum value:0x10
234+
* @if_id: ID of the interface the queue levels in the table
235+
* belong to.
236+
* @reserved: Reserved byte. Set to zero.
237+
* @next_table_index: Index (in bytes) to the next table in the buffer. Index
238+
* shall count from the start of the block including the
239+
* 16-byte header. Value of zero indicates end of the list.
240+
* @reserved2: Reserved bytes. Set to zero
241+
* @ql: Queue level table with variable length
242+
*/
243+
struct mux_qlth {
244+
__le32 signature;
245+
__le16 table_length;
246+
u8 if_id;
247+
u8 reserved;
248+
__le32 next_table_index;
249+
__le32 reserved2;
250+
struct mux_qlth_ql ql;
251+
};
252+
253+
/**
254+
* struct mux_adb - Structure of State of a single UL data block.
255+
* @dest_skb: Current UL skb for the data block.
256+
* @buf: ADB memory
257+
* @adgh: ADGH pointer
258+
* @qlth_skb: QLTH pointer
259+
* @next_table_index: Pointer to next table index.
260+
* @free_list: List of alloc. ADB for the UL sess.
261+
* @size: Size of the ADB memory.
262+
* @if_cnt: Statistic counter
263+
* @dg_cnt_total: Datagram count total
264+
* @payload_size: Payload Size
265+
* @dg: Datagram table.
266+
* @pp_qlt: Pointers to hold Queue Level Tables of session
267+
* @adbh: ADBH pointer
268+
* @qlt_updated: Queue level table updated
269+
* @dg_count: Datagram count
270+
*/
196271
struct mux_adb {
197-
struct sk_buff *dest_skb; /* Current UL skb for the data block. */
198-
u8 *buf; /* ADB memory. */
199-
struct mux_adgh *adgh; /* ADGH pointer */
200-
struct sk_buff *qlth_skb; /* QLTH pointer */
201-
u32 *next_table_index; /* Pointer to next table index. */
202-
struct sk_buff_head free_list; /* List of alloc. ADB for the UL sess.*/
203-
int size; /* Size of the ADB memory. */
204-
u32 if_cnt; /* Statistic counter */
272+
struct sk_buff *dest_skb;
273+
u8 *buf;
274+
struct mux_adgh *adgh;
275+
struct sk_buff *qlth_skb;
276+
u32 *next_table_index;
277+
struct sk_buff_head free_list;
278+
int size;
279+
u32 if_cnt;
205280
u32 dg_cnt_total;
206281
u32 payload_size;
282+
struct mux_adth_dg
283+
dg[IPC_MEM_MUX_IP_SESSION_ENTRIES][IPC_MEM_MAX_UL_DG_ENTRIES];
284+
struct mux_qlth *pp_qlt[IPC_MEM_MUX_IP_SESSION_ENTRIES];
285+
struct mux_adbh *adbh;
286+
u32 qlt_updated[IPC_MEM_MUX_IP_SESSION_ENTRIES];
287+
u32 dg_count[IPC_MEM_MUX_IP_SESSION_ENTRIES];
207288
};
208289

209-
/* Temporary ACB state. */
290+
/**
291+
* struct mux_acb - Structure of Temporary ACB state.
292+
* @skb: Used UL skb.
293+
* @if_id: Session id.
294+
* @buf_p: Command buffer.
295+
* @wanted_response: Wanted Response
296+
* @got_response: Got response
297+
* @cmd: command
298+
* @got_param: Received command/response parameter
299+
*/
210300
struct mux_acb {
211301
struct sk_buff *skb; /* Used UL skb. */
212302
int if_id; /* Session id. */
303+
u8 *buf_p;
213304
u32 wanted_response;
214305
u32 got_response;
215306
u32 cmd;
@@ -241,6 +332,12 @@ struct mux_acb {
241332
* @wwan_q_offset: This will hold the offset of the given instance
242333
* Useful while passing or receiving packets from
243334
* wwan/imem layer.
335+
* @adb_finish_timer: Timer for forcefully finishing the ADB
336+
* @acb_tx_sequence_nr: Sequence number for the ACB header.
337+
* @params: user configurable parameters
338+
* @adb_tx_sequence_nr: Sequence number for ADB header
339+
* @acc_adb_size: Statistic data for logging
340+
* @acc_payload_size: Statistic data for logging
244341
* @initialized: MUX object is initialized
245342
* @ev_mux_net_transmit_pending:
246343
* 0 means inform the IPC tasklet to pass the
@@ -269,10 +366,16 @@ struct iosm_mux {
269366
long long ul_data_pend_bytes;
270367
struct mux_acb acb;
271368
int wwan_q_offset;
369+
struct hrtimer adb_finish_timer;
370+
u16 acb_tx_sequence_nr;
371+
struct ipc_params *params;
372+
u16 adb_tx_sequence_nr;
373+
unsigned long long acc_adb_size;
374+
unsigned long long acc_payload_size;
272375
u8 initialized:1,
273376
ev_mux_net_transmit_pending:1,
274-
adb_prep_ongoing:1;
275-
};
377+
adb_prep_ongoing;
378+
} __packed;
276379

277380
/* MUX configuration structure */
278381
struct ipc_mux_config {

0 commit comments

Comments
 (0)