@@ -1564,8 +1564,67 @@ static int ionic_set_features(struct net_device *netdev,
15641564 return err ;
15651565}
15661566
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+
15671625static int ionic_set_mac_address (struct net_device * netdev , void * sa )
15681626{
1627+ struct ionic_lif * lif = netdev_priv (netdev );
15691628 struct sockaddr * addr = sa ;
15701629 u8 * mac ;
15711630 int err ;
@@ -1574,6 +1633,14 @@ static int ionic_set_mac_address(struct net_device *netdev, void *sa)
15741633 if (ether_addr_equal (netdev -> dev_addr , mac ))
15751634 return 0 ;
15761635
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+
15771644 err = eth_prepare_mac_addr_change (netdev , addr );
15781645 if (err )
15791646 return err ;
@@ -2963,6 +3030,9 @@ static void ionic_lif_handle_fw_up(struct ionic_lif *lif)
29633030
29643031 mutex_lock (& lif -> queue_lock );
29653032
3033+ if (test_and_clear_bit (IONIC_LIF_F_BROKEN , lif -> state ))
3034+ dev_info (ionic -> dev , "FW Up: clearing broken state\n" );
3035+
29663036 err = ionic_qcqs_alloc (lif );
29673037 if (err )
29683038 goto err_unlock ;
@@ -3169,6 +3239,7 @@ static int ionic_station_set(struct ionic_lif *lif)
31693239 .attr = IONIC_LIF_ATTR_MAC ,
31703240 },
31713241 };
3242+ u8 mac_address [ETH_ALEN ];
31723243 struct sockaddr addr ;
31733244 int err ;
31743245
@@ -3177,21 +3248,35 @@ static int ionic_station_set(struct ionic_lif *lif)
31773248 return err ;
31783249 netdev_dbg (lif -> netdev , "found initial MAC addr %pM\n" ,
31793250 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+ }
31823268
31833269 if (!is_zero_ether_addr (netdev -> dev_addr )) {
31843270 /* If the netdev mac is non-zero and doesn't match the default
31853271 * device address, it was set by something earlier and we're
31863272 * likely here again after a fw-upgrade reset. We need to be
31873273 * sure the netdev mac is in our filter list.
31883274 */
3189- if (!ether_addr_equal (ctx .comp .lif_getattr .mac ,
3190- netdev -> dev_addr ))
3275+ if (!ether_addr_equal (mac_address , netdev -> dev_addr ))
31913276 ionic_lif_addr_add (lif , netdev -> dev_addr );
31923277 } else {
31933278 /* 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 );
31953280 addr .sa_family = AF_INET ;
31963281 err = eth_prepare_mac_addr_change (netdev , & addr );
31973282 if (err ) {
0 commit comments