summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Mustacchi <rm@fingolfin.org>2020-05-18 17:16:48 -0700
committerRobert Mustacchi <rm@fingolfin.org>2020-06-12 09:43:33 -0700
commitf2fe7acaed48e65ea8626868085ea6e40a63b3a9 (patch)
tree31ffcbaba9c5e523a42e0d0fa724debe0d13f42a
parenta377495feb6d6c6a51d6cca4065a74f320f29a07 (diff)
downloadillumos-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.c165
-rw-r--r--usr/src/uts/common/io/ixgbe/ixgbe_sw.h8
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;