diff options
author | Robert Mustacchi <rm@fingolfin.org> | 2020-05-18 17:16:48 -0700 |
---|---|---|
committer | Robert Mustacchi <rm@fingolfin.org> | 2020-06-12 09:43:33 -0700 |
commit | f2fe7acaed48e65ea8626868085ea6e40a63b3a9 (patch) | |
tree | 31ffcbaba9c5e523a42e0d0fa724debe0d13f42a | |
parent | a377495feb6d6c6a51d6cca4065a74f320f29a07 (diff) | |
download | illumos-joyent-f2fe7acaed48e65ea8626868085ea6e40a63b3a9.tar.gz |
12763 ixgbe ufm support
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Reviewed by: Andy Fiddaman <omnios@citrus-it.co.uk>
Approved by: Joshua Clulow <josh@sysmgr.org>
-rw-r--r-- | usr/src/uts/common/io/ixgbe/ixgbe_main.c | 165 | ||||
-rw-r--r-- | usr/src/uts/common/io/ixgbe/ixgbe_sw.h | 8 |
2 files changed, 173 insertions, 0 deletions
diff --git a/usr/src/uts/common/io/ixgbe/ixgbe_main.c b/usr/src/uts/common/io/ixgbe/ixgbe_main.c index 3463be30b9..86c46bee44 100644 --- a/usr/src/uts/common/io/ixgbe/ixgbe_main.c +++ b/usr/src/uts/common/io/ixgbe/ixgbe_main.c @@ -30,6 +30,7 @@ * Copyright (c) 2013 Saso Kiselkov. All rights reserved. * Copyright (c) 2013 OSN Online Service Nuernberg GmbH. All rights reserved. * Copyright 2016 OmniTI Computer Consulting, Inc. All rights reserved. + * Copyright 2020 Oxide Computer Company */ #include "ixgbe_sw.h" @@ -133,6 +134,13 @@ static int ixgbe_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, const void *impl_data); static void ixgbe_fm_init(ixgbe_t *); static void ixgbe_fm_fini(ixgbe_t *); +static int ixgbe_ufm_fill_image(ddi_ufm_handle_t *, void *arg, uint_t, + ddi_ufm_image_t *); +static int ixgbe_ufm_fill_slot(ddi_ufm_handle_t *, void *, uint_t, uint_t, + ddi_ufm_slot_t *); +static int ixgbe_ufm_getcaps(ddi_ufm_handle_t *, void *, ddi_ufm_cap_t *); +static int ixgbe_ufm_readimg(ddi_ufm_handle_t *, void *, uint_t, uint_t, + uint64_t, uint64_t, void *, uint64_t *); char *ixgbe_priv_props[] = { "_tx_copy_thresh", @@ -355,6 +363,14 @@ static adapter_info_t ixgbe_X550_cap = { | IXGBE_FLAG_RSC_CAPABLE) /* capability flags */ }; +static ddi_ufm_ops_t ixgbe_ufm_ops = { + .ddi_ufm_op_fill_image = ixgbe_ufm_fill_image, + .ddi_ufm_op_fill_slot = ixgbe_ufm_fill_slot, + .ddi_ufm_op_getcaps = ixgbe_ufm_getcaps, + .ddi_ufm_op_readimg = ixgbe_ufm_readimg +}; + + /* * Module Initialization Functions. */ @@ -650,6 +666,16 @@ ixgbe_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) } ixgbe->attach_progress |= ATTACH_PROGRESS_ENABLE_INTR; + if (ixgbe->hw.bus.func == 0) { + if (ddi_ufm_init(devinfo, DDI_UFM_CURRENT_VERSION, + &ixgbe_ufm_ops, &ixgbe->ixgbe_ufmh, ixgbe) != 0) { + ixgbe_error(ixgbe, "Failed to enable DDI UFM support"); + goto attach_fail; + } + ixgbe->attach_progress |= ATTACH_PROGRESS_UFM; + ddi_ufm_update(ixgbe->ixgbe_ufmh); + } + ixgbe_log(ixgbe, "%s", ixgbe_ident); atomic_or_32(&ixgbe->ixgbe_state, IXGBE_INITIALIZED); @@ -798,6 +824,13 @@ ixgbe_unconfigure(dev_info_t *devinfo, ixgbe_t *ixgbe) } /* + * Clean up the UFM subsystem. Note this only is set on function 0. + */ + if (ixgbe->attach_progress & ATTACH_PROGRESS_UFM) { + ddi_ufm_fini(ixgbe->ixgbe_ufmh); + } + + /* * Unregister MAC */ if (ixgbe->attach_progress & ATTACH_PROGRESS_MAC) { @@ -6710,3 +6743,135 @@ ixgbe_remmac(void *arg, const uint8_t *mac_addr) return (0); } + +static int +ixgbe_ufm_fill_image(ddi_ufm_handle_t *ufmh, void *arg, uint_t imgno, + ddi_ufm_image_t *imgp) +{ + ixgbe_t *ixgbe = arg; + const char *type; + + if (imgno != 0) { + return (EINVAL); + } + + ddi_ufm_image_set_desc(imgp, "NVM"); + ddi_ufm_image_set_nslots(imgp, 1); + switch (ixgbe->hw.eeprom.type) { + case ixgbe_eeprom_spi: + type = "SPI EEPROM"; + break; + case ixgbe_flash: + type = "Flash"; + break; + default: + type = NULL; + break; + } + + if (type != NULL) { + nvlist_t *nvl; + + nvl = fnvlist_alloc(); + fnvlist_add_string(nvl, "image-type", type); + /* + * The DDI takes ownership of the nvlist_t at this point. + */ + ddi_ufm_image_set_misc(imgp, nvl); + } + + return (0); +} + +static int +ixgbe_ufm_fill_slot(ddi_ufm_handle_t *ufmh, void *arg, uint_t imgno, + uint_t slotno, ddi_ufm_slot_t *slotp) +{ + ixgbe_t *ixgbe = arg; + + if (imgno != 0 || slotno != 0) { + return (EINVAL); + } + + /* + * Unfortunately there is no generic versioning in the ixgbe family + * eeprom parts. + */ + ddi_ufm_slot_set_version(slotp, "unknown"); + ddi_ufm_slot_set_attrs(slotp, DDI_UFM_ATTR_ACTIVE | + DDI_UFM_ATTR_READABLE | DDI_UFM_ATTR_WRITEABLE); + ddi_ufm_slot_set_imgsize(slotp, ixgbe->hw.eeprom.word_size * 2); + + return (0); +} + +static int +ixgbe_ufm_getcaps(ddi_ufm_handle_t *ufmh, void *arg, ddi_ufm_cap_t *caps) +{ + ixgbe_t *ixgbe = arg; + + *caps = 0; + switch (ixgbe->hw.eeprom.type) { + case ixgbe_eeprom_spi: + case ixgbe_flash: + *caps |= DDI_UFM_CAP_REPORT; + if (ixgbe->hw.eeprom.ops.read_buffer != NULL) { + *caps |= DDI_UFM_CAP_READIMG; + } + break; + default: + break; + } + + return (0); +} + +static int +ixgbe_ufm_readimg(ddi_ufm_handle_t *ufmh, void *arg, uint_t imgno, + uint_t slotno, uint64_t len, uint64_t offset, void *buf, uint64_t *nread) +{ + int ret; + uint16_t wordoff, nwords, *buf16 = buf; + ixgbe_t *ixgbe = arg; + uint32_t imgsize = ixgbe->hw.eeprom.word_size * 2; + + if (imgno != 0 || slotno != 0) { + return (EINVAL); + } + + if (len > imgsize || offset > imgsize || len + offset > imgsize) { + return (EINVAL); + } + + if (ixgbe->hw.eeprom.ops.read_buffer == NULL) { + return (ENOTSUP); + } + + /* + * Hardware provides us a means to read 16-bit words. For the time + * being, restrict offset and length to be 2 byte aligned. We should + * probably reduce this restriction. We could probably just use a bounce + * buffer. + */ + if ((offset % 2) != 0 || (len % 2) != 0) { + return (EINVAL); + } + + wordoff = offset >> 1; + nwords = len >> 1; + mutex_enter(&ixgbe->gen_lock); + ret = ixgbe_read_eeprom_buffer(&ixgbe->hw, wordoff, nwords, buf16); + mutex_exit(&ixgbe->gen_lock); + + if (ret == 0) { + uint16_t i; + *nread = len; + for (i = 0; i < nwords; i++) { + buf16[i] = LE_16(buf16[i]); + } + } else { + ret = EIO; + } + + return (ret); +} diff --git a/usr/src/uts/common/io/ixgbe/ixgbe_sw.h b/usr/src/uts/common/io/ixgbe/ixgbe_sw.h index 8bf93afe9c..0ff20ca9a2 100644 --- a/usr/src/uts/common/io/ixgbe/ixgbe_sw.h +++ b/usr/src/uts/common/io/ixgbe/ixgbe_sw.h @@ -28,6 +28,7 @@ * Copyright (c) 2013 Saso Kiselkov. All rights reserved. * Copyright 2016 OmniTI Computer Consulting, Inc. All rights reserved. * Copyright 2019 Joyent, Inc. + * Copyright 2020 Oxide Computer Company */ #ifndef _IXGBE_SW_H @@ -74,6 +75,7 @@ extern "C" { #include <sys/fm/util.h> #include <sys/disp.h> #include <sys/fm/io/ddi.h> +#include <sys/ddi_ufm.h> #include "ixgbe_api.h" #define MODULE_NAME "ixgbe" /* module name */ @@ -214,6 +216,7 @@ extern "C" { #define ATTACH_PROGRESS_LINK_TIMER 0x8000 /* link check timer */ #define ATTACH_PROGRESS_OVERTEMP_TASKQ 0x10000 /* Over-temp taskq created */ #define ATTACH_PROGRESS_PHY_TASKQ 0x20000 /* Ext. PHY taskq created */ +#define ATTACH_PROGRESS_UFM 0x40000 /* UFM support */ #define PROP_DEFAULT_MTU "default_mtu" #define PROP_FLOW_CONTROL "flow_control" @@ -749,6 +752,11 @@ typedef struct ixgbe { uint32_t ixgbe_led_index; /* + * UFM state + */ + ddi_ufm_handle_t *ixgbe_ufmh; + + /* * Kstat definitions */ kstat_t *ixgbe_ks; |