bnxt_en: Improve flow control autoneg with Firmware 1.2.1 interface.
[deliverable/linux.git] / drivers / net / ethernet / broadcom / bnxt / bnxt.c
index aabbd51db981d270df258b1e0bf10a64488eb2b2..2b5a54162f8009cd8f9f7b8fc97a9bb23550fef4 100644 (file)
@@ -1,6 +1,6 @@
 /* Broadcom NetXtreme-C/E network driver.
  *
- * Copyright (c) 2014-2015 Broadcom Corporation
+ * Copyright (c) 2014-2016 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -2653,7 +2653,7 @@ static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len,
        /* Write request msg to hwrm channel */
        __iowrite32_copy(bp->bar0, data, msg_len / 4);
 
-       for (i = msg_len; i < HWRM_MAX_REQ_LEN; i += 4)
+       for (i = msg_len; i < BNXT_HWRM_MAX_REQ_LEN; i += 4)
                writel(0, bp->bar0 + i);
 
        /* currently supports only one outstanding message */
@@ -2763,7 +2763,7 @@ static int bnxt_hwrm_func_drv_rgtr(struct bnxt *bp)
         * only checks if it is non-zero to enable async event forwarding
         */
        req.async_event_fwd[0] |= cpu_to_le32(1);
-       req.os_type = cpu_to_le16(1);
+       req.os_type = cpu_to_le16(FUNC_DRV_RGTR_REQ_OS_TYPE_LINUX);
        req.ver_maj = DRV_VER_MAJ;
        req.ver_min = DRV_VER_MIN;
        req.ver_upd = DRV_VER_UPD;
@@ -3391,11 +3391,11 @@ static int bnxt_hwrm_ring_alloc(struct bnxt *bp)
                struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
                struct bnxt_ring_struct *ring = &cpr->cp_ring_struct;
 
+               cpr->cp_doorbell = bp->bar1 + i * 0x80;
                rc = hwrm_ring_alloc_send_msg(bp, ring, HWRM_RING_ALLOC_CMPL, i,
                                              INVALID_STATS_CTX_ID);
                if (rc)
                        goto err_out;
-               cpr->cp_doorbell = bp->bar1 + i * 0x80;
                BNXT_CP_DB(cpr->cp_doorbell, cpr->cp_raw_cons);
                bp->grp_info[i].cp_fw_ring_id = ring->fw_ring_id;
        }
@@ -3726,7 +3726,7 @@ int bnxt_hwrm_func_qcaps(struct bnxt *bp)
 
                pf->fw_fid = le16_to_cpu(resp->fid);
                pf->port_id = le16_to_cpu(resp->port_id);
-               memcpy(pf->mac_addr, resp->perm_mac_address, ETH_ALEN);
+               memcpy(pf->mac_addr, resp->mac_address, ETH_ALEN);
                memcpy(bp->dev->dev_addr, pf->mac_addr, ETH_ALEN);
                pf->max_rsscos_ctxs = le16_to_cpu(resp->max_rsscos_ctx);
                pf->max_cp_rings = le16_to_cpu(resp->max_cmpl_rings);
@@ -3751,7 +3751,7 @@ int bnxt_hwrm_func_qcaps(struct bnxt *bp)
                struct bnxt_vf_info *vf = &bp->vf;
 
                vf->fw_fid = le16_to_cpu(resp->fid);
-               memcpy(vf->mac_addr, resp->perm_mac_address, ETH_ALEN);
+               memcpy(vf->mac_addr, resp->mac_address, ETH_ALEN);
                if (is_valid_ether_addr(vf->mac_addr))
                        /* overwrite netdev dev_adr with admin VF MAC */
                        memcpy(bp->dev->dev_addr, vf->mac_addr, ETH_ALEN);
@@ -3830,6 +3830,7 @@ static int bnxt_hwrm_ver_get(struct bnxt *bp)
        struct hwrm_ver_get_input req = {0};
        struct hwrm_ver_get_output *resp = bp->hwrm_cmd_resp_addr;
 
+       bp->hwrm_max_req_len = HWRM_MAX_REQ_LEN;
        bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_VER_GET, -1, -1);
        req.hwrm_intf_maj = HWRM_VERSION_MAJOR;
        req.hwrm_intf_min = HWRM_VERSION_MINOR;
@@ -3841,6 +3842,8 @@ static int bnxt_hwrm_ver_get(struct bnxt *bp)
 
        memcpy(&bp->ver_resp, resp, sizeof(struct hwrm_ver_get_output));
 
+       bp->hwrm_spec_code = resp->hwrm_intf_maj << 16 |
+                            resp->hwrm_intf_min << 8 | resp->hwrm_intf_upd;
        if (resp->hwrm_intf_maj < 1) {
                netdev_warn(bp->dev, "HWRM interface %d.%d.%d is older than 1.0.0.\n",
                            resp->hwrm_intf_maj, resp->hwrm_intf_min,
@@ -3855,6 +3858,9 @@ static int bnxt_hwrm_ver_get(struct bnxt *bp)
        if (!bp->hwrm_cmd_timeout)
                bp->hwrm_cmd_timeout = DFLT_HWRM_CMD_TIMEOUT;
 
+       if (resp->hwrm_intf_maj >= 1)
+               bp->hwrm_max_req_len = le16_to_cpu(resp->max_req_win_len);
+
 hwrm_ver_get_exit:
        mutex_unlock(&bp->hwrm_cmd_lock);
        return rc;
@@ -4519,7 +4525,6 @@ static int bnxt_update_link(struct bnxt *bp, bool chng_link_state)
        else
                link_info->link_speed = 0;
        link_info->force_link_speed = le16_to_cpu(resp->force_link_speed);
-       link_info->auto_link_speed = le16_to_cpu(resp->auto_link_speed);
        link_info->support_speeds = le16_to_cpu(resp->support_speeds);
        link_info->auto_link_speeds = le16_to_cpu(resp->auto_link_speed_mask);
        link_info->lp_auto_link_speeds =
@@ -4529,8 +4534,8 @@ static int bnxt_update_link(struct bnxt *bp, bool chng_link_state)
        link_info->phy_ver[1] = resp->phy_min;
        link_info->phy_ver[2] = resp->phy_bld;
        link_info->media_type = resp->media_type;
-       link_info->transceiver = resp->transceiver_type;
-       link_info->phy_addr = resp->phy_addr;
+       link_info->transceiver = resp->xcvr_pkg_type;
+       link_info->phy_addr = resp->eee_config_phy_addr;
 
        /* TODO: need to add more logic to report VF link */
        if (chng_link_state) {
@@ -4552,10 +4557,13 @@ static void
 bnxt_hwrm_set_pause_common(struct bnxt *bp, struct hwrm_port_phy_cfg_input *req)
 {
        if (bp->link_info.autoneg & BNXT_AUTONEG_FLOW_CTRL) {
+               if (bp->hwrm_spec_code >= 0x10201)
+                       req->auto_pause =
+                               PORT_PHY_CFG_REQ_AUTO_PAUSE_AUTONEG_PAUSE;
                if (bp->link_info.req_flow_ctrl & BNXT_LINK_PAUSE_RX)
                        req->auto_pause |= PORT_PHY_CFG_REQ_AUTO_PAUSE_RX;
                if (bp->link_info.req_flow_ctrl & BNXT_LINK_PAUSE_TX)
-                       req->auto_pause |= PORT_PHY_CFG_REQ_AUTO_PAUSE_RX;
+                       req->auto_pause |= PORT_PHY_CFG_REQ_AUTO_PAUSE_TX;
                req->enables |=
                        cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_AUTO_PAUSE);
        } else {
@@ -4565,6 +4573,11 @@ bnxt_hwrm_set_pause_common(struct bnxt *bp, struct hwrm_port_phy_cfg_input *req)
                        req->force_pause |= PORT_PHY_CFG_REQ_FORCE_PAUSE_TX;
                req->enables |=
                        cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_FORCE_PAUSE);
+               if (bp->hwrm_spec_code >= 0x10201) {
+                       req->auto_pause = req->force_pause;
+                       req->enables |= cpu_to_le32(
+                               PORT_PHY_CFG_REQ_ENABLES_AUTO_PAUSE);
+               }
        }
 }
 
@@ -4577,7 +4590,7 @@ static void bnxt_hwrm_set_link_common(struct bnxt *bp,
 
        if (autoneg & BNXT_AUTONEG_SPEED) {
                req->auto_mode |=
-                       PORT_PHY_CFG_REQ_AUTO_MODE_MASK;
+                       PORT_PHY_CFG_REQ_AUTO_MODE_SPEED_MASK;
 
                req->enables |= cpu_to_le32(
                        PORT_PHY_CFG_REQ_ENABLES_AUTO_LINK_SPEED_MASK);
@@ -4591,9 +4604,6 @@ static void bnxt_hwrm_set_link_common(struct bnxt *bp,
                req->flags |= cpu_to_le32(PORT_PHY_CFG_REQ_FLAGS_FORCE);
        }
 
-       /* currently don't support half duplex */
-       req->auto_duplex = PORT_PHY_CFG_REQ_AUTO_DUPLEX_FULL;
-       req->enables |= cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_AUTO_DUPLEX);
        /* tell chimp that the setting takes effect immediately */
        req->flags |= cpu_to_le32(PORT_PHY_CFG_REQ_FLAGS_RESET_PHY);
 }
@@ -4654,7 +4664,8 @@ static int bnxt_update_phy_setting(struct bnxt *bp)
                return rc;
        }
        if ((link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL) &&
-           link_info->auto_pause_setting != link_info->req_flow_ctrl)
+           (link_info->auto_pause_setting & BNXT_LINK_PAUSE_BOTH) !=
+           link_info->req_flow_ctrl)
                update_pause = true;
        if (!(link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL) &&
            link_info->force_pause_setting != link_info->req_flow_ctrl)
@@ -5823,15 +5834,24 @@ static int bnxt_probe_phy(struct bnxt *bp)
 
        /*initialize the ethool setting copy with NVM settings */
        if (BNXT_AUTO_MODE(link_info->auto_mode)) {
-               link_info->autoneg = BNXT_AUTONEG_SPEED |
-                                    BNXT_AUTONEG_FLOW_CTRL;
+               link_info->autoneg = BNXT_AUTONEG_SPEED;
+               if (bp->hwrm_spec_code >= 0x10201) {
+                       if (link_info->auto_pause_setting &
+                           PORT_PHY_CFG_REQ_AUTO_PAUSE_AUTONEG_PAUSE)
+                               link_info->autoneg |= BNXT_AUTONEG_FLOW_CTRL;
+               } else {
+                       link_info->autoneg |= BNXT_AUTONEG_FLOW_CTRL;
+               }
                link_info->advertising = link_info->auto_link_speeds;
-               link_info->req_flow_ctrl = link_info->auto_pause_setting;
        } else {
                link_info->req_link_speed = link_info->force_link_speed;
                link_info->req_duplex = link_info->duplex_setting;
-               link_info->req_flow_ctrl = link_info->force_pause_setting;
        }
+       if (link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL)
+               link_info->req_flow_ctrl =
+                       link_info->auto_pause_setting & BNXT_LINK_PAUSE_BOTH;
+       else
+               link_info->req_flow_ctrl = link_info->force_pause_setting;
        return rc;
 }
 
This page took 0.026925 seconds and 5 git commands to generate.