1// SPDX-License-Identifier: GPL-2.0
2/* Marvell RVU Admin Function driver
3 *
4 * Copyright (C) 2018 Marvell.
5 *
6 */
7
8#include <linux/module.h>
9#include <linux/interrupt.h>
10#include <linux/pci.h>
11
12#include "rvu_reg.h"
13#include "mbox.h"
14#include "rvu_trace.h"
15
16static const u16 msgs_offset = ALIGN(sizeof(struct mbox_hdr), MBOX_MSG_ALIGN);
17
18void __otx2_mbox_reset(struct otx2_mbox *mbox, int devid)
19{
20	struct otx2_mbox_dev *mdev = &mbox->dev[devid];
21	struct mbox_hdr *tx_hdr, *rx_hdr;
22	void *hw_mbase = mdev->hwbase;
23
24	tx_hdr = hw_mbase + mbox->tx_start;
25	rx_hdr = hw_mbase + mbox->rx_start;
26
27	mdev->msg_size = 0;
28	mdev->rsp_size = 0;
29	tx_hdr->num_msgs = 0;
30	tx_hdr->msg_size = 0;
31	rx_hdr->num_msgs = 0;
32	rx_hdr->msg_size = 0;
33}
34EXPORT_SYMBOL(__otx2_mbox_reset);
35
36void otx2_mbox_reset(struct otx2_mbox *mbox, int devid)
37{
38	struct otx2_mbox_dev *mdev = &mbox->dev[devid];
39
40	spin_lock(&mdev->mbox_lock);
41	__otx2_mbox_reset(mbox, devid);
42	spin_unlock(&mdev->mbox_lock);
43}
44EXPORT_SYMBOL(otx2_mbox_reset);
45
46void otx2_mbox_destroy(struct otx2_mbox *mbox)
47{
48	mbox->reg_base = NULL;
49	mbox->hwbase = NULL;
50
51	kfree(mbox->dev);
52	mbox->dev = NULL;
53}
54EXPORT_SYMBOL(otx2_mbox_destroy);
55
56static int otx2_mbox_setup(struct otx2_mbox *mbox, struct pci_dev *pdev,
57			   void *reg_base, int direction, int ndevs)
58{
59	switch (direction) {
60	case MBOX_DIR_AFPF:
61	case MBOX_DIR_PFVF:
62		mbox->tx_start = MBOX_DOWN_TX_START;
63		mbox->rx_start = MBOX_DOWN_RX_START;
64		mbox->tx_size  = MBOX_DOWN_TX_SIZE;
65		mbox->rx_size  = MBOX_DOWN_RX_SIZE;
66		break;
67	case MBOX_DIR_PFAF:
68	case MBOX_DIR_VFPF:
69		mbox->tx_start = MBOX_DOWN_RX_START;
70		mbox->rx_start = MBOX_DOWN_TX_START;
71		mbox->tx_size  = MBOX_DOWN_RX_SIZE;
72		mbox->rx_size  = MBOX_DOWN_TX_SIZE;
73		break;
74	case MBOX_DIR_AFPF_UP:
75	case MBOX_DIR_PFVF_UP:
76		mbox->tx_start = MBOX_UP_TX_START;
77		mbox->rx_start = MBOX_UP_RX_START;
78		mbox->tx_size  = MBOX_UP_TX_SIZE;
79		mbox->rx_size  = MBOX_UP_RX_SIZE;
80		break;
81	case MBOX_DIR_PFAF_UP:
82	case MBOX_DIR_VFPF_UP:
83		mbox->tx_start = MBOX_UP_RX_START;
84		mbox->rx_start = MBOX_UP_TX_START;
85		mbox->tx_size  = MBOX_UP_RX_SIZE;
86		mbox->rx_size  = MBOX_UP_TX_SIZE;
87		break;
88	default:
89		return -ENODEV;
90	}
91
92	switch (direction) {
93	case MBOX_DIR_AFPF:
94	case MBOX_DIR_AFPF_UP:
95		mbox->trigger = RVU_AF_AFPF_MBOX0;
96		mbox->tr_shift = 4;
97		break;
98	case MBOX_DIR_PFAF:
99	case MBOX_DIR_PFAF_UP:
100		mbox->trigger = RVU_PF_PFAF_MBOX1;
101		mbox->tr_shift = 0;
102		break;
103	case MBOX_DIR_PFVF:
104	case MBOX_DIR_PFVF_UP:
105		mbox->trigger = RVU_PF_VFX_PFVF_MBOX0;
106		mbox->tr_shift = 12;
107		break;
108	case MBOX_DIR_VFPF:
109	case MBOX_DIR_VFPF_UP:
110		mbox->trigger = RVU_VF_VFPF_MBOX1;
111		mbox->tr_shift = 0;
112		break;
113	default:
114		return -ENODEV;
115	}
116
117	mbox->reg_base = reg_base;
118	mbox->pdev = pdev;
119
120	mbox->dev = kcalloc(ndevs, sizeof(struct otx2_mbox_dev), GFP_KERNEL);
121	if (!mbox->dev) {
122		otx2_mbox_destroy(mbox);
123		return -ENOMEM;
124	}
125	mbox->ndevs = ndevs;
126
127	return 0;
128}
129
130int otx2_mbox_init(struct otx2_mbox *mbox, void *hwbase, struct pci_dev *pdev,
131		   void *reg_base, int direction, int ndevs)
132{
133	struct otx2_mbox_dev *mdev;
134	int devid, err;
135
136	err = otx2_mbox_setup(mbox, pdev, reg_base, direction, ndevs);
137	if (err)
138		return err;
139
140	mbox->hwbase = hwbase;
141
142	for (devid = 0; devid < ndevs; devid++) {
143		mdev = &mbox->dev[devid];
144		mdev->mbase = mbox->hwbase + (devid * MBOX_SIZE);
145		mdev->hwbase = mdev->mbase;
146		spin_lock_init(&mdev->mbox_lock);
147		/* Init header to reset value */
148		otx2_mbox_reset(mbox, devid);
149	}
150
151	return 0;
152}
153EXPORT_SYMBOL(otx2_mbox_init);
154
155/* Initialize mailbox with the set of mailbox region addresses
156 * in the array hwbase.
157 */
158int otx2_mbox_regions_init(struct otx2_mbox *mbox, void **hwbase,
159			   struct pci_dev *pdev, void *reg_base,
160			   int direction, int ndevs, unsigned long *pf_bmap)
161{
162	struct otx2_mbox_dev *mdev;
163	int devid, err;
164
165	err = otx2_mbox_setup(mbox, pdev, reg_base, direction, ndevs);
166	if (err)
167		return err;
168
169	mbox->hwbase = hwbase[0];
170
171	for (devid = 0; devid < ndevs; devid++) {
172		if (!test_bit(devid, pf_bmap))
173			continue;
174
175		mdev = &mbox->dev[devid];
176		mdev->mbase = hwbase[devid];
177		mdev->hwbase = hwbase[devid];
178		spin_lock_init(&mdev->mbox_lock);
179		/* Init header to reset value */
180		otx2_mbox_reset(mbox, devid);
181	}
182
183	return 0;
184}
185EXPORT_SYMBOL(otx2_mbox_regions_init);
186
187int otx2_mbox_wait_for_rsp(struct otx2_mbox *mbox, int devid)
188{
189	unsigned long timeout = jiffies + msecs_to_jiffies(MBOX_RSP_TIMEOUT);
190	struct otx2_mbox_dev *mdev = &mbox->dev[devid];
191	struct device *sender = &mbox->pdev->dev;
192
193	while (!time_after(jiffies, timeout)) {
194		if (mdev->num_msgs == mdev->msgs_acked)
195			return 0;
196		usleep_range(800, 1000);
197	}
198	dev_dbg(sender, "timed out while waiting for rsp\n");
199	return -EIO;
200}
201EXPORT_SYMBOL(otx2_mbox_wait_for_rsp);
202
203int otx2_mbox_busy_poll_for_rsp(struct otx2_mbox *mbox, int devid)
204{
205	struct otx2_mbox_dev *mdev = &mbox->dev[devid];
206	unsigned long timeout = jiffies + 1 * HZ;
207
208	while (!time_after(jiffies, timeout)) {
209		if (mdev->num_msgs == mdev->msgs_acked)
210			return 0;
211		cpu_relax();
212	}
213	return -EIO;
214}
215EXPORT_SYMBOL(otx2_mbox_busy_poll_for_rsp);
216
217static void otx2_mbox_msg_send_data(struct otx2_mbox *mbox, int devid, u64 data)
218{
219	struct otx2_mbox_dev *mdev = &mbox->dev[devid];
220	struct mbox_hdr *tx_hdr, *rx_hdr;
221	void *hw_mbase = mdev->hwbase;
222	u64 intr_val;
223
224	tx_hdr = hw_mbase + mbox->tx_start;
225	rx_hdr = hw_mbase + mbox->rx_start;
226
227	/* If bounce buffer is implemented copy mbox messages from
228	 * bounce buffer to hw mbox memory.
229	 */
230	if (mdev->mbase != hw_mbase)
231		memcpy(hw_mbase + mbox->tx_start + msgs_offset,
232		       mdev->mbase + mbox->tx_start + msgs_offset,
233		       mdev->msg_size);
234
235	spin_lock(&mdev->mbox_lock);
236
237	tx_hdr->msg_size = mdev->msg_size;
238
239	/* Reset header for next messages */
240	mdev->msg_size = 0;
241	mdev->rsp_size = 0;
242	mdev->msgs_acked = 0;
243
244	/* Sync mbox data into memory */
245	smp_wmb();
246
247	/* num_msgs != 0 signals to the peer that the buffer has a number of
248	 * messages.  So this should be written after writing all the messages
249	 * to the shared memory.
250	 */
251	tx_hdr->num_msgs = mdev->num_msgs;
252	rx_hdr->num_msgs = 0;
253
254	trace_otx2_msg_send(mbox->pdev, tx_hdr->num_msgs, tx_hdr->msg_size);
255
256	spin_unlock(&mdev->mbox_lock);
257
258	/* Check if interrupt pending */
259	intr_val = readq((void __iomem *)mbox->reg_base +
260		     (mbox->trigger | (devid << mbox->tr_shift)));
261
262	intr_val |= data;
263	/* The interrupt should be fired after num_msgs is written
264	 * to the shared memory
265	 */
266	writeq(intr_val, (void __iomem *)mbox->reg_base +
267	       (mbox->trigger | (devid << mbox->tr_shift)));
268}
269
270void otx2_mbox_msg_send(struct otx2_mbox *mbox, int devid)
271{
272	otx2_mbox_msg_send_data(mbox, devid, MBOX_DOWN_MSG);
273}
274EXPORT_SYMBOL(otx2_mbox_msg_send);
275
276void otx2_mbox_msg_send_up(struct otx2_mbox *mbox, int devid)
277{
278	otx2_mbox_msg_send_data(mbox, devid, MBOX_UP_MSG);
279}
280EXPORT_SYMBOL(otx2_mbox_msg_send_up);
281
282bool otx2_mbox_wait_for_zero(struct otx2_mbox *mbox, int devid)
283{
284	u64 data;
285
286	data = readq((void __iomem *)mbox->reg_base +
287		     (mbox->trigger | (devid << mbox->tr_shift)));
288
289	/* If data is non-zero wait for ~1ms and return to caller
290	 * whether data has changed to zero or not after the wait.
291	 */
292	if (!data)
293		return true;
294
295	usleep_range(950, 1000);
296
297	data = readq((void __iomem *)mbox->reg_base +
298		     (mbox->trigger | (devid << mbox->tr_shift)));
299
300	return data == 0;
301}
302EXPORT_SYMBOL(otx2_mbox_wait_for_zero);
303
304struct mbox_msghdr *otx2_mbox_alloc_msg_rsp(struct otx2_mbox *mbox, int devid,
305					    int size, int size_rsp)
306{
307	struct otx2_mbox_dev *mdev = &mbox->dev[devid];
308	struct mbox_msghdr *msghdr = NULL;
309
310	spin_lock(&mdev->mbox_lock);
311	size = ALIGN(size, MBOX_MSG_ALIGN);
312	size_rsp = ALIGN(size_rsp, MBOX_MSG_ALIGN);
313	/* Check if there is space in mailbox */
314	if ((mdev->msg_size + size) > mbox->tx_size - msgs_offset)
315		goto exit;
316	if ((mdev->rsp_size + size_rsp) > mbox->rx_size - msgs_offset)
317		goto exit;
318
319	if (mdev->msg_size == 0)
320		mdev->num_msgs = 0;
321	mdev->num_msgs++;
322
323	msghdr = mdev->mbase + mbox->tx_start + msgs_offset + mdev->msg_size;
324
325	/* Clear the whole msg region */
326	memset(msghdr, 0, size);
327	/* Init message header with reset values */
328	msghdr->ver = OTX2_MBOX_VERSION;
329	mdev->msg_size += size;
330	mdev->rsp_size += size_rsp;
331	msghdr->next_msgoff = mdev->msg_size + msgs_offset;
332exit:
333	spin_unlock(&mdev->mbox_lock);
334
335	return msghdr;
336}
337EXPORT_SYMBOL(otx2_mbox_alloc_msg_rsp);
338
339struct mbox_msghdr *otx2_mbox_get_rsp(struct otx2_mbox *mbox, int devid,
340				      struct mbox_msghdr *msg)
341{
342	unsigned long imsg = mbox->tx_start + msgs_offset;
343	unsigned long irsp = mbox->rx_start + msgs_offset;
344	struct otx2_mbox_dev *mdev = &mbox->dev[devid];
345	u16 msgs;
346
347	spin_lock(&mdev->mbox_lock);
348
349	if (mdev->num_msgs != mdev->msgs_acked)
350		goto error;
351
352	for (msgs = 0; msgs < mdev->msgs_acked; msgs++) {
353		struct mbox_msghdr *pmsg = mdev->mbase + imsg;
354		struct mbox_msghdr *prsp = mdev->mbase + irsp;
355
356		if (msg == pmsg) {
357			if (pmsg->id != prsp->id)
358				goto error;
359			spin_unlock(&mdev->mbox_lock);
360			return prsp;
361		}
362
363		imsg = mbox->tx_start + pmsg->next_msgoff;
364		irsp = mbox->rx_start + prsp->next_msgoff;
365	}
366
367error:
368	spin_unlock(&mdev->mbox_lock);
369	return ERR_PTR(-ENODEV);
370}
371EXPORT_SYMBOL(otx2_mbox_get_rsp);
372
373int otx2_mbox_check_rsp_msgs(struct otx2_mbox *mbox, int devid)
374{
375	unsigned long ireq = mbox->tx_start + msgs_offset;
376	unsigned long irsp = mbox->rx_start + msgs_offset;
377	struct otx2_mbox_dev *mdev = &mbox->dev[devid];
378	int rc = -ENODEV;
379	u16 msgs;
380
381	spin_lock(&mdev->mbox_lock);
382
383	if (mdev->num_msgs != mdev->msgs_acked)
384		goto exit;
385
386	for (msgs = 0; msgs < mdev->msgs_acked; msgs++) {
387		struct mbox_msghdr *preq = mdev->mbase + ireq;
388		struct mbox_msghdr *prsp = mdev->mbase + irsp;
389
390		if (preq->id != prsp->id) {
391			trace_otx2_msg_check(mbox->pdev, preq->id,
392					     prsp->id, prsp->rc);
393			goto exit;
394		}
395		if (prsp->rc) {
396			rc = prsp->rc;
397			trace_otx2_msg_check(mbox->pdev, preq->id,
398					     prsp->id, prsp->rc);
399			goto exit;
400		}
401
402		ireq = mbox->tx_start + preq->next_msgoff;
403		irsp = mbox->rx_start + prsp->next_msgoff;
404	}
405	rc = 0;
406exit:
407	spin_unlock(&mdev->mbox_lock);
408	return rc;
409}
410EXPORT_SYMBOL(otx2_mbox_check_rsp_msgs);
411
412int
413otx2_reply_invalid_msg(struct otx2_mbox *mbox, int devid, u16 pcifunc, u16 id)
414{
415	struct msg_rsp *rsp;
416
417	rsp = (struct msg_rsp *)
418	       otx2_mbox_alloc_msg(mbox, devid, sizeof(*rsp));
419	if (!rsp)
420		return -ENOMEM;
421	rsp->hdr.id = id;
422	rsp->hdr.sig = OTX2_MBOX_RSP_SIG;
423	rsp->hdr.rc = MBOX_MSG_INVALID;
424	rsp->hdr.pcifunc = pcifunc;
425	return 0;
426}
427EXPORT_SYMBOL(otx2_reply_invalid_msg);
428
429bool otx2_mbox_nonempty(struct otx2_mbox *mbox, int devid)
430{
431	struct otx2_mbox_dev *mdev = &mbox->dev[devid];
432	bool ret;
433
434	spin_lock(&mdev->mbox_lock);
435	ret = mdev->num_msgs != 0;
436	spin_unlock(&mdev->mbox_lock);
437
438	return ret;
439}
440EXPORT_SYMBOL(otx2_mbox_nonempty);
441
442const char *otx2_mbox_id2name(u16 id)
443{
444	switch (id) {
445#define M(_name, _id, _1, _2, _3) case _id: return # _name;
446	MBOX_MESSAGES
447#undef M
448	default:
449		return "INVALID ID";
450	}
451}
452EXPORT_SYMBOL(otx2_mbox_id2name);
453
454MODULE_AUTHOR("Marvell.");
455MODULE_DESCRIPTION("Marvell RVU NIC Mbox helpers");
456MODULE_LICENSE("GPL v2");
457