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(mbox: &pf->mbox); |
20 | if (!req) { |
21 | mutex_unlock(lock: &pf->mbox.lock); |
22 | return -ENOMEM; |
23 | } |
24 | |
25 | ether_addr_copy(dst: req->mac_addr, src: mac); |
26 | err = otx2_sync_mbox_msg(mbox: &pf->mbox); |
27 | |
28 | if (!err) { |
29 | rsp = (struct cgx_mac_addr_add_rsp *) |
30 | otx2_mbox_get_rsp(mbox: &pf->mbox.mbox, devid: 0, msg: &req->hdr); |
31 | *dmac_index = rsp->index; |
32 | } |
33 | |
34 | mutex_unlock(lock: &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(mbox: &pf->mbox); |
47 | if (!req) { |
48 | mutex_unlock(lock: &pf->mbox.lock); |
49 | return -ENOMEM; |
50 | } |
51 | |
52 | req->index = *dmac_index; |
53 | |
54 | ether_addr_copy(dst: req->mac_addr, src: pf->netdev->dev_addr); |
55 | err = otx2_sync_mbox_msg(mbox: &pf->mbox); |
56 | |
57 | if (err) |
58 | goto out; |
59 | |
60 | rsp = (struct cgx_mac_addr_set_or_get *) |
61 | otx2_mbox_get_rsp(mbox: &pf->mbox.mbox, devid: 0, msg: &req->hdr); |
62 | |
63 | if (IS_ERR_OR_NULL(ptr: rsp)) { |
64 | err = -EINVAL; |
65 | goto out; |
66 | } |
67 | |
68 | *dmac_index = rsp->index; |
69 | out: |
70 | mutex_unlock(lock: &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(addr1: mac, addr2: pf->netdev->dev_addr)) |
84 | return otx2_dmacflt_add_pfmac(pf, dmac_index: dmacindex); |
85 | else |
86 | return otx2_dmacflt_do_add(pf, mac, dmac_index: 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(mbox: &pfvf->mbox); |
97 | if (!req) { |
98 | mutex_unlock(lock: &pfvf->mbox.lock); |
99 | return -ENOMEM; |
100 | } |
101 | |
102 | req->index = dmac_index; |
103 | |
104 | err = otx2_sync_mbox_msg(mbox: &pfvf->mbox); |
105 | mutex_unlock(lock: &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(mbox: &pf->mbox); |
117 | if (!req) { |
118 | mutex_unlock(lock: &pf->mbox.lock); |
119 | return -ENOMEM; |
120 | } |
121 | req->index = dmac_index; |
122 | |
123 | err = otx2_sync_mbox_msg(mbox: &pf->mbox); |
124 | |
125 | mutex_unlock(lock: &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(addr1: mac, addr2: pf->netdev->dev_addr)) |
135 | return otx2_dmacflt_remove_pfmac(pf, dmac_index: dmacindex); |
136 | else |
137 | return otx2_dmacflt_do_remove(pfvf: pf, mac, dmac_index: 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(mbox: &pf->mbox); |
152 | |
153 | if (!msg) { |
154 | mutex_unlock(lock: &pf->mbox.lock); |
155 | return -ENOMEM; |
156 | } |
157 | |
158 | err = otx2_sync_mbox_msg(mbox: &pf->mbox); |
159 | if (err) |
160 | goto out; |
161 | |
162 | rsp = (struct cgx_max_dmac_entries_get_rsp *) |
163 | otx2_mbox_get_rsp(mbox: &pf->mbox.mbox, devid: 0, msg: &msg->hdr); |
164 | |
165 | if (IS_ERR_OR_NULL(ptr: 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(lock: &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(mbox: &pf->mbox); |
186 | |
187 | if (!req) { |
188 | mutex_unlock(lock: &pf->mbox.lock); |
189 | return -ENOMEM; |
190 | } |
191 | |
192 | ether_addr_copy(dst: req->mac_addr, src: 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(mbox: &pf->mbox); |
198 | if (rc) |
199 | goto out; |
200 | |
201 | rsp = (struct cgx_mac_addr_update_rsp *) |
202 | otx2_mbox_get_rsp(mbox: &pf->mbox.mbox, devid: 0, msg: &req->hdr); |
203 | |
204 | pf->flow_cfg->bmap_to_dmacindex[bit_pos] = rsp->index; |
205 | |
206 | out: |
207 | mutex_unlock(lock: &pf->mbox.lock); |
208 | return rc; |
209 | } |
210 | |