u32 tx_rate;
 };
 
+#define BE_FLAGS_LINK_STATUS_INIT              1
+
 struct be_adapter {
        struct pci_dev *pdev;
        struct net_device *netdev;
        struct delayed_work work;
        u16 work_counter;
 
+       u32 flags;
        /* Ethtool knobs and info */
        char fw_ver[FW_VER_LEN];
        int if_handle;          /* Used to configure filtering */
 
 extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm,
                u16 num_popped);
-extern void be_link_status_update(struct be_adapter *adapter, u32 link_status);
+extern void be_link_status_update(struct be_adapter *adapter, u8 link_status);
 extern void be_parse_stats(struct be_adapter *adapter);
 extern int be_load_fw(struct be_adapter *adapter, u8 *func);
 #endif                         /* BE_H */
 
 static void be_async_link_state_process(struct be_adapter *adapter,
                struct be_async_event_link_state *evt)
 {
-       be_link_status_update(adapter, evt->port_link_status);
+       /* When link status changes, link speed must be re-queried from FW */
+       adapter->link_speed = -1;
+
+       /* For the initial link status do not rely on the ASYNC event as
+        * it may not be received in some cases.
+        */
+       if (adapter->flags & BE_FLAGS_LINK_STATUS_INIT)
+               be_link_status_update(adapter, evt->port_link_status);
 }
 
 /* Grp5 CoS Priority evt */
 
 /* Uses synchronous mcc */
 int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed,
-                       u16 *link_speed, u32 dom)
+                            u16 *link_speed, u8 *link_status, u32 dom)
 {
        struct be_mcc_wrb *wrb;
        struct be_cmd_req_link_status *req;
 
        spin_lock_bh(&adapter->mcc_lock);
 
+       if (link_status)
+               *link_status = LINK_DOWN;
+
        wrb = wrb_from_mccq(adapter);
        if (!wrb) {
                status = -EBUSY;
        }
        req = embedded_payload(wrb);
 
-       if (lancer_chip(adapter))
+       if (adapter->generation == BE_GEN3 || lancer_chip(adapter))
                req->hdr.version = 1;
 
        be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
        if (!status) {
                struct be_cmd_resp_link_status *resp = embedded_payload(wrb);
                if (resp->mac_speed != PHY_LINK_SPEED_ZERO) {
-                       *link_speed = le16_to_cpu(resp->link_speed);
+                       if (link_speed)
+                               *link_speed = le16_to_cpu(resp->link_speed);
                        if (mac_speed)
                                *mac_speed = resp->mac_speed;
                }
+               if (link_status)
+                       *link_status = resp->logical_link_status;
        }
 
 err:
 
        u8 mgmt_mac_duplex;
        u8 mgmt_mac_speed;
        u16 link_speed;
-       u32 rsvd0;
+       u8 logical_link_status;
+       u8 rsvd1[3];
 } __packed;
 
 /******************** Port Identification ***************************/
                        int type);
 extern int be_cmd_rxq_destroy(struct be_adapter *adapter,
                        struct be_queue_info *q);
-extern int be_cmd_link_status_query(struct be_adapter *adapter,
-                       u8 *mac_speed, u16 *link_speed, u32 dom);
+extern int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed,
+                                   u16 *link_speed, u8 *link_status, u32 dom);
 extern int be_cmd_reset(struct be_adapter *adapter);
 extern int be_cmd_get_stats(struct be_adapter *adapter,
                        struct be_dma_mem *nonemb_cmd);
 
        struct be_phy_info phy_info;
        u8 mac_speed = 0;
        u16 link_speed = 0;
+       u8 link_status;
        int status;
 
        if ((adapter->link_speed < 0) || (!(netdev->flags & IFF_UP))) {
                status = be_cmd_link_status_query(adapter, &mac_speed,
-                                               &link_speed, 0);
+                                                 &link_speed, &link_status, 0);
+               if (!status)
+                       be_link_status_update(adapter, link_status);
 
                /* link_speed is in units of 10 Mbps */
                if (link_speed) {
        }
 
        if (be_cmd_link_status_query(adapter, &mac_speed,
-                               &qos_link_speed, 0) != 0) {
+                                    &qos_link_speed, NULL, 0) != 0) {
                test->flags |= ETH_TEST_FL_FAILED;
                data[4] = -1;
        } else if (!mac_speed) {
 
        return stats;
 }
 
-void be_link_status_update(struct be_adapter *adapter, u32 link_status)
+void be_link_status_update(struct be_adapter *adapter, u8 link_status)
 {
        struct net_device *netdev = adapter->netdev;
 
-       /* when link status changes, link speed must be re-queried from card */
-       adapter->link_speed = -1;
-       if ((link_status & LINK_STATUS_MASK) == LINK_UP) {
-               netif_carrier_on(netdev);
-               dev_info(&adapter->pdev->dev, "%s: Link up\n", netdev->name);
-       } else {
+       if (!(adapter->flags & BE_FLAGS_LINK_STATUS_INIT)) {
                netif_carrier_off(netdev);
-               dev_info(&adapter->pdev->dev, "%s: Link down\n", netdev->name);
+               adapter->flags |= BE_FLAGS_LINK_STATUS_INIT;
        }
+
+       if ((link_status & LINK_STATUS_MASK) == LINK_UP)
+               netif_carrier_on(netdev);
+       else
+               netif_carrier_off(netdev);
 }
 
 static void be_tx_stats_update(struct be_tx_obj *txo,
        struct be_adapter *adapter = netdev_priv(netdev);
        struct be_eq_obj *tx_eq = &adapter->tx_eq;
        struct be_rx_obj *rxo;
+       u8 link_status;
        int status, i;
 
        status = be_rx_queues_setup(adapter);
        /* Now that interrupts are on we can process async mcc */
        be_async_mcc_enable(adapter);
 
+       status = be_cmd_link_status_query(adapter, NULL, NULL,
+                                         &link_status, 0);
+       if (!status)
+               be_link_status_update(adapter, link_status);
+
        return 0;
 err:
        be_close(adapter->netdev);
 
        for_all_vfs(adapter, vf_cfg, vf) {
                status = be_cmd_link_status_query(adapter, NULL, &lnk_speed,
-                                                 vf + 1);
+                                                 NULL, vf + 1);
                if (status)
                        goto err;
                vf_cfg->tx_rate = lnk_speed * 10;