Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/gve/gve_main.c
| /*- | /*- | ||||||||
| * SPDX-License-Identifier: BSD-3-Clause | * SPDX-License-Identifier: BSD-3-Clause | ||||||||
| * | * | ||||||||
| * Copyright (c) 2023 Google LLC | * Copyright (c) 2023-2024 Google LLC | ||||||||
| * | * | ||||||||
| * Redistribution and use in source and binary forms, with or without modification, | * Redistribution and use in source and binary forms, with or without modification, | ||||||||
| * are permitted provided that the following conditions are met: | * are permitted provided that the following conditions are met: | ||||||||
| * | * | ||||||||
| * 1. Redistributions of source code must retain the above copyright notice, this | * 1. Redistributions of source code must retain the above copyright notice, this | ||||||||
| * list of conditions and the following disclaimer. | * list of conditions and the following disclaimer. | ||||||||
| * | * | ||||||||
| * 2. Redistributions in binary form must reproduce the above copyright notice, | * 2. Redistributions in binary form must reproduce the above copyright notice, | ||||||||
| Show All 12 Lines | |||||||||
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||||||
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||||||||
| * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||||||
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||||
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||||
| */ | */ | ||||||||
| #include "gve.h" | #include "gve.h" | ||||||||
| #include "gve_adminq.h" | #include "gve_adminq.h" | ||||||||
| #include "gve_dqo.h" | |||||||||
| #define GVE_DRIVER_VERSION "GVE-FBSD-1.0.1\n" | #define GVE_DRIVER_VERSION "GVE-FBSD-1.2.0\n" | ||||||||
| #define GVE_VERSION_MAJOR 1 | #define GVE_VERSION_MAJOR 1 | ||||||||
| #define GVE_VERSION_MINOR 0 | #define GVE_VERSION_MINOR 2 | ||||||||
| #define GVE_VERSION_SUB 1 | #define GVE_VERSION_SUB 0 | ||||||||
| #define GVE_DEFAULT_RX_COPYBREAK 256 | #define GVE_DEFAULT_RX_COPYBREAK 256 | ||||||||
| /* Devices supported by this driver. */ | /* Devices supported by this driver. */ | ||||||||
| static struct gve_dev { | static struct gve_dev { | ||||||||
| uint16_t vendor_id; | uint16_t vendor_id; | ||||||||
| uint16_t device_id; | uint16_t device_id; | ||||||||
| const char *name; | const char *name; | ||||||||
| ▲ Show 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | if (if_getcapenable(ifp) & IFCAP_TXCSUM) | ||||||||
| if_sethwassistbits(ifp, CSUM_TCP | CSUM_UDP, 0); | if_sethwassistbits(ifp, CSUM_TCP | CSUM_UDP, 0); | ||||||||
| if (if_getcapenable(ifp) & IFCAP_TXCSUM_IPV6) | if (if_getcapenable(ifp) & IFCAP_TXCSUM_IPV6) | ||||||||
| if_sethwassistbits(ifp, CSUM_IP6_TCP | CSUM_IP6_UDP, 0); | if_sethwassistbits(ifp, CSUM_IP6_TCP | CSUM_IP6_UDP, 0); | ||||||||
| if (if_getcapenable(ifp) & IFCAP_TSO4) | if (if_getcapenable(ifp) & IFCAP_TSO4) | ||||||||
| if_sethwassistbits(ifp, CSUM_IP_TSO, 0); | if_sethwassistbits(ifp, CSUM_IP_TSO, 0); | ||||||||
| if (if_getcapenable(ifp) & IFCAP_TSO6) | if (if_getcapenable(ifp) & IFCAP_TSO6) | ||||||||
| if_sethwassistbits(ifp, CSUM_IP6_TSO, 0); | if_sethwassistbits(ifp, CSUM_IP6_TSO, 0); | ||||||||
| if (gve_is_gqi(priv)) { | |||||||||
| err = gve_register_qpls(priv); | err = gve_register_qpls(priv); | ||||||||
| if (err != 0) | if (err != 0) | ||||||||
| goto reset; | goto reset; | ||||||||
| } | |||||||||
| err = gve_create_rx_rings(priv); | err = gve_create_rx_rings(priv); | ||||||||
| if (err != 0) | if (err != 0) | ||||||||
| goto reset; | goto reset; | ||||||||
| err = gve_create_tx_rings(priv); | err = gve_create_tx_rings(priv); | ||||||||
| if (err != 0) | if (err != 0) | ||||||||
| goto reset; | goto reset; | ||||||||
| Show All 13 Lines | |||||||||
| reset: | reset: | ||||||||
| gve_schedule_reset(priv); | gve_schedule_reset(priv); | ||||||||
| return (err); | return (err); | ||||||||
| } | } | ||||||||
| static void | static void | ||||||||
| gve_down(struct gve_priv *priv) | gve_down(struct gve_priv *priv) | ||||||||
| { | { | ||||||||
| int err; | |||||||||
| GVE_IFACE_LOCK_ASSERT(priv->gve_iface_lock); | GVE_IFACE_LOCK_ASSERT(priv->gve_iface_lock); | ||||||||
| if (!gve_get_state_flag(priv, GVE_STATE_FLAG_QUEUES_UP)) | if (!gve_get_state_flag(priv, GVE_STATE_FLAG_QUEUES_UP)) | ||||||||
| return; | return; | ||||||||
| if (gve_get_state_flag(priv, GVE_STATE_FLAG_LINK_UP)) { | if (gve_get_state_flag(priv, GVE_STATE_FLAG_LINK_UP)) { | ||||||||
| if_link_state_change(priv->ifp, LINK_STATE_DOWN); | if_link_state_change(priv->ifp, LINK_STATE_DOWN); | ||||||||
| gve_clear_state_flag(priv, GVE_STATE_FLAG_LINK_UP); | gve_clear_state_flag(priv, GVE_STATE_FLAG_LINK_UP); | ||||||||
| } | } | ||||||||
| if_setdrvflagbits(priv->ifp, IFF_DRV_OACTIVE, IFF_DRV_RUNNING); | if_setdrvflagbits(priv->ifp, IFF_DRV_OACTIVE, IFF_DRV_RUNNING); | ||||||||
| if (gve_destroy_rx_rings(priv) != 0) | err = gve_destroy_rx_rings(priv); | ||||||||
| if (err != 0) | |||||||||
| goto reset; | goto reset; | ||||||||
| if (gve_destroy_tx_rings(priv) != 0) | err = gve_destroy_tx_rings(priv); | ||||||||
| if (err != 0) | |||||||||
markj: This part of the change (adding `err`) seems superfluous. Is something missing? | |||||||||
shailend_google.comAuthorUnsubmitted Done Inline ActionsSorry, it is superfluous, removing it shailend_google.com: Sorry, it is superfluous, removing it | |||||||||
| goto reset; | goto reset; | ||||||||
| if (gve_is_gqi(priv)) { | |||||||||
| if (gve_unregister_qpls(priv) != 0) | if (gve_unregister_qpls(priv) != 0) | ||||||||
| goto reset; | goto reset; | ||||||||
| } | |||||||||
| if (gve_is_gqi(priv)) | |||||||||
| gve_mask_all_queue_irqs(priv); | gve_mask_all_queue_irqs(priv); | ||||||||
| gve_clear_state_flag(priv, GVE_STATE_FLAG_QUEUES_UP); | gve_clear_state_flag(priv, GVE_STATE_FLAG_QUEUES_UP); | ||||||||
| priv->interface_down_cnt++; | priv->interface_down_cnt++; | ||||||||
| return; | return; | ||||||||
| reset: | reset: | ||||||||
| gve_schedule_reset(priv); | gve_schedule_reset(priv); | ||||||||
| } | } | ||||||||
| ▲ Show 20 Lines • Show All 173 Lines • ▼ Show 20 Lines | gve_setup_ifnet(device_t dev, struct gve_priv *priv) | ||||||||
| if_initname(ifp, device_get_name(dev), device_get_unit(dev)); | if_initname(ifp, device_get_name(dev), device_get_unit(dev)); | ||||||||
| if_setsoftc(ifp, priv); | if_setsoftc(ifp, priv); | ||||||||
| if_setdev(ifp, dev); | if_setdev(ifp, dev); | ||||||||
| if_setinitfn(ifp, gve_init); | if_setinitfn(ifp, gve_init); | ||||||||
| if_setioctlfn(ifp, gve_ioctl); | if_setioctlfn(ifp, gve_ioctl); | ||||||||
| if_settransmitfn(ifp, gve_xmit_ifp); | if_settransmitfn(ifp, gve_xmit_ifp); | ||||||||
| if_setqflushfn(ifp, gve_qflush); | if_setqflushfn(ifp, gve_qflush); | ||||||||
| /* | |||||||||
| * Set TSO limits, must match the arguments to bus_dma_tag_create | |||||||||
| * when creating tx->dqo.buf_dmatag | |||||||||
| */ | |||||||||
| if (!gve_is_gqi(priv)) { | |||||||||
| if_sethwtsomax(ifp, GVE_TSO_MAXSIZE_DQO); | |||||||||
| if_sethwtsomaxsegcount(ifp, GVE_TX_MAX_DATA_DESCS_DQO); | |||||||||
| if_sethwtsomaxsegsize(ifp, GVE_TX_MAX_BUF_SIZE_DQO); | |||||||||
| } | |||||||||
| #if __FreeBSD_version >= 1400086 | #if __FreeBSD_version >= 1400086 | ||||||||
| if_setflags(ifp, IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST); | if_setflags(ifp, IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST); | ||||||||
| #else | #else | ||||||||
| if_setflags(ifp, IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | IFF_KNOWSEPOCH); | if_setflags(ifp, IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | IFF_KNOWSEPOCH); | ||||||||
| #endif | #endif | ||||||||
| ifmedia_init(&priv->media, IFM_IMASK, gve_media_change, gve_media_status); | ifmedia_init(&priv->media, IFM_IMASK, gve_media_change, gve_media_status); | ||||||||
| if_setgetcounterfn(ifp, gve_get_counter); | if_setgetcounterfn(ifp, gve_get_counter); | ||||||||
| ▲ Show 20 Lines • Show All 66 Lines • ▼ Show 20 Lines | |||||||||
| } | } | ||||||||
| static void | static void | ||||||||
| gve_free_rings(struct gve_priv *priv) | gve_free_rings(struct gve_priv *priv) | ||||||||
| { | { | ||||||||
| gve_free_irqs(priv); | gve_free_irqs(priv); | ||||||||
| gve_free_tx_rings(priv); | gve_free_tx_rings(priv); | ||||||||
| gve_free_rx_rings(priv); | gve_free_rx_rings(priv); | ||||||||
| if (gve_is_gqi(priv)) | |||||||||
| gve_free_qpls(priv); | gve_free_qpls(priv); | ||||||||
| } | } | ||||||||
| static int | static int | ||||||||
| gve_alloc_rings(struct gve_priv *priv) | gve_alloc_rings(struct gve_priv *priv) | ||||||||
| { | { | ||||||||
| int err; | int err; | ||||||||
| if (gve_is_gqi(priv)) { | |||||||||
| err = gve_alloc_qpls(priv); | err = gve_alloc_qpls(priv); | ||||||||
| if (err != 0) | if (err != 0) | ||||||||
| goto abort; | goto abort; | ||||||||
| } | |||||||||
| err = gve_alloc_rx_rings(priv); | err = gve_alloc_rx_rings(priv); | ||||||||
| if (err != 0) | if (err != 0) | ||||||||
| goto abort; | goto abort; | ||||||||
| err = gve_alloc_tx_rings(priv); | err = gve_alloc_tx_rings(priv); | ||||||||
| if (err != 0) | if (err != 0) | ||||||||
| goto abort; | goto abort; | ||||||||
| Show All 23 Lines | if (gve_get_state_flag(priv, GVE_STATE_FLAG_RESOURCES_OK)) { | ||||||||
| } | } | ||||||||
| if (bootverbose) | if (bootverbose) | ||||||||
| device_printf(priv->dev, "Deconfigured device resources\n"); | device_printf(priv->dev, "Deconfigured device resources\n"); | ||||||||
| gve_clear_state_flag(priv, GVE_STATE_FLAG_RESOURCES_OK); | gve_clear_state_flag(priv, GVE_STATE_FLAG_RESOURCES_OK); | ||||||||
| } | } | ||||||||
| gve_free_irq_db_array(priv); | gve_free_irq_db_array(priv); | ||||||||
| gve_free_counter_array(priv); | gve_free_counter_array(priv); | ||||||||
| if (priv->ptype_lut_dqo) { | |||||||||
| free(priv->ptype_lut_dqo, M_GVE); | |||||||||
| priv->ptype_lut_dqo = NULL; | |||||||||
| } | } | ||||||||
| } | |||||||||
| static int | static int | ||||||||
| gve_configure_resources(struct gve_priv *priv) | gve_configure_resources(struct gve_priv *priv) | ||||||||
| { | { | ||||||||
| int err; | int err; | ||||||||
| if (gve_get_state_flag(priv, GVE_STATE_FLAG_RESOURCES_OK)) | if (gve_get_state_flag(priv, GVE_STATE_FLAG_RESOURCES_OK)) | ||||||||
| return (0); | return (0); | ||||||||
| Show All 9 Lines | gve_configure_resources(struct gve_priv *priv) | ||||||||
| err = gve_adminq_configure_device_resources(priv); | err = gve_adminq_configure_device_resources(priv); | ||||||||
| if (err != 0) { | if (err != 0) { | ||||||||
| device_printf(priv->dev, "Failed to configure device resources: err=%d\n", | device_printf(priv->dev, "Failed to configure device resources: err=%d\n", | ||||||||
| err); | err); | ||||||||
| err = (ENXIO); | err = (ENXIO); | ||||||||
| goto abort; | goto abort; | ||||||||
| } | } | ||||||||
| if (!gve_is_gqi(priv)) { | |||||||||
| priv->ptype_lut_dqo = malloc(sizeof(*priv->ptype_lut_dqo), M_GVE, | |||||||||
| M_WAITOK | M_ZERO); | |||||||||
| if (!priv->ptype_lut_dqo) { | |||||||||
| err = (ENOMEM); | |||||||||
markjUnsubmitted Done Inline Actions
but M_WAITOK allocations never fail, so this check should be removed. markj: but `M_WAITOK` allocations never fail, so this check should be removed. | |||||||||
| goto abort; | |||||||||
| } | |||||||||
| err = gve_adminq_get_ptype_map_dqo(priv, priv->ptype_lut_dqo); | |||||||||
| if (err != 0) { | |||||||||
| device_printf(priv->dev, "Failed to configure ptype lut: err=%d\n", | |||||||||
| err); | |||||||||
| goto abort; | |||||||||
| } | |||||||||
| } | |||||||||
| gve_set_state_flag(priv, GVE_STATE_FLAG_RESOURCES_OK); | gve_set_state_flag(priv, GVE_STATE_FLAG_RESOURCES_OK); | ||||||||
| if (bootverbose) | if (bootverbose) | ||||||||
| device_printf(priv->dev, "Configured device resources\n"); | device_printf(priv->dev, "Configured device resources\n"); | ||||||||
| return (0); | return (0); | ||||||||
| abort: | abort: | ||||||||
| gve_deconfigure_resources(priv); | gve_deconfigure_resources(priv); | ||||||||
| return (err); | return (err); | ||||||||
| ▲ Show 20 Lines • Show All 200 Lines • ▼ Show 20 Lines | |||||||||
| } | } | ||||||||
| static int | static int | ||||||||
| gve_attach(device_t dev) | gve_attach(device_t dev) | ||||||||
| { | { | ||||||||
| struct gve_priv *priv; | struct gve_priv *priv; | ||||||||
| int rid; | int rid; | ||||||||
| int err; | int err; | ||||||||
| snprintf(gve_version, sizeof(gve_version), "%d.%d.%d", | |||||||||
| GVE_VERSION_MAJOR, GVE_VERSION_MINOR, GVE_VERSION_SUB); | |||||||||
| priv = device_get_softc(dev); | priv = device_get_softc(dev); | ||||||||
| priv->dev = dev; | priv->dev = dev; | ||||||||
| GVE_IFACE_LOCK_INIT(priv->gve_iface_lock); | GVE_IFACE_LOCK_INIT(priv->gve_iface_lock); | ||||||||
| pci_enable_busmaster(dev); | pci_enable_busmaster(dev); | ||||||||
| rid = PCIR_BAR(GVE_REGISTER_BAR); | rid = PCIR_BAR(GVE_REGISTER_BAR); | ||||||||
| ▲ Show 20 Lines • Show All 112 Lines • Show Last 20 Lines | |||||||||
This part of the change (adding err) seems superfluous. Is something missing?