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

octep_ctrl_mbox.c (7163B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* Marvell Octeon EP (EndPoint) Ethernet Driver
      3 *
      4 * Copyright (C) 2020 Marvell.
      5 *
      6 */
      7#include <linux/types.h>
      8#include <linux/errno.h>
      9#include <linux/string.h>
     10#include <linux/mutex.h>
     11#include <linux/jiffies.h>
     12#include <linux/sched.h>
     13#include <linux/sched/signal.h>
     14#include <linux/io.h>
     15#include <linux/pci.h>
     16#include <linux/etherdevice.h>
     17
     18#include "octep_ctrl_mbox.h"
     19#include "octep_config.h"
     20#include "octep_main.h"
     21
     22/* Timeout in msecs for message response */
     23#define OCTEP_CTRL_MBOX_MSG_TIMEOUT_MS			100
     24/* Time in msecs to wait for message response */
     25#define OCTEP_CTRL_MBOX_MSG_WAIT_MS			10
     26
     27#define OCTEP_CTRL_MBOX_INFO_MAGIC_NUM_OFFSET(m)	(m)
     28#define OCTEP_CTRL_MBOX_INFO_BARMEM_SZ_OFFSET(m)	((m) + 8)
     29#define OCTEP_CTRL_MBOX_INFO_HOST_STATUS_OFFSET(m)	((m) + 24)
     30#define OCTEP_CTRL_MBOX_INFO_FW_STATUS_OFFSET(m)	((m) + 144)
     31
     32#define OCTEP_CTRL_MBOX_H2FQ_INFO_OFFSET(m)		((m) + OCTEP_CTRL_MBOX_INFO_SZ)
     33#define OCTEP_CTRL_MBOX_H2FQ_PROD_OFFSET(m)		(OCTEP_CTRL_MBOX_H2FQ_INFO_OFFSET(m))
     34#define OCTEP_CTRL_MBOX_H2FQ_CONS_OFFSET(m)		((OCTEP_CTRL_MBOX_H2FQ_INFO_OFFSET(m)) + 4)
     35#define OCTEP_CTRL_MBOX_H2FQ_ELEM_SZ_OFFSET(m)		((OCTEP_CTRL_MBOX_H2FQ_INFO_OFFSET(m)) + 8)
     36#define OCTEP_CTRL_MBOX_H2FQ_ELEM_CNT_OFFSET(m)		((OCTEP_CTRL_MBOX_H2FQ_INFO_OFFSET(m)) + 12)
     37
     38#define OCTEP_CTRL_MBOX_F2HQ_INFO_OFFSET(m)		((m) + \
     39							 OCTEP_CTRL_MBOX_INFO_SZ + \
     40							 OCTEP_CTRL_MBOX_H2FQ_INFO_SZ)
     41#define OCTEP_CTRL_MBOX_F2HQ_PROD_OFFSET(m)		(OCTEP_CTRL_MBOX_F2HQ_INFO_OFFSET(m))
     42#define OCTEP_CTRL_MBOX_F2HQ_CONS_OFFSET(m)		((OCTEP_CTRL_MBOX_F2HQ_INFO_OFFSET(m)) + 4)
     43#define OCTEP_CTRL_MBOX_F2HQ_ELEM_SZ_OFFSET(m)		((OCTEP_CTRL_MBOX_F2HQ_INFO_OFFSET(m)) + 8)
     44#define OCTEP_CTRL_MBOX_F2HQ_ELEM_CNT_OFFSET(m)		((OCTEP_CTRL_MBOX_F2HQ_INFO_OFFSET(m)) + 12)
     45
     46#define OCTEP_CTRL_MBOX_Q_OFFSET(m, i)			((m) + \
     47							 (sizeof(struct octep_ctrl_mbox_msg) * (i)))
     48
     49static u32 octep_ctrl_mbox_circq_inc(u32 index, u32 mask)
     50{
     51	return (index + 1) & mask;
     52}
     53
     54static u32 octep_ctrl_mbox_circq_space(u32 pi, u32 ci, u32 mask)
     55{
     56	return mask - ((pi - ci) & mask);
     57}
     58
     59static u32 octep_ctrl_mbox_circq_depth(u32 pi, u32 ci, u32 mask)
     60{
     61	return ((pi - ci) & mask);
     62}
     63
     64int octep_ctrl_mbox_init(struct octep_ctrl_mbox *mbox)
     65{
     66	u64 magic_num, status;
     67
     68	if (!mbox)
     69		return -EINVAL;
     70
     71	if (!mbox->barmem) {
     72		pr_info("octep_ctrl_mbox : Invalid barmem %p\n", mbox->barmem);
     73		return -EINVAL;
     74	}
     75
     76	magic_num = readq(OCTEP_CTRL_MBOX_INFO_MAGIC_NUM_OFFSET(mbox->barmem));
     77	if (magic_num != OCTEP_CTRL_MBOX_MAGIC_NUMBER) {
     78		pr_info("octep_ctrl_mbox : Invalid magic number %llx\n", magic_num);
     79		return -EINVAL;
     80	}
     81
     82	status = readq(OCTEP_CTRL_MBOX_INFO_FW_STATUS_OFFSET(mbox->barmem));
     83	if (status != OCTEP_CTRL_MBOX_STATUS_READY) {
     84		pr_info("octep_ctrl_mbox : Firmware is not ready.\n");
     85		return -EINVAL;
     86	}
     87
     88	mbox->barmem_sz = readl(OCTEP_CTRL_MBOX_INFO_BARMEM_SZ_OFFSET(mbox->barmem));
     89
     90	writeq(OCTEP_CTRL_MBOX_STATUS_INIT, OCTEP_CTRL_MBOX_INFO_HOST_STATUS_OFFSET(mbox->barmem));
     91
     92	mbox->h2fq.elem_cnt = readl(OCTEP_CTRL_MBOX_H2FQ_ELEM_CNT_OFFSET(mbox->barmem));
     93	mbox->h2fq.elem_sz = readl(OCTEP_CTRL_MBOX_H2FQ_ELEM_SZ_OFFSET(mbox->barmem));
     94	mbox->h2fq.mask = (mbox->h2fq.elem_cnt - 1);
     95	mutex_init(&mbox->h2fq_lock);
     96
     97	mbox->f2hq.elem_cnt = readl(OCTEP_CTRL_MBOX_F2HQ_ELEM_CNT_OFFSET(mbox->barmem));
     98	mbox->f2hq.elem_sz = readl(OCTEP_CTRL_MBOX_F2HQ_ELEM_SZ_OFFSET(mbox->barmem));
     99	mbox->f2hq.mask = (mbox->f2hq.elem_cnt - 1);
    100	mutex_init(&mbox->f2hq_lock);
    101
    102	mbox->h2fq.hw_prod = OCTEP_CTRL_MBOX_H2FQ_PROD_OFFSET(mbox->barmem);
    103	mbox->h2fq.hw_cons = OCTEP_CTRL_MBOX_H2FQ_CONS_OFFSET(mbox->barmem);
    104	mbox->h2fq.hw_q = mbox->barmem +
    105			  OCTEP_CTRL_MBOX_INFO_SZ +
    106			  OCTEP_CTRL_MBOX_H2FQ_INFO_SZ +
    107			  OCTEP_CTRL_MBOX_F2HQ_INFO_SZ;
    108
    109	mbox->f2hq.hw_prod = OCTEP_CTRL_MBOX_F2HQ_PROD_OFFSET(mbox->barmem);
    110	mbox->f2hq.hw_cons = OCTEP_CTRL_MBOX_F2HQ_CONS_OFFSET(mbox->barmem);
    111	mbox->f2hq.hw_q = mbox->h2fq.hw_q +
    112			  ((mbox->h2fq.elem_sz + sizeof(union octep_ctrl_mbox_msg_hdr)) *
    113			   mbox->h2fq.elem_cnt);
    114
    115	/* ensure ready state is seen after everything is initialized */
    116	wmb();
    117	writeq(OCTEP_CTRL_MBOX_STATUS_READY, OCTEP_CTRL_MBOX_INFO_HOST_STATUS_OFFSET(mbox->barmem));
    118
    119	pr_info("Octep ctrl mbox : Init successful.\n");
    120
    121	return 0;
    122}
    123
    124int octep_ctrl_mbox_send(struct octep_ctrl_mbox *mbox, struct octep_ctrl_mbox_msg *msg)
    125{
    126	unsigned long timeout = msecs_to_jiffies(OCTEP_CTRL_MBOX_MSG_TIMEOUT_MS);
    127	unsigned long period = msecs_to_jiffies(OCTEP_CTRL_MBOX_MSG_WAIT_MS);
    128	struct octep_ctrl_mbox_q *q;
    129	unsigned long expire;
    130	u64 *mbuf, *word0;
    131	u8 __iomem *qidx;
    132	u16 pi, ci;
    133	int i;
    134
    135	if (!mbox || !msg)
    136		return -EINVAL;
    137
    138	q = &mbox->h2fq;
    139	pi = readl(q->hw_prod);
    140	ci = readl(q->hw_cons);
    141
    142	if (!octep_ctrl_mbox_circq_space(pi, ci, q->mask))
    143		return -ENOMEM;
    144
    145	qidx = OCTEP_CTRL_MBOX_Q_OFFSET(q->hw_q, pi);
    146	mbuf = (u64 *)msg->msg;
    147	word0 = &msg->hdr.word0;
    148
    149	mutex_lock(&mbox->h2fq_lock);
    150	for (i = 1; i <= msg->hdr.sizew; i++)
    151		writeq(*mbuf++, (qidx + (i * 8)));
    152
    153	writeq(*word0, qidx);
    154
    155	pi = octep_ctrl_mbox_circq_inc(pi, q->mask);
    156	writel(pi, q->hw_prod);
    157	mutex_unlock(&mbox->h2fq_lock);
    158
    159	/* don't check for notification response */
    160	if (msg->hdr.flags & OCTEP_CTRL_MBOX_MSG_HDR_FLAG_NOTIFY)
    161		return 0;
    162
    163	expire = jiffies + timeout;
    164	while (true) {
    165		*word0 = readq(qidx);
    166		if (msg->hdr.flags == OCTEP_CTRL_MBOX_MSG_HDR_FLAG_RESP)
    167			break;
    168		schedule_timeout_interruptible(period);
    169		if (signal_pending(current) || time_after(jiffies, expire)) {
    170			pr_info("octep_ctrl_mbox: Timed out\n");
    171			return -EBUSY;
    172		}
    173	}
    174	mbuf = (u64 *)msg->msg;
    175	for (i = 1; i <= msg->hdr.sizew; i++)
    176		*mbuf++ = readq(qidx + (i * 8));
    177
    178	return 0;
    179}
    180
    181int octep_ctrl_mbox_recv(struct octep_ctrl_mbox *mbox, struct octep_ctrl_mbox_msg *msg)
    182{
    183	struct octep_ctrl_mbox_q *q;
    184	u32 count, pi, ci;
    185	u8 __iomem *qidx;
    186	u64 *mbuf;
    187	int i;
    188
    189	if (!mbox || !msg)
    190		return -EINVAL;
    191
    192	q = &mbox->f2hq;
    193	pi = readl(q->hw_prod);
    194	ci = readl(q->hw_cons);
    195	count = octep_ctrl_mbox_circq_depth(pi, ci, q->mask);
    196	if (!count)
    197		return -EAGAIN;
    198
    199	qidx = OCTEP_CTRL_MBOX_Q_OFFSET(q->hw_q, ci);
    200	mbuf = (u64 *)msg->msg;
    201
    202	mutex_lock(&mbox->f2hq_lock);
    203
    204	msg->hdr.word0 = readq(qidx);
    205	for (i = 1; i <= msg->hdr.sizew; i++)
    206		*mbuf++ = readq(qidx + (i * 8));
    207
    208	ci = octep_ctrl_mbox_circq_inc(ci, q->mask);
    209	writel(ci, q->hw_cons);
    210
    211	mutex_unlock(&mbox->f2hq_lock);
    212
    213	if (msg->hdr.flags != OCTEP_CTRL_MBOX_MSG_HDR_FLAG_REQ || !mbox->process_req)
    214		return 0;
    215
    216	mbox->process_req(mbox->user_ctx, msg);
    217	mbuf = (u64 *)msg->msg;
    218	for (i = 1; i <= msg->hdr.sizew; i++)
    219		writeq(*mbuf++, (qidx + (i * 8)));
    220
    221	writeq(msg->hdr.word0, qidx);
    222
    223	return 0;
    224}
    225
    226int octep_ctrl_mbox_uninit(struct octep_ctrl_mbox *mbox)
    227{
    228	if (!mbox)
    229		return -EINVAL;
    230
    231	writeq(OCTEP_CTRL_MBOX_STATUS_UNINIT,
    232	       OCTEP_CTRL_MBOX_INFO_HOST_STATUS_OFFSET(mbox->barmem));
    233	/* ensure uninit state is written before uninitialization */
    234	wmb();
    235
    236	mutex_destroy(&mbox->h2fq_lock);
    237	mutex_destroy(&mbox->f2hq_lock);
    238
    239	writeq(OCTEP_CTRL_MBOX_STATUS_INVALID,
    240	       OCTEP_CTRL_MBOX_INFO_HOST_STATUS_OFFSET(mbox->barmem));
    241
    242	pr_info("Octep ctrl mbox : Uninit successful.\n");
    243
    244	return 0;
    245}