cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

iosm_ipc_protocol_ops.c (14659B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2020-21 Intel Corporation.
      4 */
      5
      6#include "iosm_ipc_protocol.h"
      7#include "iosm_ipc_protocol_ops.h"
      8
      9/* Get the next free message element.*/
     10static union ipc_mem_msg_entry *
     11ipc_protocol_free_msg_get(struct iosm_protocol *ipc_protocol, int *index)
     12{
     13	u32 head = le32_to_cpu(ipc_protocol->p_ap_shm->msg_head);
     14	u32 new_head = (head + 1) % IPC_MEM_MSG_ENTRIES;
     15	union ipc_mem_msg_entry *msg;
     16
     17	if (new_head == le32_to_cpu(ipc_protocol->p_ap_shm->msg_tail)) {
     18		dev_err(ipc_protocol->dev, "message ring is full");
     19		return NULL;
     20	}
     21
     22	/* Get the pointer to the next free message element,
     23	 * reset the fields and mark is as invalid.
     24	 */
     25	msg = &ipc_protocol->p_ap_shm->msg_ring[head];
     26	memset(msg, 0, sizeof(*msg));
     27
     28	/* return index in message ring */
     29	*index = head;
     30
     31	return msg;
     32}
     33
     34/* Updates the message ring Head pointer */
     35void ipc_protocol_msg_hp_update(struct iosm_imem *ipc_imem)
     36{
     37	struct iosm_protocol *ipc_protocol = ipc_imem->ipc_protocol;
     38	u32 head = le32_to_cpu(ipc_protocol->p_ap_shm->msg_head);
     39	u32 new_head = (head + 1) % IPC_MEM_MSG_ENTRIES;
     40
     41	/* Update head pointer and fire doorbell. */
     42	ipc_protocol->p_ap_shm->msg_head = cpu_to_le32(new_head);
     43	ipc_protocol->old_msg_tail =
     44		le32_to_cpu(ipc_protocol->p_ap_shm->msg_tail);
     45
     46	ipc_pm_signal_hpda_doorbell(&ipc_protocol->pm, IPC_HP_MR, false);
     47}
     48
     49/* Allocate and prepare a OPEN_PIPE message.
     50 * This also allocates the memory for the new TDR structure and
     51 * updates the pipe structure referenced in the preparation arguments.
     52 */
     53static int ipc_protocol_msg_prepipe_open(struct iosm_protocol *ipc_protocol,
     54					 union ipc_msg_prep_args *args)
     55{
     56	int index;
     57	union ipc_mem_msg_entry *msg =
     58		ipc_protocol_free_msg_get(ipc_protocol, &index);
     59	struct ipc_pipe *pipe = args->pipe_open.pipe;
     60	struct ipc_protocol_td *tdr;
     61	struct sk_buff **skbr;
     62
     63	if (!msg) {
     64		dev_err(ipc_protocol->dev, "failed to get free message");
     65		return -EIO;
     66	}
     67
     68	/* Allocate the skbuf elements for the skbuf which are on the way.
     69	 * SKB ring is internal memory allocation for driver. No need to
     70	 * re-calculate the start and end addresses.
     71	 */
     72	skbr = kcalloc(pipe->nr_of_entries, sizeof(*skbr), GFP_ATOMIC);
     73	if (!skbr)
     74		return -ENOMEM;
     75
     76	/* Allocate the transfer descriptors for the pipe. */
     77	tdr = dma_alloc_coherent(&ipc_protocol->pcie->pci->dev,
     78				 pipe->nr_of_entries * sizeof(*tdr),
     79				 &pipe->phy_tdr_start, GFP_ATOMIC);
     80	if (!tdr) {
     81		kfree(skbr);
     82		dev_err(ipc_protocol->dev, "tdr alloc error");
     83		return -ENOMEM;
     84	}
     85
     86	pipe->max_nr_of_queued_entries = pipe->nr_of_entries - 1;
     87	pipe->nr_of_queued_entries = 0;
     88	pipe->tdr_start = tdr;
     89	pipe->skbr_start = skbr;
     90	pipe->old_tail = 0;
     91
     92	ipc_protocol->p_ap_shm->head_array[pipe->pipe_nr] = 0;
     93
     94	msg->open_pipe.type_of_message = IPC_MEM_MSG_OPEN_PIPE;
     95	msg->open_pipe.pipe_nr = pipe->pipe_nr;
     96	msg->open_pipe.tdr_addr = cpu_to_le64(pipe->phy_tdr_start);
     97	msg->open_pipe.tdr_entries = cpu_to_le16(pipe->nr_of_entries);
     98	msg->open_pipe.accumulation_backoff =
     99				cpu_to_le32(pipe->accumulation_backoff);
    100	msg->open_pipe.irq_vector = cpu_to_le32(pipe->irq);
    101
    102	return index;
    103}
    104
    105static int ipc_protocol_msg_prepipe_close(struct iosm_protocol *ipc_protocol,
    106					  union ipc_msg_prep_args *args)
    107{
    108	int index = -1;
    109	union ipc_mem_msg_entry *msg =
    110		ipc_protocol_free_msg_get(ipc_protocol, &index);
    111	struct ipc_pipe *pipe = args->pipe_close.pipe;
    112
    113	if (!msg)
    114		return -EIO;
    115
    116	msg->close_pipe.type_of_message = IPC_MEM_MSG_CLOSE_PIPE;
    117	msg->close_pipe.pipe_nr = pipe->pipe_nr;
    118
    119	dev_dbg(ipc_protocol->dev, "IPC_MEM_MSG_CLOSE_PIPE(pipe_nr=%d)",
    120		msg->close_pipe.pipe_nr);
    121
    122	return index;
    123}
    124
    125static int ipc_protocol_msg_prep_sleep(struct iosm_protocol *ipc_protocol,
    126				       union ipc_msg_prep_args *args)
    127{
    128	int index = -1;
    129	union ipc_mem_msg_entry *msg =
    130		ipc_protocol_free_msg_get(ipc_protocol, &index);
    131
    132	if (!msg) {
    133		dev_err(ipc_protocol->dev, "failed to get free message");
    134		return -EIO;
    135	}
    136
    137	/* Prepare and send the host sleep message to CP to enter or exit D3. */
    138	msg->host_sleep.type_of_message = IPC_MEM_MSG_SLEEP;
    139	msg->host_sleep.target = args->sleep.target; /* 0=host, 1=device */
    140
    141	/* state; 0=enter, 1=exit 2=enter w/o protocol */
    142	msg->host_sleep.state = args->sleep.state;
    143
    144	dev_dbg(ipc_protocol->dev, "IPC_MEM_MSG_SLEEP(target=%d; state=%d)",
    145		msg->host_sleep.target, msg->host_sleep.state);
    146
    147	return index;
    148}
    149
    150static int ipc_protocol_msg_prep_feature_set(struct iosm_protocol *ipc_protocol,
    151					     union ipc_msg_prep_args *args)
    152{
    153	int index = -1;
    154	union ipc_mem_msg_entry *msg =
    155		ipc_protocol_free_msg_get(ipc_protocol, &index);
    156
    157	if (!msg) {
    158		dev_err(ipc_protocol->dev, "failed to get free message");
    159		return -EIO;
    160	}
    161
    162	msg->feature_set.type_of_message = IPC_MEM_MSG_FEATURE_SET;
    163	msg->feature_set.reset_enable = args->feature_set.reset_enable <<
    164					RESET_BIT;
    165
    166	dev_dbg(ipc_protocol->dev, "IPC_MEM_MSG_FEATURE_SET(reset_enable=%d)",
    167		msg->feature_set.reset_enable >> RESET_BIT);
    168
    169	return index;
    170}
    171
    172/* Processes the message consumed by CP. */
    173bool ipc_protocol_msg_process(struct iosm_imem *ipc_imem, int irq)
    174{
    175	struct iosm_protocol *ipc_protocol = ipc_imem->ipc_protocol;
    176	struct ipc_rsp **rsp_ring = ipc_protocol->rsp_ring;
    177	bool msg_processed = false;
    178	u32 i;
    179
    180	if (le32_to_cpu(ipc_protocol->p_ap_shm->msg_tail) >=
    181			IPC_MEM_MSG_ENTRIES) {
    182		dev_err(ipc_protocol->dev, "msg_tail out of range: %d",
    183			le32_to_cpu(ipc_protocol->p_ap_shm->msg_tail));
    184		return msg_processed;
    185	}
    186
    187	if (irq != IMEM_IRQ_DONT_CARE &&
    188	    irq != ipc_protocol->p_ap_shm->ci.msg_irq_vector)
    189		return msg_processed;
    190
    191	for (i = ipc_protocol->old_msg_tail;
    192	     i != le32_to_cpu(ipc_protocol->p_ap_shm->msg_tail);
    193	     i = (i + 1) % IPC_MEM_MSG_ENTRIES) {
    194		union ipc_mem_msg_entry *msg =
    195			&ipc_protocol->p_ap_shm->msg_ring[i];
    196
    197		dev_dbg(ipc_protocol->dev, "msg[%d]: type=%u status=%d", i,
    198			msg->common.type_of_message,
    199			msg->common.completion_status);
    200
    201		/* Update response with status and wake up waiting requestor */
    202		if (rsp_ring[i]) {
    203			rsp_ring[i]->status =
    204				le32_to_cpu(msg->common.completion_status);
    205			complete(&rsp_ring[i]->completion);
    206			rsp_ring[i] = NULL;
    207		}
    208		msg_processed = true;
    209	}
    210
    211	ipc_protocol->old_msg_tail = i;
    212	return msg_processed;
    213}
    214
    215/* Sends data from UL list to CP for the provided pipe by updating the Head
    216 * pointer of given pipe.
    217 */
    218bool ipc_protocol_ul_td_send(struct iosm_protocol *ipc_protocol,
    219			     struct ipc_pipe *pipe,
    220			     struct sk_buff_head *p_ul_list)
    221{
    222	struct ipc_protocol_td *td;
    223	bool hpda_pending = false;
    224	struct sk_buff *skb;
    225	s32 free_elements;
    226	u32 head;
    227	u32 tail;
    228
    229	if (!ipc_protocol->p_ap_shm) {
    230		dev_err(ipc_protocol->dev, "driver is not initialized");
    231		return false;
    232	}
    233
    234	/* Get head and tail of the td list and calculate
    235	 * the number of free elements.
    236	 */
    237	head = le32_to_cpu(ipc_protocol->p_ap_shm->head_array[pipe->pipe_nr]);
    238	tail = pipe->old_tail;
    239
    240	while (!skb_queue_empty(p_ul_list)) {
    241		if (head < tail)
    242			free_elements = tail - head - 1;
    243		else
    244			free_elements =
    245				pipe->nr_of_entries - head + ((s32)tail - 1);
    246
    247		if (free_elements <= 0) {
    248			dev_dbg(ipc_protocol->dev,
    249				"no free td elements for UL pipe %d",
    250				pipe->pipe_nr);
    251			break;
    252		}
    253
    254		/* Get the td address. */
    255		td = &pipe->tdr_start[head];
    256
    257		/* Take the first element of the uplink list and add it
    258		 * to the td list.
    259		 */
    260		skb = skb_dequeue(p_ul_list);
    261		if (WARN_ON(!skb))
    262			break;
    263
    264		/* Save the reference to the uplink skbuf. */
    265		pipe->skbr_start[head] = skb;
    266
    267		td->buffer.address = IPC_CB(skb)->mapping;
    268		td->scs = cpu_to_le32(skb->len) & cpu_to_le32(SIZE_MASK);
    269		td->next = 0;
    270
    271		pipe->nr_of_queued_entries++;
    272
    273		/* Calculate the new head and save it. */
    274		head++;
    275		if (head >= pipe->nr_of_entries)
    276			head = 0;
    277
    278		ipc_protocol->p_ap_shm->head_array[pipe->pipe_nr] =
    279			cpu_to_le32(head);
    280	}
    281
    282	if (pipe->old_head != head) {
    283		dev_dbg(ipc_protocol->dev, "New UL TDs Pipe:%d", pipe->pipe_nr);
    284
    285		pipe->old_head = head;
    286		/* Trigger doorbell because of pending UL packets. */
    287		hpda_pending = true;
    288	}
    289
    290	return hpda_pending;
    291}
    292
    293/* Checks for Tail pointer update from CP and returns the data as SKB. */
    294struct sk_buff *ipc_protocol_ul_td_process(struct iosm_protocol *ipc_protocol,
    295					   struct ipc_pipe *pipe)
    296{
    297	struct ipc_protocol_td *p_td = &pipe->tdr_start[pipe->old_tail];
    298	struct sk_buff *skb = pipe->skbr_start[pipe->old_tail];
    299
    300	pipe->nr_of_queued_entries--;
    301	pipe->old_tail++;
    302	if (pipe->old_tail >= pipe->nr_of_entries)
    303		pipe->old_tail = 0;
    304
    305	if (!p_td->buffer.address) {
    306		dev_err(ipc_protocol->dev, "Td buffer address is NULL");
    307		return NULL;
    308	}
    309
    310	if (p_td->buffer.address != IPC_CB(skb)->mapping) {
    311		dev_err(ipc_protocol->dev,
    312			"pipe %d: invalid buf_addr or skb_data",
    313			pipe->pipe_nr);
    314		return NULL;
    315	}
    316
    317	return skb;
    318}
    319
    320/* Allocates an SKB for CP to send data and updates the Head Pointer
    321 * of the given Pipe#.
    322 */
    323bool ipc_protocol_dl_td_prepare(struct iosm_protocol *ipc_protocol,
    324				struct ipc_pipe *pipe)
    325{
    326	struct ipc_protocol_td *td;
    327	dma_addr_t mapping = 0;
    328	u32 head, new_head;
    329	struct sk_buff *skb;
    330	u32 tail;
    331
    332	/* Get head and tail of the td list and calculate
    333	 * the number of free elements.
    334	 */
    335	head = le32_to_cpu(ipc_protocol->p_ap_shm->head_array[pipe->pipe_nr]);
    336	tail = le32_to_cpu(ipc_protocol->p_ap_shm->tail_array[pipe->pipe_nr]);
    337
    338	new_head = head + 1;
    339	if (new_head >= pipe->nr_of_entries)
    340		new_head = 0;
    341
    342	if (new_head == tail)
    343		return false;
    344
    345	/* Get the td address. */
    346	td = &pipe->tdr_start[head];
    347
    348	/* Allocate the skbuf for the descriptor. */
    349	skb = ipc_pcie_alloc_skb(ipc_protocol->pcie, pipe->buf_size, GFP_ATOMIC,
    350				 &mapping, DMA_FROM_DEVICE,
    351				 IPC_MEM_DL_ETH_OFFSET);
    352	if (!skb)
    353		return false;
    354
    355	td->buffer.address = mapping;
    356	td->scs = cpu_to_le32(pipe->buf_size) & cpu_to_le32(SIZE_MASK);
    357	td->next = 0;
    358
    359	/* store the new head value. */
    360	ipc_protocol->p_ap_shm->head_array[pipe->pipe_nr] =
    361		cpu_to_le32(new_head);
    362
    363	/* Save the reference to the skbuf. */
    364	pipe->skbr_start[head] = skb;
    365
    366	pipe->nr_of_queued_entries++;
    367
    368	return true;
    369}
    370
    371/* Processes DL TD's */
    372struct sk_buff *ipc_protocol_dl_td_process(struct iosm_protocol *ipc_protocol,
    373					   struct ipc_pipe *pipe)
    374{
    375	struct ipc_protocol_td *p_td;
    376	struct sk_buff *skb;
    377
    378	if (!pipe->tdr_start)
    379		return NULL;
    380
    381	/* Copy the reference to the downlink buffer. */
    382	p_td = &pipe->tdr_start[pipe->old_tail];
    383	skb = pipe->skbr_start[pipe->old_tail];
    384
    385	/* Reset the ring elements. */
    386	pipe->skbr_start[pipe->old_tail] = NULL;
    387
    388	pipe->nr_of_queued_entries--;
    389
    390	pipe->old_tail++;
    391	if (pipe->old_tail >= pipe->nr_of_entries)
    392		pipe->old_tail = 0;
    393
    394	if (!skb) {
    395		dev_err(ipc_protocol->dev, "skb is null");
    396		goto ret;
    397	} else if (!p_td->buffer.address) {
    398		dev_err(ipc_protocol->dev, "td/buffer address is null");
    399		ipc_pcie_kfree_skb(ipc_protocol->pcie, skb);
    400		skb = NULL;
    401		goto ret;
    402	}
    403
    404	if (p_td->buffer.address != IPC_CB(skb)->mapping) {
    405		dev_err(ipc_protocol->dev, "invalid buf=%llx or skb=%p",
    406			(unsigned long long)p_td->buffer.address, skb->data);
    407		ipc_pcie_kfree_skb(ipc_protocol->pcie, skb);
    408		skb = NULL;
    409		goto ret;
    410	} else if ((le32_to_cpu(p_td->scs) & SIZE_MASK) > pipe->buf_size) {
    411		dev_err(ipc_protocol->dev, "invalid buffer size %d > %d",
    412			le32_to_cpu(p_td->scs) & SIZE_MASK,
    413			pipe->buf_size);
    414		ipc_pcie_kfree_skb(ipc_protocol->pcie, skb);
    415		skb = NULL;
    416		goto ret;
    417	} else if (le32_to_cpu(p_td->scs) >> COMPLETION_STATUS ==
    418		  IPC_MEM_TD_CS_ABORT) {
    419		/* Discard aborted buffers. */
    420		dev_dbg(ipc_protocol->dev, "discard 'aborted' buffers");
    421		ipc_pcie_kfree_skb(ipc_protocol->pcie, skb);
    422		skb = NULL;
    423		goto ret;
    424	}
    425
    426	/* Set the length field in skbuf. */
    427	skb_put(skb, le32_to_cpu(p_td->scs) & SIZE_MASK);
    428
    429ret:
    430	return skb;
    431}
    432
    433void ipc_protocol_get_head_tail_index(struct iosm_protocol *ipc_protocol,
    434				      struct ipc_pipe *pipe, u32 *head,
    435				      u32 *tail)
    436{
    437	struct ipc_protocol_ap_shm *ipc_ap_shm = ipc_protocol->p_ap_shm;
    438
    439	if (head)
    440		*head = le32_to_cpu(ipc_ap_shm->head_array[pipe->pipe_nr]);
    441
    442	if (tail)
    443		*tail = le32_to_cpu(ipc_ap_shm->tail_array[pipe->pipe_nr]);
    444}
    445
    446/* Frees the TDs given to CP.  */
    447void ipc_protocol_pipe_cleanup(struct iosm_protocol *ipc_protocol,
    448			       struct ipc_pipe *pipe)
    449{
    450	struct sk_buff *skb;
    451	u32 head;
    452	u32 tail;
    453
    454	/* Get the start and the end of the buffer list. */
    455	head = le32_to_cpu(ipc_protocol->p_ap_shm->head_array[pipe->pipe_nr]);
    456	tail = pipe->old_tail;
    457
    458	/* Reset tail and head to 0. */
    459	ipc_protocol->p_ap_shm->tail_array[pipe->pipe_nr] = 0;
    460	ipc_protocol->p_ap_shm->head_array[pipe->pipe_nr] = 0;
    461
    462	/* Free pending uplink and downlink buffers. */
    463	if (pipe->skbr_start) {
    464		while (head != tail) {
    465			/* Get the reference to the skbuf,
    466			 * which is on the way and free it.
    467			 */
    468			skb = pipe->skbr_start[tail];
    469			if (skb)
    470				ipc_pcie_kfree_skb(ipc_protocol->pcie, skb);
    471
    472			tail++;
    473			if (tail >= pipe->nr_of_entries)
    474				tail = 0;
    475		}
    476
    477		kfree(pipe->skbr_start);
    478		pipe->skbr_start = NULL;
    479	}
    480
    481	pipe->old_tail = 0;
    482
    483	/* Free and reset the td and skbuf circular buffers. kfree is save! */
    484	if (pipe->tdr_start) {
    485		dma_free_coherent(&ipc_protocol->pcie->pci->dev,
    486				  sizeof(*pipe->tdr_start) * pipe->nr_of_entries,
    487				  pipe->tdr_start, pipe->phy_tdr_start);
    488
    489		pipe->tdr_start = NULL;
    490	}
    491}
    492
    493enum ipc_mem_device_ipc_state ipc_protocol_get_ipc_status(struct iosm_protocol
    494							  *ipc_protocol)
    495{
    496	return (enum ipc_mem_device_ipc_state)
    497		le32_to_cpu(ipc_protocol->p_ap_shm->device_info.ipc_status);
    498}
    499
    500enum ipc_mem_exec_stage
    501ipc_protocol_get_ap_exec_stage(struct iosm_protocol *ipc_protocol)
    502{
    503	return le32_to_cpu(ipc_protocol->p_ap_shm->device_info.execution_stage);
    504}
    505
    506int ipc_protocol_msg_prep(struct iosm_imem *ipc_imem,
    507			  enum ipc_msg_prep_type msg_type,
    508			  union ipc_msg_prep_args *args)
    509{
    510	struct iosm_protocol *ipc_protocol = ipc_imem->ipc_protocol;
    511
    512	switch (msg_type) {
    513	case IPC_MSG_PREP_SLEEP:
    514		return ipc_protocol_msg_prep_sleep(ipc_protocol, args);
    515
    516	case IPC_MSG_PREP_PIPE_OPEN:
    517		return ipc_protocol_msg_prepipe_open(ipc_protocol, args);
    518
    519	case IPC_MSG_PREP_PIPE_CLOSE:
    520		return ipc_protocol_msg_prepipe_close(ipc_protocol, args);
    521
    522	case IPC_MSG_PREP_FEATURE_SET:
    523		return ipc_protocol_msg_prep_feature_set(ipc_protocol, args);
    524
    525		/* Unsupported messages in protocol */
    526	case IPC_MSG_PREP_MAP:
    527	case IPC_MSG_PREP_UNMAP:
    528	default:
    529		dev_err(ipc_protocol->dev,
    530			"unsupported message type: %d in protocol", msg_type);
    531		return -EINVAL;
    532	}
    533}
    534
    535u32
    536ipc_protocol_pm_dev_get_sleep_notification(struct iosm_protocol *ipc_protocol)
    537{
    538	struct ipc_protocol_ap_shm *ipc_ap_shm = ipc_protocol->p_ap_shm;
    539
    540	return le32_to_cpu(ipc_ap_shm->device_info.device_sleep_notification);
    541}