1 // SPDX-License-Identifier: GPL-2.0
2 /* Marvell RVU Ethernet driver
3  *
4  * Copyright (C) 2021 Marvell.
5  *
6  */
7 
8 #include "otx2_common.h"
9 
10 static int otx2_dmacflt_do_add(struct otx2_nic *pf, const u8 *mac,
11 			       u32 *dmac_index)
12 {
13 	struct cgx_mac_addr_add_req *req;
14 	struct cgx_mac_addr_add_rsp *rsp;
15 	int err;
16 
17 	mutex_lock(&pf->mbox.lock);
18 
19 	req = otx2_mbox_alloc_msg_cgx_mac_addr_add(&pf->mbox);
20 	if (!req) {
21 		mutex_unlock(&pf->mbox.lock);
22 		return -ENOMEM;
23 	}
24 
25 	ether_addr_copy(req->mac_addr, mac);
26 	err = otx2_sync_mbox_msg(&pf->mbox);
27 
28 	if (!err) {
29 		rsp = (struct cgx_mac_addr_add_rsp *)
30 			 otx2_mbox_get_rsp(&pf->mbox.mbox, 0, &req->hdr);
31 		if (IS_ERR(rsp)) {
32 			mutex_unlock(&pf->mbox.lock);
33 			return PTR_ERR(rsp);
34 		}
35 
36 		*dmac_index = rsp->index;
37 	}
38 
39 	mutex_unlock(&pf->mbox.lock);
40 	return err;
41 }
42 
43 static int otx2_dmacflt_add_pfmac(struct otx2_nic *pf, u32 *dmac_index)
44 {
45 	struct cgx_mac_addr_set_or_get *req;
46 	struct cgx_mac_addr_set_or_get *rsp;
47 	int err;
48 
49 	mutex_lock(&pf->mbox.lock);
50 
51 	req = otx2_mbox_alloc_msg_cgx_mac_addr_set(&pf->mbox);
52 	if (!req) {
53 		mutex_unlock(&pf->mbox.lock);
54 		return -ENOMEM;
55 	}
56 
57 	req->index = *dmac_index;
58 
59 	ether_addr_copy(req->mac_addr, pf->netdev->dev_addr);
60 	err = otx2_sync_mbox_msg(&pf->mbox);
61 
62 	if (err)
63 		goto out;
64 
65 	rsp = (struct cgx_mac_addr_set_or_get *)
66 		otx2_mbox_get_rsp(&pf->mbox.mbox, 0, &req->hdr);
67 
68 	if (IS_ERR_OR_NULL(rsp)) {
69 		err = -EINVAL;
70 		goto out;
71 	}
72 
73 	*dmac_index = rsp->index;
74 out:
75 	mutex_unlock(&pf->mbox.lock);
76 	return err;
77 }
78 
79 int otx2_dmacflt_add(struct otx2_nic *pf, const u8 *mac, u32 bit_pos)
80 {
81 	u32 *dmacindex;
82 
83 	/* Store dmacindex returned by CGX/RPM driver which will
84 	 * be used for macaddr update/remove
85 	 */
86 	dmacindex = &pf->flow_cfg->bmap_to_dmacindex[bit_pos];
87 
88 	if (ether_addr_equal(mac, pf->netdev->dev_addr))
89 		return otx2_dmacflt_add_pfmac(pf, dmacindex);
90 	else
91 		return otx2_dmacflt_do_add(pf, mac, dmacindex);
92 }
93 
94 static int otx2_dmacflt_do_remove(struct otx2_nic *pfvf, const u8 *mac,
95 				  u32 dmac_index)
96 {
97 	struct cgx_mac_addr_del_req *req;
98 	int err;
99 
100 	mutex_lock(&pfvf->mbox.lock);
101 	req = otx2_mbox_alloc_msg_cgx_mac_addr_del(&pfvf->mbox);
102 	if (!req) {
103 		mutex_unlock(&pfvf->mbox.lock);
104 		return -ENOMEM;
105 	}
106 
107 	req->index = dmac_index;
108 
109 	err = otx2_sync_mbox_msg(&pfvf->mbox);
110 	mutex_unlock(&pfvf->mbox.lock);
111 
112 	return err;
113 }
114 
115 static int otx2_dmacflt_remove_pfmac(struct otx2_nic *pf, u32 dmac_index)
116 {
117 	struct cgx_mac_addr_reset_req *req;
118 	int err;
119 
120 	mutex_lock(&pf->mbox.lock);
121 	req = otx2_mbox_alloc_msg_cgx_mac_addr_reset(&pf->mbox);
122 	if (!req) {
123 		mutex_unlock(&pf->mbox.lock);
124 		return -ENOMEM;
125 	}
126 	req->index = dmac_index;
127 
128 	err = otx2_sync_mbox_msg(&pf->mbox);
129 
130 	mutex_unlock(&pf->mbox.lock);
131 	return err;
132 }
133 
134 int otx2_dmacflt_remove(struct otx2_nic *pf, const u8 *mac,
135 			u32 bit_pos)
136 {
137 	u32 dmacindex = pf->flow_cfg->bmap_to_dmacindex[bit_pos];
138 
139 	if (ether_addr_equal(mac, pf->netdev->dev_addr))
140 		return otx2_dmacflt_remove_pfmac(pf, dmacindex);
141 	else
142 		return otx2_dmacflt_do_remove(pf, mac, dmacindex);
143 }
144 
145 /* CGX/RPM blocks support max unicast entries of 32.
146  * on typical configuration MAC block associated
147  * with 4 lmacs, each lmac will have 8 dmac entries
148  */
149 int otx2_dmacflt_get_max_cnt(struct otx2_nic *pf)
150 {
151 	struct cgx_max_dmac_entries_get_rsp *rsp;
152 	struct msg_req *msg;
153 	int err;
154 
155 	mutex_lock(&pf->mbox.lock);
156 	msg = otx2_mbox_alloc_msg_cgx_mac_max_entries_get(&pf->mbox);
157 
158 	if (!msg) {
159 		mutex_unlock(&pf->mbox.lock);
160 		return -ENOMEM;
161 	}
162 
163 	err = otx2_sync_mbox_msg(&pf->mbox);
164 	if (err)
165 		goto out;
166 
167 	rsp = (struct cgx_max_dmac_entries_get_rsp *)
168 		     otx2_mbox_get_rsp(&pf->mbox.mbox, 0, &msg->hdr);
169 
170 	if (IS_ERR_OR_NULL(rsp)) {
171 		err = -EINVAL;
172 		goto out;
173 	}
174 
175 	pf->flow_cfg->dmacflt_max_flows = rsp->max_dmac_filters;
176 
177 out:
178 	mutex_unlock(&pf->mbox.lock);
179 	return err;
180 }
181 
182 int otx2_dmacflt_update(struct otx2_nic *pf, u8 *mac, u32 bit_pos)
183 {
184 	struct cgx_mac_addr_update_req *req;
185 	struct cgx_mac_addr_update_rsp *rsp;
186 	int rc;
187 
188 	mutex_lock(&pf->mbox.lock);
189 
190 	req = otx2_mbox_alloc_msg_cgx_mac_addr_update(&pf->mbox);
191 
192 	if (!req) {
193 		mutex_unlock(&pf->mbox.lock);
194 		return -ENOMEM;
195 	}
196 
197 	ether_addr_copy(req->mac_addr, mac);
198 	req->index = pf->flow_cfg->bmap_to_dmacindex[bit_pos];
199 
200 	/* check the response and change index */
201 
202 	rc = otx2_sync_mbox_msg(&pf->mbox);
203 	if (rc)
204 		goto out;
205 
206 	rsp = (struct cgx_mac_addr_update_rsp *)
207 		otx2_mbox_get_rsp(&pf->mbox.mbox, 0, &req->hdr);
208 	if (IS_ERR(rsp)) {
209 		rc = PTR_ERR(rsp);
210 		goto out;
211 	}
212 
213 	pf->flow_cfg->bmap_to_dmacindex[bit_pos] = rsp->index;
214 
215 out:
216 	mutex_unlock(&pf->mbox.lock);
217 	return rc;
218 }
219