1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (C) 2020 Marvell. */
3 
4 #include "otx2_cpt_common.h"
5 #include "otx2_cptlf.h"
6 
otx2_cpt_send_mbox_msg(struct otx2_mbox * mbox,struct pci_dev * pdev)7 int otx2_cpt_send_mbox_msg(struct otx2_mbox *mbox, struct pci_dev *pdev)
8 {
9 	int ret;
10 
11 	otx2_mbox_msg_send(mbox, 0);
12 	ret = otx2_mbox_wait_for_rsp(mbox, 0);
13 	if (ret == -EIO) {
14 		dev_err(&pdev->dev, "RVU MBOX timeout.\n");
15 		return ret;
16 	} else if (ret) {
17 		dev_err(&pdev->dev, "RVU MBOX error: %d.\n", ret);
18 		return -EFAULT;
19 	}
20 	return ret;
21 }
22 
otx2_cpt_send_ready_msg(struct otx2_mbox * mbox,struct pci_dev * pdev)23 int otx2_cpt_send_ready_msg(struct otx2_mbox *mbox, struct pci_dev *pdev)
24 {
25 	struct mbox_msghdr *req;
26 
27 	req = otx2_mbox_alloc_msg_rsp(mbox, 0, sizeof(*req),
28 				      sizeof(struct ready_msg_rsp));
29 	if (req == NULL) {
30 		dev_err(&pdev->dev, "RVU MBOX failed to get message.\n");
31 		return -EFAULT;
32 	}
33 	req->id = MBOX_MSG_READY;
34 	req->sig = OTX2_MBOX_REQ_SIG;
35 	req->pcifunc = 0;
36 
37 	return otx2_cpt_send_mbox_msg(mbox, pdev);
38 }
39 
otx2_cpt_send_af_reg_requests(struct otx2_mbox * mbox,struct pci_dev * pdev)40 int otx2_cpt_send_af_reg_requests(struct otx2_mbox *mbox, struct pci_dev *pdev)
41 {
42 	return otx2_cpt_send_mbox_msg(mbox, pdev);
43 }
44 
otx2_cpt_add_read_af_reg(struct otx2_mbox * mbox,struct pci_dev * pdev,u64 reg,u64 * val,int blkaddr)45 int otx2_cpt_add_read_af_reg(struct otx2_mbox *mbox, struct pci_dev *pdev,
46 			     u64 reg, u64 *val, int blkaddr)
47 {
48 	struct cpt_rd_wr_reg_msg *reg_msg;
49 
50 	reg_msg = (struct cpt_rd_wr_reg_msg *)
51 			otx2_mbox_alloc_msg_rsp(mbox, 0, sizeof(*reg_msg),
52 						sizeof(*reg_msg));
53 	if (reg_msg == NULL) {
54 		dev_err(&pdev->dev, "RVU MBOX failed to get message.\n");
55 		return -EFAULT;
56 	}
57 
58 	reg_msg->hdr.id = MBOX_MSG_CPT_RD_WR_REGISTER;
59 	reg_msg->hdr.sig = OTX2_MBOX_REQ_SIG;
60 	reg_msg->hdr.pcifunc = 0;
61 
62 	reg_msg->is_write = 0;
63 	reg_msg->reg_offset = reg;
64 	reg_msg->ret_val = val;
65 	reg_msg->blkaddr = blkaddr;
66 
67 	return 0;
68 }
69 
otx2_cpt_add_write_af_reg(struct otx2_mbox * mbox,struct pci_dev * pdev,u64 reg,u64 val,int blkaddr)70 int otx2_cpt_add_write_af_reg(struct otx2_mbox *mbox, struct pci_dev *pdev,
71 			      u64 reg, u64 val, int blkaddr)
72 {
73 	struct cpt_rd_wr_reg_msg *reg_msg;
74 
75 	reg_msg = (struct cpt_rd_wr_reg_msg *)
76 			otx2_mbox_alloc_msg_rsp(mbox, 0, sizeof(*reg_msg),
77 						sizeof(*reg_msg));
78 	if (reg_msg == NULL) {
79 		dev_err(&pdev->dev, "RVU MBOX failed to get message.\n");
80 		return -EFAULT;
81 	}
82 
83 	reg_msg->hdr.id = MBOX_MSG_CPT_RD_WR_REGISTER;
84 	reg_msg->hdr.sig = OTX2_MBOX_REQ_SIG;
85 	reg_msg->hdr.pcifunc = 0;
86 
87 	reg_msg->is_write = 1;
88 	reg_msg->reg_offset = reg;
89 	reg_msg->val = val;
90 	reg_msg->blkaddr = blkaddr;
91 
92 	return 0;
93 }
94 
otx2_cpt_read_af_reg(struct otx2_mbox * mbox,struct pci_dev * pdev,u64 reg,u64 * val,int blkaddr)95 int otx2_cpt_read_af_reg(struct otx2_mbox *mbox, struct pci_dev *pdev,
96 			 u64 reg, u64 *val, int blkaddr)
97 {
98 	int ret;
99 
100 	ret = otx2_cpt_add_read_af_reg(mbox, pdev, reg, val, blkaddr);
101 	if (ret)
102 		return ret;
103 
104 	return otx2_cpt_send_mbox_msg(mbox, pdev);
105 }
106 
otx2_cpt_write_af_reg(struct otx2_mbox * mbox,struct pci_dev * pdev,u64 reg,u64 val,int blkaddr)107 int otx2_cpt_write_af_reg(struct otx2_mbox *mbox, struct pci_dev *pdev,
108 			  u64 reg, u64 val, int blkaddr)
109 {
110 	int ret;
111 
112 	ret = otx2_cpt_add_write_af_reg(mbox, pdev, reg, val, blkaddr);
113 	if (ret)
114 		return ret;
115 
116 	return otx2_cpt_send_mbox_msg(mbox, pdev);
117 }
118 
otx2_cpt_attach_rscrs_msg(struct otx2_cptlfs_info * lfs)119 int otx2_cpt_attach_rscrs_msg(struct otx2_cptlfs_info *lfs)
120 {
121 	struct otx2_mbox *mbox = lfs->mbox;
122 	struct rsrc_attach *req;
123 	int ret;
124 
125 	req = (struct rsrc_attach *)
126 			otx2_mbox_alloc_msg_rsp(mbox, 0, sizeof(*req),
127 						sizeof(struct msg_rsp));
128 	if (req == NULL) {
129 		dev_err(&lfs->pdev->dev, "RVU MBOX failed to get message.\n");
130 		return -EFAULT;
131 	}
132 
133 	req->hdr.id = MBOX_MSG_ATTACH_RESOURCES;
134 	req->hdr.sig = OTX2_MBOX_REQ_SIG;
135 	req->hdr.pcifunc = 0;
136 	req->cptlfs = lfs->lfs_num;
137 	ret = otx2_cpt_send_mbox_msg(mbox, lfs->pdev);
138 	if (ret)
139 		return ret;
140 
141 	if (!lfs->are_lfs_attached)
142 		ret = -EINVAL;
143 
144 	return ret;
145 }
146 
otx2_cpt_detach_rsrcs_msg(struct otx2_cptlfs_info * lfs)147 int otx2_cpt_detach_rsrcs_msg(struct otx2_cptlfs_info *lfs)
148 {
149 	struct otx2_mbox *mbox = lfs->mbox;
150 	struct rsrc_detach *req;
151 	int ret;
152 
153 	req = (struct rsrc_detach *)
154 				otx2_mbox_alloc_msg_rsp(mbox, 0, sizeof(*req),
155 							sizeof(struct msg_rsp));
156 	if (req == NULL) {
157 		dev_err(&lfs->pdev->dev, "RVU MBOX failed to get message.\n");
158 		return -EFAULT;
159 	}
160 
161 	req->hdr.id = MBOX_MSG_DETACH_RESOURCES;
162 	req->hdr.sig = OTX2_MBOX_REQ_SIG;
163 	req->hdr.pcifunc = 0;
164 	ret = otx2_cpt_send_mbox_msg(mbox, lfs->pdev);
165 	if (ret)
166 		return ret;
167 
168 	if (lfs->are_lfs_attached)
169 		ret = -EINVAL;
170 
171 	return ret;
172 }
173 
otx2_cpt_msix_offset_msg(struct otx2_cptlfs_info * lfs)174 int otx2_cpt_msix_offset_msg(struct otx2_cptlfs_info *lfs)
175 {
176 	struct otx2_mbox *mbox = lfs->mbox;
177 	struct pci_dev *pdev = lfs->pdev;
178 	struct mbox_msghdr *req;
179 	int ret, i;
180 
181 	req = otx2_mbox_alloc_msg_rsp(mbox, 0, sizeof(*req),
182 				      sizeof(struct msix_offset_rsp));
183 	if (req == NULL) {
184 		dev_err(&pdev->dev, "RVU MBOX failed to get message.\n");
185 		return -EFAULT;
186 	}
187 
188 	req->id = MBOX_MSG_MSIX_OFFSET;
189 	req->sig = OTX2_MBOX_REQ_SIG;
190 	req->pcifunc = 0;
191 	ret = otx2_cpt_send_mbox_msg(mbox, pdev);
192 	if (ret)
193 		return ret;
194 
195 	for (i = 0; i < lfs->lfs_num; i++) {
196 		if (lfs->lf[i].msix_offset == MSIX_VECTOR_INVALID) {
197 			dev_err(&pdev->dev,
198 				"Invalid msix offset %d for LF %d\n",
199 				lfs->lf[i].msix_offset, i);
200 			return -EINVAL;
201 		}
202 	}
203 	return ret;
204 }
205