1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47#include <linux/types.h>
48#include <linux/mutex.h>
49#include <linux/slab.h>
50#include <linux/delay.h>
51#include <linux/pci.h>
52#include <linux/dma-mapping.h>
53#include <adf_accel_devices.h>
54#include "adf_drv.h"
55#include "adf_dh895xcc_hw_data.h"
56
57#define ADF_ADMINMSG_LEN 32
58
59struct adf_admin_comms {
60 dma_addr_t phy_addr;
61 void *virt_addr;
62 void __iomem *mailbox_addr;
63 struct mutex lock;
64};
65
66int adf_put_admin_msg_sync(struct adf_accel_dev *accel_dev,
67 uint32_t ae, void *in, void *out)
68{
69 struct adf_admin_comms *admin = accel_dev->admin;
70 int offset = ae * ADF_ADMINMSG_LEN * 2;
71 void __iomem *mailbox = admin->mailbox_addr;
72 int mb_offset = ae * ADF_DH895XCC_MAILBOX_STRIDE;
73 int times, received;
74
75 mutex_lock(&admin->lock);
76
77 if (ADF_CSR_RD(mailbox, mb_offset) == 1) {
78 mutex_unlock(&admin->lock);
79 return -EAGAIN;
80 }
81
82 memcpy(admin->virt_addr + offset, in, ADF_ADMINMSG_LEN);
83 ADF_CSR_WR(mailbox, mb_offset, 1);
84 received = 0;
85 for (times = 0; times < 50; times++) {
86 msleep(20);
87 if (ADF_CSR_RD(mailbox, mb_offset) == 0) {
88 received = 1;
89 break;
90 }
91 }
92 if (received)
93 memcpy(out, admin->virt_addr + offset +
94 ADF_ADMINMSG_LEN, ADF_ADMINMSG_LEN);
95 else
96 pr_err("QAT: Failed to send admin msg to accelerator\n");
97
98 mutex_unlock(&admin->lock);
99 return received ? 0 : -EFAULT;
100}
101
102int adf_init_admin_comms(struct adf_accel_dev *accel_dev)
103{
104 struct adf_admin_comms *admin;
105 struct adf_bar *pmisc = &GET_BARS(accel_dev)[ADF_DH895XCC_PMISC_BAR];
106 void __iomem *csr = pmisc->virt_addr;
107 void __iomem *mailbox = csr + ADF_DH895XCC_MAILBOX_BASE_OFFSET;
108 uint64_t reg_val;
109
110 admin = kzalloc_node(sizeof(*accel_dev->admin), GFP_KERNEL,
111 dev_to_node(&GET_DEV(accel_dev)));
112 if (!admin)
113 return -ENOMEM;
114 admin->virt_addr = dma_zalloc_coherent(&GET_DEV(accel_dev), PAGE_SIZE,
115 &admin->phy_addr, GFP_KERNEL);
116 if (!admin->virt_addr) {
117 dev_err(&GET_DEV(accel_dev), "Failed to allocate dma buff\n");
118 kfree(admin);
119 return -ENOMEM;
120 }
121 reg_val = (uint64_t)admin->phy_addr;
122 ADF_CSR_WR(csr, ADF_DH895XCC_ADMINMSGUR_OFFSET, reg_val >> 32);
123 ADF_CSR_WR(csr, ADF_DH895XCC_ADMINMSGLR_OFFSET, reg_val);
124 mutex_init(&admin->lock);
125 admin->mailbox_addr = mailbox;
126 accel_dev->admin = admin;
127 return 0;
128}
129
130void adf_exit_admin_comms(struct adf_accel_dev *accel_dev)
131{
132 struct adf_admin_comms *admin = accel_dev->admin;
133
134 if (!admin)
135 return;
136
137 if (admin->virt_addr)
138 dma_free_coherent(&GET_DEV(accel_dev), PAGE_SIZE,
139 admin->virt_addr, admin->phy_addr);
140
141 mutex_destroy(&admin->lock);
142 kfree(admin);
143 accel_dev->admin = NULL;
144}
145