0001
0002
0003
0004
0005
0006 #include "iosm_ipc_protocol.h"
0007 #include "iosm_ipc_protocol_ops.h"
0008
0009
0010 static union ipc_mem_msg_entry *
0011 ipc_protocol_free_msg_get(struct iosm_protocol *ipc_protocol, int *index)
0012 {
0013 u32 head = le32_to_cpu(ipc_protocol->p_ap_shm->msg_head);
0014 u32 new_head = (head + 1) % IPC_MEM_MSG_ENTRIES;
0015 union ipc_mem_msg_entry *msg;
0016
0017 if (new_head == le32_to_cpu(ipc_protocol->p_ap_shm->msg_tail)) {
0018 dev_err(ipc_protocol->dev, "message ring is full");
0019 return NULL;
0020 }
0021
0022
0023
0024
0025 msg = &ipc_protocol->p_ap_shm->msg_ring[head];
0026 memset(msg, 0, sizeof(*msg));
0027
0028
0029 *index = head;
0030
0031 return msg;
0032 }
0033
0034
0035 void ipc_protocol_msg_hp_update(struct iosm_imem *ipc_imem)
0036 {
0037 struct iosm_protocol *ipc_protocol = ipc_imem->ipc_protocol;
0038 u32 head = le32_to_cpu(ipc_protocol->p_ap_shm->msg_head);
0039 u32 new_head = (head + 1) % IPC_MEM_MSG_ENTRIES;
0040
0041
0042 ipc_protocol->p_ap_shm->msg_head = cpu_to_le32(new_head);
0043 ipc_protocol->old_msg_tail =
0044 le32_to_cpu(ipc_protocol->p_ap_shm->msg_tail);
0045
0046 ipc_pm_signal_hpda_doorbell(&ipc_protocol->pm, IPC_HP_MR, false);
0047 }
0048
0049
0050
0051
0052
0053 static int ipc_protocol_msg_prepipe_open(struct iosm_protocol *ipc_protocol,
0054 union ipc_msg_prep_args *args)
0055 {
0056 int index;
0057 union ipc_mem_msg_entry *msg =
0058 ipc_protocol_free_msg_get(ipc_protocol, &index);
0059 struct ipc_pipe *pipe = args->pipe_open.pipe;
0060 struct ipc_protocol_td *tdr;
0061 struct sk_buff **skbr;
0062
0063 if (!msg) {
0064 dev_err(ipc_protocol->dev, "failed to get free message");
0065 return -EIO;
0066 }
0067
0068
0069
0070
0071
0072 skbr = kcalloc(pipe->nr_of_entries, sizeof(*skbr), GFP_ATOMIC);
0073 if (!skbr)
0074 return -ENOMEM;
0075
0076
0077 tdr = dma_alloc_coherent(&ipc_protocol->pcie->pci->dev,
0078 pipe->nr_of_entries * sizeof(*tdr),
0079 &pipe->phy_tdr_start, GFP_ATOMIC);
0080 if (!tdr) {
0081 kfree(skbr);
0082 dev_err(ipc_protocol->dev, "tdr alloc error");
0083 return -ENOMEM;
0084 }
0085
0086 pipe->max_nr_of_queued_entries = pipe->nr_of_entries - 1;
0087 pipe->nr_of_queued_entries = 0;
0088 pipe->tdr_start = tdr;
0089 pipe->skbr_start = skbr;
0090 pipe->old_tail = 0;
0091
0092 ipc_protocol->p_ap_shm->head_array[pipe->pipe_nr] = 0;
0093
0094 msg->open_pipe.type_of_message = IPC_MEM_MSG_OPEN_PIPE;
0095 msg->open_pipe.pipe_nr = pipe->pipe_nr;
0096 msg->open_pipe.tdr_addr = cpu_to_le64(pipe->phy_tdr_start);
0097 msg->open_pipe.tdr_entries = cpu_to_le16(pipe->nr_of_entries);
0098 msg->open_pipe.accumulation_backoff =
0099 cpu_to_le32(pipe->accumulation_backoff);
0100 msg->open_pipe.irq_vector = cpu_to_le32(pipe->irq);
0101
0102 return index;
0103 }
0104
0105 static int ipc_protocol_msg_prepipe_close(struct iosm_protocol *ipc_protocol,
0106 union ipc_msg_prep_args *args)
0107 {
0108 int index = -1;
0109 union ipc_mem_msg_entry *msg =
0110 ipc_protocol_free_msg_get(ipc_protocol, &index);
0111 struct ipc_pipe *pipe = args->pipe_close.pipe;
0112
0113 if (!msg)
0114 return -EIO;
0115
0116 msg->close_pipe.type_of_message = IPC_MEM_MSG_CLOSE_PIPE;
0117 msg->close_pipe.pipe_nr = pipe->pipe_nr;
0118
0119 dev_dbg(ipc_protocol->dev, "IPC_MEM_MSG_CLOSE_PIPE(pipe_nr=%d)",
0120 msg->close_pipe.pipe_nr);
0121
0122 return index;
0123 }
0124
0125 static int ipc_protocol_msg_prep_sleep(struct iosm_protocol *ipc_protocol,
0126 union ipc_msg_prep_args *args)
0127 {
0128 int index = -1;
0129 union ipc_mem_msg_entry *msg =
0130 ipc_protocol_free_msg_get(ipc_protocol, &index);
0131
0132 if (!msg) {
0133 dev_err(ipc_protocol->dev, "failed to get free message");
0134 return -EIO;
0135 }
0136
0137
0138 msg->host_sleep.type_of_message = IPC_MEM_MSG_SLEEP;
0139 msg->host_sleep.target = args->sleep.target;
0140
0141
0142 msg->host_sleep.state = args->sleep.state;
0143
0144 dev_dbg(ipc_protocol->dev, "IPC_MEM_MSG_SLEEP(target=%d; state=%d)",
0145 msg->host_sleep.target, msg->host_sleep.state);
0146
0147 return index;
0148 }
0149
0150 static int ipc_protocol_msg_prep_feature_set(struct iosm_protocol *ipc_protocol,
0151 union ipc_msg_prep_args *args)
0152 {
0153 int index = -1;
0154 union ipc_mem_msg_entry *msg =
0155 ipc_protocol_free_msg_get(ipc_protocol, &index);
0156
0157 if (!msg) {
0158 dev_err(ipc_protocol->dev, "failed to get free message");
0159 return -EIO;
0160 }
0161
0162 msg->feature_set.type_of_message = IPC_MEM_MSG_FEATURE_SET;
0163 msg->feature_set.reset_enable = args->feature_set.reset_enable <<
0164 RESET_BIT;
0165
0166 dev_dbg(ipc_protocol->dev, "IPC_MEM_MSG_FEATURE_SET(reset_enable=%d)",
0167 msg->feature_set.reset_enable >> RESET_BIT);
0168
0169 return index;
0170 }
0171
0172
0173 bool ipc_protocol_msg_process(struct iosm_imem *ipc_imem, int irq)
0174 {
0175 struct iosm_protocol *ipc_protocol = ipc_imem->ipc_protocol;
0176 struct ipc_rsp **rsp_ring = ipc_protocol->rsp_ring;
0177 bool msg_processed = false;
0178 u32 i;
0179
0180 if (le32_to_cpu(ipc_protocol->p_ap_shm->msg_tail) >=
0181 IPC_MEM_MSG_ENTRIES) {
0182 dev_err(ipc_protocol->dev, "msg_tail out of range: %d",
0183 le32_to_cpu(ipc_protocol->p_ap_shm->msg_tail));
0184 return msg_processed;
0185 }
0186
0187 if (irq != IMEM_IRQ_DONT_CARE &&
0188 irq != ipc_protocol->p_ap_shm->ci.msg_irq_vector)
0189 return msg_processed;
0190
0191 for (i = ipc_protocol->old_msg_tail;
0192 i != le32_to_cpu(ipc_protocol->p_ap_shm->msg_tail);
0193 i = (i + 1) % IPC_MEM_MSG_ENTRIES) {
0194 union ipc_mem_msg_entry *msg =
0195 &ipc_protocol->p_ap_shm->msg_ring[i];
0196
0197 dev_dbg(ipc_protocol->dev, "msg[%d]: type=%u status=%d", i,
0198 msg->common.type_of_message,
0199 msg->common.completion_status);
0200
0201
0202 if (rsp_ring[i]) {
0203 rsp_ring[i]->status =
0204 le32_to_cpu(msg->common.completion_status);
0205 complete(&rsp_ring[i]->completion);
0206 rsp_ring[i] = NULL;
0207 }
0208 msg_processed = true;
0209 }
0210
0211 ipc_protocol->old_msg_tail = i;
0212 return msg_processed;
0213 }
0214
0215
0216
0217
0218 bool ipc_protocol_ul_td_send(struct iosm_protocol *ipc_protocol,
0219 struct ipc_pipe *pipe,
0220 struct sk_buff_head *p_ul_list)
0221 {
0222 struct ipc_protocol_td *td;
0223 bool hpda_pending = false;
0224 struct sk_buff *skb;
0225 s32 free_elements;
0226 u32 head;
0227 u32 tail;
0228
0229 if (!ipc_protocol->p_ap_shm) {
0230 dev_err(ipc_protocol->dev, "driver is not initialized");
0231 return false;
0232 }
0233
0234
0235
0236
0237 head = le32_to_cpu(ipc_protocol->p_ap_shm->head_array[pipe->pipe_nr]);
0238 tail = pipe->old_tail;
0239
0240 while (!skb_queue_empty(p_ul_list)) {
0241 if (head < tail)
0242 free_elements = tail - head - 1;
0243 else
0244 free_elements =
0245 pipe->nr_of_entries - head + ((s32)tail - 1);
0246
0247 if (free_elements <= 0) {
0248 dev_dbg(ipc_protocol->dev,
0249 "no free td elements for UL pipe %d",
0250 pipe->pipe_nr);
0251 break;
0252 }
0253
0254
0255 td = &pipe->tdr_start[head];
0256
0257
0258
0259
0260 skb = skb_dequeue(p_ul_list);
0261 if (WARN_ON(!skb))
0262 break;
0263
0264
0265 pipe->skbr_start[head] = skb;
0266
0267 td->buffer.address = IPC_CB(skb)->mapping;
0268 td->scs = cpu_to_le32(skb->len) & cpu_to_le32(SIZE_MASK);
0269 td->next = 0;
0270
0271 pipe->nr_of_queued_entries++;
0272
0273
0274 head++;
0275 if (head >= pipe->nr_of_entries)
0276 head = 0;
0277
0278 ipc_protocol->p_ap_shm->head_array[pipe->pipe_nr] =
0279 cpu_to_le32(head);
0280 }
0281
0282 if (pipe->old_head != head) {
0283 dev_dbg(ipc_protocol->dev, "New UL TDs Pipe:%d", pipe->pipe_nr);
0284
0285 pipe->old_head = head;
0286
0287 hpda_pending = true;
0288 }
0289
0290 return hpda_pending;
0291 }
0292
0293
0294 struct sk_buff *ipc_protocol_ul_td_process(struct iosm_protocol *ipc_protocol,
0295 struct ipc_pipe *pipe)
0296 {
0297 struct ipc_protocol_td *p_td = &pipe->tdr_start[pipe->old_tail];
0298 struct sk_buff *skb = pipe->skbr_start[pipe->old_tail];
0299
0300 pipe->nr_of_queued_entries--;
0301 pipe->old_tail++;
0302 if (pipe->old_tail >= pipe->nr_of_entries)
0303 pipe->old_tail = 0;
0304
0305 if (!p_td->buffer.address) {
0306 dev_err(ipc_protocol->dev, "Td buffer address is NULL");
0307 return NULL;
0308 }
0309
0310 if (p_td->buffer.address != IPC_CB(skb)->mapping) {
0311 dev_err(ipc_protocol->dev,
0312 "pipe %d: invalid buf_addr or skb_data",
0313 pipe->pipe_nr);
0314 return NULL;
0315 }
0316
0317 return skb;
0318 }
0319
0320
0321
0322
0323 bool ipc_protocol_dl_td_prepare(struct iosm_protocol *ipc_protocol,
0324 struct ipc_pipe *pipe)
0325 {
0326 struct ipc_protocol_td *td;
0327 dma_addr_t mapping = 0;
0328 u32 head, new_head;
0329 struct sk_buff *skb;
0330 u32 tail;
0331
0332
0333
0334
0335 head = le32_to_cpu(ipc_protocol->p_ap_shm->head_array[pipe->pipe_nr]);
0336 tail = le32_to_cpu(ipc_protocol->p_ap_shm->tail_array[pipe->pipe_nr]);
0337
0338 new_head = head + 1;
0339 if (new_head >= pipe->nr_of_entries)
0340 new_head = 0;
0341
0342 if (new_head == tail)
0343 return false;
0344
0345
0346 td = &pipe->tdr_start[head];
0347
0348
0349 skb = ipc_pcie_alloc_skb(ipc_protocol->pcie, pipe->buf_size, GFP_ATOMIC,
0350 &mapping, DMA_FROM_DEVICE,
0351 IPC_MEM_DL_ETH_OFFSET);
0352 if (!skb)
0353 return false;
0354
0355 td->buffer.address = mapping;
0356 td->scs = cpu_to_le32(pipe->buf_size) & cpu_to_le32(SIZE_MASK);
0357 td->next = 0;
0358
0359
0360 ipc_protocol->p_ap_shm->head_array[pipe->pipe_nr] =
0361 cpu_to_le32(new_head);
0362
0363
0364 pipe->skbr_start[head] = skb;
0365
0366 pipe->nr_of_queued_entries++;
0367
0368 return true;
0369 }
0370
0371
0372 struct sk_buff *ipc_protocol_dl_td_process(struct iosm_protocol *ipc_protocol,
0373 struct ipc_pipe *pipe)
0374 {
0375 struct ipc_protocol_td *p_td;
0376 struct sk_buff *skb;
0377
0378 if (!pipe->tdr_start)
0379 return NULL;
0380
0381
0382 p_td = &pipe->tdr_start[pipe->old_tail];
0383 skb = pipe->skbr_start[pipe->old_tail];
0384
0385
0386 pipe->skbr_start[pipe->old_tail] = NULL;
0387
0388 pipe->nr_of_queued_entries--;
0389
0390 pipe->old_tail++;
0391 if (pipe->old_tail >= pipe->nr_of_entries)
0392 pipe->old_tail = 0;
0393
0394 if (!skb) {
0395 dev_err(ipc_protocol->dev, "skb is null");
0396 goto ret;
0397 } else if (!p_td->buffer.address) {
0398 dev_err(ipc_protocol->dev, "td/buffer address is null");
0399 ipc_pcie_kfree_skb(ipc_protocol->pcie, skb);
0400 skb = NULL;
0401 goto ret;
0402 }
0403
0404 if (p_td->buffer.address != IPC_CB(skb)->mapping) {
0405 dev_err(ipc_protocol->dev, "invalid buf=%llx or skb=%p",
0406 (unsigned long long)p_td->buffer.address, skb->data);
0407 ipc_pcie_kfree_skb(ipc_protocol->pcie, skb);
0408 skb = NULL;
0409 goto ret;
0410 } else if ((le32_to_cpu(p_td->scs) & SIZE_MASK) > pipe->buf_size) {
0411 dev_err(ipc_protocol->dev, "invalid buffer size %d > %d",
0412 le32_to_cpu(p_td->scs) & SIZE_MASK,
0413 pipe->buf_size);
0414 ipc_pcie_kfree_skb(ipc_protocol->pcie, skb);
0415 skb = NULL;
0416 goto ret;
0417 } else if (le32_to_cpu(p_td->scs) >> COMPLETION_STATUS ==
0418 IPC_MEM_TD_CS_ABORT) {
0419
0420 dev_dbg(ipc_protocol->dev, "discard 'aborted' buffers");
0421 ipc_pcie_kfree_skb(ipc_protocol->pcie, skb);
0422 skb = NULL;
0423 goto ret;
0424 }
0425
0426
0427 skb_put(skb, le32_to_cpu(p_td->scs) & SIZE_MASK);
0428
0429 ret:
0430 return skb;
0431 }
0432
0433 void ipc_protocol_get_head_tail_index(struct iosm_protocol *ipc_protocol,
0434 struct ipc_pipe *pipe, u32 *head,
0435 u32 *tail)
0436 {
0437 struct ipc_protocol_ap_shm *ipc_ap_shm = ipc_protocol->p_ap_shm;
0438
0439 if (head)
0440 *head = le32_to_cpu(ipc_ap_shm->head_array[pipe->pipe_nr]);
0441
0442 if (tail)
0443 *tail = le32_to_cpu(ipc_ap_shm->tail_array[pipe->pipe_nr]);
0444 }
0445
0446
0447 void ipc_protocol_pipe_cleanup(struct iosm_protocol *ipc_protocol,
0448 struct ipc_pipe *pipe)
0449 {
0450 struct sk_buff *skb;
0451 u32 head;
0452 u32 tail;
0453
0454
0455 head = le32_to_cpu(ipc_protocol->p_ap_shm->head_array[pipe->pipe_nr]);
0456 tail = pipe->old_tail;
0457
0458
0459 ipc_protocol->p_ap_shm->tail_array[pipe->pipe_nr] = 0;
0460 ipc_protocol->p_ap_shm->head_array[pipe->pipe_nr] = 0;
0461
0462
0463 if (pipe->skbr_start) {
0464 while (head != tail) {
0465
0466
0467
0468 skb = pipe->skbr_start[tail];
0469 if (skb)
0470 ipc_pcie_kfree_skb(ipc_protocol->pcie, skb);
0471
0472 tail++;
0473 if (tail >= pipe->nr_of_entries)
0474 tail = 0;
0475 }
0476
0477 kfree(pipe->skbr_start);
0478 pipe->skbr_start = NULL;
0479 }
0480
0481 pipe->old_tail = 0;
0482
0483
0484 if (pipe->tdr_start) {
0485 dma_free_coherent(&ipc_protocol->pcie->pci->dev,
0486 sizeof(*pipe->tdr_start) * pipe->nr_of_entries,
0487 pipe->tdr_start, pipe->phy_tdr_start);
0488
0489 pipe->tdr_start = NULL;
0490 }
0491 }
0492
0493 enum ipc_mem_device_ipc_state ipc_protocol_get_ipc_status(struct iosm_protocol
0494 *ipc_protocol)
0495 {
0496 return (enum ipc_mem_device_ipc_state)
0497 le32_to_cpu(ipc_protocol->p_ap_shm->device_info.ipc_status);
0498 }
0499
0500 enum ipc_mem_exec_stage
0501 ipc_protocol_get_ap_exec_stage(struct iosm_protocol *ipc_protocol)
0502 {
0503 return le32_to_cpu(ipc_protocol->p_ap_shm->device_info.execution_stage);
0504 }
0505
0506 int ipc_protocol_msg_prep(struct iosm_imem *ipc_imem,
0507 enum ipc_msg_prep_type msg_type,
0508 union ipc_msg_prep_args *args)
0509 {
0510 struct iosm_protocol *ipc_protocol = ipc_imem->ipc_protocol;
0511
0512 switch (msg_type) {
0513 case IPC_MSG_PREP_SLEEP:
0514 return ipc_protocol_msg_prep_sleep(ipc_protocol, args);
0515
0516 case IPC_MSG_PREP_PIPE_OPEN:
0517 return ipc_protocol_msg_prepipe_open(ipc_protocol, args);
0518
0519 case IPC_MSG_PREP_PIPE_CLOSE:
0520 return ipc_protocol_msg_prepipe_close(ipc_protocol, args);
0521
0522 case IPC_MSG_PREP_FEATURE_SET:
0523 return ipc_protocol_msg_prep_feature_set(ipc_protocol, args);
0524
0525
0526 case IPC_MSG_PREP_MAP:
0527 case IPC_MSG_PREP_UNMAP:
0528 default:
0529 dev_err(ipc_protocol->dev,
0530 "unsupported message type: %d in protocol", msg_type);
0531 return -EINVAL;
0532 }
0533 }
0534
0535 u32
0536 ipc_protocol_pm_dev_get_sleep_notification(struct iosm_protocol *ipc_protocol)
0537 {
0538 struct ipc_protocol_ap_shm *ipc_ap_shm = ipc_protocol->p_ap_shm;
0539
0540 return le32_to_cpu(ipc_ap_shm->device_info.device_sleep_notification);
0541 }