From patchwork Sun Mar 20 16:28:58 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Kravkov X-Patchwork-Id: 87665 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id BE25CB6F11 for ; Mon, 21 Mar 2011 03:38:16 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751581Ab1CTQiN (ORCPT ); Sun, 20 Mar 2011 12:38:13 -0400 Received: from mms3.broadcom.com ([216.31.210.19]:1637 "EHLO MMS3.broadcom.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751490Ab1CTQiL (ORCPT ); Sun, 20 Mar 2011 12:38:11 -0400 Received: from [10.9.200.131] by MMS3.broadcom.com with ESMTP (Broadcom SMTP Relay (Email Firewall v6.3.2)); Sun, 20 Mar 2011 09:40:29 -0700 X-Server-Uuid: B55A25B1-5D7D-41F8-BC53-C57E7AD3C201 Received: from mail-irva-13.broadcom.com (10.11.16.103) by IRVEXCHHUB01.corp.ad.broadcom.com (10.9.200.131) with Microsoft SMTP Server id 8.2.247.2; Sun, 20 Mar 2011 09:38:00 -0700 Received: from [10.185.7.55] (lb-tlvb-dmitry.il.broadcom.com [10.185.7.55]) by mail-irva-13.broadcom.com (Postfix) with ESMTP id C4C9E74D04; Sun, 20 Mar 2011 09:37:58 -0700 (PDT) Subject: [net-next 1/5] bnx2x: link report improvements From: "Dmitry Kravkov" To: davem@davemloft.net, netdev@vger.kernel.org cc: "Eilon Greenstein" , "Vladislav Zolotarov" Date: Sun, 20 Mar 2011 18:28:58 +0200 Message-ID: <1300638538.17303.22.camel@lb-tlvb-dmitry> MIME-Version: 1.0 X-Mailer: Evolution 2.30.3 X-WSS-ID: 6198F2771VK2113696-01-01 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org To avoid link notification duplication, remember last reported state. From: Vladislav Zolotarov Signed-off-by: Dmitry Kravkov Signed-off-by: Vladislav Zolotarov Signed-off-by: Eilon Greenstein --- drivers/net/bnx2x/bnx2x.h | 21 ++++++++ drivers/net/bnx2x/bnx2x_cmn.c | 99 +++++++++++++++++++++++++++++++-------- drivers/net/bnx2x/bnx2x_cmn.h | 2 - drivers/net/bnx2x/bnx2x_main.c | 21 ++++----- 4 files changed, 108 insertions(+), 35 deletions(-) diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h index b7ff87b..6f3d48f 100644 --- a/drivers/net/bnx2x/bnx2x.h +++ b/drivers/net/bnx2x/bnx2x.h @@ -893,6 +893,22 @@ typedef enum { (&bp->def_status_blk->sp_sb.\ index_values[HC_SP_INDEX_EQ_CONS]) +/* This is a data that will be used to create a link report message. + * We will keep the data used for the last link report in order + * to prevent reporting the same link parameters twice. + */ +struct bnx2x_link_report_data { + u16 line_speed; /* Effective line speed */ + unsigned long link_report_flags;/* BNX2X_LINK_REPORT_XXX flags */ +}; + +enum { + BNX2X_LINK_REPORT_FD, /* Full DUPLEX */ + BNX2X_LINK_REPORT_LINK_DOWN, + BNX2X_LINK_REPORT_RX_FC_ON, + BNX2X_LINK_REPORT_TX_FC_ON, +}; + struct bnx2x { /* Fields used in the tx and intr/napi performance paths * are grouped together in the beginning of the structure @@ -1026,6 +1042,9 @@ struct bnx2x { struct link_params link_params; struct link_vars link_vars; + u32 link_cnt; + struct bnx2x_link_report_data last_reported_link; + struct mdio_if_info mdio; struct bnx2x_common common; @@ -1442,6 +1461,8 @@ struct bnx2x_func_init_params { #define WAIT_RAMROD_POLL 0x01 #define WAIT_RAMROD_COMMON 0x02 +void bnx2x_read_mf_cfg(struct bnx2x *bp); + /* dmae */ void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32); void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr, diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c index e83ac6d..267177b 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.c +++ b/drivers/net/bnx2x/bnx2x_cmn.c @@ -758,35 +758,91 @@ u16 bnx2x_get_mf_speed(struct bnx2x *bp) return line_speed; } +/* Fill Link report data according to the current link + * configuration. + * + * @param bp + * @param data + */ +static inline void bnx2x_fill_report_data(struct bnx2x *bp, + struct bnx2x_link_report_data *data) +{ + u16 line_speed = bnx2x_get_mf_speed(bp); + + memset(data, 0, sizeof(*data)); + + /* Fill the report data: efective line speed */ + data->line_speed = line_speed; + + /* Link is down */ + if (!bp->link_vars.link_up || (bp->flags & MF_FUNC_DIS)) + set_bit(BNX2X_LINK_REPORT_LINK_DOWN, &data->link_report_flags); + + /* Full DUPLEX */ + if (bp->link_vars.duplex == DUPLEX_FULL) + set_bit(BNX2X_LINK_REPORT_FD, &data->link_report_flags); + + /* Rx Flow Control is ON */ + if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_RX) + set_bit(BNX2X_LINK_REPORT_RX_FC_ON, &data->link_report_flags); + + /* Tx Flow Control is ON */ + if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_TX) + set_bit(BNX2X_LINK_REPORT_TX_FC_ON, &data->link_report_flags); +} + void bnx2x_link_report(struct bnx2x *bp) { - if (bp->flags & MF_FUNC_DIS) { - netif_carrier_off(bp->dev); - netdev_err(bp->dev, "NIC Link is Down\n"); - return; - } + struct bnx2x_link_report_data cur_data; - if (bp->link_vars.link_up) { - u16 line_speed; + /* reread mf_cfg */ + if (!CHIP_IS_E1(bp)) + bnx2x_read_mf_cfg(bp); - if (bp->state == BNX2X_STATE_OPEN) - netif_carrier_on(bp->dev); - netdev_info(bp->dev, "NIC Link is Up, "); + /* Read the current link report info */ + bnx2x_fill_report_data(bp, &cur_data); + + /* Don't report link down or exactly the same link status twice */ + if (!memcmp(&cur_data, &bp->last_reported_link, sizeof(cur_data)) || + (test_bit(BNX2X_LINK_REPORT_LINK_DOWN, + &bp->last_reported_link.link_report_flags) && + test_bit(BNX2X_LINK_REPORT_LINK_DOWN, + &cur_data.link_report_flags))) + return; - line_speed = bnx2x_get_mf_speed(bp); + bp->link_cnt++; - pr_cont("%d Mbps ", line_speed); + /* We are going to report a new link parameters now - + * remember the current data for the next time. + */ + memcpy(&bp->last_reported_link, &cur_data, sizeof(cur_data)); - if (bp->link_vars.duplex == DUPLEX_FULL) + if (test_bit(BNX2X_LINK_REPORT_LINK_DOWN, + &cur_data.link_report_flags)) { + netif_carrier_off(bp->dev); + netdev_err(bp->dev, "NIC Link is Down\n"); + return; + } else { + netif_carrier_on(bp->dev); + netdev_info(bp->dev, "NIC Link is Up, "); + pr_cont("%d Mbps ", cur_data.line_speed); + + if (test_and_clear_bit(BNX2X_LINK_REPORT_FD, + &cur_data.link_report_flags)) pr_cont("full duplex"); else pr_cont("half duplex"); - if (bp->link_vars.flow_ctrl != BNX2X_FLOW_CTRL_NONE) { - if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_RX) { + /* Handle the FC at the end so that only these flags would be + * possibly set. This way we may easily check if there is no FC + * enabled. + */ + if (cur_data.link_report_flags) { + if (test_bit(BNX2X_LINK_REPORT_RX_FC_ON, + &cur_data.link_report_flags)) { pr_cont(", receive "); - if (bp->link_vars.flow_ctrl & - BNX2X_FLOW_CTRL_TX) + if (test_bit(BNX2X_LINK_REPORT_TX_FC_ON, + &cur_data.link_report_flags)) pr_cont("& transmit "); } else { pr_cont(", transmit "); @@ -794,10 +850,6 @@ void bnx2x_link_report(struct bnx2x *bp) pr_cont("flow control ON"); } pr_cont("\n"); - - } else { /* link_down */ - netif_carrier_off(bp->dev); - netdev_err(bp->dev, "NIC Link is Down\n"); } } @@ -1345,6 +1397,11 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) bp->state = BNX2X_STATE_OPENING_WAIT4_LOAD; + /* Set the initial link reported state to link down */ + memset(&bp->last_reported_link, 0, sizeof(bp->last_reported_link)); + set_bit(BNX2X_LINK_REPORT_LINK_DOWN, + &bp->last_reported_link.link_report_flags); + /* must be called before memory allocation and HW init */ bnx2x_ilt_set_info(bp); diff --git a/drivers/net/bnx2x/bnx2x_cmn.h b/drivers/net/bnx2x/bnx2x_cmn.h index ef37b98..10cf462 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.h +++ b/drivers/net/bnx2x/bnx2x_cmn.h @@ -67,8 +67,6 @@ void bnx2x__link_status_update(struct bnx2x *bp); * Report link status to upper layer * * @param bp - * - * @return int */ void bnx2x_link_report(struct bnx2x *bp); diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index 9d48659..bc847b1 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -2043,7 +2043,7 @@ static int bnx2x_get_cmng_fns_mode(struct bnx2x *bp) return CMNG_FNS_NONE; } -static void bnx2x_read_mf_cfg(struct bnx2x *bp) +void bnx2x_read_mf_cfg(struct bnx2x *bp) { int vn, n = (CHIP_MODE_IS_4_PORT(bp) ? 2 : 1); @@ -2130,7 +2130,6 @@ static inline void bnx2x_link_sync_notify(struct bnx2x *bp) /* This function is called upon link interrupt */ static void bnx2x_link_attn(struct bnx2x *bp) { - u32 prev_link_status = bp->link_vars.link_status; /* Make sure that we are synced with the current statistics */ bnx2x_stats_handle(bp, STATS_EVENT_STOP); @@ -2175,17 +2174,15 @@ static void bnx2x_link_attn(struct bnx2x *bp) "single function mode without fairness\n"); } + bnx2x_link_report(bp); + if (IS_MF(bp)) bnx2x_link_sync_notify(bp); - - /* indicate link status only if link status actually changed */ - if (prev_link_status != bp->link_vars.link_status) - bnx2x_link_report(bp); } void bnx2x__link_status_update(struct bnx2x *bp) { - if ((bp->state != BNX2X_STATE_OPEN) || (bp->flags & MF_FUNC_DIS)) + if (bp->state != BNX2X_STATE_OPEN) return; bnx2x_link_status_update(&bp->link_params, &bp->link_vars); @@ -2195,10 +2192,6 @@ void bnx2x__link_status_update(struct bnx2x *bp) else bnx2x_stats_handle(bp, STATS_EVENT_STOP); - /* the link status update could be the result of a DCC event - hence re-read the shmem mf configuration */ - bnx2x_read_mf_cfg(bp); - /* indicate link status */ bnx2x_link_report(bp); } @@ -3127,10 +3120,14 @@ static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn) if (val & DRV_STATUS_SET_MF_BW) bnx2x_set_mf_bw(bp); - bnx2x__link_status_update(bp); if ((bp->port.pmf == 0) && (val & DRV_STATUS_PMF)) bnx2x_pmf_update(bp); + /* Always call it here: bnx2x_link_report() will + * prevent the link indication duplication. + */ + bnx2x__link_status_update(bp); + if (bp->port.pmf && (val & DRV_STATUS_DCBX_NEGOTIATION_RESULTS) && bp->dcbx_enabled > 0)