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