@@ -48,6 +48,8 @@ int __fbnic_open(struct fbnic_net *fbn)
48
48
err = fbnic_pcs_irq_enable (fbd );
49
49
if (err )
50
50
goto release_ownership ;
51
+ /* Pull the BMC config and initialize the RPC */
52
+ fbnic_bmc_rpc_init (fbd );
51
53
52
54
return 0 ;
53
55
release_ownership :
@@ -86,12 +88,240 @@ static int fbnic_stop(struct net_device *netdev)
86
88
return 0 ;
87
89
}
88
90
91
+ static int fbnic_uc_sync (struct net_device * netdev , const unsigned char * addr )
92
+ {
93
+ struct fbnic_net * fbn = netdev_priv (netdev );
94
+ struct fbnic_mac_addr * avail_addr ;
95
+
96
+ if (WARN_ON (!is_valid_ether_addr (addr )))
97
+ return - EADDRNOTAVAIL ;
98
+
99
+ avail_addr = __fbnic_uc_sync (fbn -> fbd , addr );
100
+ if (!avail_addr )
101
+ return - ENOSPC ;
102
+
103
+ /* Add type flag indicating this address is in use by the host */
104
+ set_bit (FBNIC_MAC_ADDR_T_UNICAST , avail_addr -> act_tcam );
105
+
106
+ return 0 ;
107
+ }
108
+
109
+ static int fbnic_uc_unsync (struct net_device * netdev , const unsigned char * addr )
110
+ {
111
+ struct fbnic_net * fbn = netdev_priv (netdev );
112
+ struct fbnic_dev * fbd = fbn -> fbd ;
113
+ int i , ret ;
114
+
115
+ /* Scan from middle of list to bottom, filling bottom up.
116
+ * Skip the first entry which is reserved for dev_addr and
117
+ * leave the last entry to use for promiscuous filtering.
118
+ */
119
+ for (i = fbd -> mac_addr_boundary , ret = - ENOENT ;
120
+ i < FBNIC_RPC_TCAM_MACDA_HOST_ADDR_IDX && ret ; i ++ ) {
121
+ struct fbnic_mac_addr * mac_addr = & fbd -> mac_addr [i ];
122
+
123
+ if (!ether_addr_equal (mac_addr -> value .addr8 , addr ))
124
+ continue ;
125
+
126
+ ret = __fbnic_uc_unsync (mac_addr );
127
+ }
128
+
129
+ return ret ;
130
+ }
131
+
132
+ static int fbnic_mc_sync (struct net_device * netdev , const unsigned char * addr )
133
+ {
134
+ struct fbnic_net * fbn = netdev_priv (netdev );
135
+ struct fbnic_mac_addr * avail_addr ;
136
+
137
+ if (WARN_ON (!is_multicast_ether_addr (addr )))
138
+ return - EADDRNOTAVAIL ;
139
+
140
+ avail_addr = __fbnic_mc_sync (fbn -> fbd , addr );
141
+ if (!avail_addr )
142
+ return - ENOSPC ;
143
+
144
+ /* Add type flag indicating this address is in use by the host */
145
+ set_bit (FBNIC_MAC_ADDR_T_MULTICAST , avail_addr -> act_tcam );
146
+
147
+ return 0 ;
148
+ }
149
+
150
+ static int fbnic_mc_unsync (struct net_device * netdev , const unsigned char * addr )
151
+ {
152
+ struct fbnic_net * fbn = netdev_priv (netdev );
153
+ struct fbnic_dev * fbd = fbn -> fbd ;
154
+ int i , ret ;
155
+
156
+ /* Scan from middle of list to top, filling top down.
157
+ * Skip over the address reserved for the BMC MAC and
158
+ * exclude index 0 as that belongs to the broadcast address
159
+ */
160
+ for (i = fbd -> mac_addr_boundary , ret = - ENOENT ;
161
+ -- i > FBNIC_RPC_TCAM_MACDA_BROADCAST_IDX && ret ;) {
162
+ struct fbnic_mac_addr * mac_addr = & fbd -> mac_addr [i ];
163
+
164
+ if (!ether_addr_equal (mac_addr -> value .addr8 , addr ))
165
+ continue ;
166
+
167
+ ret = __fbnic_mc_unsync (mac_addr );
168
+ }
169
+
170
+ return ret ;
171
+ }
172
+
173
+ void __fbnic_set_rx_mode (struct net_device * netdev )
174
+ {
175
+ struct fbnic_net * fbn = netdev_priv (netdev );
176
+ bool uc_promisc = false, mc_promisc = false;
177
+ struct fbnic_dev * fbd = fbn -> fbd ;
178
+ struct fbnic_mac_addr * mac_addr ;
179
+ int err ;
180
+
181
+ /* Populate host address from dev_addr */
182
+ mac_addr = & fbd -> mac_addr [FBNIC_RPC_TCAM_MACDA_HOST_ADDR_IDX ];
183
+ if (!ether_addr_equal (mac_addr -> value .addr8 , netdev -> dev_addr ) ||
184
+ mac_addr -> state != FBNIC_TCAM_S_VALID ) {
185
+ ether_addr_copy (mac_addr -> value .addr8 , netdev -> dev_addr );
186
+ mac_addr -> state = FBNIC_TCAM_S_UPDATE ;
187
+ set_bit (FBNIC_MAC_ADDR_T_UNICAST , mac_addr -> act_tcam );
188
+ }
189
+
190
+ /* Populate broadcast address if broadcast is enabled */
191
+ mac_addr = & fbd -> mac_addr [FBNIC_RPC_TCAM_MACDA_BROADCAST_IDX ];
192
+ if (netdev -> flags & IFF_BROADCAST ) {
193
+ if (!is_broadcast_ether_addr (mac_addr -> value .addr8 ) ||
194
+ mac_addr -> state != FBNIC_TCAM_S_VALID ) {
195
+ eth_broadcast_addr (mac_addr -> value .addr8 );
196
+ mac_addr -> state = FBNIC_TCAM_S_ADD ;
197
+ }
198
+ set_bit (FBNIC_MAC_ADDR_T_BROADCAST , mac_addr -> act_tcam );
199
+ } else if (mac_addr -> state == FBNIC_TCAM_S_VALID ) {
200
+ __fbnic_xc_unsync (mac_addr , FBNIC_MAC_ADDR_T_BROADCAST );
201
+ }
202
+
203
+ /* Synchronize unicast and multicast address lists */
204
+ err = __dev_uc_sync (netdev , fbnic_uc_sync , fbnic_uc_unsync );
205
+ if (err == - ENOSPC )
206
+ uc_promisc = true;
207
+ err = __dev_mc_sync (netdev , fbnic_mc_sync , fbnic_mc_unsync );
208
+ if (err == - ENOSPC )
209
+ mc_promisc = true;
210
+
211
+ uc_promisc |= !!(netdev -> flags & IFF_PROMISC );
212
+ mc_promisc |= !!(netdev -> flags & IFF_ALLMULTI ) || uc_promisc ;
213
+
214
+ /* Populate last TCAM entry with promiscuous entry and 0/1 bit mask */
215
+ mac_addr = & fbd -> mac_addr [FBNIC_RPC_TCAM_MACDA_PROMISC_IDX ];
216
+ if (uc_promisc ) {
217
+ if (!is_zero_ether_addr (mac_addr -> value .addr8 ) ||
218
+ mac_addr -> state != FBNIC_TCAM_S_VALID ) {
219
+ eth_zero_addr (mac_addr -> value .addr8 );
220
+ eth_broadcast_addr (mac_addr -> mask .addr8 );
221
+ clear_bit (FBNIC_MAC_ADDR_T_ALLMULTI ,
222
+ mac_addr -> act_tcam );
223
+ set_bit (FBNIC_MAC_ADDR_T_PROMISC ,
224
+ mac_addr -> act_tcam );
225
+ mac_addr -> state = FBNIC_TCAM_S_ADD ;
226
+ }
227
+ } else if (mc_promisc &&
228
+ (!fbnic_bmc_present (fbd ) || !fbd -> fw_cap .all_multi )) {
229
+ /* We have to add a special handler for multicast as the
230
+ * BMC may have an all-multi rule already in place. As such
231
+ * adding a rule ourselves won't do any good so we will have
232
+ * to modify the rules for the ALL MULTI below if the BMC
233
+ * already has the rule in place.
234
+ */
235
+ if (!is_multicast_ether_addr (mac_addr -> value .addr8 ) ||
236
+ mac_addr -> state != FBNIC_TCAM_S_VALID ) {
237
+ eth_zero_addr (mac_addr -> value .addr8 );
238
+ eth_broadcast_addr (mac_addr -> mask .addr8 );
239
+ mac_addr -> value .addr8 [0 ] ^= 1 ;
240
+ mac_addr -> mask .addr8 [0 ] ^= 1 ;
241
+ set_bit (FBNIC_MAC_ADDR_T_ALLMULTI ,
242
+ mac_addr -> act_tcam );
243
+ clear_bit (FBNIC_MAC_ADDR_T_PROMISC ,
244
+ mac_addr -> act_tcam );
245
+ mac_addr -> state = FBNIC_TCAM_S_ADD ;
246
+ }
247
+ } else if (mac_addr -> state == FBNIC_TCAM_S_VALID ) {
248
+ if (test_bit (FBNIC_MAC_ADDR_T_BMC , mac_addr -> act_tcam )) {
249
+ clear_bit (FBNIC_MAC_ADDR_T_ALLMULTI ,
250
+ mac_addr -> act_tcam );
251
+ clear_bit (FBNIC_MAC_ADDR_T_PROMISC ,
252
+ mac_addr -> act_tcam );
253
+ } else {
254
+ mac_addr -> state = FBNIC_TCAM_S_DELETE ;
255
+ }
256
+ }
257
+
258
+ /* Add rules for BMC all multicast if it is enabled */
259
+ fbnic_bmc_rpc_all_multi_config (fbd , mc_promisc );
260
+
261
+ /* Sift out any unshared BMC rules and place them in BMC only section */
262
+ fbnic_sift_macda (fbd );
263
+
264
+ /* Write updates to hardware */
265
+ fbnic_write_macda (fbd );
266
+ }
267
+
268
+ static void fbnic_set_rx_mode (struct net_device * netdev )
269
+ {
270
+ /* No need to update the hardware if we are not running */
271
+ if (netif_running (netdev ))
272
+ __fbnic_set_rx_mode (netdev );
273
+ }
274
+
275
+ static int fbnic_set_mac (struct net_device * netdev , void * p )
276
+ {
277
+ struct sockaddr * addr = p ;
278
+
279
+ if (!is_valid_ether_addr (addr -> sa_data ))
280
+ return - EADDRNOTAVAIL ;
281
+
282
+ eth_hw_addr_set (netdev , addr -> sa_data );
283
+
284
+ fbnic_set_rx_mode (netdev );
285
+
286
+ return 0 ;
287
+ }
288
+
289
+ void fbnic_clear_rx_mode (struct net_device * netdev )
290
+ {
291
+ struct fbnic_net * fbn = netdev_priv (netdev );
292
+ struct fbnic_dev * fbd = fbn -> fbd ;
293
+ int idx ;
294
+
295
+ for (idx = ARRAY_SIZE (fbd -> mac_addr ); idx -- ;) {
296
+ struct fbnic_mac_addr * mac_addr = & fbd -> mac_addr [idx ];
297
+
298
+ if (mac_addr -> state != FBNIC_TCAM_S_VALID )
299
+ continue ;
300
+
301
+ bitmap_clear (mac_addr -> act_tcam ,
302
+ FBNIC_MAC_ADDR_T_HOST_START ,
303
+ FBNIC_MAC_ADDR_T_HOST_LEN );
304
+
305
+ if (bitmap_empty (mac_addr -> act_tcam ,
306
+ FBNIC_RPC_TCAM_ACT_NUM_ENTRIES ))
307
+ mac_addr -> state = FBNIC_TCAM_S_DELETE ;
308
+ }
309
+
310
+ /* Write updates to hardware */
311
+ fbnic_write_macda (fbd );
312
+
313
+ __dev_uc_unsync (netdev , NULL );
314
+ __dev_mc_unsync (netdev , NULL );
315
+ }
316
+
89
317
static const struct net_device_ops fbnic_netdev_ops = {
90
318
.ndo_open = fbnic_open ,
91
319
.ndo_stop = fbnic_stop ,
92
320
.ndo_validate_addr = eth_validate_addr ,
93
321
.ndo_start_xmit = fbnic_xmit_frame ,
94
322
.ndo_features_check = fbnic_features_check ,
323
+ .ndo_set_mac_address = fbnic_set_mac ,
324
+ .ndo_set_rx_mode = fbnic_set_rx_mode ,
95
325
};
96
326
97
327
void fbnic_reset_queues (struct fbnic_net * fbn ,
0 commit comments