@@ -1564,8 +1564,67 @@ static int ionic_set_features(struct net_device *netdev,
1564
1564
return err ;
1565
1565
}
1566
1566
1567
+ static int ionic_set_attr_mac (struct ionic_lif * lif , u8 * mac )
1568
+ {
1569
+ struct ionic_admin_ctx ctx = {
1570
+ .work = COMPLETION_INITIALIZER_ONSTACK (ctx .work ),
1571
+ .cmd .lif_setattr = {
1572
+ .opcode = IONIC_CMD_LIF_SETATTR ,
1573
+ .index = cpu_to_le16 (lif -> index ),
1574
+ .attr = IONIC_LIF_ATTR_MAC ,
1575
+ },
1576
+ };
1577
+
1578
+ ether_addr_copy (ctx .cmd .lif_setattr .mac , mac );
1579
+ return ionic_adminq_post_wait (lif , & ctx );
1580
+ }
1581
+
1582
+ static int ionic_get_attr_mac (struct ionic_lif * lif , u8 * mac_addr )
1583
+ {
1584
+ struct ionic_admin_ctx ctx = {
1585
+ .work = COMPLETION_INITIALIZER_ONSTACK (ctx .work ),
1586
+ .cmd .lif_getattr = {
1587
+ .opcode = IONIC_CMD_LIF_GETATTR ,
1588
+ .index = cpu_to_le16 (lif -> index ),
1589
+ .attr = IONIC_LIF_ATTR_MAC ,
1590
+ },
1591
+ };
1592
+ int err ;
1593
+
1594
+ err = ionic_adminq_post_wait (lif , & ctx );
1595
+ if (err )
1596
+ return err ;
1597
+
1598
+ ether_addr_copy (mac_addr , ctx .comp .lif_getattr .mac );
1599
+ return 0 ;
1600
+ }
1601
+
1602
+ static int ionic_program_mac (struct ionic_lif * lif , u8 * mac )
1603
+ {
1604
+ u8 get_mac [ETH_ALEN ];
1605
+ int err ;
1606
+
1607
+ err = ionic_set_attr_mac (lif , mac );
1608
+ if (err )
1609
+ return err ;
1610
+
1611
+ err = ionic_get_attr_mac (lif , get_mac );
1612
+ if (err )
1613
+ return err ;
1614
+
1615
+ /* To deal with older firmware that silently ignores the set attr mac:
1616
+ * doesn't actually change the mac and doesn't return an error, so we
1617
+ * do the get attr to verify whether or not the set actually happened
1618
+ */
1619
+ if (!ether_addr_equal (get_mac , mac ))
1620
+ return 1 ;
1621
+
1622
+ return 0 ;
1623
+ }
1624
+
1567
1625
static int ionic_set_mac_address (struct net_device * netdev , void * sa )
1568
1626
{
1627
+ struct ionic_lif * lif = netdev_priv (netdev );
1569
1628
struct sockaddr * addr = sa ;
1570
1629
u8 * mac ;
1571
1630
int err ;
@@ -1574,6 +1633,14 @@ static int ionic_set_mac_address(struct net_device *netdev, void *sa)
1574
1633
if (ether_addr_equal (netdev -> dev_addr , mac ))
1575
1634
return 0 ;
1576
1635
1636
+ err = ionic_program_mac (lif , mac );
1637
+ if (err < 0 )
1638
+ return err ;
1639
+
1640
+ if (err > 0 )
1641
+ netdev_dbg (netdev , "%s: SET and GET ATTR Mac are not equal-due to old FW running\n" ,
1642
+ __func__ );
1643
+
1577
1644
err = eth_prepare_mac_addr_change (netdev , addr );
1578
1645
if (err )
1579
1646
return err ;
@@ -2963,6 +3030,9 @@ static void ionic_lif_handle_fw_up(struct ionic_lif *lif)
2963
3030
2964
3031
mutex_lock (& lif -> queue_lock );
2965
3032
3033
+ if (test_and_clear_bit (IONIC_LIF_F_BROKEN , lif -> state ))
3034
+ dev_info (ionic -> dev , "FW Up: clearing broken state\n" );
3035
+
2966
3036
err = ionic_qcqs_alloc (lif );
2967
3037
if (err )
2968
3038
goto err_unlock ;
@@ -3169,6 +3239,7 @@ static int ionic_station_set(struct ionic_lif *lif)
3169
3239
.attr = IONIC_LIF_ATTR_MAC ,
3170
3240
},
3171
3241
};
3242
+ u8 mac_address [ETH_ALEN ];
3172
3243
struct sockaddr addr ;
3173
3244
int err ;
3174
3245
@@ -3177,21 +3248,35 @@ static int ionic_station_set(struct ionic_lif *lif)
3177
3248
return err ;
3178
3249
netdev_dbg (lif -> netdev , "found initial MAC addr %pM\n" ,
3179
3250
ctx .comp .lif_getattr .mac );
3180
- if (is_zero_ether_addr (ctx .comp .lif_getattr .mac ))
3181
- return 0 ;
3251
+ ether_addr_copy (mac_address , ctx .comp .lif_getattr .mac );
3252
+
3253
+ if (is_zero_ether_addr (mac_address )) {
3254
+ eth_hw_addr_random (netdev );
3255
+ netdev_dbg (netdev , "Random Mac generated: %pM\n" , netdev -> dev_addr );
3256
+ ether_addr_copy (mac_address , netdev -> dev_addr );
3257
+
3258
+ err = ionic_program_mac (lif , mac_address );
3259
+ if (err < 0 )
3260
+ return err ;
3261
+
3262
+ if (err > 0 ) {
3263
+ netdev_dbg (netdev , "%s:SET/GET ATTR Mac are not same-due to old FW running\n" ,
3264
+ __func__ );
3265
+ return 0 ;
3266
+ }
3267
+ }
3182
3268
3183
3269
if (!is_zero_ether_addr (netdev -> dev_addr )) {
3184
3270
/* If the netdev mac is non-zero and doesn't match the default
3185
3271
* device address, it was set by something earlier and we're
3186
3272
* likely here again after a fw-upgrade reset. We need to be
3187
3273
* sure the netdev mac is in our filter list.
3188
3274
*/
3189
- if (!ether_addr_equal (ctx .comp .lif_getattr .mac ,
3190
- netdev -> dev_addr ))
3275
+ if (!ether_addr_equal (mac_address , netdev -> dev_addr ))
3191
3276
ionic_lif_addr_add (lif , netdev -> dev_addr );
3192
3277
} else {
3193
3278
/* Update the netdev mac with the device's mac */
3194
- memcpy (addr .sa_data , ctx . comp . lif_getattr . mac , netdev -> addr_len );
3279
+ ether_addr_copy (addr .sa_data , mac_address );
3195
3280
addr .sa_family = AF_INET ;
3196
3281
err = eth_prepare_mac_addr_change (netdev , & addr );
3197
3282
if (err ) {
0 commit comments