From 15f0a394c6573f4cb65a13095288ab9b9f8135f9 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 1 Oct 2009 11:58:24 +0000 Subject: net: Convert ethtool {get_stats, self_test}_count() ops to get_sset_count() These string query operations were supposed to be replaced by the generic get_sset_count() starting in 2007. Convert the remaining implementations. Also remove calls to these operations to initialise drvinfo->n_stats. The ethtool core code already does that. Signed-off-by: Ben Hutchings Acked-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 60 +++++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 29 deletions(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 20f0ed956df2..c0abfc4fb34b 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -9818,11 +9818,6 @@ static const struct { { "idle check (online)" } }; -static int bnx2x_self_test_count(struct net_device *dev) -{ - return BNX2X_NUM_TESTS; -} - static int bnx2x_test_registers(struct bnx2x *bp) { int idx, i, rc = -ENODEV; @@ -10436,6 +10431,36 @@ static const struct { #define IS_E1HMF_MODE_STAT(bp) \ (IS_E1HMF(bp) && !(bp->msglevel & BNX2X_MSG_STATS)) +static int bnx2x_get_sset_count(struct net_device *dev, int stringset) +{ + struct bnx2x *bp = netdev_priv(dev); + int i, num_stats; + + switch(stringset) { + case ETH_SS_STATS: + if (is_multi(bp)) { + num_stats = BNX2X_NUM_Q_STATS * bp->num_rx_queues; + if (!IS_E1HMF_MODE_STAT(bp)) + num_stats += BNX2X_NUM_STATS; + } else { + if (IS_E1HMF_MODE_STAT(bp)) { + num_stats = 0; + for (i = 0; i < BNX2X_NUM_STATS; i++) + if (IS_FUNC_STAT(i)) + num_stats++; + } else + num_stats = BNX2X_NUM_STATS; + } + return num_stats; + + case ETH_SS_TEST: + return BNX2X_NUM_TESTS; + + default: + return -EINVAL; + } +} + static void bnx2x_get_strings(struct net_device *dev, u32 stringset, u8 *buf) { struct bnx2x *bp = netdev_priv(dev); @@ -10473,28 +10498,6 @@ static void bnx2x_get_strings(struct net_device *dev, u32 stringset, u8 *buf) } } -static int bnx2x_get_stats_count(struct net_device *dev) -{ - struct bnx2x *bp = netdev_priv(dev); - int i, num_stats; - - if (is_multi(bp)) { - num_stats = BNX2X_NUM_Q_STATS * bp->num_rx_queues; - if (!IS_E1HMF_MODE_STAT(bp)) - num_stats += BNX2X_NUM_STATS; - } else { - if (IS_E1HMF_MODE_STAT(bp)) { - num_stats = 0; - for (i = 0; i < BNX2X_NUM_STATS; i++) - if (IS_FUNC_STAT(i)) - num_stats++; - } else - num_stats = BNX2X_NUM_STATS; - } - - return num_stats; -} - static void bnx2x_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *buf) { @@ -10637,11 +10640,10 @@ static const struct ethtool_ops bnx2x_ethtool_ops = { .set_sg = ethtool_op_set_sg, .get_tso = ethtool_op_get_tso, .set_tso = bnx2x_set_tso, - .self_test_count = bnx2x_self_test_count, .self_test = bnx2x_self_test, + .get_sset_count = bnx2x_get_sset_count, .get_strings = bnx2x_get_strings, .phys_id = bnx2x_phys_id, - .get_stats_count = bnx2x_get_stats_count, .get_ethtool_stats = bnx2x_get_ethtool_stats, }; -- cgit v1.2.3-59-g8ed1b From 2891290219d8a28a923560d53d24c00fa96fa09f Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sat, 10 Oct 2009 13:46:53 +0000 Subject: bnx2x: Refactor bnx2x_sp_post(). Some of the SPQ (slow-path queue) operations will be used by the cnic code in later patches. Signed-off-by: Shmulik Ravid - Rabinovitz Signed-off-by: Michael Chan Acked-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 62 +++++++++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 24 deletions(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index c0abfc4fb34b..713d66939383 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -2638,11 +2638,40 @@ static void bnx2x_dcc_event(struct bnx2x *bp, u32 dcc_event) bnx2x_fw_command(bp, DRV_MSG_CODE_DCC_OK); } +/* must be called under the spq lock */ +static inline struct eth_spe *bnx2x_sp_get_next(struct bnx2x *bp) +{ + struct eth_spe *next_spe = bp->spq_prod_bd; + + if (bp->spq_prod_bd == bp->spq_last_bd) { + bp->spq_prod_bd = bp->spq; + bp->spq_prod_idx = 0; + DP(NETIF_MSG_TIMER, "end of spq\n"); + } else { + bp->spq_prod_bd++; + bp->spq_prod_idx++; + } + return next_spe; +} + +/* must be called under the spq lock */ +static inline void bnx2x_sp_prod_update(struct bnx2x *bp) +{ + int func = BP_FUNC(bp); + + /* Make sure that BD data is updated before writing the producer */ + wmb(); + + REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_SPQ_PROD_OFFSET(func), + bp->spq_prod_idx); + mmiowb(); +} + /* the slow path queue is odd since completions arrive on the fastpath ring */ static int bnx2x_sp_post(struct bnx2x *bp, int command, int cid, u32 data_hi, u32 data_lo, int common) { - int func = BP_FUNC(bp); + struct eth_spe *spe; DP(BNX2X_MSG_SP/*NETIF_MSG_TIMER*/, "SPQE (%x:%x) command %d hw_cid %x data (%x:%x) left %x\n", @@ -2664,38 +2693,23 @@ static int bnx2x_sp_post(struct bnx2x *bp, int command, int cid, return -EBUSY; } + spe = bnx2x_sp_get_next(bp); + /* CID needs port number to be encoded int it */ - bp->spq_prod_bd->hdr.conn_and_cmd_data = + spe->hdr.conn_and_cmd_data = cpu_to_le32(((command << SPE_HDR_CMD_ID_SHIFT) | HW_CID(bp, cid))); - bp->spq_prod_bd->hdr.type = cpu_to_le16(ETH_CONNECTION_TYPE); + spe->hdr.type = cpu_to_le16(ETH_CONNECTION_TYPE); if (common) - bp->spq_prod_bd->hdr.type |= + spe->hdr.type |= cpu_to_le16((1 << SPE_HDR_COMMON_RAMROD_SHIFT)); - bp->spq_prod_bd->data.mac_config_addr.hi = cpu_to_le32(data_hi); - bp->spq_prod_bd->data.mac_config_addr.lo = cpu_to_le32(data_lo); + spe->data.mac_config_addr.hi = cpu_to_le32(data_hi); + spe->data.mac_config_addr.lo = cpu_to_le32(data_lo); bp->spq_left--; - if (bp->spq_prod_bd == bp->spq_last_bd) { - bp->spq_prod_bd = bp->spq; - bp->spq_prod_idx = 0; - DP(NETIF_MSG_TIMER, "end of spq\n"); - - } else { - bp->spq_prod_bd++; - bp->spq_prod_idx++; - } - - /* Make sure that BD data is updated before writing the producer */ - wmb(); - - REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_SPQ_PROD_OFFSET(func), - bp->spq_prod_idx); - - mmiowb(); - + bnx2x_sp_prod_update(bp); spin_unlock_bh(&bp->spq_lock); return 0; } -- cgit v1.2.3-59-g8ed1b From e665bfda5b8fea586ddd028b26a6e2ed9e987c6b Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sat, 10 Oct 2009 13:46:54 +0000 Subject: bnx2x: Refactor MAC address setup code. For iSCSI MAC address setup in later patches. Signed-off-by: Shmulik Ravid - Rabinovitz Signed-off-by: Michael Chan Acked-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x.h | 4 +- drivers/net/bnx2x_main.c | 162 ++++++++++++++++++++++++++++++++--------------- 2 files changed, 114 insertions(+), 52 deletions(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index bbf842284ebb..1f0706328a3f 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h @@ -863,8 +863,8 @@ struct bnx2x { /* Flags for marking that there is a STAT_QUERY or SET_MAC ramrod pending */ - u8 stats_pending; - u8 set_mac_pending; + int stats_pending; + int set_mac_pending; /* End of fields used in the performance code paths */ diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 713d66939383..02ce3b31050c 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -1026,12 +1026,15 @@ static void bnx2x_sp_event(struct bnx2x_fastpath *fp, case (RAMROD_CMD_ID_ETH_SET_MAC | BNX2X_STATE_OPEN): case (RAMROD_CMD_ID_ETH_SET_MAC | BNX2X_STATE_DIAG): DP(NETIF_MSG_IFUP, "got set mac ramrod\n"); - bp->set_mac_pending = 0; + bp->set_mac_pending--; + smp_wmb(); break; case (RAMROD_CMD_ID_ETH_SET_MAC | BNX2X_STATE_CLOSING_WAIT4_HALT): case (RAMROD_CMD_ID_ETH_SET_MAC | BNX2X_STATE_DISABLED): DP(NETIF_MSG_IFDOWN, "got (un)set mac ramrod\n"); + bp->set_mac_pending--; + smp_wmb(); break; default: @@ -2530,7 +2533,7 @@ u32 bnx2x_fw_command(struct bnx2x *bp, u32 command) } static void bnx2x_set_storm_rx_mode(struct bnx2x *bp); -static void bnx2x_set_mac_addr_e1h(struct bnx2x *bp, int set); +static void bnx2x_set_eth_mac_addr_e1h(struct bnx2x *bp, int set); static void bnx2x_set_rx_mode(struct net_device *dev); static void bnx2x_e1h_disable(struct bnx2x *bp) @@ -2546,7 +2549,7 @@ static void bnx2x_e1h_disable(struct bnx2x *bp) REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0); - bnx2x_set_mac_addr_e1h(bp, 0); + bnx2x_set_eth_mac_addr_e1h(bp, 0); for (i = 0; i < MC_HASH_SIZE; i++) REG_WR(bp, MC_HASH_OFFSET(bp, i), 0); @@ -2560,7 +2563,7 @@ static void bnx2x_e1h_enable(struct bnx2x *bp) REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 1); - bnx2x_set_mac_addr_e1h(bp, 1); + bnx2x_set_eth_mac_addr_e1h(bp, 1); /* Tx queue should be only reenabled */ netif_tx_wake_all_queues(bp->dev); @@ -7036,7 +7039,19 @@ static void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw) * Init service functions */ -static void bnx2x_set_mac_addr_e1(struct bnx2x *bp, int set) +/** + * Sets a MAC in a CAM for a few L2 Clients for E1 chip + * + * @param bp driver descriptor + * @param set set or clear an entry (1 or 0) + * @param mac pointer to a buffer containing a MAC + * @param cl_bit_vec bit vector of clients to register a MAC for + * @param cam_offset offset in a CAM to use + * @param with_bcast set broadcast MAC as well + */ +static void bnx2x_set_mac_addr_e1_gen(struct bnx2x *bp, int set, u8 *mac, + u32 cl_bit_vec, u8 cam_offset, + u8 with_bcast) { struct mac_configuration_cmd *config = bnx2x_sp(bp, mac_config); int port = BP_PORT(bp); @@ -7045,25 +7060,25 @@ static void bnx2x_set_mac_addr_e1(struct bnx2x *bp, int set) * unicasts 0-31:port0 32-63:port1 * multicast 64-127:port0 128-191:port1 */ - config->hdr.length = 2; - config->hdr.offset = port ? 32 : 0; - config->hdr.client_id = bp->fp->cl_id; + config->hdr.length = 1 + (with_bcast ? 1 : 0); + config->hdr.offset = cam_offset; + config->hdr.client_id = 0xff; config->hdr.reserved1 = 0; /* primary MAC */ config->config_table[0].cam_entry.msb_mac_addr = - swab16(*(u16 *)&bp->dev->dev_addr[0]); + swab16(*(u16 *)&mac[0]); config->config_table[0].cam_entry.middle_mac_addr = - swab16(*(u16 *)&bp->dev->dev_addr[2]); + swab16(*(u16 *)&mac[2]); config->config_table[0].cam_entry.lsb_mac_addr = - swab16(*(u16 *)&bp->dev->dev_addr[4]); + swab16(*(u16 *)&mac[4]); config->config_table[0].cam_entry.flags = cpu_to_le16(port); if (set) config->config_table[0].target_table_entry.flags = 0; else CAM_INVALIDATE(config->config_table[0]); config->config_table[0].target_table_entry.clients_bit_vector = - cpu_to_le32(1 << BP_L_ID(bp)); + cpu_to_le32(cl_bit_vec); config->config_table[0].target_table_entry.vlan_id = 0; DP(NETIF_MSG_IFUP, "%s MAC (%04x:%04x:%04x)\n", @@ -7073,47 +7088,58 @@ static void bnx2x_set_mac_addr_e1(struct bnx2x *bp, int set) config->config_table[0].cam_entry.lsb_mac_addr); /* broadcast */ - config->config_table[1].cam_entry.msb_mac_addr = cpu_to_le16(0xffff); - config->config_table[1].cam_entry.middle_mac_addr = cpu_to_le16(0xffff); - config->config_table[1].cam_entry.lsb_mac_addr = cpu_to_le16(0xffff); - config->config_table[1].cam_entry.flags = cpu_to_le16(port); - if (set) - config->config_table[1].target_table_entry.flags = - TSTORM_CAM_TARGET_TABLE_ENTRY_BROADCAST; - else - CAM_INVALIDATE(config->config_table[1]); - config->config_table[1].target_table_entry.clients_bit_vector = - cpu_to_le32(1 << BP_L_ID(bp)); - config->config_table[1].target_table_entry.vlan_id = 0; + if (with_bcast) { + config->config_table[1].cam_entry.msb_mac_addr = + cpu_to_le16(0xffff); + config->config_table[1].cam_entry.middle_mac_addr = + cpu_to_le16(0xffff); + config->config_table[1].cam_entry.lsb_mac_addr = + cpu_to_le16(0xffff); + config->config_table[1].cam_entry.flags = cpu_to_le16(port); + if (set) + config->config_table[1].target_table_entry.flags = + TSTORM_CAM_TARGET_TABLE_ENTRY_BROADCAST; + else + CAM_INVALIDATE(config->config_table[1]); + config->config_table[1].target_table_entry.clients_bit_vector = + cpu_to_le32(cl_bit_vec); + config->config_table[1].target_table_entry.vlan_id = 0; + } bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, 0, U64_HI(bnx2x_sp_mapping(bp, mac_config)), U64_LO(bnx2x_sp_mapping(bp, mac_config)), 0); } -static void bnx2x_set_mac_addr_e1h(struct bnx2x *bp, int set) +/** + * Sets a MAC in a CAM for a few L2 Clients for E1H chip + * + * @param bp driver descriptor + * @param set set or clear an entry (1 or 0) + * @param mac pointer to a buffer containing a MAC + * @param cl_bit_vec bit vector of clients to register a MAC for + * @param cam_offset offset in a CAM to use + */ +static void bnx2x_set_mac_addr_e1h_gen(struct bnx2x *bp, int set, u8 *mac, + u32 cl_bit_vec, u8 cam_offset) { struct mac_configuration_cmd_e1h *config = (struct mac_configuration_cmd_e1h *)bnx2x_sp(bp, mac_config); - /* CAM allocation for E1H - * unicasts: by func number - * multicast: 20+FUNC*20, 20 each - */ config->hdr.length = 1; - config->hdr.offset = BP_FUNC(bp); - config->hdr.client_id = bp->fp->cl_id; + config->hdr.offset = cam_offset; + config->hdr.client_id = 0xff; config->hdr.reserved1 = 0; /* primary MAC */ config->config_table[0].msb_mac_addr = - swab16(*(u16 *)&bp->dev->dev_addr[0]); + swab16(*(u16 *)&mac[0]); config->config_table[0].middle_mac_addr = - swab16(*(u16 *)&bp->dev->dev_addr[2]); + swab16(*(u16 *)&mac[2]); config->config_table[0].lsb_mac_addr = - swab16(*(u16 *)&bp->dev->dev_addr[4]); + swab16(*(u16 *)&mac[4]); config->config_table[0].clients_bit_vector = - cpu_to_le32(1 << BP_L_ID(bp)); + cpu_to_le32(cl_bit_vec); config->config_table[0].vlan_id = 0; config->config_table[0].e1hov_id = cpu_to_le16(bp->e1hov); if (set) @@ -7122,11 +7148,11 @@ static void bnx2x_set_mac_addr_e1h(struct bnx2x *bp, int set) config->config_table[0].flags = MAC_CONFIGURATION_ENTRY_E1H_ACTION_TYPE; - DP(NETIF_MSG_IFUP, "%s MAC (%04x:%04x:%04x) E1HOV %d CLID %d\n", + DP(NETIF_MSG_IFUP, "%s MAC (%04x:%04x:%04x) E1HOV %d CLID mask %d\n", (set ? "setting" : "clearing"), config->config_table[0].msb_mac_addr, config->config_table[0].middle_mac_addr, - config->config_table[0].lsb_mac_addr, bp->e1hov, BP_L_ID(bp)); + config->config_table[0].lsb_mac_addr, bp->e1hov, cl_bit_vec); bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, 0, U64_HI(bnx2x_sp_mapping(bp, mac_config)), @@ -7178,6 +7204,31 @@ static int bnx2x_wait_ramrod(struct bnx2x *bp, int state, int idx, return -EBUSY; } +static void bnx2x_set_eth_mac_addr_e1h(struct bnx2x *bp, int set) +{ + bp->set_mac_pending++; + smp_wmb(); + + bnx2x_set_mac_addr_e1h_gen(bp, set, bp->dev->dev_addr, + (1 << bp->fp->cl_id), BP_FUNC(bp)); + + /* Wait for a completion */ + bnx2x_wait_ramrod(bp, 0, 0, &bp->set_mac_pending, set ? 0 : 1); +} + +static void bnx2x_set_eth_mac_addr_e1(struct bnx2x *bp, int set) +{ + bp->set_mac_pending++; + smp_wmb(); + + bnx2x_set_mac_addr_e1_gen(bp, set, bp->dev->dev_addr, + (1 << bp->fp->cl_id), (BP_PORT(bp) ? 32 : 0), + 1); + + /* Wait for a completion */ + bnx2x_wait_ramrod(bp, 0, 0, &bp->set_mac_pending, set ? 0 : 1); +} + static int bnx2x_setup_leading(struct bnx2x *bp) { int rc; @@ -7452,9 +7503,9 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) } if (CHIP_IS_E1(bp)) - bnx2x_set_mac_addr_e1(bp, 1); + bnx2x_set_eth_mac_addr_e1(bp, 1); else - bnx2x_set_mac_addr_e1h(bp, 1); + bnx2x_set_eth_mac_addr_e1h(bp, 1); } if (bp->port.pmf) @@ -7717,7 +7768,7 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) struct mac_configuration_cmd *config = bnx2x_sp(bp, mcast_config); - bnx2x_set_mac_addr_e1(bp, 0); + bnx2x_set_eth_mac_addr_e1(bp, 0); for (i = 0; i < config->hdr.length; i++) CAM_INVALIDATE(config->config_table[i]); @@ -7730,6 +7781,9 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) config->hdr.client_id = bp->fp->cl_id; config->hdr.reserved1 = 0; + bp->set_mac_pending++; + smp_wmb(); + bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, 0, U64_HI(bnx2x_sp_mapping(bp, mcast_config)), U64_LO(bnx2x_sp_mapping(bp, mcast_config)), 0); @@ -7737,7 +7791,7 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) } else { /* E1H */ REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0); - bnx2x_set_mac_addr_e1h(bp, 0); + bnx2x_set_eth_mac_addr_e1h(bp, 0); for (i = 0; i < MC_HASH_SIZE; i++) REG_WR(bp, MC_HASH_OFFSET(bp, i), 0); @@ -8520,6 +8574,14 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp) bp->link_params.req_flow_ctrl, bp->port.advertising); } +static void __devinit bnx2x_set_mac_buf(u8 *mac_buf, u32 mac_lo, u16 mac_hi) +{ + mac_hi = cpu_to_be16(mac_hi); + mac_lo = cpu_to_be32(mac_lo); + memcpy(mac_buf, &mac_hi, sizeof(mac_hi)); + memcpy(mac_buf + sizeof(mac_hi), &mac_lo, sizeof(mac_lo)); +} + static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp) { int port = BP_PORT(bp); @@ -8601,12 +8663,7 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp) val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_upper); val = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_lower); - bp->dev->dev_addr[0] = (u8)(val2 >> 8 & 0xff); - bp->dev->dev_addr[1] = (u8)(val2 & 0xff); - bp->dev->dev_addr[2] = (u8)(val >> 24 & 0xff); - bp->dev->dev_addr[3] = (u8)(val >> 16 & 0xff); - bp->dev->dev_addr[4] = (u8)(val >> 8 & 0xff); - bp->dev->dev_addr[5] = (u8)(val & 0xff); + bnx2x_set_mac_buf(bp->dev->dev_addr, val, val2); memcpy(bp->link_params.mac_addr, bp->dev->dev_addr, ETH_ALEN); memcpy(bp->dev->perm_addr, bp->dev->dev_addr, ETH_ALEN); } @@ -10232,14 +10289,16 @@ static int bnx2x_test_intr(struct bnx2x *bp) config->hdr.client_id = bp->fp->cl_id; config->hdr.reserved1 = 0; + bp->set_mac_pending++; + smp_wmb(); rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, 0, U64_HI(bnx2x_sp_mapping(bp, mac_config)), U64_LO(bnx2x_sp_mapping(bp, mac_config)), 0); if (rc == 0) { - bp->set_mac_pending++; for (i = 0; i < 10; i++) { if (!bp->set_mac_pending) break; + smp_rmb(); msleep_interruptible(10); } if (i == 10) @@ -11337,6 +11396,9 @@ static void bnx2x_set_rx_mode(struct net_device *dev) config->hdr.client_id = bp->fp->cl_id; config->hdr.reserved1 = 0; + bp->set_mac_pending++; + smp_wmb(); + bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, 0, U64_HI(bnx2x_sp_mapping(bp, mcast_config)), U64_LO(bnx2x_sp_mapping(bp, mcast_config)), @@ -11386,9 +11448,9 @@ static int bnx2x_change_mac_addr(struct net_device *dev, void *p) memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); if (netif_running(dev)) { if (CHIP_IS_E1(bp)) - bnx2x_set_mac_addr_e1(bp, 1); + bnx2x_set_eth_mac_addr_e1(bp, 1); else - bnx2x_set_mac_addr_e1h(bp, 1); + bnx2x_set_eth_mac_addr_e1h(bp, 1); } return 0; -- cgit v1.2.3-59-g8ed1b From 37b091bacba7bd329eced9a56998b6247da414c4 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sat, 10 Oct 2009 13:46:55 +0000 Subject: bnx2x: Add hw init code to support iSCSI. Add code to initialize hardware blocks used for iSCSI. Signed-off-by: Michael Chan Signed-off-by: Shmulik Ravid - Rabinovitz Acked-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x.h | 59 ++++++++++--- drivers/net/bnx2x_main.c | 210 ++++++++++++++++++++++++++++++++++------------- 2 files changed, 200 insertions(+), 69 deletions(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index 1f0706328a3f..e94ce8370253 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h @@ -762,7 +762,11 @@ struct bnx2x_eth_stats { (offsetof(struct bnx2x_eth_stats, stat_name) / 4) +#ifdef BCM_CNIC +#define MAX_CONTEXT 15 +#else #define MAX_CONTEXT 16 +#endif union cdu_context { struct eth_context eth; @@ -811,13 +815,21 @@ struct bnx2x { struct bnx2x_fastpath fp[MAX_CONTEXT]; void __iomem *regview; void __iomem *doorbells; +#ifdef BCM_CNIC +#define BNX2X_DB_SIZE (18*BCM_PAGE_SIZE) +#else #define BNX2X_DB_SIZE (16*BCM_PAGE_SIZE) +#endif struct net_device *dev; struct pci_dev *pdev; atomic_t intr_sem; +#ifdef BCM_CNIC + struct msix_entry msix_table[MAX_CONTEXT+2]; +#else struct msix_entry msix_table[MAX_CONTEXT+1]; +#endif #define INT_MODE_INTx 1 #define INT_MODE_MSI 2 #define INT_MODE_MSIX 3 @@ -891,6 +903,11 @@ struct bnx2x { #define BP_E1HVN(bp) (bp->func >> 1) #define BP_L_ID(bp) (BP_E1HVN(bp) << 2) +#ifdef BCM_CNIC +#define BCM_CNIC_CID_START 16 +#define BCM_ISCSI_ETH_CL_ID 17 +#endif + int pm_cap; int pcie_cap; int mrrs; @@ -960,24 +977,44 @@ struct bnx2x { #define BNX2X_MAX_MULTICAST 64 #define BNX2X_MAX_EMUL_MULTI 16 + u32 rx_mode_cl_mask; + dma_addr_t def_status_blk_mapping; struct bnx2x_slowpath *slowpath; dma_addr_t slowpath_mapping; -#ifdef BCM_ISCSI - void *t1; - dma_addr_t t1_mapping; - void *t2; - dma_addr_t t2_mapping; - void *timers; - dma_addr_t timers_mapping; - void *qm; - dma_addr_t qm_mapping; -#endif - int dropless_fc; +#ifdef BCM_CNIC + u32 cnic_flags; +#define BNX2X_CNIC_FLAG_MAC_SET 1 + + void *t1; + dma_addr_t t1_mapping; + void *t2; + dma_addr_t t2_mapping; + void *timers; + dma_addr_t timers_mapping; + void *qm; + dma_addr_t qm_mapping; + struct cnic_ops *cnic_ops; + void *cnic_data; + u32 cnic_tag; + struct cnic_eth_dev cnic_eth_dev; + struct host_status_block *cnic_sb; + dma_addr_t cnic_sb_mapping; +#define CNIC_SB_ID(bp) BP_L_ID(bp) + struct eth_spe *cnic_kwq; + struct eth_spe *cnic_kwq_prod; + struct eth_spe *cnic_kwq_cons; + struct eth_spe *cnic_kwq_last; + u16 cnic_kwq_pending; + u16 cnic_spq_pending; + struct mutex cnic_mutex; + u8 iscsi_mac[6]; +#endif + int dmae_ready; /* used to synchronize dmae accesses */ struct mutex dmae_mutex; diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 02ce3b31050c..f7b71100e95c 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -742,6 +742,9 @@ static void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw) if (msix) { synchronize_irq(bp->msix_table[0].vector); offset = 1; +#ifdef BCM_CNIC + offset++; +#endif for_each_queue(bp, i) synchronize_irq(bp->msix_table[i + offset].vector); } else @@ -5252,7 +5255,7 @@ static void bnx2x_set_storm_rx_mode(struct bnx2x *bp) { struct tstorm_eth_mac_filter_config tstorm_mac_filter = {0}; int mode = bp->rx_mode; - int mask = (1 << BP_L_ID(bp)); + int mask = bp->rx_mode_cl_mask; int func = BP_FUNC(bp); int port = BP_PORT(bp); int i; @@ -5365,6 +5368,7 @@ static void bnx2x_init_internal_func(struct bnx2x *bp) (*(u32 *)&tstorm_config)); bp->rx_mode = BNX2X_RX_MODE_NONE; /* no rx until link is up */ + bp->rx_mode_cl_mask = (1 << BP_L_ID(bp)); bnx2x_set_storm_rx_mode(bp); for_each_queue(bp, i) { @@ -5582,7 +5586,11 @@ static void bnx2x_nic_init(struct bnx2x *bp, u32 load_code) fp->state = BNX2X_FP_STATE_CLOSED; fp->index = i; fp->cl_id = BP_L_ID(bp) + i; +#ifdef BCM_CNIC + fp->sb_id = fp->cl_id + 1; +#else fp->sb_id = fp->cl_id; +#endif /* Suitable Rx and Tx SBs are served by the same client */ if (i >= bp->num_rx_queues) fp->cl_id -= bp->num_rx_queues; @@ -5884,7 +5892,7 @@ static int bnx2x_int_mem_test(struct bnx2x *bp) msleep(50); bnx2x_init_block(bp, BRB1_BLOCK, COMMON_STAGE); bnx2x_init_block(bp, PRS_BLOCK, COMMON_STAGE); -#ifndef BCM_ISCSI +#ifndef BCM_CNIC /* set NIC mode */ REG_WR(bp, PRS_REG_NIC_MODE, 1); #endif @@ -6023,6 +6031,9 @@ static void bnx2x_setup_fan_failure_detection(struct bnx2x *bp) static int bnx2x_init_common(struct bnx2x *bp) { u32 val, i; +#ifdef BCM_CNIC + u32 wb_write[2]; +#endif DP(BNX2X_MSG_MCP, "starting common init func %d\n", BP_FUNC(bp)); @@ -6065,7 +6076,7 @@ static int bnx2x_init_common(struct bnx2x *bp) #endif REG_WR(bp, PXP2_REG_RQ_CDU_P_SIZE, 2); -#ifdef BCM_ISCSI +#ifdef BCM_CNIC REG_WR(bp, PXP2_REG_RQ_TM_P_SIZE, 5); REG_WR(bp, PXP2_REG_RQ_QM_P_SIZE, 5); REG_WR(bp, PXP2_REG_RQ_SRC_P_SIZE, 5); @@ -6108,11 +6119,26 @@ static int bnx2x_init_common(struct bnx2x *bp) bnx2x_read_dmae(bp, USEM_REG_PASSIVE_BUFFER, 3); bnx2x_init_block(bp, QM_BLOCK, COMMON_STAGE); + +#ifdef BCM_CNIC + wb_write[0] = 0; + wb_write[1] = 0; + for (i = 0; i < 64; i++) { + REG_WR(bp, QM_REG_BASEADDR + i*4, 1024 * 4 * (i%16)); + bnx2x_init_ind_wr(bp, QM_REG_PTRTBL + i*8, wb_write, 2); + + if (CHIP_IS_E1H(bp)) { + REG_WR(bp, QM_REG_BASEADDR_EXT_A + i*4, 1024*4*(i%16)); + bnx2x_init_ind_wr(bp, QM_REG_PTRTBL_EXT_A + i*8, + wb_write, 2); + } + } +#endif /* soft reset pulse */ REG_WR(bp, QM_REG_SOFT_RESET, 1); REG_WR(bp, QM_REG_SOFT_RESET, 0); -#ifdef BCM_ISCSI +#ifdef BCM_CNIC bnx2x_init_block(bp, TIMERS_BLOCK, COMMON_STAGE); #endif @@ -6126,8 +6152,10 @@ static int bnx2x_init_common(struct bnx2x *bp) bnx2x_init_block(bp, BRB1_BLOCK, COMMON_STAGE); bnx2x_init_block(bp, PRS_BLOCK, COMMON_STAGE); REG_WR(bp, PRS_REG_A_PRSU_20, 0xf); +#ifndef BCM_CNIC /* set NIC mode */ REG_WR(bp, PRS_REG_NIC_MODE, 1); +#endif if (CHIP_IS_E1H(bp)) REG_WR(bp, PRS_REG_E1HOV_MODE, IS_E1HMF(bp)); @@ -6162,6 +6190,18 @@ static int bnx2x_init_common(struct bnx2x *bp) /* TODO: replace with something meaningful */ } bnx2x_init_block(bp, SRCH_BLOCK, COMMON_STAGE); +#ifdef BCM_CNIC + REG_WR(bp, SRC_REG_KEYSEARCH_0, 0x63285672); + REG_WR(bp, SRC_REG_KEYSEARCH_1, 0x24b8f2cc); + REG_WR(bp, SRC_REG_KEYSEARCH_2, 0x223aef9b); + REG_WR(bp, SRC_REG_KEYSEARCH_3, 0x26001e3a); + REG_WR(bp, SRC_REG_KEYSEARCH_4, 0x7ae91116); + REG_WR(bp, SRC_REG_KEYSEARCH_5, 0x5ce5230b); + REG_WR(bp, SRC_REG_KEYSEARCH_6, 0x298d8adf); + REG_WR(bp, SRC_REG_KEYSEARCH_7, 0x6eb0ff09); + REG_WR(bp, SRC_REG_KEYSEARCH_8, 0x1830f82f); + REG_WR(bp, SRC_REG_KEYSEARCH_9, 0x01e46be7); +#endif REG_WR(bp, SRC_REG_SOFT_RST, 0); if (sizeof(union cdu_context) != 1024) @@ -6278,38 +6318,14 @@ static int bnx2x_init_port(struct bnx2x *bp) bnx2x_init_block(bp, TCM_BLOCK, init_stage); bnx2x_init_block(bp, UCM_BLOCK, init_stage); bnx2x_init_block(bp, CCM_BLOCK, init_stage); -#ifdef BCM_ISCSI - /* Port0 1 - * Port1 385 */ - i++; - wb_write[0] = ONCHIP_ADDR1(bp->timers_mapping); - wb_write[1] = ONCHIP_ADDR2(bp->timers_mapping); - REG_WR_DMAE(bp, PXP2_REG_RQ_ONCHIP_AT + i*8, wb_write, 2); - REG_WR(bp, PXP2_REG_PSWRQ_TM0_L2P + func*4, PXP_ONE_ILT(i)); - - /* Port0 2 - * Port1 386 */ - i++; - wb_write[0] = ONCHIP_ADDR1(bp->qm_mapping); - wb_write[1] = ONCHIP_ADDR2(bp->qm_mapping); - REG_WR_DMAE(bp, PXP2_REG_RQ_ONCHIP_AT + i*8, wb_write, 2); - REG_WR(bp, PXP2_REG_PSWRQ_QM0_L2P + func*4, PXP_ONE_ILT(i)); - - /* Port0 3 - * Port1 387 */ - i++; - wb_write[0] = ONCHIP_ADDR1(bp->t1_mapping); - wb_write[1] = ONCHIP_ADDR2(bp->t1_mapping); - REG_WR_DMAE(bp, PXP2_REG_RQ_ONCHIP_AT + i*8, wb_write, 2); - REG_WR(bp, PXP2_REG_PSWRQ_SRC0_L2P + func*4, PXP_ONE_ILT(i)); -#endif bnx2x_init_block(bp, XCM_BLOCK, init_stage); -#ifdef BCM_ISCSI - REG_WR(bp, TM_REG_LIN0_SCAN_TIME + func*4, 1024/64*20); - REG_WR(bp, TM_REG_LIN0_MAX_ACTIVE_CID + func*4, 31); +#ifdef BCM_CNIC + REG_WR(bp, QM_REG_CONNNUM_0 + port*4, 1024/16 - 1); bnx2x_init_block(bp, TIMERS_BLOCK, init_stage); + REG_WR(bp, TM_REG_LIN0_SCAN_TIME + port*4, 20); + REG_WR(bp, TM_REG_LIN0_MAX_ACTIVE_CID + port*4, 31); #endif bnx2x_init_block(bp, DQ_BLOCK, init_stage); @@ -6367,18 +6383,8 @@ static int bnx2x_init_port(struct bnx2x *bp) msleep(5); REG_WR(bp, PBF_REG_INIT_P0 + port*4, 0); -#ifdef BCM_ISCSI - /* tell the searcher where the T2 table is */ - REG_WR(bp, SRC_REG_COUNTFREE0 + func*4, 16*1024/64); - - wb_write[0] = U64_LO(bp->t2_mapping); - wb_write[1] = U64_HI(bp->t2_mapping); - REG_WR_DMAE(bp, SRC_REG_FIRSTFREE0 + func*4, wb_write, 2); - wb_write[0] = U64_LO((u64)bp->t2_mapping + 16*1024 - 64); - wb_write[1] = U64_HI((u64)bp->t2_mapping + 16*1024 - 64); - REG_WR_DMAE(bp, SRC_REG_LASTFREE0 + func*4, wb_write, 2); - - REG_WR(bp, SRC_REG_NUMBER_HASH_BITS0 + func*4, 10); +#ifdef BCM_CNIC + bnx2x_init_block(bp, SRCH_BLOCK, init_stage); #endif bnx2x_init_block(bp, CDU_BLOCK, init_stage); bnx2x_init_block(bp, CFC_BLOCK, init_stage); @@ -6487,7 +6493,12 @@ static int bnx2x_init_port(struct bnx2x *bp) #define PXP_ONE_ILT(x) (((x) << 10) | x) #define PXP_ILT_RANGE(f, l) (((l) << 10) | f) +#ifdef BCM_CNIC +#define CNIC_ILT_LINES 127 +#define CNIC_CTX_PER_ILT 16 +#else #define CNIC_ILT_LINES 0 +#endif static void bnx2x_ilt_wr(struct bnx2x *bp, u32 index, dma_addr_t addr) { @@ -6526,6 +6537,46 @@ static int bnx2x_init_func(struct bnx2x *bp) REG_WR(bp, PXP2_REG_PSWRQ_CDU0_L2P + func*4, PXP_ILT_RANGE(i, i + CNIC_ILT_LINES)); +#ifdef BCM_CNIC + i += 1 + CNIC_ILT_LINES; + bnx2x_ilt_wr(bp, i, bp->timers_mapping); + if (CHIP_IS_E1(bp)) + REG_WR(bp, PXP2_REG_PSWRQ_TM0_L2P + func*4, PXP_ONE_ILT(i)); + else { + REG_WR(bp, PXP2_REG_RQ_TM_FIRST_ILT, i); + REG_WR(bp, PXP2_REG_RQ_TM_LAST_ILT, i); + } + + i++; + bnx2x_ilt_wr(bp, i, bp->qm_mapping); + if (CHIP_IS_E1(bp)) + REG_WR(bp, PXP2_REG_PSWRQ_QM0_L2P + func*4, PXP_ONE_ILT(i)); + else { + REG_WR(bp, PXP2_REG_RQ_QM_FIRST_ILT, i); + REG_WR(bp, PXP2_REG_RQ_QM_LAST_ILT, i); + } + + i++; + bnx2x_ilt_wr(bp, i, bp->t1_mapping); + if (CHIP_IS_E1(bp)) + REG_WR(bp, PXP2_REG_PSWRQ_SRC0_L2P + func*4, PXP_ONE_ILT(i)); + else { + REG_WR(bp, PXP2_REG_RQ_SRC_FIRST_ILT, i); + REG_WR(bp, PXP2_REG_RQ_SRC_LAST_ILT, i); + } + + /* tell the searcher where the T2 table is */ + REG_WR(bp, SRC_REG_COUNTFREE0 + port*4, 16*1024/64); + + bnx2x_wb_wr(bp, SRC_REG_FIRSTFREE0 + port*16, + U64_LO(bp->t2_mapping), U64_HI(bp->t2_mapping)); + + bnx2x_wb_wr(bp, SRC_REG_LASTFREE0 + port*16, + U64_LO((u64)bp->t2_mapping + 16*1024 - 64), + U64_HI((u64)bp->t2_mapping + 16*1024 - 64)); + + REG_WR(bp, SRC_REG_NUMBER_HASH_BITS0 + port*4, 10); +#endif if (CHIP_IS_E1H(bp)) { bnx2x_init_block(bp, MISC_BLOCK, FUNC0_STAGE + func); @@ -6610,6 +6661,9 @@ static int bnx2x_init_hw(struct bnx2x *bp, u32 load_code) bnx2x_zero_def_sb(bp); for_each_queue(bp, i) bnx2x_zero_sb(bp, BP_L_ID(bp) + i); +#ifdef BCM_CNIC + bnx2x_zero_sb(bp, BP_L_ID(bp) + i); +#endif init_hw_err: bnx2x_gunzip_end(bp); @@ -6685,11 +6739,13 @@ static void bnx2x_free_mem(struct bnx2x *bp) BNX2X_PCI_FREE(bp->slowpath, bp->slowpath_mapping, sizeof(struct bnx2x_slowpath)); -#ifdef BCM_ISCSI +#ifdef BCM_CNIC BNX2X_PCI_FREE(bp->t1, bp->t1_mapping, 64*1024); BNX2X_PCI_FREE(bp->t2, bp->t2_mapping, 16*1024); BNX2X_PCI_FREE(bp->timers, bp->timers_mapping, 8*1024); BNX2X_PCI_FREE(bp->qm, bp->qm_mapping, 128*1024); + BNX2X_PCI_FREE(bp->cnic_sb, bp->cnic_sb_mapping, + sizeof(struct host_status_block)); #endif BNX2X_PCI_FREE(bp->spq, bp->spq_mapping, BCM_PAGE_SIZE); @@ -6768,32 +6824,26 @@ static int bnx2x_alloc_mem(struct bnx2x *bp) BNX2X_PCI_ALLOC(bp->slowpath, &bp->slowpath_mapping, sizeof(struct bnx2x_slowpath)); -#ifdef BCM_ISCSI +#ifdef BCM_CNIC BNX2X_PCI_ALLOC(bp->t1, &bp->t1_mapping, 64*1024); - /* Initialize T1 */ - for (i = 0; i < 64*1024; i += 64) { - *(u64 *)((char *)bp->t1 + i + 56) = 0x0UL; - *(u64 *)((char *)bp->t1 + i + 3) = 0x0UL; - } - /* allocate searcher T2 table we allocate 1/4 of alloc num for T2 (which is not entered into the ILT) */ BNX2X_PCI_ALLOC(bp->t2, &bp->t2_mapping, 16*1024); - /* Initialize T2 */ + /* Initialize T2 (for 1024 connections) */ for (i = 0; i < 16*1024; i += 64) - * (u64 *)((char *)bp->t2 + i + 56) = bp->t2_mapping + i + 64; - - /* now fixup the last line in the block to point to the next block */ - *(u64 *)((char *)bp->t2 + 1024*16-8) = bp->t2_mapping; + *(u64 *)((char *)bp->t2 + i + 56) = bp->t2_mapping + i + 64; - /* Timer block array (MAX_CONN*8) phys uncached for now 1024 conns */ + /* Timer block array (8*MAX_CONN) phys uncached for now 1024 conns */ BNX2X_PCI_ALLOC(bp->timers, &bp->timers_mapping, 8*1024); /* QM queues (128*MAX_CONN) */ BNX2X_PCI_ALLOC(bp->qm, &bp->qm_mapping, 128*1024); + + BNX2X_PCI_ALLOC(bp->cnic_sb, &bp->cnic_sb_mapping, + sizeof(struct host_status_block)); #endif /* Slow path ring */ @@ -6869,6 +6919,9 @@ static void bnx2x_free_msix_irqs(struct bnx2x *bp) DP(NETIF_MSG_IFDOWN, "released sp irq (%d)\n", bp->msix_table[0].vector); +#ifdef BCM_CNIC + offset++; +#endif for_each_queue(bp, i) { DP(NETIF_MSG_IFDOWN, "about to release fp #%d->%d irq " "state %x\n", i, bp->msix_table[i + offset].vector, @@ -6902,6 +6955,12 @@ static int bnx2x_enable_msix(struct bnx2x *bp) bp->msix_table[0].entry = igu_vec; DP(NETIF_MSG_IFUP, "msix_table[0].entry = %d (slowpath)\n", igu_vec); +#ifdef BCM_CNIC + igu_vec = BP_L_ID(bp) + offset; + bp->msix_table[1].entry = igu_vec; + DP(NETIF_MSG_IFUP, "msix_table[1].entry = %d (CNIC)\n", igu_vec); + offset++; +#endif for_each_queue(bp, i) { igu_vec = BP_L_ID(bp) + offset + i; bp->msix_table[i + offset].entry = igu_vec; @@ -6932,6 +6991,9 @@ static int bnx2x_req_msix_irqs(struct bnx2x *bp) return -EBUSY; } +#ifdef BCM_CNIC + offset++; +#endif for_each_queue(bp, i) { struct bnx2x_fastpath *fp = &bp->fp[i]; @@ -7496,10 +7558,18 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) } if (bp->state == BNX2X_STATE_OPEN) { +#ifdef BCM_CNIC + /* Enable Timer scan */ + REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + BP_PORT(bp)*4, 1); +#endif for_each_nondefault_queue(bp, i) { rc = bnx2x_setup_multi(bp, i); if (rc) +#ifdef BCM_CNIC + goto load_error4; +#else goto load_error3; +#endif } if (CHIP_IS_E1(bp)) @@ -7549,6 +7619,11 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) return 0; +#ifdef BCM_CNIC +load_error4: + /* Disable Timer scan */ + REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + BP_PORT(bp)*4, 0); +#endif load_error3: bnx2x_int_disable_sync(bp, 1); if (!BP_NOMCP(bp)) { @@ -7656,6 +7731,19 @@ static void bnx2x_reset_func(struct bnx2x *bp) REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, 0); REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, 0); +#ifdef BCM_CNIC + /* Disable Timer scan */ + REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 0); + /* + * Wait for at least 10ms and up to 2 second for the timers scan to + * complete + */ + for (i = 0; i < 200; i++) { + msleep(10); + if (!REG_RD(bp, TM_REG_LIN0_SCAN_ON + port*4)) + break; + } +#endif /* Clear ILT */ base = FUNC_ILT_BASE(func); for (i = base; i < base + ILT_PER_FUNC; i++) @@ -8666,6 +8754,12 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp) bnx2x_set_mac_buf(bp->dev->dev_addr, val, val2); memcpy(bp->link_params.mac_addr, bp->dev->dev_addr, ETH_ALEN); memcpy(bp->dev->perm_addr, bp->dev->dev_addr, ETH_ALEN); + +#ifdef BCM_CNIC + val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].iscsi_mac_upper); + val = SHMEM_RD(bp, dev_info.port_hw_config[port].iscsi_mac_lower); + bnx2x_set_mac_buf(bp->iscsi_mac, val, val2); +#endif } static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp) -- cgit v1.2.3-59-g8ed1b From 993ac7b5183f82edc9696cd17faae03523e00e09 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sat, 10 Oct 2009 13:46:56 +0000 Subject: bnx2x: Add main CNIC interface functions. Add the main CNIC registration, callback, MAC addr. setup functions. Signed-off-by: Michael Chan Signed-off-by: Shmulik Ravid - Rabinovitz Acked-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x.h | 4 + drivers/net/bnx2x_main.c | 388 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/net/cnic_if.h | 14 +- 3 files changed, 404 insertions(+), 2 deletions(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index e94ce8370253..60fa14f31d73 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h @@ -24,6 +24,10 @@ #define BCM_VLAN 1 #endif +#if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE) +#define BCM_CNIC 1 +#include "cnic_if.h" +#endif #define BNX2X_MULTI_QUEUE diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index f7b71100e95c..b4e9c6ebac54 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -969,6 +969,9 @@ static void bnx2x_tx_int(struct bnx2x_fastpath *fp) } } +#ifdef BCM_CNIC +static void bnx2x_cnic_cfc_comp(struct bnx2x *bp, int cid); +#endif static void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe) @@ -1025,6 +1028,12 @@ static void bnx2x_sp_event(struct bnx2x_fastpath *fp, bnx2x_fp(bp, cid, state) = BNX2X_FP_STATE_CLOSED; break; +#ifdef BCM_CNIC + case (RAMROD_CMD_ID_ETH_CFC_DEL | BNX2X_STATE_OPEN): + DP(NETIF_MSG_IFDOWN, "got delete ramrod for CID %d\n", cid); + bnx2x_cnic_cfc_comp(bp, cid); + break; +#endif case (RAMROD_CMD_ID_ETH_SET_MAC | BNX2X_STATE_OPEN): case (RAMROD_CMD_ID_ETH_SET_MAC | BNX2X_STATE_DIAG): @@ -1810,6 +1819,20 @@ static irqreturn_t bnx2x_interrupt(int irq, void *dev_instance) } } +#ifdef BCM_CNIC + mask = 0x2 << CNIC_SB_ID(bp); + if (status & (mask | 0x1)) { + struct cnic_ops *c_ops = NULL; + + rcu_read_lock(); + c_ops = rcu_dereference(bp->cnic_ops); + if (c_ops) + c_ops->cnic_handler(bp->cnic_data, NULL); + rcu_read_unlock(); + + status &= ~mask; + } +#endif if (unlikely(status & 0x1)) { queue_delayed_work(bnx2x_wq, &bp->sp_task, 0); @@ -3247,6 +3270,17 @@ static irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance) return IRQ_HANDLED; #endif +#ifdef BCM_CNIC + { + struct cnic_ops *c_ops; + + rcu_read_lock(); + c_ops = rcu_dereference(bp->cnic_ops); + if (c_ops) + c_ops->cnic_handler(bp->cnic_data, NULL); + rcu_read_unlock(); + } +#endif queue_delayed_work(bnx2x_wq, &bp->sp_task, 0); return IRQ_HANDLED; @@ -7291,6 +7325,44 @@ static void bnx2x_set_eth_mac_addr_e1(struct bnx2x *bp, int set) bnx2x_wait_ramrod(bp, 0, 0, &bp->set_mac_pending, set ? 0 : 1); } +#ifdef BCM_CNIC +/** + * Set iSCSI MAC(s) at the next enties in the CAM after the ETH + * MAC(s). This function will wait until the ramdord completion + * returns. + * + * @param bp driver handle + * @param set set or clear the CAM entry + * + * @return 0 if cussess, -ENODEV if ramrod doesn't return. + */ +static int bnx2x_set_iscsi_eth_mac_addr(struct bnx2x *bp, int set) +{ + u32 cl_bit_vec = (1 << BCM_ISCSI_ETH_CL_ID); + + bp->set_mac_pending++; + smp_wmb(); + + /* Send a SET_MAC ramrod */ + if (CHIP_IS_E1(bp)) + bnx2x_set_mac_addr_e1_gen(bp, set, bp->iscsi_mac, + cl_bit_vec, (BP_PORT(bp) ? 32 : 0) + 2, + 1); + else + /* CAM allocation for E1H + * unicasts: by func number + * multicast: 20+FUNC*20, 20 each + */ + bnx2x_set_mac_addr_e1h_gen(bp, set, bp->iscsi_mac, + cl_bit_vec, E1H_FUNC_MAX + BP_FUNC(bp)); + + /* Wait for a completion when setting */ + bnx2x_wait_ramrod(bp, 0, 0, &bp->set_mac_pending, set ? 0 : 1); + + return 0; +} +#endif + static int bnx2x_setup_leading(struct bnx2x *bp) { int rc; @@ -7416,6 +7488,10 @@ static int bnx2x_set_int_mode(struct bnx2x *bp) return rc; } +#ifdef BCM_CNIC +static int bnx2x_cnic_notify(struct bnx2x *bp, int cmd); +static void bnx2x_setup_cnic_irq_info(struct bnx2x *bp); +#endif /* must be called with rtnl_lock */ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) @@ -7576,6 +7652,15 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) bnx2x_set_eth_mac_addr_e1(bp, 1); else bnx2x_set_eth_mac_addr_e1h(bp, 1); +#ifdef BCM_CNIC + /* Set iSCSI L2 MAC */ + mutex_lock(&bp->cnic_mutex); + if (bp->cnic_eth_dev.drv_state & CNIC_DRV_STATE_REGD) { + bnx2x_set_iscsi_eth_mac_addr(bp, 1); + bp->cnic_flags |= BNX2X_CNIC_FLAG_MAC_SET; + } + mutex_unlock(&bp->cnic_mutex); +#endif } if (bp->port.pmf) @@ -7616,6 +7701,11 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) /* start the timer */ mod_timer(&bp->timer, jiffies + bp->current_interval); +#ifdef BCM_CNIC + bnx2x_setup_cnic_irq_info(bp); + if (bp->state == BNX2X_STATE_OPEN) + bnx2x_cnic_notify(bp, CNIC_CTL_START_CMD); +#endif return 0; @@ -7810,6 +7900,9 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) u32 reset_code = 0; int i, cnt, rc; +#ifdef BCM_CNIC + bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD); +#endif bp->state = BNX2X_STATE_CLOSING_WAIT4_HALT; /* Set "drop all" */ @@ -7886,6 +7979,15 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) REG_WR(bp, MISC_REG_E1HMF_MODE, 0); } +#ifdef BCM_CNIC + /* Clear iSCSI L2 MAC */ + mutex_lock(&bp->cnic_mutex); + if (bp->cnic_flags & BNX2X_CNIC_FLAG_MAC_SET) { + bnx2x_set_iscsi_eth_mac_addr(bp, 0); + bp->cnic_flags &= ~BNX2X_CNIC_FLAG_MAC_SET; + } + mutex_unlock(&bp->cnic_mutex); +#endif if (unload_mode == UNLOAD_NORMAL) reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS; @@ -8855,6 +8957,9 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp) smp_wmb(); /* Ensure that bp->intr_sem update is SMP-safe */ mutex_init(&bp->port.phy_mutex); +#ifdef BCM_CNIC + mutex_init(&bp->cnic_mutex); +#endif INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task); INIT_WORK(&bp->reset_task, bnx2x_reset_task); @@ -12448,4 +12553,287 @@ static void __exit bnx2x_cleanup(void) module_init(bnx2x_init); module_exit(bnx2x_cleanup); +#ifdef BCM_CNIC + +/* count denotes the number of new completions we have seen */ +static void bnx2x_cnic_sp_post(struct bnx2x *bp, int count) +{ + struct eth_spe *spe; + +#ifdef BNX2X_STOP_ON_ERROR + if (unlikely(bp->panic)) + return; +#endif + + spin_lock_bh(&bp->spq_lock); + bp->cnic_spq_pending -= count; + + for (; bp->cnic_spq_pending < bp->cnic_eth_dev.max_kwqe_pending; + bp->cnic_spq_pending++) { + + if (!bp->cnic_kwq_pending) + break; + + spe = bnx2x_sp_get_next(bp); + *spe = *bp->cnic_kwq_cons; + + bp->cnic_kwq_pending--; + + DP(NETIF_MSG_TIMER, "pending on SPQ %d, on KWQ %d count %d\n", + bp->cnic_spq_pending, bp->cnic_kwq_pending, count); + + if (bp->cnic_kwq_cons == bp->cnic_kwq_last) + bp->cnic_kwq_cons = bp->cnic_kwq; + else + bp->cnic_kwq_cons++; + } + bnx2x_sp_prod_update(bp); + spin_unlock_bh(&bp->spq_lock); +} + +static int bnx2x_cnic_sp_queue(struct net_device *dev, + struct kwqe_16 *kwqes[], u32 count) +{ + struct bnx2x *bp = netdev_priv(dev); + int i; + +#ifdef BNX2X_STOP_ON_ERROR + if (unlikely(bp->panic)) + return -EIO; +#endif + + spin_lock_bh(&bp->spq_lock); + + for (i = 0; i < count; i++) { + struct eth_spe *spe = (struct eth_spe *)kwqes[i]; + + if (bp->cnic_kwq_pending == MAX_SP_DESC_CNT) + break; + + *bp->cnic_kwq_prod = *spe; + + bp->cnic_kwq_pending++; + + DP(NETIF_MSG_TIMER, "L5 SPQE %x %x %x:%x pos %d\n", + spe->hdr.conn_and_cmd_data, spe->hdr.type, + spe->data.mac_config_addr.hi, + spe->data.mac_config_addr.lo, + bp->cnic_kwq_pending); + + if (bp->cnic_kwq_prod == bp->cnic_kwq_last) + bp->cnic_kwq_prod = bp->cnic_kwq; + else + bp->cnic_kwq_prod++; + } + + spin_unlock_bh(&bp->spq_lock); + + if (bp->cnic_spq_pending < bp->cnic_eth_dev.max_kwqe_pending) + bnx2x_cnic_sp_post(bp, 0); + + return i; +} + +static int bnx2x_cnic_ctl_send(struct bnx2x *bp, struct cnic_ctl_info *ctl) +{ + struct cnic_ops *c_ops; + int rc = 0; + + mutex_lock(&bp->cnic_mutex); + c_ops = bp->cnic_ops; + if (c_ops) + rc = c_ops->cnic_ctl(bp->cnic_data, ctl); + mutex_unlock(&bp->cnic_mutex); + + return rc; +} + +static int bnx2x_cnic_ctl_send_bh(struct bnx2x *bp, struct cnic_ctl_info *ctl) +{ + struct cnic_ops *c_ops; + int rc = 0; + + rcu_read_lock(); + c_ops = rcu_dereference(bp->cnic_ops); + if (c_ops) + rc = c_ops->cnic_ctl(bp->cnic_data, ctl); + rcu_read_unlock(); + + return rc; +} + +/* + * for commands that have no data + */ +static int bnx2x_cnic_notify(struct bnx2x *bp, int cmd) +{ + struct cnic_ctl_info ctl = {0}; + + ctl.cmd = cmd; + + return bnx2x_cnic_ctl_send(bp, &ctl); +} + +static void bnx2x_cnic_cfc_comp(struct bnx2x *bp, int cid) +{ + struct cnic_ctl_info ctl; + + /* first we tell CNIC and only then we count this as a completion */ + ctl.cmd = CNIC_CTL_COMPLETION_CMD; + ctl.data.comp.cid = cid; + + bnx2x_cnic_ctl_send_bh(bp, &ctl); + bnx2x_cnic_sp_post(bp, 1); +} + +static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl) +{ + struct bnx2x *bp = netdev_priv(dev); + int rc = 0; + + switch (ctl->cmd) { + case DRV_CTL_CTXTBL_WR_CMD: { + u32 index = ctl->data.io.offset; + dma_addr_t addr = ctl->data.io.dma_addr; + + bnx2x_ilt_wr(bp, index, addr); + break; + } + + case DRV_CTL_COMPLETION_CMD: { + int count = ctl->data.comp.comp_count; + + bnx2x_cnic_sp_post(bp, count); + break; + } + + /* rtnl_lock is held. */ + case DRV_CTL_START_L2_CMD: { + u32 cli = ctl->data.ring.client_id; + + bp->rx_mode_cl_mask |= (1 << cli); + bnx2x_set_storm_rx_mode(bp); + break; + } + + /* rtnl_lock is held. */ + case DRV_CTL_STOP_L2_CMD: { + u32 cli = ctl->data.ring.client_id; + + bp->rx_mode_cl_mask &= ~(1 << cli); + bnx2x_set_storm_rx_mode(bp); + break; + } + + default: + BNX2X_ERR("unknown command %x\n", ctl->cmd); + rc = -EINVAL; + } + + return rc; +} + +static void bnx2x_setup_cnic_irq_info(struct bnx2x *bp) +{ + struct cnic_eth_dev *cp = &bp->cnic_eth_dev; + + if (bp->flags & USING_MSIX_FLAG) { + cp->drv_state |= CNIC_DRV_STATE_USING_MSIX; + cp->irq_arr[0].irq_flags |= CNIC_IRQ_FL_MSIX; + cp->irq_arr[0].vector = bp->msix_table[1].vector; + } else { + cp->drv_state &= ~CNIC_DRV_STATE_USING_MSIX; + cp->irq_arr[0].irq_flags &= ~CNIC_IRQ_FL_MSIX; + } + cp->irq_arr[0].status_blk = bp->cnic_sb; + cp->irq_arr[0].status_blk_num = CNIC_SB_ID(bp); + cp->irq_arr[1].status_blk = bp->def_status_blk; + cp->irq_arr[1].status_blk_num = DEF_SB_ID; + + cp->num_irq = 2; +} + +static int bnx2x_register_cnic(struct net_device *dev, struct cnic_ops *ops, + void *data) +{ + struct bnx2x *bp = netdev_priv(dev); + struct cnic_eth_dev *cp = &bp->cnic_eth_dev; + + if (ops == NULL) + return -EINVAL; + + if (atomic_read(&bp->intr_sem) != 0) + return -EBUSY; + + bp->cnic_kwq = kzalloc(PAGE_SIZE, GFP_KERNEL); + if (!bp->cnic_kwq) + return -ENOMEM; + + bp->cnic_kwq_cons = bp->cnic_kwq; + bp->cnic_kwq_prod = bp->cnic_kwq; + bp->cnic_kwq_last = bp->cnic_kwq + MAX_SP_DESC_CNT; + + bp->cnic_spq_pending = 0; + bp->cnic_kwq_pending = 0; + + bp->cnic_data = data; + + cp->num_irq = 0; + cp->drv_state = CNIC_DRV_STATE_REGD; + + bnx2x_init_sb(bp, bp->cnic_sb, bp->cnic_sb_mapping, CNIC_SB_ID(bp)); + + bnx2x_setup_cnic_irq_info(bp); + bnx2x_set_iscsi_eth_mac_addr(bp, 1); + bp->cnic_flags |= BNX2X_CNIC_FLAG_MAC_SET; + rcu_assign_pointer(bp->cnic_ops, ops); + + return 0; +} + +static int bnx2x_unregister_cnic(struct net_device *dev) +{ + struct bnx2x *bp = netdev_priv(dev); + struct cnic_eth_dev *cp = &bp->cnic_eth_dev; + + mutex_lock(&bp->cnic_mutex); + if (bp->cnic_flags & BNX2X_CNIC_FLAG_MAC_SET) { + bp->cnic_flags &= ~BNX2X_CNIC_FLAG_MAC_SET; + bnx2x_set_iscsi_eth_mac_addr(bp, 0); + } + cp->drv_state = 0; + rcu_assign_pointer(bp->cnic_ops, NULL); + mutex_unlock(&bp->cnic_mutex); + synchronize_rcu(); + kfree(bp->cnic_kwq); + bp->cnic_kwq = NULL; + + return 0; +} + +struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev) +{ + struct bnx2x *bp = netdev_priv(dev); + struct cnic_eth_dev *cp = &bp->cnic_eth_dev; + + cp->drv_owner = THIS_MODULE; + cp->chip_id = CHIP_ID(bp); + cp->pdev = bp->pdev; + cp->io_base = bp->regview; + cp->io_base2 = bp->doorbells; + cp->max_kwqe_pending = 8; + cp->ctx_blk_size = CNIC_CTX_PER_ILT * sizeof(union cdu_context); + cp->ctx_tbl_offset = FUNC_ILT_BASE(BP_FUNC(bp)) + 1; + cp->ctx_tbl_len = CNIC_ILT_LINES; + cp->starting_cid = BCM_CNIC_CID_START; + cp->drv_submit_kwqes_16 = bnx2x_cnic_sp_queue; + cp->drv_ctl = bnx2x_drv_ctl; + cp->drv_register_cnic = bnx2x_register_cnic; + cp->drv_unregister_cnic = bnx2x_unregister_cnic; + + return cp; +} +EXPORT_SYMBOL(bnx2x_cnic_probe); + +#endif /* BCM_CNIC */ diff --git a/drivers/net/cnic_if.h b/drivers/net/cnic_if.h index d8b09efdcb52..8aaf98bdd4f7 100644 --- a/drivers/net/cnic_if.h +++ b/drivers/net/cnic_if.h @@ -12,8 +12,8 @@ #ifndef CNIC_IF_H #define CNIC_IF_H -#define CNIC_MODULE_VERSION "2.0.1" -#define CNIC_MODULE_RELDATE "Oct 01, 2009" +#define CNIC_MODULE_VERSION "2.1.0" +#define CNIC_MODULE_RELDATE "Oct 10, 2009" #define CNIC_ULP_RDMA 0 #define CNIC_ULP_ISCSI 1 @@ -81,6 +81,8 @@ struct kcqe { #define DRV_CTL_CTX_WR_CMD 0x103 #define DRV_CTL_CTXTBL_WR_CMD 0x104 #define DRV_CTL_COMPLETION_CMD 0x105 +#define DRV_CTL_START_L2_CMD 0x106 +#define DRV_CTL_STOP_L2_CMD 0x107 struct cnic_ctl_completion { u32 cid; @@ -105,11 +107,17 @@ struct drv_ctl_io { dma_addr_t dma_addr; }; +struct drv_ctl_l2_ring { + u32 client_id; + u32 cid; +}; + struct drv_ctl_info { int cmd; union { struct drv_ctl_completion comp; struct drv_ctl_io io; + struct drv_ctl_l2_ring ring; char bytes[MAX_DRV_CTL_DATA]; } data; }; @@ -143,6 +151,7 @@ struct cnic_eth_dev { u32 max_kwqe_pending; struct pci_dev *pdev; void __iomem *io_base; + void __iomem *io_base2; u32 ctx_tbl_offset; u32 ctx_tbl_len; @@ -298,5 +307,6 @@ extern int cnic_register_driver(int ulp_type, struct cnic_ulp_ops *ulp_ops); extern int cnic_unregister_driver(int ulp_type); extern struct cnic_eth_dev *bnx2_cnic_probe(struct net_device *dev); +extern struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev); #endif -- cgit v1.2.3-59-g8ed1b From b015e3d112cab1880d262c56655c3ff60e179ceb Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Thu, 15 Oct 2009 00:17:20 -0700 Subject: bnx2x: Allowing 0 as initial fairness value Value of zero was used to disable the fairness mechanism. Though the code (driver and FW) allowed changing the value at run time, it did not allow to do that if the mechanism was disabled to begin with. Fixed the FW to allow turning on and off the mechanism at run time. Fixed the code to read the value from the chip at the right sequence. Without this fix, if the initial value was set to zero, traffic could not run on the interface. Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_hsi.h | 4 ++-- drivers/net/bnx2x_main.c | 56 ++++++++++++++++++++++++------------------------ firmware/Makefile | 2 +- firmware/WHENCE | 4 ++-- 4 files changed, 33 insertions(+), 33 deletions(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x_hsi.h b/drivers/net/bnx2x_hsi.h index 994743d892ea..dc2f8ed5fd07 100644 --- a/drivers/net/bnx2x_hsi.h +++ b/drivers/net/bnx2x_hsi.h @@ -1259,8 +1259,8 @@ struct host_func_stats { #define BCM_5710_FW_MAJOR_VERSION 5 -#define BCM_5710_FW_MINOR_VERSION 0 -#define BCM_5710_FW_REVISION_VERSION 21 +#define BCM_5710_FW_MINOR_VERSION 2 +#define BCM_5710_FW_REVISION_VERSION 7 #define BCM_5710_FW_ENGINEERING_VERSION 0 #define BCM_5710_FW_COMPILE_FLAGS 1 diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index b4e9c6ebac54..691cf1541892 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -2333,8 +2333,14 @@ static void bnx2x_calc_vn_weight_sum(struct bnx2x *bp) } /* ... only if all min rates are zeros - disable fairness */ - if (all_zero) - bp->vn_weight_sum = 0; + if (all_zero) { + bp->cmng.flags.cmng_enables &= + ~CMNG_FLAGS_PER_PORT_FAIRNESS_VN; + DP(NETIF_MSG_IFUP, "All MIN values are zeroes" + " fairness will be disabled\n"); + } else + bp->cmng.flags.cmng_enables |= + CMNG_FLAGS_PER_PORT_FAIRNESS_VN; } static void bnx2x_init_vn_minmax(struct bnx2x *bp, int func) @@ -2353,17 +2359,14 @@ static void bnx2x_init_vn_minmax(struct bnx2x *bp, int func) } else { vn_min_rate = ((vn_cfg & FUNC_MF_CFG_MIN_BW_MASK) >> FUNC_MF_CFG_MIN_BW_SHIFT) * 100; - /* If fairness is enabled (not all min rates are zeroes) and - if current min rate is zero - set it to 1. - This is a requirement of the algorithm. */ - if (bp->vn_weight_sum && (vn_min_rate == 0)) + /* If min rate is zero - set it to 1 */ + if (!vn_min_rate) vn_min_rate = DEF_MIN_RATE; vn_max_rate = ((vn_cfg & FUNC_MF_CFG_MAX_BW_MASK) >> FUNC_MF_CFG_MAX_BW_SHIFT) * 100; } - DP(NETIF_MSG_IFUP, - "func %d: vn_min_rate=%d vn_max_rate=%d vn_weight_sum=%d\n", + "func %d: vn_min_rate %d vn_max_rate %d vn_weight_sum %d\n", func, vn_min_rate, vn_max_rate, bp->vn_weight_sum); memset(&m_rs_vn, 0, sizeof(struct rate_shaping_vars_per_vn)); @@ -2490,7 +2493,6 @@ static void bnx2x__link_status_update(struct bnx2x *bp) else bnx2x_stats_handle(bp, STATS_EVENT_STOP); - bp->mf_config = SHMEM_RD(bp, mf_cfg.func_mf_config[func].config); bnx2x_calc_vn_weight_sum(bp); /* indicate link status */ @@ -2634,10 +2636,7 @@ static void bnx2x_update_min_max(struct bnx2x *bp) static void bnx2x_dcc_event(struct bnx2x *bp, u32 dcc_event) { - int func = BP_FUNC(bp); - DP(BNX2X_MSG_MCP, "dcc_event 0x%x\n", dcc_event); - bp->mf_config = SHMEM_RD(bp, mf_cfg.func_mf_config[func].config); if (dcc_event & DRV_STATUS_DCC_DISABLE_ENABLE_PF) { @@ -3067,6 +3066,8 @@ static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn) int func = BP_FUNC(bp); REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_12 + func*4, 0); + bp->mf_config = SHMEM_RD(bp, + mf_cfg.func_mf_config[func].config); val = SHMEM_RD(bp, func_mb[func].drv_status); if (val & DRV_STATUS_DCC_EVENT_MASK) bnx2x_dcc_event(bp, @@ -5559,20 +5560,18 @@ static void bnx2x_init_internal_func(struct bnx2x *bp) bp->link_vars.line_speed = SPEED_10000; bnx2x_init_port_minmax(bp); + if (!BP_NOMCP(bp)) + bp->mf_config = + SHMEM_RD(bp, mf_cfg.func_mf_config[func].config); bnx2x_calc_vn_weight_sum(bp); for (vn = VN_0; vn < E1HVN_MAX; vn++) bnx2x_init_vn_minmax(bp, 2*vn + port); /* Enable rate shaping and fairness */ - bp->cmng.flags.cmng_enables = + bp->cmng.flags.cmng_enables |= CMNG_FLAGS_PER_PORT_RATE_SHAPING_VN; - if (bp->vn_weight_sum) - bp->cmng.flags.cmng_enables |= - CMNG_FLAGS_PER_PORT_FAIRNESS_VN; - else - DP(NETIF_MSG_IFUP, "All MIN values are zeroes" - " fairness will be disabled\n"); + } else { /* rate shaping and fairness are disabled */ DP(NETIF_MSG_IFUP, @@ -9038,17 +9037,18 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) if (netif_carrier_ok(dev)) { cmd->speed = bp->link_vars.line_speed; cmd->duplex = bp->link_vars.duplex; - } else { - cmd->speed = bp->link_params.req_line_speed; - cmd->duplex = bp->link_params.req_duplex; - } - if (IS_E1HMF(bp)) { - u16 vn_max_rate; + if (IS_E1HMF(bp)) { + u16 vn_max_rate; - vn_max_rate = ((bp->mf_config & FUNC_MF_CFG_MAX_BW_MASK) >> + vn_max_rate = + ((bp->mf_config & FUNC_MF_CFG_MAX_BW_MASK) >> FUNC_MF_CFG_MAX_BW_SHIFT) * 100; - if (vn_max_rate < cmd->speed) - cmd->speed = vn_max_rate; + if (vn_max_rate < cmd->speed) + cmd->speed = vn_max_rate; + } + } else { + cmd->speed = -1; + cmd->duplex = -1; } if (bp->link_params.switch_cfg == SWITCH_CFG_10G) { diff --git a/firmware/Makefile b/firmware/Makefile index a6c7c3e47e42..45c04660a44d 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -32,7 +32,7 @@ fw-shipped-$(CONFIG_ADAPTEC_STARFIRE) += adaptec/starfire_rx.bin \ adaptec/starfire_tx.bin fw-shipped-$(CONFIG_ATARI_DSP56K) += dsp56k/bootstrap.bin fw-shipped-$(CONFIG_ATM_AMBASSADOR) += atmsar11.fw -fw-shipped-$(CONFIG_BNX2X) += bnx2x-e1-5.0.21.0.fw bnx2x-e1h-5.0.21.0.fw +fw-shipped-$(CONFIG_BNX2X) += bnx2x-e1-5.2.7.0.fw bnx2x-e1h-5.2.7.0.fw fw-shipped-$(CONFIG_BNX2) += bnx2/bnx2-mips-09-5.0.0.j3.fw \ bnx2/bnx2-rv2p-09-5.0.0.j3.fw \ bnx2/bnx2-rv2p-09ax-5.0.0.j3.fw \ diff --git a/firmware/WHENCE b/firmware/WHENCE index c437e14f0b11..a07aede9fcc3 100644 --- a/firmware/WHENCE +++ b/firmware/WHENCE @@ -674,8 +674,8 @@ Found in hex form in kernel source. Driver: bnx2x: Broadcom Everest -File: bnx2x-e1-4.8.53.0.fw.ihex -File: bnx2x-e1h-4.8.53.0.fw.ihex +File: bnx2x-e1-5.2.7.0.fw.ihex +File: bnx2x-e1h-5.2.7.0.fw.ihex License: Copyright (c) 2007-2009 Broadcom Corporation -- cgit v1.2.3-59-g8ed1b From f34d28ea0174df63253dc20a95de0b48e3d8145a Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Thu, 15 Oct 2009 00:18:08 -0700 Subject: bnx2x: Changing the Disabled state to a flag When working with DCC, a function can be disabled or enabled (virtual link down or up). Using the function state introduced some race conditions with the load/unload flow. Using a separate flag to indicate that the function is disabled. Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x.h | 2 +- drivers/net/bnx2x_main.c | 34 +++++++++++++++++++--------------- 2 files changed, 20 insertions(+), 16 deletions(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index 60fa14f31d73..185a6bab2227 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h @@ -900,6 +900,7 @@ struct bnx2x { #define BP_NOMCP(bp) (bp->flags & NO_MCP_FLAG) #define HW_VLAN_TX_FLAG 0x400 #define HW_VLAN_RX_FLAG 0x800 +#define MF_FUNC_DIS 0x1000 int func; #define BP_PORT(bp) (bp->func % PORT_MAX) @@ -965,7 +966,6 @@ struct bnx2x { #define BNX2X_STATE_CLOSING_WAIT4_HALT 0x4000 #define BNX2X_STATE_CLOSING_WAIT4_DELETE 0x5000 #define BNX2X_STATE_CLOSING_WAIT4_UNLOAD 0x6000 -#define BNX2X_STATE_DISABLED 0xd000 #define BNX2X_STATE_DIAG 0xe000 #define BNX2X_STATE_ERROR 0xf000 diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 691cf1541892..e7b3b27d16b6 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -1043,7 +1043,6 @@ static void bnx2x_sp_event(struct bnx2x_fastpath *fp, break; case (RAMROD_CMD_ID_ETH_SET_MAC | BNX2X_STATE_CLOSING_WAIT4_HALT): - case (RAMROD_CMD_ID_ETH_SET_MAC | BNX2X_STATE_DISABLED): DP(NETIF_MSG_IFDOWN, "got (un)set mac ramrod\n"); bp->set_mac_pending--; smp_wmb(); @@ -2157,7 +2156,7 @@ static void bnx2x_calc_fc_adv(struct bnx2x *bp) static void bnx2x_link_report(struct bnx2x *bp) { - if (bp->state == BNX2X_STATE_DISABLED) { + if (bp->flags & MF_FUNC_DIS) { netif_carrier_off(bp->dev); printk(KERN_ERR PFX "%s NIC Link is Down\n", bp->dev->name); return; @@ -2437,8 +2436,7 @@ static void bnx2x_link_attn(struct bnx2x *bp) memset(&(pstats->mac_stx[0]), 0, sizeof(struct mac_stx)); } - if ((bp->state == BNX2X_STATE_OPEN) || - (bp->state == BNX2X_STATE_DISABLED)) + if (bp->state == BNX2X_STATE_OPEN) bnx2x_stats_handle(bp, STATS_EVENT_LINK_UP); } @@ -2481,9 +2479,7 @@ static void bnx2x_link_attn(struct bnx2x *bp) static void bnx2x__link_status_update(struct bnx2x *bp) { - int func = BP_FUNC(bp); - - if (bp->state != BNX2X_STATE_OPEN) + if ((bp->state != BNX2X_STATE_OPEN) || (bp->flags & MF_FUNC_DIS)) return; bnx2x_link_status_update(&bp->link_params, &bp->link_vars); @@ -2640,14 +2636,19 @@ static void bnx2x_dcc_event(struct bnx2x *bp, u32 dcc_event) if (dcc_event & DRV_STATUS_DCC_DISABLE_ENABLE_PF) { + /* + * This is the only place besides the function initialization + * where the bp->flags can change so it is done without any + * locks + */ if (bp->mf_config & FUNC_MF_CFG_FUNC_DISABLED) { DP(NETIF_MSG_IFDOWN, "mf_cfg function disabled\n"); - bp->state = BNX2X_STATE_DISABLED; + bp->flags |= MF_FUNC_DIS; bnx2x_e1h_disable(bp); } else { DP(NETIF_MSG_IFUP, "mf_cfg function enabled\n"); - bp->state = BNX2X_STATE_OPEN; + bp->flags &= ~MF_FUNC_DIS; bnx2x_e1h_enable(bp); } @@ -4695,8 +4696,7 @@ static void bnx2x_timer(unsigned long data) } } - if ((bp->state == BNX2X_STATE_OPEN) || - (bp->state == BNX2X_STATE_DISABLED)) + if (bp->state == BNX2X_STATE_OPEN) bnx2x_stats_handle(bp, STATS_EVENT_UPDATE); timer_restart: @@ -7629,7 +7629,7 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) if (CHIP_IS_E1H(bp)) if (bp->mf_config & FUNC_MF_CFG_FUNC_DISABLED) { DP(NETIF_MSG_IFUP, "mf_cfg function disabled\n"); - bp->state = BNX2X_STATE_DISABLED; + bp->flags |= MF_FUNC_DIS; } if (bp->state == BNX2X_STATE_OPEN) { @@ -9034,7 +9034,9 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->supported = bp->port.supported; cmd->advertising = bp->port.advertising; - if (netif_carrier_ok(dev)) { + if ((bp->state == BNX2X_STATE_OPEN) && + !(bp->flags & MF_FUNC_DIS) && + (bp->link_vars.link_up)) { cmd->speed = bp->link_vars.line_speed; cmd->duplex = bp->link_vars.duplex; if (IS_E1HMF(bp)) { @@ -9433,6 +9435,9 @@ static u32 bnx2x_get_link(struct net_device *dev) { struct bnx2x *bp = netdev_priv(dev); + if (bp->flags & MF_FUNC_DIS) + return 0; + return bp->link_vars.link_up; } @@ -9837,8 +9842,7 @@ static int bnx2x_set_eeprom(struct net_device *dev, } else if (eeprom->magic == 0x50485952) { /* 'PHYR' (0x50485952): re-init link after FW upgrade */ - if ((bp->state == BNX2X_STATE_OPEN) || - (bp->state == BNX2X_STATE_DISABLED)) { + if (bp->state == BNX2X_STATE_OPEN) { bnx2x_acquire_phy_lock(bp); rc |= bnx2x_link_reset(&bp->link_params, &bp->link_vars, 1); -- cgit v1.2.3-59-g8ed1b From c4ff7cbf88be8bb0e3f942089f0ef0a40d98d654 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Thu, 15 Oct 2009 00:18:27 -0700 Subject: bnx2x: Adding FW mailbox mutex DCC commands are not protected with the RTNL lock, so a mutex should be added Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x.h | 3 +++ drivers/net/bnx2x_main.c | 7 +++++-- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index 185a6bab2227..c3b32f71e024 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h @@ -1023,6 +1023,9 @@ struct bnx2x { /* used to synchronize dmae accesses */ struct mutex dmae_mutex; + /* used to protect the FW mail box */ + struct mutex fw_mb_mutex; + /* used to synchronize stats collecting */ int stats_state; /* used by dmae command loader */ diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index e7b3b27d16b6..7c5c3000bbb4 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -2528,6 +2528,7 @@ u32 bnx2x_fw_command(struct bnx2x *bp, u32 command) u32 cnt = 1; u8 delay = CHIP_REV_IS_SLOW(bp) ? 100 : 10; + mutex_lock(&bp->fw_mb_mutex); SHMEM_WR(bp, func_mb[func].drv_mb_header, (command | seq)); DP(BNX2X_MSG_MCP, "wrote command (%x) to FW MB\n", (command | seq)); @@ -2537,8 +2538,8 @@ u32 bnx2x_fw_command(struct bnx2x *bp, u32 command) rc = SHMEM_RD(bp, func_mb[func].fw_mb_header); - /* Give the FW up to 2 second (200*10ms) */ - } while ((seq != (rc & FW_MSG_SEQ_NUMBER_MASK)) && (cnt++ < 200)); + /* Give the FW up to 5 second (500*10ms) */ + } while ((seq != (rc & FW_MSG_SEQ_NUMBER_MASK)) && (cnt++ < 500)); DP(BNX2X_MSG_MCP, "[after %d ms] read (%x) seq is (%x) from FW MB\n", cnt*delay, rc, seq); @@ -2552,6 +2553,7 @@ u32 bnx2x_fw_command(struct bnx2x *bp, u32 command) bnx2x_fw_dump(bp); rc = 0; } + mutex_unlock(&bp->fw_mb_mutex); return rc; } @@ -8956,6 +8958,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp) smp_wmb(); /* Ensure that bp->intr_sem update is SMP-safe */ mutex_init(&bp->port.phy_mutex); + mutex_init(&bp->fw_mb_mutex); #ifdef BCM_CNIC mutex_init(&bp->cnic_mutex); #endif -- cgit v1.2.3-59-g8ed1b From 061bc702f6912b6e45b9aaf1c9bf2f8122406d47 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Thu, 15 Oct 2009 00:18:47 -0700 Subject: bnx2x: Do not call load/unload functionality from DCC There is really no need to clear the MAC or the FW filtering rules - it was added for completion, but caused race conditions with load/unload. Removing this redundant code Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 7c5c3000bbb4..42cd957c668b 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -2565,21 +2565,12 @@ static void bnx2x_set_rx_mode(struct net_device *dev); static void bnx2x_e1h_disable(struct bnx2x *bp) { int port = BP_PORT(bp); - int i; - - bp->rx_mode = BNX2X_RX_MODE_NONE; - bnx2x_set_storm_rx_mode(bp); netif_tx_disable(bp->dev); bp->dev->trans_start = jiffies; /* prevent tx timeout */ REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0); - bnx2x_set_eth_mac_addr_e1h(bp, 0); - - for (i = 0; i < MC_HASH_SIZE; i++) - REG_WR(bp, MC_HASH_OFFSET(bp, i), 0); - netif_carrier_off(bp->dev); } @@ -2589,13 +2580,13 @@ static void bnx2x_e1h_enable(struct bnx2x *bp) REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 1); - bnx2x_set_eth_mac_addr_e1h(bp, 1); - /* Tx queue should be only reenabled */ netif_tx_wake_all_queues(bp->dev); - /* Initialize the receive filter. */ - bnx2x_set_rx_mode(bp->dev); + /* + * Should not call netif_carrier_on since it will be called if the link + * is up when checking for link state + */ } static void bnx2x_update_min_max(struct bnx2x *bp) @@ -10538,7 +10529,7 @@ static void bnx2x_self_test(struct net_device *dev, /* disable input for TX port IF */ REG_WR(bp, NIG_REG_EGRESS_UMP0_IN_EN + port*4, 0); - link_up = bp->link_vars.link_up; + link_up = (bnx2x_link_test(bp) == 0); bnx2x_nic_unload(bp, UNLOAD_NORMAL); bnx2x_nic_load(bp, LOAD_DIAG); /* wait until link state is restored */ -- cgit v1.2.3-59-g8ed1b From 35c5f8fef12a2e4b788aa45ff72206ce4ac8e4b4 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Thu, 15 Oct 2009 00:19:05 -0700 Subject: bnx2x: Report the maximal available BW as link speed The device is limited to the maximal BW allocation, so it should be displayed as the link speed to notify the user. Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 42cd957c668b..ba131f463198 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -2163,11 +2163,23 @@ static void bnx2x_link_report(struct bnx2x *bp) } if (bp->link_vars.link_up) { + u16 line_speed; + if (bp->state == BNX2X_STATE_OPEN) netif_carrier_on(bp->dev); printk(KERN_INFO PFX "%s NIC Link is Up, ", bp->dev->name); - printk("%d Mbps ", bp->link_vars.line_speed); + line_speed = bp->link_vars.line_speed; + if (IS_E1HMF(bp)) { + u16 vn_max_rate; + + vn_max_rate = + ((bp->mf_config & FUNC_MF_CFG_MAX_BW_MASK) >> + FUNC_MF_CFG_MAX_BW_SHIFT) * 100; + if (vn_max_rate < line_speed) + line_speed = vn_max_rate; + } + printk("%d Mbps ", line_speed); if (bp->link_vars.duplex == DUPLEX_FULL) printk("full duplex"); -- cgit v1.2.3-59-g8ed1b From b2d76447dfb8c695324c61c87f63e414f44fce5a Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Thu, 15 Oct 2009 00:19:31 -0700 Subject: bnx2x: Update to version 1.52.1-1 Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index ba131f463198..59b58d8f0fa8 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -56,8 +56,8 @@ #include "bnx2x_init_ops.h" #include "bnx2x_dump.h" -#define DRV_MODULE_VERSION "1.52.1" -#define DRV_MODULE_RELDATE "2009/08/12" +#define DRV_MODULE_VERSION "1.52.1-1" +#define DRV_MODULE_RELDATE "2009/10/13" #define BNX2X_BC_VER 0x040200 #include -- cgit v1.2.3-59-g8ed1b From 7846e471b5b5cac5e09c8e6ebeb67e18279db8e3 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Thu, 5 Nov 2009 19:18:07 +0200 Subject: bnx2x: Fix CL73 autoneg issues - Advertise 1G KX4 in CL73 when 1G speed capability is enabled - Add flow-control negotiation over CL73 - External loopback test on Serdes should be done in FORCE mode, since in CL73 it is unable to link up with the same core using AUTONEG - Fix bnx2x_set_led function to support CL73 link leds Signed-off-by: Yaniv Rosner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_link.c | 132 ++++++++++++++++++++++++++++++----------------- drivers/net/bnx2x_link.h | 3 +- drivers/net/bnx2x_main.c | 16 ++---- drivers/net/bnx2x_reg.h | 18 +++++-- 4 files changed, 104 insertions(+), 65 deletions(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c index b5964cb7e761..eabdd1155a5a 100644 --- a/drivers/net/bnx2x_link.c +++ b/drivers/net/bnx2x_link.c @@ -1228,7 +1228,7 @@ static void bnx2x_set_autoneg(struct link_params *params, params->phy_addr, MDIO_REG_BANK_CL73_USERB0, MDIO_CL73_USERB0_CL73_UCTRL, - MDIO_CL73_USERB0_CL73_UCTRL_USTAT1_MUXSEL); + 0xe); /* Enable BAM Station Manager*/ CL45_WR_OVER_CL22(bp, params->port, @@ -1239,29 +1239,25 @@ static void bnx2x_set_autoneg(struct link_params *params, MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_STATION_MNGR_EN | MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_NP_AFTER_BP_EN); - /* Merge CL73 and CL37 aneg resolution */ - CL45_RD_OVER_CL22(bp, params->port, - params->phy_addr, - MDIO_REG_BANK_CL73_USERB0, - MDIO_CL73_USERB0_CL73_BAM_CTRL3, - ®_val); - - if (params->speed_cap_mask & - PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) { - /* Set the CL73 AN speed */ + /* Advertise CL73 link speeds */ CL45_RD_OVER_CL22(bp, params->port, params->phy_addr, MDIO_REG_BANK_CL73_IEEEB1, MDIO_CL73_IEEEB1_AN_ADV2, ®_val); + if (params->speed_cap_mask & + PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) + reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4; + if (params->speed_cap_mask & + PORT_HW_CFG_SPEED_CAPABILITY_D0_1G) + reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX; CL45_WR_OVER_CL22(bp, params->port, params->phy_addr, MDIO_REG_BANK_CL73_IEEEB1, MDIO_CL73_IEEEB1_AN_ADV2, - reg_val | MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4); + reg_val); - } /* CL73 Autoneg Enabled */ reg_val = MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN; @@ -1389,12 +1385,23 @@ static void bnx2x_set_ieee_aneg_advertisment(struct link_params *params, u16 ieee_fc) { struct bnx2x *bp = params->bp; + u16 val; /* for AN, we are always publishing full duplex */ CL45_WR_OVER_CL22(bp, params->port, params->phy_addr, MDIO_REG_BANK_COMBO_IEEE0, MDIO_COMBO_IEEE0_AUTO_NEG_ADV, ieee_fc); + CL45_RD_OVER_CL22(bp, params->port, + params->phy_addr, + MDIO_REG_BANK_CL73_IEEEB1, + MDIO_CL73_IEEEB1_AN_ADV1, &val); + val &= ~MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_BOTH; + val |= ((ieee_fc<<3) & MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK); + CL45_WR_OVER_CL22(bp, params->port, + params->phy_addr, + MDIO_REG_BANK_CL73_IEEEB1, + MDIO_CL73_IEEEB1_AN_ADV1, val); } static void bnx2x_restart_autoneg(struct link_params *params, u8 enable_cl73) @@ -1630,21 +1637,49 @@ static void bnx2x_flow_ctrl_resolve(struct link_params *params, (!(vars->phy_flags & PHY_SGMII_FLAG)) && (XGXS_EXT_PHY_TYPE(params->ext_phy_config) == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)) { - CL45_RD_OVER_CL22(bp, params->port, - params->phy_addr, - MDIO_REG_BANK_COMBO_IEEE0, - MDIO_COMBO_IEEE0_AUTO_NEG_ADV, - &ld_pause); - CL45_RD_OVER_CL22(bp, params->port, - params->phy_addr, - MDIO_REG_BANK_COMBO_IEEE0, - MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1, - &lp_pause); - pause_result = (ld_pause & + if ((gp_status & + (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE | + MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) == + (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE | + MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) { + + CL45_RD_OVER_CL22(bp, params->port, + params->phy_addr, + MDIO_REG_BANK_CL73_IEEEB1, + MDIO_CL73_IEEEB1_AN_ADV1, + &ld_pause); + CL45_RD_OVER_CL22(bp, params->port, + params->phy_addr, + MDIO_REG_BANK_CL73_IEEEB1, + MDIO_CL73_IEEEB1_AN_LP_ADV1, + &lp_pause); + pause_result = (ld_pause & + MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK) + >> 8; + pause_result |= (lp_pause & + MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE_MASK) + >> 10; + DP(NETIF_MSG_LINK, "pause_result CL73 0x%x\n", + pause_result); + } else { + + CL45_RD_OVER_CL22(bp, params->port, + params->phy_addr, + MDIO_REG_BANK_COMBO_IEEE0, + MDIO_COMBO_IEEE0_AUTO_NEG_ADV, + &ld_pause); + CL45_RD_OVER_CL22(bp, params->port, + params->phy_addr, + MDIO_REG_BANK_COMBO_IEEE0, + MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1, + &lp_pause); + pause_result = (ld_pause & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>5; - pause_result |= (lp_pause & + pause_result |= (lp_pause & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>7; - DP(NETIF_MSG_LINK, "pause_result 0x%x\n", pause_result); + DP(NETIF_MSG_LINK, "pause_result CL37 0x%x\n", + pause_result); + } bnx2x_pause_resolve(vars, pause_result); } else if ((params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) && (bnx2x_ext_phy_resolve_fc(params, vars))) { @@ -1990,8 +2025,7 @@ static u8 bnx2x_emac_program(struct link_params *params, GRCBASE_EMAC0 + port*0x400 + EMAC_REG_EMAC_MODE, mode); - bnx2x_set_led(bp, params->port, LED_MODE_OPER, - line_speed, params->hw_led_mode, params->chip_id); + bnx2x_set_led(params, LED_MODE_OPER, line_speed); return 0; } @@ -3547,7 +3581,10 @@ static void bnx2x_init_internal_phy(struct link_params *params, bnx2x_set_preemphasis(params); /* forced speed requested? */ - if (vars->line_speed != SPEED_AUTO_NEG) { + if (vars->line_speed != SPEED_AUTO_NEG || + ((XGXS_EXT_PHY_TYPE(params->ext_phy_config) == + PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) && + params->loopback_mode == LOOPBACK_EXT)) { DP(NETIF_MSG_LINK, "not SGMII, no AN\n"); /* disable autoneg */ @@ -5731,13 +5768,15 @@ u8 bnx2x_override_led_value(struct bnx2x *bp, u8 port, } -u8 bnx2x_set_led(struct bnx2x *bp, u8 port, u8 mode, u32 speed, - u16 hw_led_mode, u32 chip_id) +u8 bnx2x_set_led(struct link_params *params, u8 mode, u32 speed) { + u8 port = params->port; + u16 hw_led_mode = params->hw_led_mode; u8 rc = 0; u32 tmp; u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0; - + u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config); + struct bnx2x *bp = params->bp; DP(NETIF_MSG_LINK, "bnx2x_set_led: port %x, mode %d\n", port, mode); DP(NETIF_MSG_LINK, "speed 0x%x, hw_led_mode 0x%x\n", speed, hw_led_mode); @@ -5752,7 +5791,14 @@ u8 bnx2x_set_led(struct bnx2x *bp, u8 port, u8 mode, u32 speed, break; case LED_MODE_OPER: - REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, hw_led_mode); + if (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) { + REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, 0); + REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 1); + } else { + REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, + hw_led_mode); + } + REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 + port*4, 0); /* Set blinking rate to ~15.9Hz */ @@ -5764,7 +5810,7 @@ u8 bnx2x_set_led(struct bnx2x *bp, u8 port, u8 mode, u32 speed, EMAC_WR(bp, EMAC_REG_EMAC_LED, (tmp & (~EMAC_LED_OVERRIDE))); - if (!CHIP_IS_E1H(bp) && + if (CHIP_IS_E1(bp) && ((speed == SPEED_2500) || (speed == SPEED_1000) || (speed == SPEED_100) || @@ -6033,10 +6079,7 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars) REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0); - bnx2x_set_led(bp, params->port, LED_MODE_OPER, - vars->line_speed, params->hw_led_mode, - params->chip_id); - + bnx2x_set_led(params, LED_MODE_OPER, vars->line_speed); } else /* No loopback */ { @@ -6094,8 +6137,6 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars, { struct bnx2x *bp = params->bp; u32 ext_phy_config = params->ext_phy_config; - u16 hw_led_mode = params->hw_led_mode; - u32 chip_id = params->chip_id; u8 port = params->port; u32 ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config); u32 val = REG_RD(bp, params->shmem_base + @@ -6130,7 +6171,7 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars, * Hold it as vars low */ /* clear link led */ - bnx2x_set_led(bp, port, LED_MODE_OFF, 0, hw_led_mode, chip_id); + bnx2x_set_led(params, LED_MODE_OFF, 0); if (reset_ext_phy) { switch (ext_phy_type) { case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT: @@ -6201,9 +6242,7 @@ static u8 bnx2x_update_link_down(struct link_params *params, u8 port = params->port; DP(NETIF_MSG_LINK, "Port %x: Link is down\n", port); - bnx2x_set_led(bp, port, LED_MODE_OFF, - 0, params->hw_led_mode, - params->chip_id); + bnx2x_set_led(params, LED_MODE_OFF, 0); /* indicate no mac active */ vars->mac_type = MAC_TYPE_NONE; @@ -6240,10 +6279,7 @@ static u8 bnx2x_update_link_up(struct link_params *params, vars->link_status |= LINK_STATUS_LINK_UP; if (link_10g) { bnx2x_bmac_enable(params, vars, 0); - bnx2x_set_led(bp, port, LED_MODE_OPER, - SPEED_10000, params->hw_led_mode, - params->chip_id); - + bnx2x_set_led(params, LED_MODE_OPER, SPEED_10000); } else { bnx2x_emac_enable(params, vars, 0); rc = bnx2x_emac_program(params, vars->line_speed, diff --git a/drivers/net/bnx2x_link.h b/drivers/net/bnx2x_link.h index f3e252264e1b..40c2981de8ed 100644 --- a/drivers/net/bnx2x_link.h +++ b/drivers/net/bnx2x_link.h @@ -178,8 +178,7 @@ u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded, Basically, the CLC takes care of the led for the link, but in case one needs to set/unset the led unnaturally, set the "mode" to LED_MODE_OPER to blink the led, and LED_MODE_OFF to set the led off.*/ -u8 bnx2x_set_led(struct bnx2x *bp, u8 port, u8 mode, u32 speed, - u16 hw_led_mode, u32 chip_id); +u8 bnx2x_set_led(struct link_params *params, u8 mode, u32 speed); #define LED_MODE_OFF 0 #define LED_MODE_OPER 2 diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 59b58d8f0fa8..6f16547a1b8a 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -10855,7 +10855,6 @@ static void bnx2x_get_ethtool_stats(struct net_device *dev, static int bnx2x_phys_id(struct net_device *dev, u32 data) { struct bnx2x *bp = netdev_priv(dev); - int port = BP_PORT(bp); int i; if (!netif_running(dev)) @@ -10869,13 +10868,10 @@ static int bnx2x_phys_id(struct net_device *dev, u32 data) for (i = 0; i < (data * 2); i++) { if ((i % 2) == 0) - bnx2x_set_led(bp, port, LED_MODE_OPER, SPEED_1000, - bp->link_params.hw_led_mode, - bp->link_params.chip_id); + bnx2x_set_led(&bp->link_params, LED_MODE_OPER, + SPEED_1000); else - bnx2x_set_led(bp, port, LED_MODE_OFF, 0, - bp->link_params.hw_led_mode, - bp->link_params.chip_id); + bnx2x_set_led(&bp->link_params, LED_MODE_OFF, 0); msleep_interruptible(500); if (signal_pending(current)) @@ -10883,10 +10879,8 @@ static int bnx2x_phys_id(struct net_device *dev, u32 data) } if (bp->link_vars.link_up) - bnx2x_set_led(bp, port, LED_MODE_OPER, - bp->link_vars.line_speed, - bp->link_params.hw_led_mode, - bp->link_params.chip_id); + bnx2x_set_led(&bp->link_params, LED_MODE_OPER, + bp->link_vars.line_speed); return 0; } diff --git a/drivers/net/bnx2x_reg.h b/drivers/net/bnx2x_reg.h index aa76cbada5e2..b80fde44c85d 100644 --- a/drivers/net/bnx2x_reg.h +++ b/drivers/net/bnx2x_reg.h @@ -4772,18 +4772,28 @@ #define PCI_ID_VAL2 0x438 -#define MDIO_REG_BANK_CL73_IEEEB0 0x0 -#define MDIO_CL73_IEEEB0_CL73_AN_CONTROL 0x0 +#define MDIO_REG_BANK_CL73_IEEEB0 0x0 +#define MDIO_CL73_IEEEB0_CL73_AN_CONTROL 0x0 #define MDIO_CL73_IEEEB0_CL73_AN_CONTROL_RESTART_AN 0x0200 #define MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN 0x1000 #define MDIO_CL73_IEEEB0_CL73_AN_CONTROL_MAIN_RST 0x8000 -#define MDIO_REG_BANK_CL73_IEEEB1 0x10 -#define MDIO_CL73_IEEEB1_AN_ADV2 0x01 +#define MDIO_REG_BANK_CL73_IEEEB1 0x10 +#define MDIO_CL73_IEEEB1_AN_ADV1 0x00 +#define MDIO_CL73_IEEEB1_AN_ADV1_PAUSE 0x0400 +#define MDIO_CL73_IEEEB1_AN_ADV1_ASYMMETRIC 0x0800 +#define MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_BOTH 0x0C00 +#define MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK 0x0C00 +#define MDIO_CL73_IEEEB1_AN_ADV2 0x01 #define MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M 0x0000 #define MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX 0x0020 #define MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4 0x0040 #define MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KR 0x0080 +#define MDIO_CL73_IEEEB1_AN_LP_ADV1 0x03 +#define MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE 0x0400 +#define MDIO_CL73_IEEEB1_AN_LP_ADV1_ASYMMETRIC 0x0800 +#define MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE_BOTH 0x0C00 +#define MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE_MASK 0x0C00 #define MDIO_REG_BANK_RX0 0x80b0 #define MDIO_RX0_RX_STATUS 0x10 -- cgit v1.2.3-59-g8ed1b From 89794a6f3bf6db552b1ff4d2ad42fdd8739ac2a2 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Thu, 5 Nov 2009 20:00:59 -0800 Subject: bnx2x: version 1.52.1-3 Signed-off-by: Yaniv Rosner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 6f16547a1b8a..61974b74909a 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -56,8 +56,8 @@ #include "bnx2x_init_ops.h" #include "bnx2x_dump.h" -#define DRV_MODULE_VERSION "1.52.1-1" -#define DRV_MODULE_RELDATE "2009/10/13" +#define DRV_MODULE_VERSION "1.52.1-3" +#define DRV_MODULE_RELDATE "2009/11/05" #define BNX2X_BC_VER 0x040200 #include -- cgit v1.2.3-59-g8ed1b From 45229b420f90bb6736dfeb7e491eb46cb02a3e9c Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 7 Nov 2009 11:53:39 +0000 Subject: bnx2x: declare MODULE_FIRMWARE Replace run-time string formatting with preprocessor string manipulation. Signed-off-by: Ben Hutchings Acked-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 61974b74909a..5b6c68abccd9 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -49,6 +49,7 @@ #include #include #include +#include #include "bnx2x.h" @@ -63,8 +64,13 @@ #include #include "bnx2x_fw_file_hdr.h" /* FW files */ -#define FW_FILE_PREFIX_E1 "bnx2x-e1-" -#define FW_FILE_PREFIX_E1H "bnx2x-e1h-" +#define FW_FILE_VERSION \ + __stringify(BCM_5710_FW_MAJOR_VERSION) "." \ + __stringify(BCM_5710_FW_MINOR_VERSION) "." \ + __stringify(BCM_5710_FW_REVISION_VERSION) "." \ + __stringify(BCM_5710_FW_ENGINEERING_VERSION) +#define FW_FILE_NAME_E1 "bnx2x-e1-" FW_FILE_VERSION ".fw" +#define FW_FILE_NAME_E1H "bnx2x-e1h-" FW_FILE_VERSION ".fw" /* Time in jiffies before concluding the transmitter is hung */ #define TX_TIMEOUT (5*HZ) @@ -77,6 +83,8 @@ MODULE_AUTHOR("Eliezer Tamir"); MODULE_DESCRIPTION("Broadcom NetXtreme II BCM57710/57711/57711E Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_MODULE_VERSION); +MODULE_FIRMWARE(FW_FILE_NAME_E1); +MODULE_FIRMWARE(FW_FILE_NAME_E1H); static int multi_mode = 1; module_param(multi_mode, int, 0); @@ -12111,21 +12119,14 @@ static inline void be16_to_cpu_n(const u8 *_source, u8 *_target, u32 n) static int __devinit bnx2x_init_firmware(struct bnx2x *bp, struct device *dev) { - char fw_file_name[40] = {0}; + const char *fw_file_name; struct bnx2x_fw_file_hdr *fw_hdr; - int rc, offset; + int rc; - /* Create a FW file name */ if (CHIP_IS_E1(bp)) - offset = sprintf(fw_file_name, FW_FILE_PREFIX_E1); + fw_file_name = FW_FILE_NAME_E1; else - offset = sprintf(fw_file_name, FW_FILE_PREFIX_E1H); - - sprintf(fw_file_name + offset, "%d.%d.%d.%d.fw", - BCM_5710_FW_MAJOR_VERSION, - BCM_5710_FW_MINOR_VERSION, - BCM_5710_FW_REVISION_VERSION, - BCM_5710_FW_ENGINEERING_VERSION); + fw_file_name = FW_FILE_NAME_E1H; printk(KERN_INFO PFX "Loading %s\n", fw_file_name); -- cgit v1.2.3-59-g8ed1b From d6a2f98b0128ad1225f959610ba21b6679b7cd96 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Mon, 9 Nov 2009 06:09:22 +0000 Subject: bnx2x: GSO implies CSUM offload Making sure that whenever the FW/HW is configured for GSO, it is also configured to CSUM offload Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 5b6c68abccd9..47d67e6aabcf 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -11129,10 +11129,10 @@ static inline u32 bnx2x_xmit_type(struct bnx2x *bp, struct sk_buff *skb) } if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) - rc |= XMIT_GSO_V4; + rc |= (XMIT_GSO_V4 | XMIT_CSUM_V4 | XMIT_CSUM_TCP); else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) - rc |= XMIT_GSO_V6; + rc |= (XMIT_GSO_V6 | XMIT_CSUM_TCP | XMIT_CSUM_V6); return rc; } -- cgit v1.2.3-59-g8ed1b From 91545f6e588c601d1dff01d396155d973db83a31 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Mon, 9 Nov 2009 06:09:28 +0000 Subject: bnx2x: Remove misleading error print Failing to allocate MSI-X vectors is not an error and should not be printed as such Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 47d67e6aabcf..ed56973794e8 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -7486,11 +7486,6 @@ static int bnx2x_set_int_mode(struct bnx2x *bp) rc = bnx2x_enable_msix(bp); if (rc) { /* failed to enable MSI-X */ - if (bp->multi_mode) - BNX2X_ERR("Multi requested but failed to " - "enable MSI-X (rx %d tx %d), " - "set number of queues to 1\n", - bp->num_rx_queues, bp->num_tx_queues); bp->num_rx_queues = 1; bp->num_tx_queues = 1; } -- cgit v1.2.3-59-g8ed1b From 7d323bfdc056a9142b8bdbab88e4d3ac6e4989e4 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Mon, 9 Nov 2009 06:09:35 +0000 Subject: bnx2x: Change coalescing granularity to 4us Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x.h | 2 +- drivers/net/bnx2x_main.c | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index c3b32f71e024..928942b74ce6 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h @@ -1191,7 +1191,7 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms, #define MAX_SP_DESC_CNT (SP_DESC_CNT - 1) -#define BNX2X_BTR 3 +#define BNX2X_BTR 1 #define MAX_SPQ_PENDING 8 diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index ed56973794e8..08e6a35cfc20 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -4928,21 +4928,21 @@ static void bnx2x_update_coalesce(struct bnx2x *bp) REG_WR8(bp, BAR_CSTRORM_INTMEM + CSTORM_SB_HC_TIMEOUT_U_OFFSET(port, sb_id, U_SB_ETH_RX_CQ_INDEX), - bp->rx_ticks/12); + bp->rx_ticks/(4 * BNX2X_BTR)); REG_WR16(bp, BAR_CSTRORM_INTMEM + CSTORM_SB_HC_DISABLE_U_OFFSET(port, sb_id, U_SB_ETH_RX_CQ_INDEX), - (bp->rx_ticks/12) ? 0 : 1); + (bp->rx_ticks/(4 * BNX2X_BTR)) ? 0 : 1); /* HC_INDEX_C_ETH_TX_CQ_CONS */ REG_WR8(bp, BAR_CSTRORM_INTMEM + CSTORM_SB_HC_TIMEOUT_C_OFFSET(port, sb_id, C_SB_ETH_TX_CQ_INDEX), - bp->tx_ticks/12); + bp->tx_ticks/(4 * BNX2X_BTR)); REG_WR16(bp, BAR_CSTRORM_INTMEM + CSTORM_SB_HC_DISABLE_C_OFFSET(port, sb_id, C_SB_ETH_TX_CQ_INDEX), - (bp->tx_ticks/12) ? 0 : 1); + (bp->tx_ticks/(4 * BNX2X_BTR)) ? 0 : 1); } } @@ -9016,8 +9016,9 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp) bp->rx_csum = 1; - bp->tx_ticks = 50; - bp->rx_ticks = 25; + /* make sure that the numbers are in the right granularity */ + bp->tx_ticks = (50 / (4 * BNX2X_BTR)) * (4 * BNX2X_BTR); + bp->rx_ticks = (25 / (4 * BNX2X_BTR)) * (4 * BNX2X_BTR); timer_interval = (CHIP_REV_IS_SLOW(bp) ? 5*HZ : HZ); bp->current_interval = (poll ? poll : timer_interval); -- cgit v1.2.3-59-g8ed1b From 0ab365f463b9c5c8b76476a1808dfde1c38f6f19 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Mon, 9 Nov 2009 06:09:37 +0000 Subject: bnx2x: version 1.52.1-4 Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 08e6a35cfc20..e2cf686d1118 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -57,8 +57,8 @@ #include "bnx2x_init_ops.h" #include "bnx2x_dump.h" -#define DRV_MODULE_VERSION "1.52.1-3" -#define DRV_MODULE_RELDATE "2009/11/05" +#define DRV_MODULE_VERSION "1.52.1-4" +#define DRV_MODULE_RELDATE "2009/11/09" #define BNX2X_BC_VER 0x040200 #include -- cgit v1.2.3-59-g8ed1b From 54b9ddaa68414fad72ab2e1042be067c902441a6 Mon Sep 17 00:00:00 2001 From: Vladislav Zolotarov Date: Mon, 16 Nov 2009 06:05:58 +0000 Subject: bnx2x: Handle Rx and Tx together in NAPI Put Tx and Rx DPC to be handled in the NAPI: - Saves status blocks. - Moves the Tx work from hardIRQ to NAPI. Signed-off-by: Vladislav Zolotarov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x.h | 21 +-- drivers/net/bnx2x_main.c | 367 +++++++++++++++++++---------------------------- 2 files changed, 157 insertions(+), 231 deletions(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index 928942b74ce6..602ab86b6392 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h @@ -259,9 +259,6 @@ struct bnx2x_eth_q_stats { struct bnx2x_fastpath { struct napi_struct napi; - - u8 is_rx_queue; - struct host_status_block *status_blk; dma_addr_t status_blk_mapping; @@ -970,8 +967,7 @@ struct bnx2x { #define BNX2X_STATE_ERROR 0xf000 int multi_mode; - int num_rx_queues; - int num_tx_queues; + int num_queues; u32 rx_mode; #define BNX2X_RX_MODE_NONE 0 @@ -1074,20 +1070,15 @@ struct bnx2x { }; -#define BNX2X_MAX_QUEUES(bp) (IS_E1HMF(bp) ? (MAX_CONTEXT/(2 * E1HVN_MAX)) \ - : (MAX_CONTEXT/2)) -#define BNX2X_NUM_QUEUES(bp) (bp->num_rx_queues + bp->num_tx_queues) -#define is_multi(bp) (BNX2X_NUM_QUEUES(bp) > 2) +#define BNX2X_MAX_QUEUES(bp) (IS_E1HMF(bp) ? (MAX_CONTEXT/E1HVN_MAX) \ + : MAX_CONTEXT) +#define BNX2X_NUM_QUEUES(bp) (bp->num_queues) +#define is_multi(bp) (BNX2X_NUM_QUEUES(bp) > 1) -#define for_each_rx_queue(bp, var) \ - for (var = 0; var < bp->num_rx_queues; var++) -#define for_each_tx_queue(bp, var) \ - for (var = bp->num_rx_queues; \ - var < BNX2X_NUM_QUEUES(bp); var++) #define for_each_queue(bp, var) \ for (var = 0; var < BNX2X_NUM_QUEUES(bp); var++) #define for_each_nondefault_queue(bp, var) \ - for (var = 1; var < bp->num_rx_queues; var++) + for (var = 1; var < BNX2X_NUM_QUEUES(bp); var++) void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32); diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index e2cf686d1118..bdecd42d2b29 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -57,7 +57,7 @@ #include "bnx2x_init_ops.h" #include "bnx2x_dump.h" -#define DRV_MODULE_VERSION "1.52.1-4" +#define DRV_MODULE_VERSION "1.52.1-5" #define DRV_MODULE_RELDATE "2009/11/09" #define BNX2X_BC_VER 0x040200 @@ -91,15 +91,10 @@ module_param(multi_mode, int, 0); MODULE_PARM_DESC(multi_mode, " Multi queue mode " "(0 Disable; 1 Enable (default))"); -static int num_rx_queues; -module_param(num_rx_queues, int, 0); -MODULE_PARM_DESC(num_rx_queues, " Number of Rx queues for multi_mode=1" - " (default is half number of CPUs)"); - -static int num_tx_queues; -module_param(num_tx_queues, int, 0); -MODULE_PARM_DESC(num_tx_queues, " Number of Tx queues for multi_mode=1" - " (default is half number of CPUs)"); +static int num_queues; +module_param(num_queues, int, 0); +MODULE_PARM_DESC(num_queues, " Number of queues for multi_mode=1" + " (default is as a number of CPUs)"); static int disable_tpa; module_param(disable_tpa, int, 0); @@ -558,7 +553,7 @@ static void bnx2x_panic_dump(struct bnx2x *bp) bp->def_att_idx, bp->attn_state, bp->spq_prod_idx); /* Rx */ - for_each_rx_queue(bp, i) { + for_each_queue(bp, i) { struct bnx2x_fastpath *fp = &bp->fp[i]; BNX2X_ERR("fp%d: rx_bd_prod(%x) rx_bd_cons(%x)" @@ -575,7 +570,7 @@ static void bnx2x_panic_dump(struct bnx2x *bp) } /* Tx */ - for_each_tx_queue(bp, i) { + for_each_queue(bp, i) { struct bnx2x_fastpath *fp = &bp->fp[i]; BNX2X_ERR("fp%d: tx_pkt_prod(%x) tx_pkt_cons(%x)" @@ -590,7 +585,7 @@ static void bnx2x_panic_dump(struct bnx2x *bp) /* Rings */ /* Rx */ - for_each_rx_queue(bp, i) { + for_each_queue(bp, i) { struct bnx2x_fastpath *fp = &bp->fp[i]; start = RX_BD(le16_to_cpu(*fp->rx_cons_sb) - 10); @@ -624,7 +619,7 @@ static void bnx2x_panic_dump(struct bnx2x *bp) } /* Tx */ - for_each_tx_queue(bp, i) { + for_each_queue(bp, i) { struct bnx2x_fastpath *fp = &bp->fp[i]; start = TX_BD(le16_to_cpu(*fp->tx_cons_sb) - 10); @@ -792,21 +787,13 @@ static inline void bnx2x_ack_sb(struct bnx2x *bp, u8 sb_id, barrier(); } -static inline u16 bnx2x_update_fpsb_idx(struct bnx2x_fastpath *fp) +static inline void bnx2x_update_fpsb_idx(struct bnx2x_fastpath *fp) { struct host_status_block *fpsb = fp->status_blk; - u16 rc = 0; barrier(); /* status block is written to by the chip */ - if (fp->fp_c_idx != fpsb->c_status_block.status_block_index) { - fp->fp_c_idx = fpsb->c_status_block.status_block_index; - rc |= 1; - } - if (fp->fp_u_idx != fpsb->u_status_block.status_block_index) { - fp->fp_u_idx = fpsb->u_status_block.status_block_index; - rc |= 2; - } - return rc; + fp->fp_c_idx = fpsb->c_status_block.status_block_index; + fp->fp_u_idx = fpsb->u_status_block.status_block_index; } static u16 bnx2x_ack_int(struct bnx2x *bp) @@ -846,6 +833,9 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fastpath *fp, u16 bd_idx = TX_BD(tx_buf->first_bd), new_cons; int nbd; + /* prefetch skb end pointer to speedup dev_kfree_skb() */ + prefetch(&skb->end); + DP(BNX2X_MSG_OFF, "pkt_idx %d buff @(%p)->skb %p\n", idx, tx_buf, skb); @@ -890,7 +880,7 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fastpath *fp, /* release skb */ WARN_ON(!skb); - dev_kfree_skb_any(skb); + dev_kfree_skb(skb); tx_buf->first_bd = 0; tx_buf->skb = NULL; @@ -920,19 +910,28 @@ static inline u16 bnx2x_tx_avail(struct bnx2x_fastpath *fp) return (s16)(fp->bp->tx_ring_size) - used; } -static void bnx2x_tx_int(struct bnx2x_fastpath *fp) +static inline int bnx2x_has_tx_work(struct bnx2x_fastpath *fp) +{ + u16 hw_cons; + + /* Tell compiler that status block fields can change */ + barrier(); + hw_cons = le16_to_cpu(*fp->tx_cons_sb); + return hw_cons != fp->tx_pkt_cons; +} + +static int bnx2x_tx_int(struct bnx2x_fastpath *fp) { struct bnx2x *bp = fp->bp; struct netdev_queue *txq; u16 hw_cons, sw_cons, bd_cons = fp->tx_bd_cons; - int done = 0; #ifdef BNX2X_STOP_ON_ERROR if (unlikely(bp->panic)) - return; + return -1; #endif - txq = netdev_get_tx_queue(bp->dev, fp->index - bp->num_rx_queues); + txq = netdev_get_tx_queue(bp->dev, fp->index); hw_cons = le16_to_cpu(*fp->tx_cons_sb); sw_cons = fp->tx_pkt_cons; @@ -953,7 +952,6 @@ static void bnx2x_tx_int(struct bnx2x_fastpath *fp) */ bd_cons = bnx2x_free_tx_pkt(bp, fp, pkt_cons); sw_cons++; - done++; } fp->tx_pkt_cons = sw_cons; @@ -975,6 +973,7 @@ static void bnx2x_tx_int(struct bnx2x_fastpath *fp) (bnx2x_tx_avail(fp) >= MAX_SKB_FRAGS + 3)) netif_tx_wake_queue(txq); } + return 0; } #ifdef BCM_CNIC @@ -1561,6 +1560,8 @@ static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) } else { rx_buf = &fp->rx_buf_ring[bd_cons]; skb = rx_buf->skb; + prefetch(skb); + prefetch((u8 *)skb + 256); len = le16_to_cpu(cqe->fast_path_cqe.pkt_len); pad = cqe->fast_path_cqe.placement_offset; @@ -1742,27 +1743,13 @@ static irqreturn_t bnx2x_msix_fp_int(int irq, void *fp_cookie) if (unlikely(bp->panic)) return IRQ_HANDLED; #endif - /* Handle Rx or Tx according to MSI-X vector */ - if (fp->is_rx_queue) { - prefetch(fp->rx_cons_sb); - prefetch(&fp->status_blk->u_status_block.status_block_index); - - napi_schedule(&bnx2x_fp(bp, fp->index, napi)); - - } else { - prefetch(fp->tx_cons_sb); - prefetch(&fp->status_blk->c_status_block.status_block_index); - - bnx2x_update_fpsb_idx(fp); - rmb(); - bnx2x_tx_int(fp); - /* Re-enable interrupts */ - bnx2x_ack_sb(bp, fp->sb_id, USTORM_ID, - le16_to_cpu(fp->fp_u_idx), IGU_INT_NOP, 1); - bnx2x_ack_sb(bp, fp->sb_id, CSTORM_ID, - le16_to_cpu(fp->fp_c_idx), IGU_INT_ENABLE, 1); - } + /* Handle Rx and Tx according to MSI-X vector */ + prefetch(fp->rx_cons_sb); + prefetch(fp->tx_cons_sb); + prefetch(&fp->status_blk->u_status_block.status_block_index); + prefetch(&fp->status_blk->c_status_block.status_block_index); + napi_schedule(&bnx2x_fp(bp, fp->index, napi)); return IRQ_HANDLED; } @@ -1797,31 +1784,14 @@ static irqreturn_t bnx2x_interrupt(int irq, void *dev_instance) mask = 0x2 << fp->sb_id; if (status & mask) { - /* Handle Rx or Tx according to SB id */ - if (fp->is_rx_queue) { - prefetch(fp->rx_cons_sb); - prefetch(&fp->status_blk->u_status_block. - status_block_index); - - napi_schedule(&bnx2x_fp(bp, fp->index, napi)); - - } else { - prefetch(fp->tx_cons_sb); - prefetch(&fp->status_blk->c_status_block. - status_block_index); - - bnx2x_update_fpsb_idx(fp); - rmb(); - bnx2x_tx_int(fp); - - /* Re-enable interrupts */ - bnx2x_ack_sb(bp, fp->sb_id, USTORM_ID, - le16_to_cpu(fp->fp_u_idx), - IGU_INT_NOP, 1); - bnx2x_ack_sb(bp, fp->sb_id, CSTORM_ID, - le16_to_cpu(fp->fp_c_idx), - IGU_INT_ENABLE, 1); - } + /* Handle Rx and Tx according to SB id */ + prefetch(fp->rx_cons_sb); + prefetch(&fp->status_blk->u_status_block. + status_block_index); + prefetch(fp->tx_cons_sb); + prefetch(&fp->status_blk->c_status_block. + status_block_index); + napi_schedule(&bnx2x_fp(bp, fp->index, napi)); status &= ~mask; } } @@ -4027,7 +3997,7 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp) estats->no_buff_discard_hi = 0; estats->no_buff_discard_lo = 0; - for_each_rx_queue(bp, i) { + for_each_queue(bp, i) { struct bnx2x_fastpath *fp = &bp->fp[i]; int cl_id = fp->cl_id; struct tstorm_per_client_stats *tclient = @@ -4244,7 +4214,7 @@ static void bnx2x_net_stats_update(struct bnx2x *bp) nstats->tx_bytes = bnx2x_hilo(&estats->total_bytes_transmitted_hi); nstats->rx_dropped = estats->mac_discard; - for_each_rx_queue(bp, i) + for_each_queue(bp, i) nstats->rx_dropped += le32_to_cpu(bp->fp[i].old_tclient.checksum_discard); @@ -4298,7 +4268,7 @@ static void bnx2x_drv_stats_update(struct bnx2x *bp) estats->rx_err_discard_pkt = 0; estats->rx_skb_alloc_failed = 0; estats->hw_csum_err = 0; - for_each_rx_queue(bp, i) { + for_each_queue(bp, i) { struct bnx2x_eth_q_stats *qstats = &bp->fp[i].eth_q_stats; estats->driver_xoff += qstats->driver_xoff; @@ -4329,7 +4299,7 @@ static void bnx2x_stats_update(struct bnx2x *bp) if (bp->msglevel & NETIF_MSG_TIMER) { struct bnx2x_fastpath *fp0_rx = bp->fp; - struct bnx2x_fastpath *fp0_tx = &(bp->fp[bp->num_rx_queues]); + struct bnx2x_fastpath *fp0_tx = bp->fp; struct tstorm_per_client_stats *old_tclient = &bp->fp->old_tclient; struct bnx2x_eth_q_stats *qstats = &bp->fp->eth_q_stats; @@ -4984,7 +4954,7 @@ static void bnx2x_init_rx_rings(struct bnx2x *bp) if (bp->flags & TPA_ENABLE_FLAG) { - for_each_rx_queue(bp, j) { + for_each_queue(bp, j) { struct bnx2x_fastpath *fp = &bp->fp[j]; for (i = 0; i < max_agg_queues; i++) { @@ -5007,16 +4977,13 @@ static void bnx2x_init_rx_rings(struct bnx2x *bp) } } - for_each_rx_queue(bp, j) { + for_each_queue(bp, j) { struct bnx2x_fastpath *fp = &bp->fp[j]; fp->rx_bd_cons = 0; fp->rx_cons_sb = BNX2X_RX_SB_INDEX; fp->rx_bd_cons_sb = BNX2X_RX_SB_BD_INDEX; - /* Mark queue as Rx */ - fp->is_rx_queue = 1; - /* "next page" elements initialization */ /* SGE ring */ for (i = 1; i <= NUM_RX_SGE_PAGES; i++) { @@ -5122,7 +5089,7 @@ static void bnx2x_init_tx_ring(struct bnx2x *bp) { int i, j; - for_each_tx_queue(bp, j) { + for_each_queue(bp, j) { struct bnx2x_fastpath *fp = &bp->fp[j]; for (i = 1; i <= NUM_TX_RINGS; i++) { @@ -5148,10 +5115,6 @@ static void bnx2x_init_tx_ring(struct bnx2x *bp) fp->tx_cons_sb = BNX2X_TX_SB_INDEX; fp->tx_pkt = 0; } - - /* clean tx statistics */ - for_each_rx_queue(bp, i) - bnx2x_fp(bp, i, tx_pkt) = 0; } static void bnx2x_init_sp_ring(struct bnx2x *bp) @@ -5180,7 +5143,8 @@ static void bnx2x_init_context(struct bnx2x *bp) { int i; - for_each_rx_queue(bp, i) { + /* Rx */ + for_each_queue(bp, i) { struct eth_context *context = bnx2x_sp(bp, context[i].eth); struct bnx2x_fastpath *fp = &bp->fp[i]; u8 cl_id = fp->cl_id; @@ -5232,10 +5196,11 @@ static void bnx2x_init_context(struct bnx2x *bp) ETH_CONNECTION_TYPE); } - for_each_tx_queue(bp, i) { + /* Tx */ + for_each_queue(bp, i) { struct bnx2x_fastpath *fp = &bp->fp[i]; struct eth_context *context = - bnx2x_sp(bp, context[i - bp->num_rx_queues].eth); + bnx2x_sp(bp, context[i].eth); context->cstorm_st_context.sb_index_number = C_SB_ETH_TX_CQ_INDEX; @@ -5263,7 +5228,7 @@ static void bnx2x_init_ind_table(struct bnx2x *bp) for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++) REG_WR8(bp, BAR_TSTRORM_INTMEM + TSTORM_INDIRECTION_TABLE_OFFSET(func) + i, - bp->fp->cl_id + (i % bp->num_rx_queues)); + bp->fp->cl_id + (i % bp->num_queues)); } static void bnx2x_set_client_config(struct bnx2x *bp) @@ -5507,7 +5472,7 @@ static void bnx2x_init_internal_func(struct bnx2x *bp) min((u32)(min((u32)8, (u32)MAX_SKB_FRAGS) * SGE_PAGE_SIZE * PAGES_PER_SGE), (u32)0xffff); - for_each_rx_queue(bp, i) { + for_each_queue(bp, i) { struct bnx2x_fastpath *fp = &bp->fp[i]; REG_WR(bp, BAR_USTRORM_INTMEM + @@ -5542,7 +5507,7 @@ static void bnx2x_init_internal_func(struct bnx2x *bp) rx_pause.cqe_thr_high = 350; rx_pause.sge_thr_high = 0; - for_each_rx_queue(bp, i) { + for_each_queue(bp, i) { struct bnx2x_fastpath *fp = &bp->fp[i]; if (!fp->disable_tpa) { @@ -5637,9 +5602,6 @@ static void bnx2x_nic_init(struct bnx2x *bp, u32 load_code) #else fp->sb_id = fp->cl_id; #endif - /* Suitable Rx and Tx SBs are served by the same client */ - if (i >= bp->num_rx_queues) - fp->cl_id -= bp->num_rx_queues; DP(NETIF_MSG_IFUP, "queue[%d]: bnx2x_init_sb(%p,%p) cl_id %d sb %d\n", i, bp, fp->status_blk, fp->cl_id, fp->sb_id); @@ -6749,7 +6711,7 @@ static void bnx2x_free_mem(struct bnx2x *bp) sizeof(struct host_status_block)); } /* Rx */ - for_each_rx_queue(bp, i) { + for_each_queue(bp, i) { /* fastpath rx rings: rx_buf rx_desc rx_comp */ BNX2X_FREE(bnx2x_fp(bp, i, rx_buf_ring)); @@ -6769,7 +6731,7 @@ static void bnx2x_free_mem(struct bnx2x *bp) BCM_PAGE_SIZE * NUM_RX_SGE_PAGES); } /* Tx */ - for_each_tx_queue(bp, i) { + for_each_queue(bp, i) { /* fastpath tx rings: tx_buf tx_desc */ BNX2X_FREE(bnx2x_fp(bp, i, tx_buf_ring)); @@ -6831,7 +6793,7 @@ static int bnx2x_alloc_mem(struct bnx2x *bp) sizeof(struct host_status_block)); } /* Rx */ - for_each_rx_queue(bp, i) { + for_each_queue(bp, i) { /* fastpath rx rings: rx_buf rx_desc rx_comp */ BNX2X_ALLOC(bnx2x_fp(bp, i, rx_buf_ring), @@ -6853,7 +6815,7 @@ static int bnx2x_alloc_mem(struct bnx2x *bp) BCM_PAGE_SIZE * NUM_RX_SGE_PAGES); } /* Tx */ - for_each_tx_queue(bp, i) { + for_each_queue(bp, i) { /* fastpath tx rings: tx_buf tx_desc */ BNX2X_ALLOC(bnx2x_fp(bp, i, tx_buf_ring), @@ -6909,7 +6871,7 @@ static void bnx2x_free_tx_skbs(struct bnx2x *bp) { int i; - for_each_tx_queue(bp, i) { + for_each_queue(bp, i) { struct bnx2x_fastpath *fp = &bp->fp[i]; u16 bd_cons = fp->tx_bd_cons; @@ -6927,7 +6889,7 @@ static void bnx2x_free_rx_skbs(struct bnx2x *bp) { int i, j; - for_each_rx_queue(bp, j) { + for_each_queue(bp, j) { struct bnx2x_fastpath *fp = &bp->fp[j]; for (i = 0; i < NUM_RX_BD; i++) { @@ -7042,12 +7004,8 @@ static int bnx2x_req_msix_irqs(struct bnx2x *bp) #endif for_each_queue(bp, i) { struct bnx2x_fastpath *fp = &bp->fp[i]; - - if (i < bp->num_rx_queues) - sprintf(fp->name, "%s-rx-%d", bp->dev->name, i); - else - sprintf(fp->name, "%s-tx-%d", - bp->dev->name, i - bp->num_rx_queues); + snprintf(fp->name, sizeof(fp->name), "%s-fp-%d", + bp->dev->name, i); rc = request_irq(bp->msix_table[i + offset].vector, bnx2x_msix_fp_int, 0, fp->name, fp); @@ -7106,7 +7064,7 @@ static void bnx2x_napi_enable(struct bnx2x *bp) { int i; - for_each_rx_queue(bp, i) + for_each_queue(bp, i) napi_enable(&bnx2x_fp(bp, i, napi)); } @@ -7114,7 +7072,7 @@ static void bnx2x_napi_disable(struct bnx2x *bp) { int i; - for_each_rx_queue(bp, i) + for_each_queue(bp, i) napi_disable(&bnx2x_fp(bp, i, napi)); } @@ -7410,88 +7368,60 @@ static int bnx2x_setup_multi(struct bnx2x *bp, int index) static int bnx2x_poll(struct napi_struct *napi, int budget); -static void bnx2x_set_int_mode_msix(struct bnx2x *bp, int *num_rx_queues_out, - int *num_tx_queues_out) +static void bnx2x_set_num_queues_msix(struct bnx2x *bp) { - int _num_rx_queues = 0, _num_tx_queues = 0; switch (bp->multi_mode) { case ETH_RSS_MODE_DISABLED: - _num_rx_queues = 1; - _num_tx_queues = 1; + bp->num_queues = 1; break; case ETH_RSS_MODE_REGULAR: - if (num_rx_queues) - _num_rx_queues = min_t(u32, num_rx_queues, - BNX2X_MAX_QUEUES(bp)); - else - _num_rx_queues = min_t(u32, num_online_cpus(), - BNX2X_MAX_QUEUES(bp)); - - if (num_tx_queues) - _num_tx_queues = min_t(u32, num_tx_queues, - BNX2X_MAX_QUEUES(bp)); + if (num_queues) + bp->num_queues = min_t(u32, num_queues, + BNX2X_MAX_QUEUES(bp)); else - _num_tx_queues = min_t(u32, num_online_cpus(), - BNX2X_MAX_QUEUES(bp)); - - /* There must be not more Tx queues than Rx queues */ - if (_num_tx_queues > _num_rx_queues) { - BNX2X_ERR("number of tx queues (%d) > " - "number of rx queues (%d)" - " defaulting to %d\n", - _num_tx_queues, _num_rx_queues, - _num_rx_queues); - _num_tx_queues = _num_rx_queues; - } + bp->num_queues = min_t(u32, num_online_cpus(), + BNX2X_MAX_QUEUES(bp)); break; default: - _num_rx_queues = 1; - _num_tx_queues = 1; + bp->num_queues = 1; break; } - - *num_rx_queues_out = _num_rx_queues; - *num_tx_queues_out = _num_tx_queues; } -static int bnx2x_set_int_mode(struct bnx2x *bp) +static int bnx2x_set_num_queues(struct bnx2x *bp) { int rc = 0; switch (int_mode) { case INT_MODE_INTx: case INT_MODE_MSI: - bp->num_rx_queues = 1; - bp->num_tx_queues = 1; + bp->num_queues = 1; DP(NETIF_MSG_IFUP, "set number of queues to 1\n"); break; case INT_MODE_MSIX: default: - /* Set interrupt mode according to bp->multi_mode value */ - bnx2x_set_int_mode_msix(bp, &bp->num_rx_queues, - &bp->num_tx_queues); + /* Set number of queues according to bp->multi_mode value */ + bnx2x_set_num_queues_msix(bp); - DP(NETIF_MSG_IFUP, "set number of queues to: rx %d tx %d\n", - bp->num_rx_queues, bp->num_tx_queues); + DP(NETIF_MSG_IFUP, "set number of queues to %d\n", + bp->num_queues); /* if we can't use MSI-X we only need one fp, * so try to enable MSI-X with the requested number of fp's * and fallback to MSI or legacy INTx with one fp */ rc = bnx2x_enable_msix(bp); - if (rc) { + if (rc) /* failed to enable MSI-X */ - bp->num_rx_queues = 1; - bp->num_tx_queues = 1; - } + bp->num_queues = 1; break; } - bp->dev->real_num_tx_queues = bp->num_tx_queues; + bp->dev->real_num_tx_queues = bp->num_queues; return rc; } @@ -7513,16 +7443,16 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) bp->state = BNX2X_STATE_OPENING_WAIT4_LOAD; - rc = bnx2x_set_int_mode(bp); + rc = bnx2x_set_num_queues(bp); if (bnx2x_alloc_mem(bp)) return -ENOMEM; - for_each_rx_queue(bp, i) + for_each_queue(bp, i) bnx2x_fp(bp, i, disable_tpa) = ((bp->flags & TPA_ENABLE_FLAG) == 0); - for_each_rx_queue(bp, i) + for_each_queue(bp, i) netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi), bnx2x_poll, 128); @@ -7536,7 +7466,7 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) } } else { /* Fall to INTx if failed to enable MSI-X due to lack of - memory (in bnx2x_set_int_mode()) */ + memory (in bnx2x_set_num_queues()) */ if ((rc != -ENOMEM) && (int_mode != INT_MODE_INTx)) bnx2x_enable_msi(bp); bnx2x_ack_int(bp); @@ -7730,14 +7660,14 @@ load_error3: bp->port.pmf = 0; /* Free SKBs, SGEs, TPA pool and driver internals */ bnx2x_free_skbs(bp); - for_each_rx_queue(bp, i) + for_each_queue(bp, i) bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE); load_error2: /* Release IRQs */ bnx2x_free_irq(bp); load_error1: bnx2x_napi_disable(bp); - for_each_rx_queue(bp, i) + for_each_queue(bp, i) netif_napi_del(&bnx2x_fp(bp, i, napi)); bnx2x_free_mem(bp); @@ -7928,7 +7858,7 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) bnx2x_free_irq(bp); /* Wait until tx fastpath tasks complete */ - for_each_tx_queue(bp, i) { + for_each_queue(bp, i) { struct bnx2x_fastpath *fp = &bp->fp[i]; cnt = 1000; @@ -8071,9 +8001,9 @@ unload_error: /* Free SKBs, SGEs, TPA pool and driver internals */ bnx2x_free_skbs(bp); - for_each_rx_queue(bp, i) + for_each_queue(bp, i) bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE); - for_each_rx_queue(bp, i) + for_each_queue(bp, i) netif_napi_del(&bnx2x_fp(bp, i, napi)); bnx2x_free_mem(bp); @@ -10269,7 +10199,7 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up) struct sk_buff *skb; unsigned char *packet; struct bnx2x_fastpath *fp_rx = &bp->fp[0]; - struct bnx2x_fastpath *fp_tx = &bp->fp[bp->num_rx_queues]; + struct bnx2x_fastpath *fp_tx = &bp->fp[0]; u16 tx_start_idx, tx_idx; u16 rx_start_idx, rx_idx; u16 pkt_prod, bd_prod; @@ -10346,7 +10276,7 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up) fp_tx->tx_db.data.prod += 2; barrier(); - DOORBELL(bp, fp_tx->index - bp->num_rx_queues, fp_tx->tx_db.raw); + DOORBELL(bp, fp_tx->index, fp_tx->tx_db.raw); mmiowb(); @@ -10725,7 +10655,7 @@ static int bnx2x_get_sset_count(struct net_device *dev, int stringset) switch(stringset) { case ETH_SS_STATS: if (is_multi(bp)) { - num_stats = BNX2X_NUM_Q_STATS * bp->num_rx_queues; + num_stats = BNX2X_NUM_Q_STATS * bp->num_queues; if (!IS_E1HMF_MODE_STAT(bp)) num_stats += BNX2X_NUM_STATS; } else { @@ -10756,7 +10686,7 @@ static void bnx2x_get_strings(struct net_device *dev, u32 stringset, u8 *buf) case ETH_SS_STATS: if (is_multi(bp)) { k = 0; - for_each_rx_queue(bp, i) { + for_each_queue(bp, i) { for (j = 0; j < BNX2X_NUM_Q_STATS; j++) sprintf(buf + (k + j)*ETH_GSTRING_LEN, bnx2x_q_stats_arr[j].string, i); @@ -10793,7 +10723,7 @@ static void bnx2x_get_ethtool_stats(struct net_device *dev, if (is_multi(bp)) { k = 0; - for_each_rx_queue(bp, i) { + for_each_queue(bp, i) { hw_stats = (u32 *)&bp->fp[i].eth_q_stats; for (j = 0; j < BNX2X_NUM_Q_STATS; j++) { if (bnx2x_q_stats_arr[j].size == 0) { @@ -10989,54 +10919,60 @@ static inline int bnx2x_has_rx_work(struct bnx2x_fastpath *fp) static int bnx2x_poll(struct napi_struct *napi, int budget) { + int work_done = 0; struct bnx2x_fastpath *fp = container_of(napi, struct bnx2x_fastpath, napi); struct bnx2x *bp = fp->bp; - int work_done = 0; + while (1) { #ifdef BNX2X_STOP_ON_ERROR - if (unlikely(bp->panic)) - goto poll_panic; + if (unlikely(bp->panic)) { + napi_complete(napi); + return 0; + } #endif - prefetch(fp->rx_buf_ring[RX_BD(fp->rx_bd_cons)].skb); - prefetch((char *)(fp->rx_buf_ring[RX_BD(fp->rx_bd_cons)].skb) + 256); - - bnx2x_update_fpsb_idx(fp); - - if (bnx2x_has_rx_work(fp)) { - work_done = bnx2x_rx_int(fp, budget); + if (bnx2x_has_tx_work(fp)) + bnx2x_tx_int(fp); - /* must not complete if we consumed full budget */ - if (work_done >= budget) - goto poll_again; - } + if (bnx2x_has_rx_work(fp)) { + work_done += bnx2x_rx_int(fp, budget - work_done); - /* bnx2x_has_rx_work() reads the status block, thus we need to - * ensure that status block indices have been actually read - * (bnx2x_update_fpsb_idx) prior to this check (bnx2x_has_rx_work) - * so that we won't write the "newer" value of the status block to IGU - * (if there was a DMA right after bnx2x_has_rx_work and - * if there is no rmb, the memory reading (bnx2x_update_fpsb_idx) - * may be postponed to right before bnx2x_ack_sb). In this case - * there will never be another interrupt until there is another update - * of the status block, while there is still unhandled work. - */ - rmb(); + /* must not complete if we consumed full budget */ + if (work_done >= budget) + break; + } - if (!bnx2x_has_rx_work(fp)) { -#ifdef BNX2X_STOP_ON_ERROR -poll_panic: -#endif - napi_complete(napi); + /* Fall out from the NAPI loop if needed */ + if (!(bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) { + bnx2x_update_fpsb_idx(fp); + /* bnx2x_has_rx_work() reads the status block, thus we need + * to ensure that status block indices have been actually read + * (bnx2x_update_fpsb_idx) prior to this check + * (bnx2x_has_rx_work) so that we won't write the "newer" + * value of the status block to IGU (if there was a DMA right + * after bnx2x_has_rx_work and if there is no rmb, the memory + * reading (bnx2x_update_fpsb_idx) may be postponed to right + * before bnx2x_ack_sb). In this case there will never be + * another interrupt until there is another update of the + * status block, while there is still unhandled work. + */ + rmb(); - bnx2x_ack_sb(bp, fp->sb_id, USTORM_ID, - le16_to_cpu(fp->fp_u_idx), IGU_INT_NOP, 1); - bnx2x_ack_sb(bp, fp->sb_id, CSTORM_ID, - le16_to_cpu(fp->fp_c_idx), IGU_INT_ENABLE, 1); + if (!(bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) { + napi_complete(napi); + /* Re-enable interrupts */ + bnx2x_ack_sb(bp, fp->sb_id, CSTORM_ID, + le16_to_cpu(fp->fp_c_idx), + IGU_INT_NOP, 1); + bnx2x_ack_sb(bp, fp->sb_id, USTORM_ID, + le16_to_cpu(fp->fp_u_idx), + IGU_INT_ENABLE, 1); + break; + } + } } -poll_again: return work_done; } @@ -11221,7 +11157,7 @@ exit_lbl: static netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct bnx2x *bp = netdev_priv(dev); - struct bnx2x_fastpath *fp, *fp_stat; + struct bnx2x_fastpath *fp; struct netdev_queue *txq; struct sw_tx_bd *tx_buf; struct eth_tx_start_bd *tx_start_bd; @@ -11243,11 +11179,10 @@ static netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) fp_index = skb_get_queue_mapping(skb); txq = netdev_get_tx_queue(dev, fp_index); - fp = &bp->fp[fp_index + bp->num_rx_queues]; - fp_stat = &bp->fp[fp_index]; + fp = &bp->fp[fp_index]; if (unlikely(bnx2x_tx_avail(fp) < (skb_shinfo(skb)->nr_frags + 3))) { - fp_stat->eth_q_stats.driver_xoff++; + fp->eth_q_stats.driver_xoff++; netif_tx_stop_queue(txq); BNX2X_ERR("BUG! Tx ring full when queue awake!\n"); return NETDEV_TX_BUSY; @@ -11473,7 +11408,7 @@ static netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) fp->tx_db.data.prod += nbd; barrier(); - DOORBELL(bp, fp->index - bp->num_rx_queues, fp->tx_db.raw); + DOORBELL(bp, fp->index, fp->tx_db.raw); mmiowb(); @@ -11484,11 +11419,11 @@ static netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) /* We want bnx2x_tx_int to "see" the updated tx_bd_prod if we put Tx into XOFF state. */ smp_mb(); - fp_stat->eth_q_stats.driver_xoff++; + fp->eth_q_stats.driver_xoff++; if (bnx2x_tx_avail(fp) >= MAX_SKB_FRAGS + 3) netif_tx_wake_queue(txq); } - fp_stat->tx_pkt++; + fp->tx_pkt++; return NETDEV_TX_OK; } @@ -12376,9 +12311,9 @@ static int bnx2x_eeh_nic_unload(struct bnx2x *bp) /* Free SKBs, SGEs, TPA pool and driver internals */ bnx2x_free_skbs(bp); - for_each_rx_queue(bp, i) + for_each_queue(bp, i) bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE); - for_each_rx_queue(bp, i) + for_each_queue(bp, i) netif_napi_del(&bnx2x_fp(bp, i, napi)); bnx2x_free_mem(bp); -- cgit v1.2.3-59-g8ed1b From 9a4e328eb2bfa23b160558cff96e17ffa65ea5cf Mon Sep 17 00:00:00 2001 From: Vladislav Zolotarov Date: Tue, 17 Nov 2009 06:16:35 +0000 Subject: bnx2x: Don't set netdev->trans_start Setting dev->trans_start caused spurious watchdog warnings. Signed-off-by: Vladislav Zolotarov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index bdecd42d2b29..77ba13520d87 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -2557,7 +2557,6 @@ static void bnx2x_e1h_disable(struct bnx2x *bp) int port = BP_PORT(bp); netif_tx_disable(bp->dev); - bp->dev->trans_start = jiffies; /* prevent tx timeout */ REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0); @@ -7098,7 +7097,6 @@ static void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw) bnx2x_int_disable_sync(bp, disable_hw); bnx2x_napi_disable(bp); netif_tx_disable(bp->dev); - bp->dev->trans_start = jiffies; /* prevent tx timeout */ } /* @@ -10282,7 +10280,6 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up) num_pkts++; fp_tx->tx_bd_prod += 2; /* start + pbd */ - bp->dev->trans_start = jiffies; udelay(100); -- cgit v1.2.3-59-g8ed1b