From owner-svn-src-all@freebsd.org Thu Dec 3 13:29:23 2015 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 09EBAA3F05C; Thu, 3 Dec 2015 13:29:23 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id BCC301141; Thu, 3 Dec 2015 13:29:22 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id tB3DTLjw005171; Thu, 3 Dec 2015 13:29:21 GMT (envelope-from hselasky@FreeBSD.org) Received: (from hselasky@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id tB3DTLa6005160; Thu, 3 Dec 2015 13:29:21 GMT (envelope-from hselasky@FreeBSD.org) Message-Id: <201512031329.tB3DTLa6005160@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: hselasky set sender to hselasky@FreeBSD.org using -f From: Hans Petter Selasky Date: Thu, 3 Dec 2015 13:29:21 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r291694 - in head/sys/ofed: drivers/net/mlx4 include/linux/mlx4 X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 03 Dec 2015 13:29:23 -0000 Author: hselasky Date: Thu Dec 3 13:29:20 2015 New Revision: 291694 URL: https://svnweb.freebsd.org/changeset/base/291694 Log: Updated the mlx4 and mlxen drivers to the latest version, v2.1.6: - Added support for dumping the SFP EEPROM content to dmesg. - Fixed handling of network interface capability IOCTLs. - Fixed race when loading and unloading the mlxen driver by applying appropriate locking. - Removed two unused C-files. MFC after: 1 week Submitted by: Mark Bloch Sponsored by: Mellanox Technologies Differential Revision: https://reviews.freebsd.org/D4283 Deleted: head/sys/ofed/drivers/net/mlx4/en_ethtool.c head/sys/ofed/drivers/net/mlx4/en_selftest.c Modified: head/sys/ofed/drivers/net/mlx4/en_main.c head/sys/ofed/drivers/net/mlx4/en_netdev.c head/sys/ofed/drivers/net/mlx4/en_port.c head/sys/ofed/drivers/net/mlx4/en_rx.c head/sys/ofed/drivers/net/mlx4/en_tx.c head/sys/ofed/drivers/net/mlx4/main.c head/sys/ofed/drivers/net/mlx4/mlx4.h head/sys/ofed/drivers/net/mlx4/mlx4_en.h head/sys/ofed/drivers/net/mlx4/mlx4_stats.h head/sys/ofed/drivers/net/mlx4/port.c head/sys/ofed/include/linux/mlx4/cq.h head/sys/ofed/include/linux/mlx4/device.h head/sys/ofed/include/linux/mlx4/qp.h Modified: head/sys/ofed/drivers/net/mlx4/en_main.c ============================================================================== --- head/sys/ofed/drivers/net/mlx4/en_main.c Thu Dec 3 12:51:54 2015 (r291693) +++ head/sys/ofed/drivers/net/mlx4/en_main.c Thu Dec 3 13:29:20 2015 (r291694) @@ -42,16 +42,7 @@ #include "mlx4_en.h" -MODULE_AUTHOR("Liran Liss, Yevgeny Petrilin"); -MODULE_DESCRIPTION("Mellanox ConnectX HCA Ethernet driver"); -MODULE_LICENSE("Dual BSD/GPL"); -#ifdef __linux__ -MODULE_VERSION(DRV_VERSION " ("DRV_RELDATE")"); -#endif - -static const char mlx4_en_version[] = - DRV_NAME ": Mellanox ConnectX HCA Ethernet driver v" - DRV_VERSION " (" DRV_RELDATE ")\n"; +/* Mellanox ConnectX HCA Ethernet driver */ #define MLX4_EN_PARM_INT(X, def_val, desc) \ static unsigned int X = def_val;\ @@ -176,8 +167,6 @@ static void *mlx4_en_add(struct mlx4_dev int i; int err; - printk_once(KERN_INFO "%s", mlx4_en_version); - mdev = kzalloc(sizeof *mdev, GFP_KERNEL); if (!mdev) { dev_err(&dev->pdev->dev, "Device struct alloc failed, " Modified: head/sys/ofed/drivers/net/mlx4/en_netdev.c ============================================================================== --- head/sys/ofed/drivers/net/mlx4/en_netdev.c Thu Dec 3 12:51:54 2015 (r291693) +++ head/sys/ofed/drivers/net/mlx4/en_netdev.c Thu Dec 3 13:29:20 2015 (r291694) @@ -658,8 +658,10 @@ static void mlx4_en_cache_mclist(struct continue; /* Make sure the list didn't grow. */ tmp = kzalloc(sizeof(struct mlx4_en_mc_list), GFP_ATOMIC); - if (tmp == NULL) + if (tmp == NULL) { + en_err(priv, "Failed to allocate multicast list\n"); break; + } memcpy(tmp->addr, LLADDR((struct sockaddr_dl *)ifma->ifma_addr), ETH_ALEN); list_add_tail(&tmp->list, &priv->mc_list); @@ -970,12 +972,12 @@ static void mlx4_en_do_set_rx_mode(struc if (!mlx4_en_QUERY_PORT(mdev, priv->port)) { if (priv->port_state.link_state) { priv->last_link_state = MLX4_DEV_EVENT_PORT_UP; - /* Important note: the following call for if_link_state_change - * is needed for interface up scenario (start port, link state - * change) */ /* update netif baudrate */ priv->dev->if_baudrate = IF_Mbps(priv->port_state.link_speed); + /* Important note: the following call for if_link_state_change + * is needed for interface up scenario (start port, link state + * change) */ if_link_state_change(priv->dev, LINK_STATE_UP); en_dbg(HW, priv, "Link Up\n"); } @@ -1195,8 +1197,8 @@ static void mlx4_en_linkstate(struct wor /* update netif baudrate */ priv->dev->if_baudrate = 0; - /* make sure the port is up before notifying the OS. - * This is tricky since we get here on INIT_PORT and + /* make sure the port is up before notifying the OS. + * This is tricky since we get here on INIT_PORT and * in such case we can't tell the OS the port is up. * To solve this there is a call to if_link_state_change * in set_rx_mode. @@ -1574,6 +1576,7 @@ static void mlx4_en_clear_stats(struct n priv->tx_ring[i]->bytes = 0; priv->tx_ring[i]->packets = 0; priv->tx_ring[i]->tx_csum = 0; + priv->tx_ring[i]->oversized_packets = 0; } for (i = 0; i < priv->rx_ring_num; i++) { priv->rx_ring[i]->bytes = 0; @@ -1643,8 +1646,6 @@ void mlx4_en_free_resources(struct mlx4_ if (priv->sysctl) sysctl_ctx_free(&priv->stat_ctx); - - } int mlx4_en_alloc_resources(struct mlx4_en_priv *priv) @@ -1729,8 +1730,11 @@ void mlx4_en_destroy_netdev(struct net_d EVENTHANDLER_DEREGISTER(vlan_unconfig, priv->vlan_detach); /* Unregister device - this will close the port if it was up */ - if (priv->registered) + if (priv->registered) { + mutex_lock(&mdev->state_lock); ether_ifdetach(dev); + mutex_unlock(&mdev->state_lock); + } if (priv->allocated) mlx4_free_hwq_res(mdev->dev, &priv->res, MLX4_EN_PAGE_SIZE); @@ -1808,13 +1812,6 @@ static int mlx4_en_calc_media(struct mlx active = IFM_ETHER; if (priv->last_link_state == MLX4_DEV_EVENT_PORT_DOWN) return (active); - /* - * [ShaharK] mlx4_en_QUERY_PORT sleeps and cannot be called under a - * non-sleepable lock. - * I moved it to the periodic mlx4_en_do_get_stats. - if (mlx4_en_QUERY_PORT(priv->mdev, priv->port)) - return (active); - */ active |= IFM_FDX; trans_type = priv->port_state.transciver; /* XXX I don't know all of the transceiver values. */ @@ -1947,12 +1944,55 @@ static int mlx4_en_ioctl(struct ifnet *d case SIOCSIFCAP: mutex_lock(&mdev->state_lock); mask = ifr->ifr_reqcap ^ dev->if_capenable; - if (mask & IFCAP_HWCSUM) - dev->if_capenable ^= IFCAP_HWCSUM; - if (mask & IFCAP_TSO4) + if (mask & IFCAP_TXCSUM) { + dev->if_capenable ^= IFCAP_TXCSUM; + dev->if_hwassist ^= (CSUM_TCP | CSUM_UDP | CSUM_IP); + + if (IFCAP_TSO4 & dev->if_capenable && + !(IFCAP_TXCSUM & dev->if_capenable)) { + dev->if_capenable &= ~IFCAP_TSO4; + dev->if_hwassist &= ~CSUM_IP_TSO; + if_printf(dev, + "tso4 disabled due to -txcsum.\n"); + } + } + if (mask & IFCAP_TXCSUM_IPV6) { + dev->if_capenable ^= IFCAP_TXCSUM_IPV6; + dev->if_hwassist ^= (CSUM_UDP_IPV6 | CSUM_TCP_IPV6); + + if (IFCAP_TSO6 & dev->if_capenable && + !(IFCAP_TXCSUM_IPV6 & dev->if_capenable)) { + dev->if_capenable &= ~IFCAP_TSO6; + dev->if_hwassist &= ~CSUM_IP6_TSO; + if_printf(dev, + "tso6 disabled due to -txcsum6.\n"); + } + } + if (mask & IFCAP_RXCSUM) + dev->if_capenable ^= IFCAP_RXCSUM; + if (mask & IFCAP_RXCSUM_IPV6) + dev->if_capenable ^= IFCAP_RXCSUM_IPV6; + + if (mask & IFCAP_TSO4) { + if (!(IFCAP_TSO4 & dev->if_capenable) && + !(IFCAP_TXCSUM & dev->if_capenable)) { + if_printf(dev, "enable txcsum first.\n"); + error = EAGAIN; + goto out; + } dev->if_capenable ^= IFCAP_TSO4; - if (mask & IFCAP_TSO6) + dev->if_hwassist ^= CSUM_IP_TSO; + } + if (mask & IFCAP_TSO6) { + if (!(IFCAP_TSO6 & dev->if_capenable) && + !(IFCAP_TXCSUM_IPV6 & dev->if_capenable)) { + if_printf(dev, "enable txcsum6 first.\n"); + error = EAGAIN; + goto out; + } dev->if_capenable ^= IFCAP_TSO6; + dev->if_hwassist ^= CSUM_IP6_TSO; + } if (mask & IFCAP_LRO) dev->if_capenable ^= IFCAP_LRO; if (mask & IFCAP_VLAN_HWTAGGING) @@ -1963,9 +2003,11 @@ static int mlx4_en_ioctl(struct ifnet *d dev->if_capenable ^= IFCAP_WOL_MAGIC; if (dev->if_drv_flags & IFF_DRV_RUNNING) mlx4_en_start_port(dev); +out: mutex_unlock(&mdev->state_lock); VLAN_CAPABILITIES(dev); break; +#if __FreeBSD_version >= 1100036 case SIOCGI2C: { struct ifi2creq i2c; @@ -1989,6 +2031,7 @@ static int mlx4_en_ioctl(struct ifnet *d error = copyout(&i2c, ifr->ifr_data, sizeof(i2c)); break; } +#endif default: error = ether_ioctl(dev, command, data); break; @@ -2088,7 +2131,6 @@ int mlx4_en_init_netdev(struct mlx4_en_d for (i = 0; i < MLX4_EN_MAC_HASH_SIZE; ++i) INIT_HLIST_HEAD(&priv->mac_hash[i]); - /* Query for default mac and max mtu */ priv->max_mtu = mdev->dev->caps.eth_mtu_cap[priv->port]; priv->mac = mdev->dev->caps.def_mac[priv->port]; @@ -2104,8 +2146,6 @@ int mlx4_en_init_netdev(struct mlx4_en_d goto out; } - - priv->stride = roundup_pow_of_two(sizeof(struct mlx4_en_rx_desc) + DS_SIZE); @@ -2127,7 +2167,7 @@ int mlx4_en_init_netdev(struct mlx4_en_d /* * Set driver features */ - dev->if_capabilities |= IFCAP_RXCSUM | IFCAP_TXCSUM; + dev->if_capabilities |= IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6; dev->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING; dev->if_capabilities |= IFCAP_VLAN_HWCSUM | IFCAP_VLAN_HWFILTER; dev->if_capabilities |= IFCAP_LINKSTATE | IFCAP_JUMBO_MTU; @@ -2136,10 +2176,12 @@ int mlx4_en_init_netdev(struct mlx4_en_d if (mdev->LSO_support) dev->if_capabilities |= IFCAP_TSO4 | IFCAP_TSO6 | IFCAP_VLAN_HWTSO; +#if __FreeBSD_version >= 1100000 /* set TSO limits so that we don't have to drop TX packets */ - dev->if_hw_tsomax = 65536 - (ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN); - dev->if_hw_tsomaxsegcount = 16; - dev->if_hw_tsomaxsegsize = 65536; /* XXX can do up to 4GByte */ + dev->if_hw_tsomax = MLX4_EN_TX_MAX_PAYLOAD_SIZE - (ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN) /* hdr */; + dev->if_hw_tsomaxsegcount = MLX4_EN_TX_MAX_MBUF_FRAGS - 1 /* hdr */; + dev->if_hw_tsomaxsegsize = MLX4_EN_TX_MAX_MBUF_SIZE; +#endif dev->if_capenable = dev->if_capabilities; @@ -2148,6 +2190,8 @@ int mlx4_en_init_netdev(struct mlx4_en_d dev->if_hwassist |= CSUM_TSO; if (dev->if_capenable & IFCAP_TXCSUM) dev->if_hwassist |= (CSUM_TCP | CSUM_UDP | CSUM_IP); + if (dev->if_capenable & IFCAP_TXCSUM_IPV6) + dev->if_hwassist |= (CSUM_UDP_IPV6 | CSUM_TCP_IPV6); /* Register for VLAN events */ @@ -2210,8 +2254,6 @@ int mlx4_en_init_netdev(struct mlx4_en_d if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS) queue_delayed_work(mdev->workqueue, &priv->service_task, SERVICE_TASK_DELAY); - - return 0; out: @@ -2293,6 +2335,162 @@ static int mlx4_en_set_tx_ring_size(SYSC return (error); } +static int mlx4_en_get_module_info(struct net_device *dev, + struct ethtool_modinfo *modinfo) +{ + struct mlx4_en_priv *priv = netdev_priv(dev); + struct mlx4_en_dev *mdev = priv->mdev; + int ret; + u8 data[4]; + + /* Read first 2 bytes to get Module & REV ID */ + ret = mlx4_get_module_info(mdev->dev, priv->port, + 0/*offset*/, 2/*size*/, data); + + if (ret < 2) { + en_err(priv, "Failed to read eeprom module first two bytes, error: 0x%x\n", -ret); + return -EIO; + } + + switch (data[0] /* identifier */) { + case MLX4_MODULE_ID_QSFP: + modinfo->type = ETH_MODULE_SFF_8436; + modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN; + break; + case MLX4_MODULE_ID_QSFP_PLUS: + if (data[1] >= 0x3) { /* revision id */ + modinfo->type = ETH_MODULE_SFF_8636; + modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN; + } else { + modinfo->type = ETH_MODULE_SFF_8436; + modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN; + } + break; + case MLX4_MODULE_ID_QSFP28: + modinfo->type = ETH_MODULE_SFF_8636; + modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN; + break; + case MLX4_MODULE_ID_SFP: + modinfo->type = ETH_MODULE_SFF_8472; + modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; + break; + default: + en_err(priv, "mlx4_en_get_module_info : Not recognized cable type\n"); + return -EINVAL; + } + + return 0; +} + +static int mlx4_en_get_module_eeprom(struct net_device *dev, + struct ethtool_eeprom *ee, + u8 *data) +{ + struct mlx4_en_priv *priv = netdev_priv(dev); + struct mlx4_en_dev *mdev = priv->mdev; + int offset = ee->offset; + int i = 0, ret; + + if (ee->len == 0) + return -EINVAL; + + memset(data, 0, ee->len); + + while (i < ee->len) { + en_dbg(DRV, priv, + "mlx4_get_module_info i(%d) offset(%d) len(%d)\n", + i, offset, ee->len - i); + + ret = mlx4_get_module_info(mdev->dev, priv->port, + offset, ee->len - i, data + i); + + if (!ret) /* Done reading */ + return 0; + + if (ret < 0) { + en_err(priv, + "mlx4_get_module_info i(%d) offset(%d) bytes_to_read(%d) - FAILED (0x%x)\n", + i, offset, ee->len - i, ret); + return -1; + } + + i += ret; + offset += ret; + } + return 0; +} + +static void mlx4_en_print_eeprom(u8 *data, __u32 len) +{ + int i; + int j = 0; + int row = 0; + const int NUM_OF_BYTES = 16; + + printf("\nOffset\t\tValues\n"); + printf("------\t\t------\n"); + while(row < len){ + printf("0x%04x\t\t",row); + for(i=0; i < NUM_OF_BYTES; i++){ + printf("%02x ", data[j]); + row++; + j++; + } + printf("\n"); + } +} + +/* Read cable EEPROM module information by first inspecting the first + * two bytes to get the length and then read the rest of the information. + * The information is printed to dmesg. */ +static int mlx4_en_read_eeprom(SYSCTL_HANDLER_ARGS) +{ + + u8* data; + int error; + int result = 0; + struct mlx4_en_priv *priv; + struct net_device *dev; + struct ethtool_modinfo modinfo; + struct ethtool_eeprom ee; + + error = sysctl_handle_int(oidp, &result, 0, req); + if (error || !req->newptr) + return (error); + + if (result == 1) { + priv = arg1; + dev = priv->dev; + data = kmalloc(PAGE_SIZE, GFP_KERNEL); + + error = mlx4_en_get_module_info(dev, &modinfo); + if (error) { + en_err(priv, + "mlx4_en_get_module_info returned with error - FAILED (0x%x)\n", + -error); + goto out; + } + + ee.len = modinfo.eeprom_len; + ee.offset = 0; + + error = mlx4_en_get_module_eeprom(dev, &ee, data); + if (error) { + en_err(priv, + "mlx4_en_get_module_eeprom returned with error - FAILED (0x%x)\n", + -error); + /* Continue printing partial information in case of an error */ + } + + /* EEPROM information will be printed in dmesg */ + mlx4_en_print_eeprom(data, ee.len); +out: + kfree(data); + } + /* Return zero to prevent sysctl failure. */ + return (0); +} + static int mlx4_en_set_tx_ppp(SYSCTL_HANDLER_ARGS) { struct mlx4_en_priv *priv; @@ -2418,7 +2616,7 @@ static void mlx4_en_sysctl_conf(struct m /* Add coalescer configuration. */ coal = SYSCTL_ADD_NODE(ctx, node_list, OID_AUTO, "coalesce", CTLFLAG_RD, NULL, "Interrupt coalesce configuration"); - coal_list = SYSCTL_CHILDREN(node); + coal_list = SYSCTL_CHILDREN(coal); SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "pkt_rate_low", CTLFLAG_RW, &priv->pkt_rate_low, 0, "Packets per-second for minimum delay"); @@ -2437,11 +2635,14 @@ static void mlx4_en_sysctl_conf(struct m SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "adaptive_rx_coal", CTLFLAG_RW, &priv->adaptive_rx_coal, 0, "Enable adaptive rx coalescing"); + /* EEPROM support */ + SYSCTL_ADD_PROC(ctx, node_list, OID_AUTO, "eeprom_info", + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0, + mlx4_en_read_eeprom, "I", "EEPROM information"); } static void mlx4_en_sysctl_stat(struct mlx4_en_priv *priv) { - struct net_device *dev; struct sysctl_ctx_list *ctx; struct sysctl_oid *node; struct sysctl_oid_list *node_list; @@ -2452,8 +2653,6 @@ static void mlx4_en_sysctl_stat(struct m char namebuf[128]; int i; - dev = priv->dev; - ctx = &priv->stat_ctx; sysctl_ctx_init(ctx); node = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(priv->sysctl), OID_AUTO, @@ -2481,6 +2680,8 @@ static void mlx4_en_sysctl_stat(struct m &priv->port_stats.wake_queue, "Queue resumed after full"); SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_timeout", CTLFLAG_RD, &priv->port_stats.tx_timeout, "Transmit timeouts"); + SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_oversized_packets", CTLFLAG_RD, + &priv->port_stats.oversized_packets, "TX oversized packets, m_defrag failed"); SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_alloc_failed", CTLFLAG_RD, &priv->port_stats.rx_alloc_failed, "RX failed to allocate mbuf"); SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_chksum_good", CTLFLAG_RD, @@ -2564,7 +2765,7 @@ struct mlx4_en_pkt_stats { SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_packets", CTLFLAG_RD, &priv->pkstats.tx_packets, "TX packets"); SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_bytes", CTLFLAG_RD, - &priv->pkstats.tx_packets, "TX Bytes"); + &priv->pkstats.tx_bytes, "TX Bytes"); SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_multicast_packets", CTLFLAG_RD, &priv->pkstats.tx_multicast_packets, "TX Multicast Packets"); SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_broadcast_packets", CTLFLAG_RD, @@ -2605,8 +2806,8 @@ struct mlx4_en_pkt_stats { CTLFLAG_RD, &tx_ring->packets, "TX packets"); SYSCTL_ADD_ULONG(ctx, ring_list, OID_AUTO, "bytes", CTLFLAG_RD, &tx_ring->bytes, "TX bytes"); - } + for (i = 0; i < priv->rx_ring_num; i++) { rx_ring = priv->rx_ring[i]; snprintf(namebuf, sizeof(namebuf), "rx_ring%d", i); Modified: head/sys/ofed/drivers/net/mlx4/en_port.c ============================================================================== --- head/sys/ofed/drivers/net/mlx4/en_port.c Thu Dec 3 12:51:54 2015 (r291693) +++ head/sys/ofed/drivers/net/mlx4/en_port.c Thu Dec 3 13:29:20 2015 (r291694) @@ -194,6 +194,7 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_e priv->port_stats.tx_chksum_offload += priv->tx_ring[i]->tx_csum; priv->port_stats.queue_stopped += priv->tx_ring[i]->queue_stopped; priv->port_stats.wake_queue += priv->tx_ring[i]->wake_queue; + priv->port_stats.oversized_packets += priv->tx_ring[i]->oversized_packets; } /* RX Statistics */ priv->pkstats.rx_packets = be64_to_cpu(mlx4_en_stats->RTOT_prio_0) + @@ -546,8 +547,9 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_e } if (!mlx4_is_mfunc(mdev->dev)) { +/* netdevice stats format */ +#if __FreeBSD_version >= 1100000 if (reset == 0) { - /* netdevice stats format */ dev = mdev->pndev[port]; if_inc_counter(dev, IFCOUNTER_IPACKETS, priv->pkstats.rx_packets - priv->pkstats_last.rx_packets); @@ -567,6 +569,18 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_e priv->pkstats.tx_multicast_packets - priv->pkstats_last.tx_multicast_packets); } priv->pkstats_last = priv->pkstats; +#else + dev = mdev->pndev[port]; + dev->if_ipackets = priv->pkstats.rx_packets; + dev->if_opackets = priv->pkstats.tx_packets; + dev->if_ibytes = priv->pkstats.rx_bytes; + dev->if_obytes = priv->pkstats.tx_bytes; + dev->if_ierrors = priv->pkstats.rx_errors; + dev->if_iqdrops = priv->pkstats.rx_dropped; + dev->if_imcasts = priv->pkstats.rx_multicast_packets; + dev->if_omcasts = priv->pkstats.tx_multicast_packets; + dev->if_collisions = 0; +#endif } spin_unlock(&priv->stats_lock); Modified: head/sys/ofed/drivers/net/mlx4/en_rx.c ============================================================================== --- head/sys/ofed/drivers/net/mlx4/en_rx.c Thu Dec 3 12:51:54 2015 (r291693) +++ head/sys/ofed/drivers/net/mlx4/en_rx.c Thu Dec 3 13:29:20 2015 (r291694) @@ -49,7 +49,8 @@ static void mlx4_en_init_rx_desc(struct struct mlx4_en_rx_ring *ring, int index) { - struct mlx4_en_rx_desc *rx_desc = ring->buf + ring->stride * index; + struct mlx4_en_rx_desc *rx_desc = (struct mlx4_en_rx_desc *) + (ring->buf + (ring->stride * index)); int possible_frags; int i; @@ -102,7 +103,8 @@ static int mlx4_en_alloc_buf(struct mlx4 static int mlx4_en_prepare_rx_desc(struct mlx4_en_priv *priv, struct mlx4_en_rx_ring *ring, int index) { - struct mlx4_en_rx_desc *rx_desc = ring->buf + (index * ring->stride); + struct mlx4_en_rx_desc *rx_desc = (struct mlx4_en_rx_desc *) + (ring->buf + (index * ring->stride)); struct mbuf **mb_list = ring->rx_info + (index << priv->log_rx_info); int i; @@ -130,7 +132,8 @@ static void mlx4_en_free_rx_desc(struct struct mlx4_en_frag_info *frag_info; struct mlx4_en_dev *mdev = priv->mdev; struct mbuf **mb_list; - struct mlx4_en_rx_desc *rx_desc = ring->buf + (index << ring->log_stride); + struct mlx4_en_rx_desc *rx_desc = (struct mlx4_en_rx_desc *) + (ring->buf + (index << ring->log_stride)); dma_addr_t dma; int nr; @@ -574,7 +577,8 @@ int mlx4_en_process_rx_cq(struct net_dev while (XNOR(cqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK, cons_index & size)) { mb_list = ring->rx_info + (index << priv->log_rx_info); - rx_desc = ring->buf + (index << ring->log_stride); + rx_desc = (struct mlx4_en_rx_desc *) + (ring->buf + (index << ring->log_stride)); /* * make sure we read the CQE after we read the ownership bit @@ -611,7 +615,8 @@ int mlx4_en_process_rx_cq(struct net_dev mb->m_pkthdr.ether_vtag = be16_to_cpu(cqe->sl_vid); mb->m_flags |= M_VLANTAG; } - if (likely(dev->if_capabilities & IFCAP_RXCSUM) && + if (likely(dev->if_capenable & + (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6)) && (cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPOK)) && (cqe->checksum == cpu_to_be16(0xffff))) { priv->port_stats.rx_chksum_good++; @@ -692,6 +697,7 @@ void mlx4_en_rx_irq(struct mlx4_cq *mcq) // Because there is no NAPI in freeBSD done = mlx4_en_poll_rx_cq(cq, MLX4_EN_RX_BUDGET); if (priv->port_up && (done == MLX4_EN_RX_BUDGET) ) { + cq->curr_poll_rx_cpu_id = curcpu; taskqueue_enqueue(cq->tq, &cq->cq_task); } else { @@ -702,8 +708,15 @@ void mlx4_en_rx_irq(struct mlx4_cq *mcq) void mlx4_en_rx_que(void *context, int pending) { struct mlx4_en_cq *cq; + struct thread *td; cq = context; + td = curthread; + + thread_lock(td); + sched_bind(td, cq->curr_poll_rx_cpu_id); + thread_unlock(td); + while (mlx4_en_poll_rx_cq(cq, MLX4_EN_RX_BUDGET) == MLX4_EN_RX_BUDGET); mlx4_en_arm_cq(cq->dev->if_softc, cq); @@ -841,8 +854,8 @@ int mlx4_en_config_rss_steer(struct mlx4 else rss_rings = priv->prof->rss_rings; - ptr = ((void *) &context) + offsetof(struct mlx4_qp_context, pri_path) - + MLX4_RSS_OFFSET_IN_QPC_PRI_PATH; + ptr = ((u8 *)&context) + offsetof(struct mlx4_qp_context, pri_path) + + MLX4_RSS_OFFSET_IN_QPC_PRI_PATH; rss_context = ptr; rss_context->base_qpn = cpu_to_be32(ilog2(rss_rings) << 24 | (rss_map->base_qpn)); Modified: head/sys/ofed/drivers/net/mlx4/en_tx.c ============================================================================== --- head/sys/ofed/drivers/net/mlx4/en_tx.c Thu Dec 3 12:51:54 2015 (r291693) +++ head/sys/ofed/drivers/net/mlx4/en_tx.c Thu Dec 3 13:29:20 2015 (r291694) @@ -249,7 +249,8 @@ static void mlx4_en_stamp_wqe(struct mlx int index, u8 owner) { struct mlx4_en_tx_info *tx_info = &ring->tx_info[index]; - struct mlx4_en_tx_desc *tx_desc = ring->buf + index * TXBB_SIZE; + struct mlx4_en_tx_desc *tx_desc = (struct mlx4_en_tx_desc *) + (ring->buf + index * TXBB_SIZE); void *end = ring->buf + ring->buf_size; __be32 *ptr = (__be32 *)tx_desc; __be32 stamp = cpu_to_be32(STAMP_VAL | (!!owner << STAMP_SHIFT)); @@ -268,7 +269,7 @@ static void mlx4_en_stamp_wqe(struct mlx *ptr = stamp; ptr += STAMP_DWORDS; if ((void *)ptr >= end) { - ptr = ring->buf; + ptr = (__be32 *)ring->buf; stamp ^= cpu_to_be32(0x80000000); } } @@ -280,7 +281,8 @@ static u32 mlx4_en_free_tx_desc(struct m { struct mlx4_en_dev *mdev = priv->mdev; struct mlx4_en_tx_info *tx_info = &ring->tx_info[index]; - struct mlx4_en_tx_desc *tx_desc = ring->buf + index * TXBB_SIZE; + struct mlx4_en_tx_desc *tx_desc = (struct mlx4_en_tx_desc *) + (ring->buf + index * TXBB_SIZE); struct mlx4_wqe_data_seg *data = (void *) tx_desc + tx_info->data_offset; struct mbuf *mb = tx_info->mb; void *end = ring->buf + ring->buf_size; @@ -307,7 +309,8 @@ static u32 mlx4_en_free_tx_desc(struct m } else { if (!tx_info->inl) { if ((void *) data >= end) { - data = ring->buf + ((void *)data - end); + data = (struct mlx4_wqe_data_seg *) + (ring->buf + ((void *)data - end)); } if (tx_info->linear) { @@ -321,7 +324,7 @@ static u32 mlx4_en_free_tx_desc(struct m for (i = 0; i < frags; i++) { /* Check for wraparound before unmapping */ if ((void *) data >= end) - data = ring->buf; + data = (struct mlx4_wqe_data_seg *)ring->buf; pci_unmap_single(mdev->pdev, (dma_addr_t) be64_to_cpu(data->addr), data->byte_count, PCI_DMA_TODEVICE); @@ -522,7 +525,7 @@ static struct mlx4_en_tx_desc *mlx4_en_b } /* Return real descriptor location */ - return ring->buf + index * TXBB_SIZE; + return (struct mlx4_en_tx_desc *)(ring->buf + index * TXBB_SIZE); } static inline void mlx4_en_xmit_poll(struct mlx4_en_priv *priv, int tx_ind) @@ -723,18 +726,14 @@ u16 mlx4_en_select_queue(struct net_devi up = (vlan_tag >> 13) % MLX4_EN_NUM_UP; } #endif - /* check if flowid is set */ - if (M_HASHTYPE_GET(mb) != M_HASHTYPE_NONE) - queue_index = mb->m_pkthdr.flowid; - else - queue_index = m_ether_tcpip_hash(MBUF_HASHFLAG_L3 | MBUF_HASHFLAG_L4, mb, hashrandom); + queue_index = m_ether_tcpip_hash(MBUF_HASHFLAG_L3 | MBUF_HASHFLAG_L4, mb, hashrandom); return ((queue_index % rings_p_up) + (up * rings_p_up)); } -static void mlx4_bf_copy(void __iomem *dst, unsigned long *src, unsigned bytecnt) +static void mlx4_bf_copy(void __iomem *dst, volatile unsigned long *src, unsigned bytecnt) { - __iowrite64_copy(dst, src, bytecnt / 8); + __iowrite64_copy(dst, __DEVOLATILE(void *, src), bytecnt / 8); } static u64 mlx4_en_mac_to_u64(u8 *addr) @@ -843,7 +842,7 @@ retry: /* See if we have enough space for whole descriptor TXBB for setting * SW ownership on next descriptor; if not, use a bounce buffer. */ if (likely(index + nr_txbb <= ring_size)) - tx_desc = ring->buf + index * TXBB_SIZE; + tx_desc = (struct mlx4_en_tx_desc *)(ring->buf + index * TXBB_SIZE); else { tx_desc = (struct mlx4_en_tx_desc *) ring->bounce_buf; bounce = true; @@ -1018,10 +1017,13 @@ mlx4_en_transmit_locked(struct ifnet *de } enqueued = 0; - if (m != NULL) { - if ((err = drbr_enqueue(dev, ring->br, m)) != 0) - return (err); - } + if (m != NULL) + /* + * If we can't insert mbuf into drbr, try to xmit anyway. + * We keep the error we got so we could return that after xmit. + */ + err = drbr_enqueue(dev, ring->br, m); + /* Process the queue */ while ((next = drbr_peek(dev, ring->br)) != NULL) { if ((err = mlx4_en_xmit(dev, tx_ind, &next)) != 0) { @@ -1075,10 +1077,14 @@ mlx4_en_transmit(struct ifnet *dev, stru int i, err = 0; /* Compute which queue to use */ - i = mlx4_en_select_queue(dev, m); + if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) { + i = m->m_pkthdr.flowid % priv->tx_ring_num; + } + else { + i = mlx4_en_select_queue(dev, m); + } ring = priv->tx_ring[i]; - if (spin_trylock(&ring->tx_lock)) { err = mlx4_en_transmit_locked(dev, i, m); spin_unlock(&ring->tx_lock); Modified: head/sys/ofed/drivers/net/mlx4/main.c ============================================================================== --- head/sys/ofed/drivers/net/mlx4/main.c Thu Dec 3 12:51:54 2015 (r291693) +++ head/sys/ofed/drivers/net/mlx4/main.c Thu Dec 3 13:29:20 2015 (r291694) @@ -33,7 +33,7 @@ * SOFTWARE. */ -#include +#include #include #include #include @@ -53,9 +53,7 @@ #include "icm.h" #include "mlx4_stats.h" -MODULE_AUTHOR("Roland Dreier"); -MODULE_DESCRIPTION("Mellanox ConnectX HCA low-level driver"); -MODULE_LICENSE("Dual BSD/GPL"); +/* Mellanox ConnectX HCA low-level driver */ struct workqueue_struct *mlx4_wq; @@ -173,7 +171,7 @@ MODULE_PARM_DESC(enable_64b_cqe_eqe, #define PF_CONTEXT_BEHAVIOUR_MASK MLX4_FUNC_CAP_64B_EQE_CQE static char mlx4_version[] __devinitdata = - DRV_NAME ": Mellanox ConnectX core driver v" + DRV_NAME ": Mellanox ConnectX VPI driver v" DRV_VERSION " (" DRV_RELDATE ")\n"; static int log_num_mac = 7; @@ -1295,6 +1293,43 @@ static inline int ibta_mtu_to_int(enum i } } +static ssize_t +show_board(struct device *device, struct device_attribute *attr, + char *buf) +{ + struct mlx4_hca_info *info = container_of(attr, struct mlx4_hca_info, + board_attr); + struct mlx4_dev *mdev = info->dev; + + return sprintf(buf, "%.*s\n", MLX4_BOARD_ID_LEN, + mdev->board_id); +} + +static ssize_t +show_hca(struct device *device, struct device_attribute *attr, + char *buf) +{ + struct mlx4_hca_info *info = container_of(attr, struct mlx4_hca_info, + hca_attr); + struct mlx4_dev *mdev = info->dev; + + return sprintf(buf, "MT%d\n", mdev->pdev->device); +} + +static ssize_t +show_firmware_version(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct mlx4_hca_info *info = container_of(attr, struct mlx4_hca_info, + firmware_attr); + struct mlx4_dev *mdev = info->dev; + + return sprintf(buf, "%d.%d.%d\n", (int)(mdev->caps.fw_ver >> 32), + (int)(mdev->caps.fw_ver >> 16) & 0xffff, + (int)mdev->caps.fw_ver & 0xffff); +} + static ssize_t show_port_ib_mtu(struct device *dev, struct device_attribute *attr, char *buf) @@ -2937,6 +2972,30 @@ no_msi: no_irq: dev->caps.num_comp_vectors = 0; dev->caps.comp_pool = 0; + return; +} + +static void +mlx4_init_hca_info(struct mlx4_dev *dev) +{ + struct mlx4_hca_info *info = &mlx4_priv(dev)->hca_info; + + info->dev = dev; + + info->firmware_attr = (struct device_attribute)__ATTR(fw_ver, S_IRUGO, + show_firmware_version, NULL); + if (device_create_file(&dev->pdev->dev, &info->firmware_attr)) + mlx4_err(dev, "Failed to add file firmware version"); + + info->hca_attr = (struct device_attribute)__ATTR(hca, S_IRUGO, show_hca, + NULL); + if (device_create_file(&dev->pdev->dev, &info->hca_attr)) + mlx4_err(dev, "Failed to add file hca type"); + + info->board_attr = (struct device_attribute)__ATTR(board_id, S_IRUGO, + show_board, NULL); + if (device_create_file(&dev->pdev->dev, &info->board_attr)) + mlx4_err(dev, "Failed to add file board id type"); } static int mlx4_init_port_info(struct mlx4_dev *dev, int port) @@ -2990,6 +3049,14 @@ static int mlx4_init_port_info(struct ml return err; } +static void +mlx4_cleanup_hca_info(struct mlx4_hca_info *info) +{ + device_remove_file(&info->dev->pdev->dev, &info->firmware_attr); + device_remove_file(&info->dev->pdev->dev, &info->board_attr); + device_remove_file(&info->dev->pdev->dev, &info->hca_attr); +} + static void mlx4_cleanup_port_info(struct mlx4_port_info *info) { if (info->port < 0) @@ -3347,6 +3414,7 @@ slave_start: goto err_steer; mlx4_init_quotas(dev); + mlx4_init_hca_info(dev); for (port = 1; port <= dev->caps.num_ports; port++) { err = mlx4_init_port_info(dev, port); @@ -3439,8 +3507,7 @@ err_disable_pdev: static int __devinit mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { - printk_once(KERN_INFO "%s", mlx4_version); - + device_set_desc(pdev->dev.bsddev, mlx4_version); return __mlx4_init_one(pdev, id->driver_data); } @@ -3460,6 +3527,7 @@ static void mlx4_remove_one(struct pci_d mlx4_stop_sense(dev); mlx4_unregister_device(dev); + mlx4_cleanup_hca_info(&priv->hca_info); for (p = 1; p <= dev->caps.num_ports; p++) { mlx4_cleanup_port_info(&priv->port[p]); mlx4_CLOSE_PORT(dev, p); Modified: head/sys/ofed/drivers/net/mlx4/mlx4.h ============================================================================== --- head/sys/ofed/drivers/net/mlx4/mlx4.h Thu Dec 3 12:51:54 2015 (r291693) +++ head/sys/ofed/drivers/net/mlx4/mlx4.h Thu Dec 3 13:29:20 2015 (r291694) @@ -51,7 +51,7 @@ #define DRV_NAME "mlx4_core" #define PFX DRV_NAME ": " -#define DRV_VERSION "2.1" +#define DRV_VERSION "2.1.6" #define DRV_RELDATE __DATE__ #define DRV_STACK_NAME "Linux-MLNX_OFED" @@ -755,6 +755,13 @@ struct mlx4_set_port_rqp_calc_context { __be32 mcast; }; +struct mlx4_hca_info { + struct mlx4_dev *dev; + struct device_attribute firmware_attr; + struct device_attribute hca_attr; + struct device_attribute board_attr; +}; + struct mlx4_port_info { struct mlx4_dev *dev; int port; @@ -845,6 +852,7 @@ struct mlx4_priv { struct mlx4_uar driver_uar; void __iomem *kar; struct mlx4_port_info port[MLX4_MAX_PORTS + 1]; + struct mlx4_hca_info hca_info; struct mlx4_sense sense; struct mutex port_mutex; struct mlx4_msix_ctl msix_ctl; Modified: head/sys/ofed/drivers/net/mlx4/mlx4_en.h ============================================================================== --- head/sys/ofed/drivers/net/mlx4/mlx4_en.h Thu Dec 3 12:51:54 2015 (r291693) +++ head/sys/ofed/drivers/net/mlx4/mlx4_en.h Thu Dec 3 13:29:20 2015 (r291694) @@ -59,8 +59,6 @@ #include "mlx4_stats.h" #define DRV_NAME "mlx4_en" -#define DRV_VERSION "2.1" -#define DRV_RELDATE __DATE__ #define MLX4_EN_MSG_LEVEL (NETIF_MSG_LINK | NETIF_MSG_IFDOWN) @@ -154,7 +152,7 @@ enum { #define MLX4_EN_NUM_UP 1 #define MAX_TX_RINGS (MLX4_EN_MAX_TX_RING_P_UP * \ - MLX4_EN_NUM_UP) + MLX4_EN_NUM_UP) #define MLX4_EN_DEF_TX_RING_SIZE 1024 #define MLX4_EN_DEF_RX_RING_SIZE 1024 @@ -265,9 +263,16 @@ struct mlx4_en_tx_desc { #define MLX4_EN_USE_SRQ 0x01000000 -#define MLX4_EN_TX_BUDGET 64*4 //Compensate for no NAPI in freeBSD - might need some fine tunning in the future. #define MLX4_EN_RX_BUDGET 64 +#define MLX4_EN_TX_MAX_DESC_SIZE 512 /* bytes */ +#define MLX4_EN_TX_MAX_MBUF_SIZE 65536 /* bytes */ +#define MLX4_EN_TX_MAX_PAYLOAD_SIZE 65536 /* bytes */ +#define MLX4_EN_TX_MAX_MBUF_FRAGS \ + ((MLX4_EN_TX_MAX_DESC_SIZE - 128) / DS_SIZE_ALIGNMENT) /* units */ +#define MLX4_EN_TX_WQE_MAX_WQEBBS \ + (MLX4_EN_TX_MAX_DESC_SIZE / TXBB_SIZE) /* units */ + #define MLX4_EN_CX3_LOW_ID 0x1000 #define MLX4_EN_CX3_HIGH_ID 0x1005 @@ -282,7 +287,7 @@ struct mlx4_en_tx_ring { u32 cons; u32 buf_size; u32 doorbell_qpn; - void *buf; + u8 *buf; u16 poll_cnt; int blocked; struct mlx4_en_tx_info *tx_info; @@ -300,6 +305,7 @@ struct mlx4_en_tx_ring { unsigned long packets; unsigned long tx_csum; unsigned long queue_stopped; + unsigned long oversized_packets; unsigned long wake_queue; struct mlx4_bf bf; bool bf_enabled; @@ -339,7 +345,7 @@ struct mlx4_en_rx_ring { u32 rx_buf_size; u32 rx_mb_size; int qpn; - void *buf; + u8 *buf; void *rx_info; unsigned long errors; unsigned long bytes; @@ -400,6 +406,7 @@ struct mlx4_en_cq { #define MLX4_EN_OPCODE_ERROR 0x1e u32 tot_rx; u32 tot_tx; + u32 curr_poll_rx_cpu_id; #ifdef CONFIG_NET_RX_BUSY_POLL unsigned int state; @@ -641,7 +648,6 @@ struct mlx4_en_priv { unsigned long last_ifq_jiffies; u64 if_counters_rx_errors; u64 if_counters_rx_no_buffer; - }; enum mlx4_en_wol { Modified: head/sys/ofed/drivers/net/mlx4/mlx4_stats.h ============================================================================== --- head/sys/ofed/drivers/net/mlx4/mlx4_stats.h Thu Dec 3 12:51:54 2015 (r291693) +++ head/sys/ofed/drivers/net/mlx4/mlx4_stats.h Thu Dec 3 13:29:20 2015 (r291694) @@ -124,6 +124,7 @@ struct mlx4_en_port_stats { unsigned long queue_stopped; unsigned long wake_queue; unsigned long tx_timeout; + unsigned long oversized_packets; unsigned long rx_alloc_failed; unsigned long rx_chksum_good; *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***