aboutsummaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/acpi_support/acpi_panasonic.c2
-rw-r--r--sys/dev/amdsmu/amdsmu.c18
-rw-r--r--sys/dev/amdsmu/amdsmu.h98
-rw-r--r--sys/dev/amdsmu/amdsmu_reg.h7
-rw-r--r--sys/dev/asmc/asmc.c1181
-rw-r--r--sys/dev/asmc/asmcvar.h965
-rw-r--r--sys/dev/dpaa/bman.c433
-rw-r--r--sys/dev/dpaa/bman.h172
-rw-r--r--sys/dev/dpaa/bman_fdt.c148
-rw-r--r--sys/dev/dpaa/bman_portals.c366
-rw-r--r--sys/dev/dpaa/bman_var.h44
-rw-r--r--sys/dev/dpaa/dpaa_common.c82
-rw-r--r--sys/dev/dpaa/dpaa_common.h195
-rw-r--r--sys/dev/dpaa/dpaa_eth.c719
-rw-r--r--sys/dev/dpaa/dpaa_eth.h116
-rw-r--r--sys/dev/dpaa/fman.c852
-rw-r--r--sys/dev/dpaa/fman.h103
-rw-r--r--sys/dev/dpaa/fman_fdt.c14
-rw-r--r--sys/dev/dpaa/fman_if.m38
-rw-r--r--sys/dev/dpaa/fman_mdio.c16
-rw-r--r--sys/dev/dpaa/fman_muram.c70
-rw-r--r--sys/dev/dpaa/fman_parser.h27
-rw-r--r--sys/dev/dpaa/fman_port.c697
-rw-r--r--sys/dev/dpaa/fman_port.h29
-rw-r--r--sys/dev/dpaa/fman_port_if.m33
-rw-r--r--sys/dev/dpaa/fman_xmdio.c284
-rw-r--r--sys/dev/dpaa/if_dtsec.c610
-rw-r--r--sys/dev/dpaa/if_dtsec.h96
-rw-r--r--sys/dev/dpaa/if_dtsec_fdt.c55
-rw-r--r--sys/dev/dpaa/if_dtsec_im.c260
-rw-r--r--sys/dev/dpaa/if_dtsec_im.h39
-rw-r--r--sys/dev/dpaa/if_dtsec_rm.c651
-rw-r--r--sys/dev/dpaa/if_dtsec_rm.h51
-rw-r--r--sys/dev/dpaa/if_memac.c820
-rw-r--r--sys/dev/dpaa/if_memac.h50
-rw-r--r--sys/dev/dpaa/if_memac_fdt.c171
-rw-r--r--sys/dev/dpaa/portals.h51
-rw-r--r--sys/dev/dpaa/portals_common.c135
-rw-r--r--sys/dev/dpaa/qman.c772
-rw-r--r--sys/dev/dpaa/qman.h184
-rw-r--r--sys/dev/dpaa/qman_fdt.c168
-rw-r--r--sys/dev/dpaa/qman_portal_if.m37
-rw-r--r--sys/dev/dpaa/qman_portals.c484
-rw-r--r--sys/dev/dpaa/qman_var.h167
-rw-r--r--sys/dev/hwpmc/hwpmc_amd.c70
-rw-r--r--sys/dev/hwpmc/hwpmc_amd.h22
-rw-r--r--sys/dev/hwpmc/hwpmc_ibs.c108
-rw-r--r--sys/dev/hwpmc/hwpmc_ibs.h20
-rw-r--r--sys/dev/ichsmb/ichsmb.c18
-rw-r--r--sys/dev/ichsmb/ichsmb_pci.c63
-rw-r--r--sys/dev/ichsmb/ichsmb_reg.h3
-rw-r--r--sys/dev/ichsmb/ichsmb_var.h3
-rw-r--r--sys/dev/iicbus/mux/iicmux.c6
-rw-r--r--sys/dev/iicbus/rtc/rs5c372a.c162
-rw-r--r--sys/dev/mfi/mfi.c7
-rw-r--r--sys/dev/mii/miidevs8
-rw-r--r--sys/dev/mii/smscphy.c4
-rw-r--r--sys/dev/mlx5/mlx5_en/mlx5_en_hw_tls_rx.c15
-rw-r--r--sys/dev/mrsas/mrsas.c3
-rw-r--r--sys/dev/netmap/netmap.c1
-rw-r--r--sys/dev/rtsx/rtsx.c4
-rw-r--r--sys/dev/smartpqi/smartpqi_cam.c4
-rw-r--r--sys/dev/smartpqi/smartpqi_defines.h8
-rw-r--r--sys/dev/smartpqi/smartpqi_discovery.c21
-rw-r--r--sys/dev/smartpqi/smartpqi_event.c17
-rw-r--r--sys/dev/smartpqi/smartpqi_main.c12
-rw-r--r--sys/dev/smartpqi/smartpqi_misc.c4
-rw-r--r--sys/dev/smartpqi/smartpqi_queue.c4
-rw-r--r--sys/dev/smartpqi/smartpqi_request.c4
-rw-r--r--sys/dev/smartpqi/smartpqi_response.c4
-rw-r--r--sys/dev/smartpqi/smartpqi_sis.c6
-rw-r--r--sys/dev/smartpqi/smartpqi_structures.h4
-rw-r--r--sys/dev/sound/pcm/sound.c9
-rw-r--r--sys/dev/sound/pcm/sound.h1
-rw-r--r--sys/dev/sound/usb/uaudio.c10
-rw-r--r--sys/dev/usb/net/if_smsc.c2
-rw-r--r--sys/dev/usb/quirk/usb_quirk.c1
-rw-r--r--sys/dev/usb/usbdevs1
-rw-r--r--sys/dev/virtio/network/if_vtnet.c611
-rw-r--r--sys/dev/virtio/network/if_vtnetvar.h16
-rw-r--r--sys/dev/virtio/p9fs/virtio_p9fs.c11
-rw-r--r--sys/dev/vt/vt_core.c3
82 files changed, 7417 insertions, 5363 deletions
diff --git a/sys/dev/acpi_support/acpi_panasonic.c b/sys/dev/acpi_support/acpi_panasonic.c
index 8fea47ee45e8..5f54ca07c5a6 100644
--- a/sys/dev/acpi_support/acpi_panasonic.c
+++ b/sys/dev/acpi_support/acpi_panasonic.c
@@ -233,7 +233,9 @@ acpi_panasonic_shutdown(device_t dev)
/* Mute the main audio during reboot to prevent static burst to speaker. */
sc = device_get_softc(dev);
mute = 1;
+ ACPI_SERIAL_BEGIN(panasonic);
hkey_sound_mute(sc->handle, HKEY_SET, &mute);
+ ACPI_SERIAL_END(panasonic);
return (0);
}
diff --git a/sys/dev/amdsmu/amdsmu.c b/sys/dev/amdsmu/amdsmu.c
index 7b97888887c5..5029336af9cb 100644
--- a/sys/dev/amdsmu/amdsmu.c
+++ b/sys/dev/amdsmu/amdsmu.c
@@ -30,11 +30,21 @@ amdsmu_match(device_t dev, const struct amdsmu_product **product_out)
const uint16_t vendorid = pci_get_vendor(dev);
const uint16_t deviceid = pci_get_device(dev);
+ const uint32_t model = CPUID_TO_MODEL(cpu_id);
+
for (size_t i = 0; i < nitems(amdsmu_products); i++) {
const struct amdsmu_product *prod = &amdsmu_products[i];
if (vendorid == prod->amdsmu_vendorid &&
deviceid == prod->amdsmu_deviceid) {
+
+ /*
+ * Some Krackan Point devices have different ip blocks
+ * based on CPU model.
+ */
+ if (prod->model != 0x00 && model != prod->model)
+ continue;
+
if (product_out != NULL)
*product_out = prod;
return (true);
@@ -105,7 +115,7 @@ amdsmu_cmd(device_t dev, enum amdsmu_msg msg, uint32_t arg, uint32_t *ret)
amdsmu_write4(sc, SMU_REG_RESPONSE, SMU_RES_WAIT);
/* Write out command to registers. */
- amdsmu_write4(sc, SMU_REG_MESSAGE, msg);
+ amdsmu_write4(sc, sc->product->amdsmu_msg, msg);
amdsmu_write4(sc, SMU_REG_ARGUMENT, arg);
/* Wait for SMU response and handle it. */
@@ -175,7 +185,7 @@ amdsmu_get_ip_blocks(device_t dev)
sc->ip_blocks_active[i] = active;
if (!active)
continue;
- printf("%s%s", amdsmu_ip_blocks_names[i],
+ printf("%s%s", sc->product->ip_blocks_names[i],
i + 1 < sc->product->ip_block_count ? " " : "\n");
}
@@ -193,10 +203,10 @@ amdsmu_get_ip_blocks(device_t dev)
/* Create the sysctl node itself for the IP block. */
snprintf(sysctl_descr, sizeof sysctl_descr,
"Metrics about the %s AMD IP block",
- amdsmu_ip_blocks_names[i]);
+ sc->product->ip_blocks_names[i]);
sc->ip_block_sysctlnodes[i] = SYSCTL_ADD_NODE(sc->sysctlctx,
SYSCTL_CHILDREN(sc->ip_blocks_sysctlnode), OID_AUTO,
- amdsmu_ip_blocks_names[i], CTLFLAG_RD, NULL, sysctl_descr);
+ sc->product->ip_blocks_names[i], CTLFLAG_RD, NULL, sysctl_descr);
if (sc->ip_block_sysctlnodes[i] == NULL) {
device_printf(dev,
"could not add sysctl node for \"%s\"\n", sysctl_descr);
diff --git a/sys/dev/amdsmu/amdsmu.h b/sys/dev/amdsmu/amdsmu.h
index 4286d515ae77..0e7c4df37a43 100644
--- a/sys/dev/amdsmu/amdsmu.h
+++ b/sys/dev/amdsmu/amdsmu.h
@@ -14,7 +14,11 @@
#include <sys/bus.h>
#include <sys/eventhandler.h>
#include <sys/kernel.h>
-#include <machine/bus.h>
+
+#include <machine/cpu.h>
+#include <machine/md_var.h>
+#include <machine/cputypes.h>
+#include <machine/specialreg.h>
#include <x86/cputypes.h>
#include <dev/amdsmu/amdsmu_reg.h>
@@ -22,26 +26,7 @@
#define SMU_RES_READ_PERIOD_US 50
#define SMU_RES_READ_MAX 20000
-static const struct amdsmu_product {
- uint16_t amdsmu_vendorid;
- uint16_t amdsmu_deviceid;
- int16_t idlemask_reg;
- size_t ip_block_count;
-} amdsmu_products[] = {
- { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_CEZANNE_ROOT,
- SMU_REG_IDLEMASK_CEZANNE, 12 },
- { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_REMBRANDT_ROOT,
- SMU_REG_IDLEMASK_PHOENIX, 12 },
- { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_PHOENIX_ROOT,
- SMU_REG_IDLEMASK_PHOENIX, 21 },
- /*
- * XXX Strix Point (PCI_DEVICEID_AMD_STRIX_POINT_ROOT) doesn't support
- * S0i3 and thus doesn't have an idlemask. Since our driver doesn't
- * yet understand this, don't attach to Strix Point for the time being.
- */
-};
-
-static const char *const amdsmu_ip_blocks_names[] = {
+static const char *amdsmu_ip_blocks_names[] = {
"DISPLAY",
"CPU",
"GFX",
@@ -66,7 +51,69 @@ static const char *const amdsmu_ip_blocks_names[] = {
"VPE",
};
-CTASSERT(nitems(amdsmu_ip_blocks_names) <= 32);
+static const char *amdsmu_ip_blocks_names_v2[] = {
+ "DISPLAY",
+ "CPU",
+ "GFX",
+ "VDD",
+ "VDD_CCX",
+ "ACP",
+ "VCN_0",
+ "VCN_1",
+ "ISP",
+ "NBIO",
+ "DF",
+ "USB3_0",
+ "USB3_1",
+ "LAPIC",
+ "USB3_2",
+ "USB4_RT0",
+ "USB4_RT1",
+ "USB4_0",
+ "USB4_1",
+ "MPM",
+ "JPEG_0",
+ "JPEG_1",
+ "IPU",
+ "UMSCH",
+ "VPE",
+};
+
+#define IP_MAX_BLOCK_NAMES 32
+
+CTASSERT(nitems(amdsmu_ip_blocks_names) <= IP_MAX_BLOCK_NAMES);
+CTASSERT(nitems(amdsmu_ip_blocks_names_v2) <= IP_MAX_BLOCK_NAMES);
+
+static const struct amdsmu_product {
+ uint16_t amdsmu_vendorid;
+ uint16_t amdsmu_deviceid;
+ uint32_t model;
+ int16_t idlemask_reg;
+ size_t ip_block_count;
+ const char **ip_blocks_names;
+ uint32_t amdsmu_msg;
+} amdsmu_products[] = {
+ { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_CEZANNE_ROOT, 0x00,
+ SMU_REG_IDLEMASK_CEZANNE, 12 , amdsmu_ip_blocks_names,
+ SMU_REG_MSG_CEZANNE},
+ { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_REMBRANDT_ROOT, 0x00,
+ SMU_REG_IDLEMASK_PHOENIX, 12 , amdsmu_ip_blocks_names,
+ SMU_REG_MSG_CEZANNE},
+ { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_PHOENIX_ROOT, 0x00,
+ SMU_REG_IDLEMASK_PHOENIX, 21 , amdsmu_ip_blocks_names,
+ SMU_REG_MSG_CEZANNE},
+ { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_KRACKAN_POINT_ROOT, 0x00,
+ SMU_REG_IDLEMASK_KRACKAN, 22, amdsmu_ip_blocks_names,
+ SMU_REG_MSG_KRACKAN },
+ { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_KRACKAN_POINT_ROOT, 0x70,
+ SMU_REG_IDLEMASK_KRACKAN, 25, amdsmu_ip_blocks_names_v2,
+ SMU_REG_MSG_KRACKAN },
+ /*
+ * XXX Strix Point (PCI_DEVICEID_AMD_STRIX_POINT_ROOT) doesn't support
+ * S0i3 and thus doesn't have an idlemask. Since our driver doesn't
+ * yet understand this, don't attach to Strix Point for the time being.
+ */
+};
struct amdsmu_softc {
const struct amdsmu_product *product;
@@ -88,14 +135,13 @@ struct amdsmu_softc {
uint32_t active_ip_blocks;
struct sysctl_oid *ip_blocks_sysctlnode;
- struct sysctl_oid *ip_block_sysctlnodes[
- nitems(amdsmu_ip_blocks_names)];
- bool ip_blocks_active[
- nitems(amdsmu_ip_blocks_names)];
+ struct sysctl_oid *ip_block_sysctlnodes[IP_MAX_BLOCK_NAMES];
+ bool ip_blocks_active[IP_MAX_BLOCK_NAMES];
bus_space_handle_t metrics_space;
struct amdsmu_metrics metrics;
uint32_t idlemask;
+ uint32_t smu_msg;
};
static inline uint32_t
diff --git a/sys/dev/amdsmu/amdsmu_reg.h b/sys/dev/amdsmu/amdsmu_reg.h
index 6afbcf006535..c71082072b60 100644
--- a/sys/dev/amdsmu/amdsmu_reg.h
+++ b/sys/dev/amdsmu/amdsmu_reg.h
@@ -16,6 +16,7 @@
* out? Also, there are way more of these. I couldn't find a centralized place
* which lists them though.
*/
+#define PCI_DEVICEID_AMD_KRACKAN_POINT_ROOT 0x1122
#define PCI_DEVICEID_AMD_CEZANNE_ROOT 0x1630
#define PCI_DEVICEID_AMD_REMBRANDT_ROOT 0x14B5
#define PCI_DEVICEID_AMD_PHOENIX_ROOT 0x14E8
@@ -28,14 +29,18 @@
#define SMU_PHYSBASE_ADDR_HI 0x13B102EC
#define SMU_MEM_SIZE 0x1000
+
#define SMU_REG_SPACE_OFF 0x10000
-#define SMU_REG_MESSAGE 0x538
#define SMU_REG_RESPONSE 0x980
#define SMU_REG_ARGUMENT 0x9BC
#define SMU_REG_IDLEMASK_CEZANNE 0x94
#define SMU_REG_IDLEMASK_PHOENIX 0xD14
+#define SMU_REG_IDLEMASK_KRACKAN 0xF14
+
+#define SMU_REG_MSG_CEZANNE 0x538
+#define SMU_REG_MSG_KRACKAN 0x938
enum amdsmu_res {
SMU_RES_WAIT = 0x00,
diff --git a/sys/dev/asmc/asmc.c b/sys/dev/asmc/asmc.c
index 0a701e6fd663..8cd7842d03fd 100644
--- a/sys/dev/asmc/asmc.c
+++ b/sys/dev/asmc/asmc.c
@@ -98,13 +98,15 @@ static void asmc_sms_calibrate(device_t dev);
static int asmc_sms_intrfast(void *arg);
static void asmc_sms_printintr(device_t dev, uint8_t);
static void asmc_sms_task(void *arg, int pending);
+static void asmc_sms_init(device_t dev);
+static void asmc_detect_capabilities(device_t dev);
#ifdef ASMC_DEBUG
void asmc_dumpall(device_t);
static int asmc_key_dump(device_t, int);
#endif
/*
- * Model functions.
+ * Sysctl handlers.
*/
static int asmc_mb_sysctl_fanid(SYSCTL_HANDLER_ARGS);
static int asmc_mb_sysctl_fanspeed(SYSCTL_HANDLER_ARGS);
@@ -121,7 +123,7 @@ static int asmc_mbp_sysctl_light_left(SYSCTL_HANDLER_ARGS);
static int asmc_mbp_sysctl_light_right(SYSCTL_HANDLER_ARGS);
static int asmc_mbp_sysctl_light_control(SYSCTL_HANDLER_ARGS);
static int asmc_mbp_sysctl_light_left_10byte(SYSCTL_HANDLER_ARGS);
-static int asmc_wol_sysctl(SYSCTL_HANDLER_ARGS);
+static int asmc_aupo_sysctl(SYSCTL_HANDLER_ARGS);
static int asmc_key_getinfo(device_t, const char *, uint8_t *, char *);
@@ -138,474 +140,220 @@ static int asmc_sensor_read(device_t, const char *, int *);
static int asmc_sensor_sysctl(SYSCTL_HANDLER_ARGS);
static int asmc_detect_sensors(device_t);
static int asmc_key_dump_by_index(device_t, int, char *, char *, uint8_t *);
+static int asmc_key_search(device_t, const char *, unsigned int *);
+static const char *asmc_temp_desc(const char *key);
-struct asmc_model {
- const char *smc_model; /* smbios.system.product env var. */
- const char *smc_desc; /* driver description */
-
- /* Helper functions */
- int (*smc_sms_x)(SYSCTL_HANDLER_ARGS);
- int (*smc_sms_y)(SYSCTL_HANDLER_ARGS);
- int (*smc_sms_z)(SYSCTL_HANDLER_ARGS);
- int (*smc_fan_id)(SYSCTL_HANDLER_ARGS);
- int (*smc_fan_speed)(SYSCTL_HANDLER_ARGS);
- int (*smc_fan_safespeed)(SYSCTL_HANDLER_ARGS);
- int (*smc_fan_minspeed)(SYSCTL_HANDLER_ARGS);
- int (*smc_fan_maxspeed)(SYSCTL_HANDLER_ARGS);
- int (*smc_fan_targetspeed)(SYSCTL_HANDLER_ARGS);
- int (*smc_light_left)(SYSCTL_HANDLER_ARGS);
- int (*smc_light_right)(SYSCTL_HANDLER_ARGS);
- int (*smc_light_control)(SYSCTL_HANDLER_ARGS);
-
- const char *smc_temps[ASMC_TEMP_MAX];
- const char *smc_tempnames[ASMC_TEMP_MAX];
- const char *smc_tempdescs[ASMC_TEMP_MAX];
+/*
+ * SMC temperature key descriptions.
+ * These are universal across all Intel Apple hardware.
+ */
+static const struct {
+ const char *key;
+ const char *desc;
+} asmc_temp_descs[] = {
+ /* Ambient / airflow */
+ { "TA0P", "Ambient" },
+ { "TA0S", "PCIe Slot 1 Ambient" },
+ { "TA0p", "Ambient Air" },
+ { "TA1P", "Ambient 2" },
+ { "TA1S", "PCIe Slot 1 PCB" },
+ { "TA1p", "Ambient Air 2" },
+ { "TA2P", "Ambient 3" },
+ { "TA2S", "PCIe Slot 2 Ambient" },
+ { "TA3S", "PCIe Slot 2 PCB" },
+ { "TA0V", "Ambient" },
+ { "TALP", "Ambient Light Proximity" },
+ { "TaLC", "Airflow Left" },
+ { "TaRC", "Airflow Right" },
+ { "Ta0P", "Airflow Proximity" },
+ /* Battery / enclosure */
+ { "TB0T", "Enclosure Bottom" },
+ { "TB1T", "Battery 1" },
+ { "TB2T", "Battery 2" },
+ { "TB3T", "Battery 3" },
+ { "TBXT", "Battery" },
+ { "Tb0P", "BLC Proximity" },
+ /* CPU */
+ { "TC0C", "CPU Core 1" },
+ { "TC0D", "CPU Die" },
+ { "TC0E", "CPU 1" },
+ { "TC0F", "CPU 2" },
+ { "TC0G", "CPU Package GPU" },
+ { "TC0H", "CPU Heatsink" },
+ { "TC0h", "CPU Heatsink" },
+ { "TC0J", "CPU" },
+ { "TC0P", "CPU Proximity" },
+ { "TC0c", "CPU Core 1 PECI" },
+ { "TC0d", "CPU Die PECI" },
+ { "TC0p", "CPU Proximity" },
+ { "TC1C", "CPU Core 2" },
+ { "TC1c", "CPU Core 2 PECI" },
+ { "TC1P", "CPU Proximity 2" },
+ { "TC2C", "CPU Core 3" },
+ { "TC2P", "CPU Proximity 3" },
+ { "TC2c", "CPU Core 3 PECI" },
+ { "TC3C", "CPU Core 4" },
+ { "TC3P", "CPU Proximity 4" },
+ { "TC3c", "CPU Core 4 PECI" },
+ { "TC4C", "CPU Core 5" },
+ { "TC5C", "CPU Core 6" },
+ { "TC6C", "CPU Core 7" },
+ { "TC7C", "CPU Core 8" },
+ { "TC8C", "CPU Core 9" },
+ { "TCGC", "PECI GPU" },
+ { "TCGc", "PECI GPU" },
+ { "TCHP", "Charger Proximity" },
+ { "TCSA", "PECI SA" },
+ { "TCSC", "PECI SA" },
+ { "TCSc", "PECI SA" },
+ { "TCTD", "CPU DTS" },
+ { "TCXC", "PECI CPU" },
+ { "TCXc", "PECI CPU" },
+ { "TCPG", "CPU Package GPU" },
+ { "TCXR", "CPU PECI DTS" },
+ /* CPU dual-socket (Mac Pro) */
+ { "TCAG", "CPU A Package" },
+ { "TCAH", "CPU A Heatsink" },
+ { "TCBG", "CPU B Package" },
+ { "TCBH", "CPU B Heatsink" },
+ /* GPU */
+ { "TG0C", "GPU Core" },
+ { "TG0D", "GPU Diode" },
+ { "TG0H", "GPU Heatsink" },
+ { "TG0M", "GPU Memory" },
+ { "TG0P", "GPU Proximity" },
+ { "TG0T", "GPU Diode" },
+ { "TG0V", "GPU" },
+ { "TG0d", "GPU Die" },
+ { "TG0h", "GPU Heatsink" },
+ { "TG0p", "GPU Proximity" },
+ { "TGTV", "GPU" },
+ { "TG1D", "GPU 2 Diode" },
+ { "TG1H", "GPU 2 Heatsink" },
+ { "TG1P", "GPU 2 Proximity" },
+ { "TG1d", "GPU 2 Die" },
+ { "TGVP", "GPU Memory Proximity" },
+ /* Storage */
+ { "TH0A", "SSD A" },
+ { "TH0B", "SSD B" },
+ { "TH0C", "SSD C" },
+ { "TH0F", "SSD" },
+ { "TH0O", "HDD" },
+ { "TH0P", "HDD Proximity" },
+ { "TH0R", "SSD" },
+ { "TH0V", "SSD" },
+ { "TH0a", "SSD A" },
+ { "TH0b", "SSD B" },
+ { "TH0c", "SSD C" },
+ { "TH1O", "HDD 2" },
+ { "TH1P", "HDD Bay 2" },
+ { "TH2P", "HDD Bay 3" },
+ { "TH3P", "HDD Bay 4" },
+ { "Th0H", "Heatpipe 1" },
+ { "Th0N", "SSD" },
+ { "Th1H", "Heatpipe 2" },
+ { "Th2H", "Heatpipe 3" },
+ /* Thunderbolt */
+ { "THSP", "Thunderbolt Proximity" },
+ { "TI0P", "Thunderbolt 1" },
+ { "TI0p", "Thunderbolt 1" },
+ { "TI1P", "Thunderbolt 2" },
+ { "TI1p", "Thunderbolt 2" },
+ { "TTLD", "Thunderbolt Left" },
+ { "TTRD", "Thunderbolt Right" },
+ { "Te0T", "Thunderbolt Diode" },
+ { "Te0t", "Thunderbolt Diode" },
+ /* LCD */
+ { "TL0P", "LCD Proximity" },
+ { "TL0V", "LCD" },
+ { "TL0p", "LCD Proximity" },
+ { "TL1P", "LCD Panel 1" },
+ { "TL1V", "LCD 1" },
+ { "TL1p", "LCD Panel 1" },
+ { "TL1v", "LCD 1" },
+ { "TL2V", "LCD 2" },
+ { "TLAV", "LCD" },
+ { "TLBV", "LCD" },
+ { "TLCV", "LCD" },
+ /* Memory */
+ { "TM0P", "Memory Proximity" },
+ { "TM0S", "Memory Slot 1" },
+ { "TM0p", "Memory Proximity" },
+ { "TM1P", "Memory Riser A 2" },
+ { "TM1S", "Memory Slot 2" },
+ { "Tm0P", "Memory Proximity" },
+ { "Tm0p", "Memory Proximity" },
+ { "Tm1P", "Memory Proximity 2" },
+ { "TMBS", "Memory Bank" },
+ { "TMCD", "Memory DIMM" },
+ /* Northbridge / MCH */
+ { "TN0C", "Northbridge Core" },
+ { "TN0D", "Northbridge Diode" },
+ { "TN0H", "MCH Heatsink" },
+ { "TN0P", "Northbridge Proximity" },
+ { "TN1D", "MCH Die 2" },
+ { "TN1P", "Northbridge Proximity 2" },
+ /* PCH */
+ { "TP0P", "PCH Proximity" },
+ { "TP0p", "PCH Proximity" },
+ { "TPCD", "PCH Die" },
+ { "TPCd", "PCH Die" },
+ /* Optical drive */
+ { "TO0P", "Optical Drive" },
+ { "TO0p", "Optical Drive" },
+ /* Power supply */
+ { "Tp0C", "Power Supply" },
+ { "Tp0P", "Power Supply Proximity" },
+ { "Tp1C", "Power Supply 2" },
+ { "Tp1P", "Power Supply Component" },
+ { "Tp1p", "Power Supply Component" },
+ { "Tp2P", "Power Supply 2" },
+ { "Tp2h", "Power Supply 2" },
+ { "Tp2H", "Power Supply 2" },
+ { "Tp3P", "Power Supply 3 Inlet" },
+ { "Tp3h", "Power Supply 3" },
+ { "Tp3H", "Power Supply 3" },
+ { "Tp4P", "Power Supply 4" },
+ { "Tp5P", "Power Supply 5" },
+ /* Palm rest / trackpad */
+ { "Ts0P", "Palm Rest" },
+ { "Ts0S", "Memory Proximity" },
+ { "Ts1P", "Palm Rest 2" },
+ { "Ts1S", "Palm Rest 2" },
+ /* Wireless */
+ { "TW0P", "Wireless Proximity" },
+ { "TW0p", "Wireless Proximity" },
+ { "TBLR", "Bluetooth" },
+ /* Camera */
+ { "TS2P", "Camera Proximity" },
+ { "TS2V", "Camera" },
+ { "TS2p", "Camera Proximity" },
+ /* Expansion */
+ { "TS0C", "Expansion Slots" },
+ { "TS0P", "Expansion Proximity" },
+ { "TS0V", "Expansion" },
+ { "TS0p", "Expansion Proximity" },
+ /* Air vent */
+ { "TV0P", "Air Vent" },
+ /* VRM */
+ { "Tv0S", "VRM 1" },
+ { "Tv1S", "VRM 2" },
+ /* Misc */
+ { "TTF0", "Fan" },
+ { "TMLB", "Logic Board" },
};
-static const struct asmc_model *asmc_match(device_t dev);
-
-#define ASMC_SMS_FUNCS \
- .smc_sms_x = asmc_mb_sysctl_sms_x, \
- .smc_sms_y = asmc_mb_sysctl_sms_y, \
- .smc_sms_z = asmc_mb_sysctl_sms_z
-
-#define ASMC_SMS_FUNCS_DISABLED \
- .smc_sms_x = NULL, \
- .smc_sms_y = NULL, \
- .smc_sms_z = NULL
-
-#define ASMC_FAN_FUNCS \
- .smc_fan_id = asmc_mb_sysctl_fanid, \
- .smc_fan_speed = asmc_mb_sysctl_fanspeed, \
- .smc_fan_safespeed = asmc_mb_sysctl_fansafespeed, \
- .smc_fan_minspeed = asmc_mb_sysctl_fanminspeed, \
- .smc_fan_maxspeed = asmc_mb_sysctl_fanmaxspeed, \
- .smc_fan_targetspeed = asmc_mb_sysctl_fantargetspeed
-
-#define ASMC_FAN_FUNCS2 \
- .smc_fan_id = asmc_mb_sysctl_fanid, \
- .smc_fan_speed = asmc_mb_sysctl_fanspeed, \
- .smc_fan_safespeed = NULL, \
- .smc_fan_minspeed = asmc_mb_sysctl_fanminspeed, \
- .smc_fan_maxspeed = asmc_mb_sysctl_fanmaxspeed, \
- .smc_fan_targetspeed = asmc_mb_sysctl_fantargetspeed
-
-#define ASMC_LIGHT_FUNCS \
- .smc_light_left = asmc_mbp_sysctl_light_left, \
- .smc_light_right = asmc_mbp_sysctl_light_right, \
- .smc_light_control = asmc_mbp_sysctl_light_control
-
-#define ASMC_LIGHT_FUNCS_10BYTE \
- .smc_light_left = asmc_mbp_sysctl_light_left_10byte, \
- .smc_light_right = NULL, \
- .smc_light_control = asmc_mbp_sysctl_light_control
-
-#define ASMC_LIGHT_FUNCS_DISABLED \
- .smc_light_left = NULL, \
- .smc_light_right = NULL, \
- .smc_light_control = NULL
-
-#define ASMC_TEMPS_FUNCS_DISABLED \
- .smc_temps = {}, \
- .smc_tempnames = {}, \
- .smc_tempdescs = {} \
-
-static const struct asmc_model asmc_models[] = {
- {
- "MacBook1,1", "Apple SMC MacBook Core Duo",
- ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS_DISABLED,
- ASMC_MB_TEMPS, ASMC_MB_TEMPNAMES, ASMC_MB_TEMPDESCS
- },
-
- {
- "MacBook2,1", "Apple SMC MacBook Core 2 Duo",
- ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS_DISABLED,
- ASMC_MB_TEMPS, ASMC_MB_TEMPNAMES, ASMC_MB_TEMPDESCS
- },
-
- {
- "MacBook3,1", "Apple SMC MacBook Core 2 Duo",
- ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS_DISABLED,
- ASMC_MB31_TEMPS, ASMC_MB31_TEMPNAMES, ASMC_MB31_TEMPDESCS
- },
-
- {
- "MacBook7,1", "Apple SMC MacBook Core 2 Duo (mid 2010)",
- ASMC_SMS_FUNCS, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS_DISABLED,
- ASMC_MB71_TEMPS, ASMC_MB71_TEMPNAMES, ASMC_MB71_TEMPDESCS
- },
-
- {
- "MacBookPro1,1", "Apple SMC MacBook Pro Core Duo (15-inch)",
- ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
- ASMC_MBP_TEMPS, ASMC_MBP_TEMPNAMES, ASMC_MBP_TEMPDESCS
- },
-
- {
- "MacBookPro1,2", "Apple SMC MacBook Pro Core Duo (17-inch)",
- ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
- ASMC_MBP_TEMPS, ASMC_MBP_TEMPNAMES, ASMC_MBP_TEMPDESCS
- },
-
- {
- "MacBookPro2,1", "Apple SMC MacBook Pro Core 2 Duo (17-inch)",
- ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
- ASMC_MBP_TEMPS, ASMC_MBP_TEMPNAMES, ASMC_MBP_TEMPDESCS
- },
-
- {
- "MacBookPro2,2", "Apple SMC MacBook Pro Core 2 Duo (15-inch)",
- ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
- ASMC_MBP_TEMPS, ASMC_MBP_TEMPNAMES, ASMC_MBP_TEMPDESCS
- },
-
- {
- "MacBookPro3,1", "Apple SMC MacBook Pro Core 2 Duo (15-inch LED)",
- ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
- ASMC_MBP_TEMPS, ASMC_MBP_TEMPNAMES, ASMC_MBP_TEMPDESCS
- },
-
- {
- "MacBookPro3,2", "Apple SMC MacBook Pro Core 2 Duo (17-inch HD)",
- ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
- ASMC_MBP_TEMPS, ASMC_MBP_TEMPNAMES, ASMC_MBP_TEMPDESCS
- },
-
- {
- "MacBookPro4,1", "Apple SMC MacBook Pro Core 2 Duo (Penryn)",
- ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
- ASMC_MBP4_TEMPS, ASMC_MBP4_TEMPNAMES, ASMC_MBP4_TEMPDESCS
- },
-
- {
- "MacBookPro5,1", "Apple SMC MacBook Pro Core 2 Duo (2008/2009)",
- ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
- ASMC_MBP51_TEMPS, ASMC_MBP51_TEMPNAMES, ASMC_MBP51_TEMPDESCS
- },
-
- {
- "MacBookPro5,5", "Apple SMC MacBook Pro Core 2 Duo (Mid 2009)",
- ASMC_SMS_FUNCS, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS,
- ASMC_MBP55_TEMPS, ASMC_MBP55_TEMPNAMES, ASMC_MBP55_TEMPDESCS
- },
-
- {
- "MacBookPro6,2", "Apple SMC MacBook Pro (Mid 2010, 15-inch)",
- ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
- ASMC_MBP62_TEMPS, ASMC_MBP62_TEMPNAMES, ASMC_MBP62_TEMPDESCS
- },
-
- {
- "MacBookPro8,1", "Apple SMC MacBook Pro (early 2011, 13-inch)",
- ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS,
- ASMC_MBP81_TEMPS, ASMC_MBP81_TEMPNAMES, ASMC_MBP81_TEMPDESCS
- },
-
- {
- "MacBookPro8,2", "Apple SMC MacBook Pro (early 2011)",
- ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
- ASMC_MBP82_TEMPS, ASMC_MBP82_TEMPNAMES, ASMC_MBP82_TEMPDESCS
- },
-
- {
- "MacBookPro8,3", "Apple SMC MacBook Pro (early 2011, 17-inch)",
- ASMC_SMS_FUNCS, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS,
- ASMC_MBP83_TEMPS, ASMC_MBP83_TEMPNAMES, ASMC_MBP83_TEMPDESCS
- },
-
- {
- "MacBookPro9,1", "Apple SMC MacBook Pro (mid 2012, 15-inch)",
- ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
- ASMC_MBP91_TEMPS, ASMC_MBP91_TEMPNAMES, ASMC_MBP91_TEMPDESCS
- },
-
- {
- "MacBookPro9,2", "Apple SMC MacBook Pro (mid 2012, 13-inch)",
- ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
- ASMC_MBP92_TEMPS, ASMC_MBP92_TEMPNAMES, ASMC_MBP92_TEMPDESCS
- },
-
- {
- "MacBookPro11,2", "Apple SMC MacBook Pro Retina Core i7 (2013/2014)",
- ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS,
- ASMC_MBP112_TEMPS, ASMC_MBP112_TEMPNAMES, ASMC_MBP112_TEMPDESCS
- },
-
- {
- "MacBookPro11,3", "Apple SMC MacBook Pro Retina Core i7 (2013/2014)",
- ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
- ASMC_MBP113_TEMPS, ASMC_MBP113_TEMPNAMES, ASMC_MBP113_TEMPDESCS
- },
-
- {
- "MacBookPro11,4", "Apple SMC MacBook Pro Retina Core i7 (mid 2015, 15-inch)",
- ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS,
- ASMC_MBP114_TEMPS, ASMC_MBP114_TEMPNAMES, ASMC_MBP114_TEMPDESCS
- },
-
- {
- "MacBookPro11,5",
- "Apple SMC MacBook Pro Retina Core i7 (mid 2015, 15-inch, AMD GPU)",
- ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS,
- ASMC_MBP115_TEMPS, ASMC_MBP115_TEMPNAMES, ASMC_MBP115_TEMPDESCS
- },
-
- {
- "MacBookPro13,1", "Apple SMC MacBook Pro Retina Core i5 (late 2016, 13-inch)",
- ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS,
- ASMC_MBP131_TEMPS, ASMC_MBP131_TEMPNAMES, ASMC_MBP131_TEMPDESCS
- },
-
- /* The Mac Mini has no SMS */
- {
- "Macmini1,1", "Apple SMC Mac Mini",
- ASMC_SMS_FUNCS_DISABLED,
- ASMC_FAN_FUNCS,
- ASMC_LIGHT_FUNCS_DISABLED,
- ASMC_MM_TEMPS, ASMC_MM_TEMPNAMES, ASMC_MM_TEMPDESCS
- },
-
- /* The Mac Mini 2,1 has no SMS */
- {
- "Macmini2,1", "Apple SMC Mac Mini 2,1",
- ASMC_SMS_FUNCS_DISABLED,
- ASMC_FAN_FUNCS,
- ASMC_LIGHT_FUNCS_DISABLED,
- ASMC_MM21_TEMPS, ASMC_MM21_TEMPNAMES, ASMC_MM21_TEMPDESCS
- },
-
- /* The Mac Mini 3,1 has no SMS */
- {
- "Macmini3,1", "Apple SMC Mac Mini 3,1",
- ASMC_SMS_FUNCS_DISABLED,
- ASMC_FAN_FUNCS,
- ASMC_LIGHT_FUNCS_DISABLED,
- ASMC_MM31_TEMPS, ASMC_MM31_TEMPNAMES, ASMC_MM31_TEMPDESCS
- },
-
- /* The Mac Mini 4,1 (Mid-2010) has no SMS */
- {
- "Macmini4,1", "Apple SMC Mac mini 4,1 (Mid-2010)",
- ASMC_SMS_FUNCS_DISABLED,
- ASMC_FAN_FUNCS2,
- ASMC_LIGHT_FUNCS_DISABLED,
- ASMC_MM41_TEMPS, ASMC_MM41_TEMPNAMES, ASMC_MM41_TEMPDESCS
- },
-
- /* The Mac Mini 5,1 has no SMS */
- /* - same sensors as Mac Mini 5,2 */
- {
- "Macmini5,1", "Apple SMC Mac Mini 5,1",
- ASMC_SMS_FUNCS_DISABLED,
- ASMC_FAN_FUNCS2,
- ASMC_LIGHT_FUNCS_DISABLED,
- ASMC_MM52_TEMPS, ASMC_MM52_TEMPNAMES, ASMC_MM52_TEMPDESCS
- },
-
- /* The Mac Mini 5,2 has no SMS */
- {
- "Macmini5,2", "Apple SMC Mac Mini 5,2",
- ASMC_SMS_FUNCS_DISABLED,
- ASMC_FAN_FUNCS2,
- ASMC_LIGHT_FUNCS_DISABLED,
- ASMC_MM52_TEMPS, ASMC_MM52_TEMPNAMES, ASMC_MM52_TEMPDESCS
- },
-
- /* The Mac Mini 5,3 has no SMS */
- /* - same sensors as Mac Mini 5,2 */
- {
- "Macmini5,3", "Apple SMC Mac Mini 5,3",
- ASMC_SMS_FUNCS_DISABLED,
- ASMC_FAN_FUNCS2,
- ASMC_LIGHT_FUNCS_DISABLED,
- ASMC_MM52_TEMPS, ASMC_MM52_TEMPNAMES, ASMC_MM52_TEMPDESCS
- },
-
- /* The Mac Mini 6,1 has no SMS */
- {
- "Macmini6,1", "Apple SMC Mac Mini 6,1",
- ASMC_SMS_FUNCS_DISABLED,
- ASMC_FAN_FUNCS2,
- ASMC_LIGHT_FUNCS_DISABLED,
- ASMC_MM61_TEMPS, ASMC_MM61_TEMPNAMES, ASMC_MM61_TEMPDESCS
- },
-
- /* The Mac Mini 6,2 has no SMS */
- {
- "Macmini6,2", "Apple SMC Mac Mini 6,2",
- ASMC_SMS_FUNCS_DISABLED,
- ASMC_FAN_FUNCS2,
- ASMC_LIGHT_FUNCS_DISABLED,
- ASMC_MM62_TEMPS, ASMC_MM62_TEMPNAMES, ASMC_MM62_TEMPDESCS
- },
-
- /* The Mac Mini 7,1 has no SMS */
- {
- "Macmini7,1", "Apple SMC Mac Mini 7,1",
- ASMC_SMS_FUNCS_DISABLED,
- ASMC_FAN_FUNCS2,
- ASMC_LIGHT_FUNCS_DISABLED,
- ASMC_MM71_TEMPS, ASMC_MM71_TEMPNAMES, ASMC_MM71_TEMPDESCS
- },
-
- /* Idem for the Mac Pro "Quad Core" (original) */
- {
- "MacPro1,1", "Apple SMC Mac Pro (Quad Core)",
- ASMC_SMS_FUNCS_DISABLED,
- ASMC_FAN_FUNCS,
- ASMC_LIGHT_FUNCS_DISABLED,
- ASMC_MP1_TEMPS, ASMC_MP1_TEMPNAMES, ASMC_MP1_TEMPDESCS
- },
-
- /* Idem for the Mac Pro (Early 2008) */
- {
- "MacPro3,1", "Apple SMC Mac Pro (Early 2008)",
- ASMC_SMS_FUNCS_DISABLED,
- ASMC_FAN_FUNCS,
- ASMC_LIGHT_FUNCS_DISABLED,
- ASMC_MP31_TEMPS, ASMC_MP31_TEMPNAMES, ASMC_MP31_TEMPDESCS
- },
-
- /* Idem for the Mac Pro (8-core) */
- {
- "MacPro2", "Apple SMC Mac Pro (8-core)",
- ASMC_SMS_FUNCS_DISABLED,
- ASMC_FAN_FUNCS,
- ASMC_LIGHT_FUNCS_DISABLED,
- ASMC_MP2_TEMPS, ASMC_MP2_TEMPNAMES, ASMC_MP2_TEMPDESCS
- },
-
- /* Idem for the MacPro 2010*/
- {
- "MacPro5,1", "Apple SMC MacPro (2010)",
- ASMC_SMS_FUNCS_DISABLED,
- ASMC_FAN_FUNCS,
- ASMC_LIGHT_FUNCS_DISABLED,
- ASMC_MP5_TEMPS, ASMC_MP5_TEMPNAMES, ASMC_MP5_TEMPDESCS
- },
-
- /* Idem for the Mac Pro 2013 (cylinder) */
- {
- "MacPro6,1", "Apple SMC Mac Pro (2013)",
- ASMC_SMS_FUNCS_DISABLED,
- ASMC_FAN_FUNCS2,
- ASMC_LIGHT_FUNCS_DISABLED,
- ASMC_MP6_TEMPS, ASMC_MP6_TEMPNAMES, ASMC_MP6_TEMPDESCS
- },
-
- {
- "MacBookAir1,1", "Apple SMC MacBook Air",
- ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS_DISABLED,
- ASMC_MBA_TEMPS, ASMC_MBA_TEMPNAMES, ASMC_MBA_TEMPDESCS
- },
-
- {
- "MacBookAir3,1", "Apple SMC MacBook Air Core 2 Duo (Late 2010)",
- ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS_DISABLED,
- ASMC_MBA3_TEMPS, ASMC_MBA3_TEMPNAMES, ASMC_MBA3_TEMPDESCS
- },
-
- {
- "MacBookAir4,1", "Apple SMC Macbook Air 11-inch (Mid 2011)",
- ASMC_SMS_FUNCS_DISABLED,
- ASMC_FAN_FUNCS2,
- ASMC_LIGHT_FUNCS,
- ASMC_MBA4_TEMPS, ASMC_MBA4_TEMPNAMES, ASMC_MBA4_TEMPDESCS
- },
-
- {
- "MacBookAir4,2", "Apple SMC Macbook Air 13-inch (Mid 2011)",
- ASMC_SMS_FUNCS_DISABLED,
- ASMC_FAN_FUNCS2,
- ASMC_LIGHT_FUNCS,
- ASMC_MBA4_TEMPS, ASMC_MBA4_TEMPNAMES, ASMC_MBA4_TEMPDESCS
- },
-
- {
- "MacBookAir5,1", "Apple SMC MacBook Air 11-inch (Mid 2012)",
- ASMC_SMS_FUNCS_DISABLED,
- ASMC_FAN_FUNCS2,
- ASMC_LIGHT_FUNCS,
- ASMC_MBA5_TEMPS, ASMC_MBA5_TEMPNAMES, ASMC_MBA5_TEMPDESCS
- },
-
- {
- "MacBookAir5,2", "Apple SMC MacBook Air 13-inch (Mid 2012)",
- ASMC_SMS_FUNCS_DISABLED,
- ASMC_FAN_FUNCS2,
- ASMC_LIGHT_FUNCS,
- ASMC_MBA5_TEMPS, ASMC_MBA5_TEMPNAMES, ASMC_MBA5_TEMPDESCS
- },
- {
- "MacBookAir6,1", "Apple SMC MacBook Air 11-inch (Early 2013)",
- ASMC_SMS_FUNCS_DISABLED,
- ASMC_FAN_FUNCS2,
- ASMC_LIGHT_FUNCS_10BYTE,
- ASMC_MBA6_TEMPS, ASMC_MBA6_TEMPNAMES, ASMC_MBA6_TEMPDESCS
- },
- {
- "MacBookAir6,2", "Apple SMC MacBook Air 13-inch (Early 2013)",
- ASMC_SMS_FUNCS_DISABLED,
- ASMC_FAN_FUNCS2,
- ASMC_LIGHT_FUNCS_10BYTE,
- ASMC_MBA6_TEMPS, ASMC_MBA6_TEMPNAMES, ASMC_MBA6_TEMPDESCS
- },
- {
- "MacBookAir7,1", "Apple SMC MacBook Air 11-inch (Early 2015)",
- ASMC_SMS_FUNCS_DISABLED,
- ASMC_FAN_FUNCS2,
- ASMC_LIGHT_FUNCS,
- ASMC_MBA7_TEMPS, ASMC_MBA7_TEMPNAMES, ASMC_MBA7_TEMPDESCS
- },
- {
- "MacBookAir7,2", "Apple SMC MacBook Air 13-inch (Early 2015)",
- ASMC_SMS_FUNCS_DISABLED,
- ASMC_FAN_FUNCS2,
- ASMC_LIGHT_FUNCS,
- ASMC_MBA7_TEMPS, ASMC_MBA7_TEMPNAMES, ASMC_MBA7_TEMPDESCS
- }
-};
+static const char *
+asmc_temp_desc(const char *key)
+{
+ unsigned int i;
-static const struct asmc_model asmc_generic_models[] = {
- {
- .smc_model = "MacBookAir",
- .smc_desc = NULL,
- ASMC_SMS_FUNCS_DISABLED,
- ASMC_FAN_FUNCS2,
- ASMC_LIGHT_FUNCS,
- ASMC_TEMPS_FUNCS_DISABLED
- },
- {
- .smc_model = "MacBookPro",
- .smc_desc = NULL,
- ASMC_SMS_FUNCS_DISABLED,
- ASMC_FAN_FUNCS2,
- ASMC_LIGHT_FUNCS,
- ASMC_TEMPS_FUNCS_DISABLED
- },
- {
- .smc_model = "MacPro",
- .smc_desc = NULL,
- ASMC_SMS_FUNCS_DISABLED,
- ASMC_FAN_FUNCS2,
- ASMC_LIGHT_FUNCS_DISABLED,
- ASMC_TEMPS_FUNCS_DISABLED
- },
- {
- .smc_model = "Macmini",
- .smc_desc = NULL,
- ASMC_SMS_FUNCS_DISABLED,
- ASMC_FAN_FUNCS2,
- ASMC_LIGHT_FUNCS_DISABLED,
- ASMC_TEMPS_FUNCS_DISABLED
+ for (i = 0; i < nitems(asmc_temp_descs); i++) {
+ if (strcmp(asmc_temp_descs[i].key, key) == 0)
+ return (asmc_temp_descs[i].desc);
}
-};
-
-#undef ASMC_SMS_FUNCS
-#undef ASMC_SMS_FUNCS_DISABLED
-#undef ASMC_FAN_FUNCS
-#undef ASMC_FAN_FUNCS2
-#undef ASMC_LIGHT_FUNCS
+ return ("Temperature");
+}
/*
* Driver methods.
@@ -651,44 +399,10 @@ DRIVER_MODULE(asmc, acpi, asmc_driver, NULL, NULL);
MODULE_DEPEND(asmc, acpi, 1, 1, 1);
MODULE_DEPEND(asmc, backlight, 1, 1, 1);
-static const struct asmc_model *
-asmc_match(device_t dev)
-{
- const struct asmc_model *model;
- char *model_name;
- int i;
-
- model = NULL;
-
- model_name = kern_getenv("smbios.system.product");
- if (model_name == NULL)
- goto out;
-
- for (i = 0; i < nitems(asmc_models); i++) {
- if (strncmp(model_name, asmc_models[i].smc_model,
- strlen(model_name)) == 0) {
- model = &asmc_models[i];
- goto out;
- }
- }
- for (i = 0; i < nitems(asmc_generic_models); i++) {
- if (strncmp(model_name, asmc_generic_models[i].smc_model,
- strlen(asmc_generic_models[i].smc_model)) == 0) {
- model = &asmc_generic_models[i];
- goto out;
- }
- }
-
-out:
- freeenv(model_name);
- return (model);
-}
-
static int
asmc_probe(device_t dev)
{
- const struct asmc_model *model;
- const char *device_desc;
+ char *product;
int rv;
if (resource_disabled("asmc", 0))
@@ -696,16 +410,9 @@ asmc_probe(device_t dev)
rv = ACPI_ID_PROBE(device_get_parent(dev), dev, asmc_ids, NULL);
if (rv > 0)
return (rv);
-
- model = asmc_match(dev);
- if (model == NULL) {
- device_printf(dev, "model not recognized\n");
- return (ENXIO);
- }
- device_desc = model->smc_desc == NULL ?
- model->smc_model : model->smc_desc;
- device_set_desc(dev, device_desc);
-
+ product = kern_getenv("smbios.system.product");
+ device_set_descf(dev, "Apple %s", product ? product : "SMC");
+ freeenv(product);
return (rv);
}
@@ -718,7 +425,6 @@ asmc_attach(device_t dev)
struct asmc_softc *sc = device_get_softc(dev);
struct sysctl_ctx_list *sysctlctx;
struct sysctl_oid *sysctlnode;
- const struct asmc_model *model;
sc->sc_ioport = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
&sc->sc_rid_port, RF_ACTIVE);
@@ -730,12 +436,20 @@ asmc_attach(device_t dev)
sysctlctx = device_get_sysctl_ctx(dev);
sysctlnode = device_get_sysctl_tree(dev);
- model = asmc_match(dev);
-
mtx_init(&sc->sc_mtx, "asmc", NULL, MTX_SPIN);
- sc->sc_model = model;
- asmc_init(dev);
+ /* Read SMC revision, key count, fan count */
+ ret = asmc_init(dev);
+ if (ret != 0) {
+ device_printf(dev, "SMC not responding\n");
+ goto err;
+ }
+
+ /* Probe SMC keys to detect capabilities */
+ asmc_detect_capabilities(dev);
+
+ /* Auto-detect and register voltage/current/power/ambient/temp sensors */
+ asmc_detect_sensors(dev);
/*
* dev.asmc.n.fan.* tree.
@@ -756,37 +470,43 @@ asmc_attach(device_t dev)
SYSCTL_CHILDREN(sc->sc_fan_tree[i]),
OID_AUTO, "id",
CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, j,
- model->smc_fan_id, "I", "Fan ID");
+ asmc_mb_sysctl_fanid, "I", "Fan ID");
SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(sc->sc_fan_tree[i]),
OID_AUTO, "speed",
CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, j,
- model->smc_fan_speed, "I", "Fan speed in RPM");
+ asmc_mb_sysctl_fanspeed, "I", "Fan speed in RPM");
- SYSCTL_ADD_PROC(sysctlctx,
- SYSCTL_CHILDREN(sc->sc_fan_tree[i]),
- OID_AUTO, "safespeed",
- CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, j,
- model->smc_fan_safespeed, "I", "Fan safe speed in RPM");
+ if (sc->sc_has_safespeed) {
+ SYSCTL_ADD_PROC(sysctlctx,
+ SYSCTL_CHILDREN(sc->sc_fan_tree[i]),
+ OID_AUTO, "safespeed",
+ CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, j,
+ asmc_mb_sysctl_fansafespeed, "I",
+ "Fan safe speed in RPM");
+ }
SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(sc->sc_fan_tree[i]),
OID_AUTO, "minspeed",
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, j,
- model->smc_fan_minspeed, "I", "Fan minimum speed in RPM");
+ asmc_mb_sysctl_fanminspeed, "I",
+ "Fan minimum speed in RPM");
SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(sc->sc_fan_tree[i]),
OID_AUTO, "maxspeed",
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, j,
- model->smc_fan_maxspeed, "I", "Fan maximum speed in RPM");
+ asmc_mb_sysctl_fanmaxspeed, "I",
+ "Fan maximum speed in RPM");
SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(sc->sc_fan_tree[i]),
OID_AUTO, "targetspeed",
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, j,
- model->smc_fan_targetspeed, "I", "Fan target speed in RPM");
+ asmc_mb_sysctl_fantargetspeed, "I",
+ "Fan target speed in RPM");
SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(sc->sc_fan_tree[i]),
@@ -803,19 +523,19 @@ asmc_attach(device_t dev)
SYSCTL_CHILDREN(sysctlnode), OID_AUTO, "temp",
CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Temperature sensors");
- for (i = 0; model->smc_temps[i]; i++) {
+ for (i = 0; i < sc->sc_temp_count; i++) {
SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(sc->sc_temp_tree),
- OID_AUTO, model->smc_tempnames[i],
+ OID_AUTO, sc->sc_temp_sensors[i],
CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, i,
asmc_temp_sysctl, "I",
- model->smc_tempdescs[i]);
+ asmc_temp_desc(sc->sc_temp_sensors[i]));
}
/*
* dev.asmc.n.light
*/
- if (model->smc_light_left) {
+ if (sc->sc_has_light) {
sc->sc_light_tree = SYSCTL_ADD_NODE(sysctlctx,
SYSCTL_CHILDREN(sysctlnode), OID_AUTO, "light",
CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
@@ -825,21 +545,29 @@ asmc_attach(device_t dev)
SYSCTL_CHILDREN(sc->sc_light_tree),
OID_AUTO, "left",
CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
- dev, 0, model->smc_light_left, "I",
- "Keyboard backlight left sensor");
+ dev, 0,
+ sc->sc_light_len == ASMC_LIGHT_LONGLEN ?
+ asmc_mbp_sysctl_light_left_10byte :
+ asmc_mbp_sysctl_light_left,
+ "I", "Keyboard backlight left sensor");
- SYSCTL_ADD_PROC(sysctlctx,
- SYSCTL_CHILDREN(sc->sc_light_tree),
- OID_AUTO, "right",
- CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, 0,
- model->smc_light_right, "I",
- "Keyboard backlight right sensor");
+ if (sc->sc_light_len != ASMC_LIGHT_LONGLEN &&
+ asmc_key_getinfo(dev, ASMC_KEY_LIGHTRIGHT,
+ NULL, NULL) == 0) {
+ SYSCTL_ADD_PROC(sysctlctx,
+ SYSCTL_CHILDREN(sc->sc_light_tree),
+ OID_AUTO, "right",
+ CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ dev, 0,
+ asmc_mbp_sysctl_light_right, "I",
+ "Keyboard backlight right sensor");
+ }
SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(sc->sc_light_tree),
OID_AUTO, "control",
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MPSAFE,
- dev, 0, model->smc_light_control, "I",
+ dev, 0, asmc_mbp_sysctl_light_control, "I",
"Keyboard backlight brightness control");
sc->sc_kbd_bkl = backlight_register("asmc", dev);
@@ -887,10 +615,15 @@ asmc_attach(device_t dev)
"SMC key type (4 chars)");
#endif
- if (model->smc_sms_x == NULL)
+ if (!sc->sc_has_sms)
goto nosms;
/*
+ * Initialize SMS hardware.
+ */
+ asmc_sms_init(dev);
+
+ /*
* dev.asmc.n.sms tree.
*/
sc->sc_sms_tree = SYSCTL_ADD_NODE(sysctlctx,
@@ -901,21 +634,21 @@ asmc_attach(device_t dev)
SYSCTL_CHILDREN(sc->sc_sms_tree),
OID_AUTO, "x",
CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
- dev, 0, model->smc_sms_x, "I",
+ dev, 0, asmc_mb_sysctl_sms_x, "I",
"Sudden Motion Sensor X value");
SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(sc->sc_sms_tree),
OID_AUTO, "y",
CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
- dev, 0, model->smc_sms_y, "I",
+ dev, 0, asmc_mb_sysctl_sms_y, "I",
"Sudden Motion Sensor Y value");
SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(sc->sc_sms_tree),
OID_AUTO, "z",
CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
- dev, 0, model->smc_sms_z, "I",
+ dev, 0, asmc_mb_sysctl_sms_z, "I",
"Sudden Motion Sensor Z value");
/*
@@ -970,6 +703,10 @@ asmc_detach(device_t dev)
if (sc->sc_kbd_bkl != NULL)
backlight_destroy(sc->sc_kbd_bkl);
+ /* Free temperature sensor key arrays */
+ for (int i = 0; i < sc->sc_temp_count; i++)
+ free(sc->sc_temp_sensors[i], M_DEVBUF);
+
/* Free sensor key arrays */
for (int i = 0; i < sc->sc_voltage_count; i++)
free(sc->sc_voltage_sensors[i], M_DEVBUF);
@@ -1036,24 +773,73 @@ asmc_dumpall(device_t dev)
}
#endif
+/*
+ * Initialize SMC: read revision, key count, fan count.
+ * SMS initialization is handled separately in asmc_sms_init().
+ */
static int
asmc_init(device_t dev)
{
struct asmc_softc *sc = device_get_softc(dev);
struct sysctl_ctx_list *sysctlctx;
uint8_t buf[6];
- int i, error = 1;
+ int error;
sysctlctx = device_get_sysctl_ctx(dev);
error = asmc_key_read(dev, ASMC_KEY_REV, buf, 6);
if (error != 0)
- goto out_err;
+ goto out;
device_printf(dev, "SMC revision: %x.%x%x%x\n", buf[0], buf[1], buf[2],
ntohs(*(uint16_t *)buf + 4));
- if (sc->sc_model->smc_sms_x == NULL)
- goto nosms;
+ /* Auto power-on after AC power loss (AUPO). */
+ if (asmc_key_read(dev, ASMC_KEY_AUPO, buf, 1) == 0) {
+ SYSCTL_ADD_PROC(sysctlctx,
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "auto_poweron",
+ CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
+ dev, 0, asmc_aupo_sysctl, "I",
+ "Auto power-on after AC power loss (0=off, 1=on)");
+ }
+
+ sc->sc_nfan = asmc_fan_count(dev);
+ if (sc->sc_nfan > ASMC_MAXFANS) {
+ device_printf(dev,
+ "more than %d fans were detected. Please report this.\n",
+ ASMC_MAXFANS);
+ sc->sc_nfan = ASMC_MAXFANS;
+ }
+
+ /*
+ * Read and cache the number of SMC keys (32 bit buffer)
+ */
+ if (asmc_key_read(dev, ASMC_NKEYS, buf, 4) == 0) {
+ sc->sc_nkeys = be32dec(buf);
+ if (bootverbose)
+ device_printf(dev, "number of keys: %d\n",
+ sc->sc_nkeys);
+ } else {
+ sc->sc_nkeys = 0;
+ }
+
+out:
+#ifdef ASMC_DEBUG
+ asmc_dumpall(dev);
+#endif
+ return (error);
+}
+
+/*
+ * Initialize the Sudden Motion Sensor hardware.
+ * Called from asmc_attach() after capabilities are detected.
+ */
+static void
+asmc_sms_init(device_t dev)
+{
+ struct asmc_softc *sc = device_get_softc(dev);
+ uint8_t buf[2];
+ int i;
/*
* We are ready to receive interrupts from the SMS.
@@ -1106,9 +892,8 @@ asmc_init(device_t dev)
for (i = 0; i < 1000; i++) {
if (asmc_key_read(dev, ASMC_KEY_SMS, buf, 2) == 0 &&
(buf[0] == ASMC_SMS_INIT1 && buf[1] == ASMC_SMS_INIT2)) {
- error = 0;
sc->sc_sms_intr_works = 1;
- goto out;
+ goto done;
}
buf[0] = ASMC_SMS_INIT1;
buf[1] = ASMC_SMS_INIT2;
@@ -1118,50 +903,71 @@ asmc_init(device_t dev)
}
device_printf(dev, "WARNING: Sudden Motion Sensor not initialized!\n");
-out:
+done:
asmc_sms_calibrate(dev);
-nosms:
- /* Wake-on-LAN convenience sysctl */
- if (asmc_key_read(dev, ASMC_KEY_AUPO, buf, 1) == 0) {
- SYSCTL_ADD_PROC(sysctlctx,
- SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
- OID_AUTO, "wol",
- CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
- dev, 0, asmc_wol_sysctl, "I",
- "Wake-on-LAN enable (0=off, 1=on)");
- }
+}
- sc->sc_nfan = asmc_fan_count(dev);
- if (sc->sc_nfan > ASMC_MAXFANS) {
- device_printf(dev,
- "more than %d fans were detected. Please report this.\n",
- ASMC_MAXFANS);
- sc->sc_nfan = ASMC_MAXFANS;
- }
+/*
+ * Probe SMC keys to detect hardware capabilities.
+ */
+static void
+asmc_detect_capabilities(device_t dev)
+{
+ struct asmc_softc *sc = device_get_softc(dev);
+ uint8_t len;
+ char type[ASMC_TYPELEN + 1];
- /*
- * Read and cache the number of SMC keys (32 bit buffer)
- */
- if (asmc_key_read(dev, ASMC_NKEYS, buf, 4) == 0) {
- sc->sc_nkeys = be32dec(buf);
- if (bootverbose)
- device_printf(dev, "number of keys: %d\n",
- sc->sc_nkeys);
+ /* SMS: require all keys used by asmc_sms_init() */
+ sc->sc_has_sms =
+ (asmc_key_getinfo(dev, ASMC_KEY_SMS,
+ &len, type) == 0 &&
+ asmc_key_getinfo(dev, ASMC_KEY_SMS_X,
+ &len, type) == 0 &&
+ asmc_key_getinfo(dev, ASMC_KEY_SMS_Y,
+ &len, type) == 0 &&
+ asmc_key_getinfo(dev, ASMC_KEY_SMS_Z,
+ &len, type) == 0 &&
+ asmc_key_getinfo(dev, ASMC_KEY_SMS_LOW,
+ &len, type) == 0 &&
+ asmc_key_getinfo(dev, ASMC_KEY_SMS_HIGH,
+ &len, type) == 0 &&
+ asmc_key_getinfo(dev, ASMC_KEY_SMS_LOW_INT,
+ &len, type) == 0 &&
+ asmc_key_getinfo(dev, ASMC_KEY_SMS_HIGH_INT,
+ &len, type) == 0 &&
+ asmc_key_getinfo(dev, ASMC_KEY_SMS_FLAG,
+ &len, type) == 0 &&
+ asmc_key_getinfo(dev, ASMC_KEY_INTOK,
+ &len, type) == 0);
+
+ /* Light sensor: require ALV0 (len 6 or 10) and LKSB */
+ if (asmc_key_getinfo(dev, ASMC_KEY_LIGHTLEFT,
+ &len, type) == 0 &&
+ (len == ASMC_LIGHT_SHORTLEN || len == ASMC_LIGHT_LONGLEN) &&
+ asmc_key_getinfo(dev, ASMC_KEY_LIGHTVALUE,
+ NULL, NULL) == 0) {
+ sc->sc_has_light = 1;
+ sc->sc_light_len = len;
} else {
- sc->sc_nkeys = 0;
+ sc->sc_has_light = 0;
+ sc->sc_light_len = 0;
}
- /*
- * Auto-detect and register voltage/current/power/ambient sensors.
- * Scans SMC keys and creates sysctls for detected sensors.
- */
- asmc_detect_sensors(dev);
+ /* Fan safe speed */
+ sc->sc_has_safespeed =
+ (asmc_key_getinfo(dev, ASMC_KEY_FANSAFESPEED0,
+ &len, type) == 0);
-out_err:
-#ifdef ASMC_DEBUG
- asmc_dumpall(dev);
-#endif
- return (error);
+ /* Ambient light interrupt source */
+ sc->sc_has_alsl =
+ (asmc_key_getinfo(dev, ASMC_KEY_LIGHTSRC,
+ &len, type) == 0);
+
+ if (bootverbose)
+ device_printf(dev,
+ "capabilities: sms=%d light=%d (len=%d) safespeed=%d alsl=%d\n",
+ sc->sc_has_sms, sc->sc_has_light, sc->sc_light_len,
+ sc->sc_has_safespeed, sc->sc_has_alsl);
}
/*
@@ -1416,7 +1222,7 @@ out:
/*
* Raw SMC key access sysctls - enables reading/writing any SMC key by name
* Usage:
- * sysctl dev.asmc.0.raw.key=AUPO # Set key, auto-detects length
+ * sysctl dev.asmc.0.raw.key=TC0P # Set key, auto-detects length
* sysctl dev.asmc.0.raw.value # Read current value (hex bytes)
* sysctl dev.asmc.0.raw.value=01 # Write new value
*/
@@ -1692,10 +1498,36 @@ asmc_sensor_sysctl(SYSCTL_HANDLER_ARGS)
}
/*
- * Detect and register voltage/current/power/ambient sensors.
- * Scans all SMC keys and identifies sensor keys by prefix.
- * Returns 0 on success, -1 on error.
+ * Scan a range of SMC key indices, adding matching sensors.
+ * Only considers 2-byte keys with a supported type.
*/
+static void
+asmc_scan_sensor_range(device_t dev, unsigned int start,
+ unsigned int end, char prefix, int *countp, char **sensors,
+ int maxcount)
+{
+ char key[ASMC_KEYLEN + 1];
+ char type[ASMC_TYPELEN + 1];
+ uint8_t len;
+ unsigned int i;
+ char *sensor_key;
+
+ for (i = start; i < end; i++) {
+ if (asmc_key_dump_by_index(dev, i, key, type, &len))
+ continue;
+ if (key[0] != prefix || len != 2)
+ continue;
+ if (!asmc_sensor_type_supported(type))
+ continue;
+ if (*countp >= maxcount)
+ break;
+ sensor_key = malloc(ASMC_KEYLEN + 1,
+ M_DEVBUF, M_WAITOK);
+ memcpy(sensor_key, key, ASMC_KEYLEN + 1);
+ sensors[(*countp)++] = sensor_key;
+ }
+}
+
static int
asmc_detect_sensors(device_t dev)
{
@@ -1705,71 +1537,88 @@ asmc_detect_sensors(device_t dev)
char key[ASMC_KEYLEN + 1];
char type[ASMC_TYPELEN + 1];
uint8_t len;
- unsigned int nkeys;
- unsigned int i;
+ unsigned int start, end, i;
int error;
char *sensor_key;
- /* Initialize counts */
sc->sc_voltage_count = 0;
sc->sc_current_count = 0;
sc->sc_power_count = 0;
sc->sc_light_count = 0;
+ sc->sc_temp_count = 0;
if (sc->sc_nkeys == 0)
return (0);
- nkeys = sc->sc_nkeys;
-
- /* Scan all keys for voltage/current/power/ambient light sensors */
- for (i = 0; i < nkeys; i++) {
- /* Get key name by index */
- error = asmc_key_dump_by_index(dev, i, key, type, &len);
- if (error != 0)
- continue;
- if (!asmc_sensor_type_supported(type))
- continue;
- /* Voltage sensors (VC*, VD*, VG*, VP*, VI*) */
- if (key[0] == 'V' && (key[1] == 'C' || key[1] == 'D' ||
- key[1] == 'G' || key[1] == 'P' || key[1] == 'I') &&
- len == 2) {
- if (sc->sc_voltage_count >= ASMC_MAX_SENSORS)
+ /*
+ * Temperature sensors: binary search for T..U range,
+ * then filter by type sp78.
+ */
+ error = asmc_key_search(dev, "T\0\0\0", &start);
+ if (error == 0)
+ error = asmc_key_search(dev, "U\0\0\0", &end);
+ if (error == 0) {
+ for (i = start; i < end; i++) {
+ if (asmc_key_dump_by_index(dev, i,
+ key, type, &len))
continue;
- sensor_key = malloc(ASMC_KEYLEN + 1,
- M_DEVBUF, M_WAITOK);
- memcpy(sensor_key, key, ASMC_KEYLEN + 1);
- sc->sc_voltage_sensors[sc->sc_voltage_count++] =
- sensor_key;
- } else if (key[0] == 'I' && (key[1] == 'C' ||
- key[1] == 'D' || key[1] == 'G' || key[1] == 'M' ||
- key[1] == 'N' || key[1] == 'O' || key[1] == 'H' ||
- key[1] == 'P' || key[1] == 'B' || key[1] == 'A' ||
- key[1] == 'L') && len == 2) {
- /* Current sensors */
- if (sc->sc_current_count >= ASMC_MAX_SENSORS)
+ if (len != 2 ||
+ strncmp(type, "sp78", 4) != 0)
continue;
+ if (sc->sc_temp_count >= ASMC_TEMP_MAX)
+ break;
sensor_key = malloc(ASMC_KEYLEN + 1,
M_DEVBUF, M_WAITOK);
memcpy(sensor_key, key, ASMC_KEYLEN + 1);
- sc->sc_current_sensors[sc->sc_current_count++] =
+ sc->sc_temp_sensors[sc->sc_temp_count++] =
sensor_key;
- } else if (key[0] == 'P' && (key[1] == 'C' ||
- key[1] == 'D' || key[1] == 'N' || key[1] == 'S' ||
- key[1] == 'T' || key[1] == 'H' || key[1] == 'F' ||
- key[1] == 'Z' || key[1] == 'z') && len == 2) {
- /* Power sensors */
- if (sc->sc_power_count >= ASMC_MAX_SENSORS)
+ }
+ }
+
+ /* Voltage sensors: V..W range */
+ error = asmc_key_search(dev, "V\0\0\0", &start);
+ if (error == 0)
+ error = asmc_key_search(dev, "W\0\0\0", &end);
+ if (error == 0)
+ asmc_scan_sensor_range(dev, start, end, 'V',
+ &sc->sc_voltage_count, sc->sc_voltage_sensors,
+ ASMC_MAX_SENSORS);
+
+ /* Current sensors: I..J range */
+ error = asmc_key_search(dev, "I\0\0\0", &start);
+ if (error == 0)
+ error = asmc_key_search(dev, "J\0\0\0", &end);
+ if (error == 0)
+ asmc_scan_sensor_range(dev, start, end, 'I',
+ &sc->sc_current_count, sc->sc_current_sensors,
+ ASMC_MAX_SENSORS);
+
+ /* Power sensors: P..Q range */
+ error = asmc_key_search(dev, "P\0\0\0", &start);
+ if (error == 0)
+ error = asmc_key_search(dev, "Q\0\0\0", &end);
+ if (error == 0)
+ asmc_scan_sensor_range(dev, start, end, 'P',
+ &sc->sc_power_count, sc->sc_power_sensors,
+ ASMC_MAX_SENSORS);
+
+ /* Ambient light sensors: AL* in A..B range */
+ error = asmc_key_search(dev, "A\0\0\0", &start);
+ if (error == 0)
+ error = asmc_key_search(dev, "B\0\0\0", &end);
+ if (error == 0) {
+ for (i = start; i < end; i++) {
+ if (asmc_key_dump_by_index(dev, i,
+ key, type, &len))
continue;
- sensor_key = malloc(ASMC_KEYLEN + 1,
- M_DEVBUF, M_WAITOK);
- memcpy(sensor_key, key, ASMC_KEYLEN + 1);
- sc->sc_power_sensors[sc->sc_power_count++] =
- sensor_key;
- } else if (key[0] == 'A' && key[1] == 'L' &&
- (key[2] == 'V' || key[2] == 'S') && len == 2) {
- /* Ambient light sensors */
- if (sc->sc_light_count >= ASMC_MAX_SENSORS)
+ if (key[0] != 'A' || key[1] != 'L' ||
+ (key[2] != 'V' && key[2] != 'S') ||
+ len != 2)
+ continue;
+ if (!asmc_sensor_type_supported(type))
continue;
+ if (sc->sc_light_count >= ASMC_MAX_SENSORS)
+ break;
sensor_key = malloc(ASMC_KEYLEN + 1,
M_DEVBUF, M_WAITOK);
memcpy(sensor_key, key, ASMC_KEYLEN + 1);
@@ -1780,9 +1629,10 @@ asmc_detect_sensors(device_t dev)
if (bootverbose)
device_printf(dev,
- "detected %d voltage, %d current, "
+ "detected %d temp, %d voltage, %d current, "
"%d power, %d light sensors\n",
- sc->sc_voltage_count, sc->sc_current_count,
+ sc->sc_temp_count, sc->sc_voltage_count,
+ sc->sc_current_count,
sc->sc_power_count, sc->sc_light_count);
/* Register sysctls for detected sensors */
@@ -1924,6 +1774,37 @@ out:
return (error);
}
+/*
+ * Binary search for the first key index >= prefix.
+ * SMC keys are sorted, so this finds the lower bound efficiently.
+ */
+static int
+asmc_key_search(device_t dev, const char *prefix, unsigned int *idx)
+{
+ struct asmc_softc *sc = device_get_softc(dev);
+ unsigned int lo, hi, mid;
+ char key[ASMC_KEYLEN + 1];
+ char type[ASMC_TYPELEN + 1];
+ uint8_t len;
+ int error;
+
+ lo = 0;
+ hi = sc->sc_nkeys;
+ while (lo < hi) {
+ mid = lo + (hi - lo) / 2;
+ error = asmc_key_dump_by_index(dev, mid,
+ key, type, &len);
+ if (error != 0)
+ return (error);
+ if (strncmp(key, prefix, ASMC_KEYLEN) < 0)
+ lo = mid + 1;
+ else
+ hi = mid;
+ }
+ *idx = lo;
+ return (0);
+}
+
static int
asmc_key_write(device_t dev, const char *key, uint8_t *buf, uint8_t len)
{
@@ -2204,7 +2085,10 @@ asmc_temp_sysctl(SYSCTL_HANDLER_ARGS)
struct asmc_softc *sc = device_get_softc(dev);
int error, val;
- val = asmc_temp_getvalue(dev, sc->sc_model->smc_temps[arg2]);
+ if (arg2 < 0 || arg2 >= sc->sc_temp_count)
+ return (EINVAL);
+
+ val = asmc_temp_getvalue(dev, sc->sc_temp_sensors[arg2]);
error = sysctl_handle_int(oidp, &val, 0, req);
return (error);
@@ -2263,6 +2147,10 @@ asmc_sms_intrfast(void *arg)
sc->sc_sms_intrtype = type;
asmc_sms_printintr(dev, type);
+ /* Don't queue SMS task for ambient light interrupts */
+ if (type == ASMC_ALSL_INT2A && sc->sc_has_alsl)
+ return (FILTER_HANDLED);
+
taskqueue_enqueue(sc->sc_sms_tq, &sc->sc_sms_task);
return (FILTER_HANDLED);
}
@@ -2285,10 +2173,9 @@ asmc_sms_printintr(device_t dev, uint8_t type)
case ASMC_ALSL_INT2A:
/*
* This suppresses console and log messages for the ambient
- * light sensor for models known to generate this interrupt.
+ * light sensor interrupt on models that have ALSL.
*/
- if (strcmp(sc->sc_model->smc_model, "MacBookPro5,5") == 0 ||
- strcmp(sc->sc_model->smc_model, "MacBookPro6,2") == 0)
+ if (sc->sc_has_alsl)
break;
/* FALLTHROUGH */
default:
@@ -2451,18 +2338,17 @@ asmc_mbp_sysctl_light_left_10byte(SYSCTL_HANDLER_ARGS)
}
/*
- * Wake-on-LAN convenience sysctl.
- * Reading returns 1 if WoL is enabled, 0 if disabled.
- * Writing 1 enables WoL, 0 disables it.
+ * Auto power-on after AC power loss (AUPO key).
+ * When non-zero the machine boots automatically when AC is restored
+ * after an unclean power loss. Useful for always-on servers / home labs.
*/
static int
-asmc_wol_sysctl(SYSCTL_HANDLER_ARGS)
+asmc_aupo_sysctl(SYSCTL_HANDLER_ARGS)
{
device_t dev = (device_t)arg1;
uint8_t aupo;
int val, error;
- /* Read current AUPO value */
if (asmc_key_read(dev, ASMC_KEY_AUPO, &aupo, 1) != 0)
return (EIO);
@@ -2471,10 +2357,7 @@ asmc_wol_sysctl(SYSCTL_HANDLER_ARGS)
if (error != 0 || req->newptr == NULL)
return (error);
- /* Clamp to 0 or 1 */
aupo = (val != 0) ? 1 : 0;
-
- /* Write AUPO */
if (asmc_key_write(dev, ASMC_KEY_AUPO, &aupo, 1) != 0)
return (EIO);
diff --git a/sys/dev/asmc/asmcvar.h b/sys/dev/asmc/asmcvar.h
index 43f679f3fef0..6388fc78fb69 100644
--- a/sys/dev/asmc/asmcvar.h
+++ b/sys/dev/asmc/asmcvar.h
@@ -33,6 +33,9 @@
#define ASMC_TYPELEN 4 /* SMC type string length */
#define ASMC_MAX_SENSORS 64 /* Max sensors per type */
+/* Maximum number of auto-detected temperature sensors */
+#define ASMC_TEMP_MAX 80
+
struct asmc_softc {
device_t sc_dev;
struct mtx sc_mtx;
@@ -45,7 +48,6 @@ struct asmc_softc {
struct sysctl_oid *sc_temp_tree;
struct sysctl_oid *sc_sms_tree;
struct sysctl_oid *sc_light_tree;
- const struct asmc_model *sc_model;
int sc_rid_port;
int sc_rid_irq;
struct resource *sc_ioport;
@@ -74,6 +76,15 @@ struct asmc_softc {
int sc_power_count;
char *sc_light_sensors[ASMC_MAX_SENSORS];
int sc_light_count;
+ /* Auto-detected temperature sensors */
+ char *sc_temp_sensors[ASMC_TEMP_MAX];
+ int sc_temp_count;
+ /* Auto-detected capabilities */
+ int sc_has_sms;
+ int sc_has_light;
+ int sc_light_len; /* ASMC_LIGHT_{SHORT,LONG}LEN */
+ int sc_has_safespeed;
+ int sc_has_alsl; /* ALSL interrupt source */
};
/*
@@ -150,9 +161,13 @@ struct asmc_softc {
/*
* Keyboard backlight.
*/
-#define ASMC_KEY_LIGHTLEFT "ALV0" /* RO; 6 bytes */
+#define ASMC_LIGHT_SHORTLEN 6 /* ALV0 short format */
+#define ASMC_LIGHT_LONGLEN 10 /* ALV0 long format (10-byte) */
+#define ASMC_KEY_LIGHTLEFT "ALV0" /* RO; 6 or 10 bytes */
#define ASMC_KEY_LIGHTRIGHT "ALV1" /* RO; 6 bytes */
#define ASMC_KEY_LIGHTVALUE "LKSB" /* WO; 2 bytes */
+#define ASMC_KEY_LIGHTSRC "ALSL" /* RO; ambient light source */
+#define ASMC_KEY_FANSAFESPEED0 "F0Sf" /* RO; 2 bytes */
/*
* Clamshell.
@@ -160,7 +175,9 @@ struct asmc_softc {
#define ASMC_KEY_CLAMSHELL "MSLD" /* RO; 1 byte */
/*
- * Auto power on / Wake-on-LAN.
+ * Auto power-on after AC power loss (AUPO).
+ * When set, the machine boots automatically when AC power is restored
+ * after an unclean power loss. This is NOT Wake-on-LAN.
*/
#define ASMC_KEY_AUPO "AUPO" /* RW; 1 byte */
@@ -168,945 +185,3 @@ struct asmc_softc {
* Interrupt keys.
*/
#define ASMC_KEY_INTOK "NTOK" /* WO; 1 byte */
-
-/*
- * Temperatures.
- *
- * First for MacBook, second for MacBook Pro, third for Intel Mac Mini,
- * fourth the Mac Pro 8-core and finally the MacBook Air.
- *
- */
-/* maximum array size for temperatures including the last NULL */
-#define ASMC_TEMP_MAX 80
-#define ASMC_MB_TEMPS { "TB0T", "TN0P", "TN1P", "Th0H", "Th1H", \
- "TM0P", NULL }
-#define ASMC_MB_TEMPNAMES { "enclosure", "northbridge1", \
- "northbridge2", "heatsink1", \
- "heatsink2", "memory", }
-#define ASMC_MB_TEMPDESCS { "Enclosure Bottomside", \
- "Northbridge Point 1", \
- "Northbridge Point 2", "Heatsink 1", \
- "Heatsink 2", "Memory Bank A", }
-
-#define ASMC_MB31_TEMPS { "TB0T", "TN0P", "Th0H", "Th1H", \
- "TM0P", NULL }
-
-#define ASMC_MB31_TEMPNAMES { "enclosure", "northbridge1", \
- "heatsink1", "heatsink2", \
- "memory", }
-
-#define ASMC_MB31_TEMPDESCS { "Enclosure Bottomside", \
- "Northbridge Point 1", \
- "Heatsink 1","Heatsink 2" \
- "Memory Bank A", }
-
-#define ASMC_MB71_TEMPS { "TB0T", "TB1T", "TB2T", "TC0D", "TC0P", \
- "TH0P", "TN0D", "TN0P", "TN0S", "TN1D", \
- "TN1E", "TN1F", "TN1G", "TN1S", "Th1H", \
- "Ts0P", "Ts0S", NULL }
-
-#define ASMC_MB71_TEMPNAMES { "enclosure_bottom0", "battery_1", "battery_2", "cpu_package", "cpu_proximity", \
- "hdd_bay", "northbridge0_diode", "northbridge0_proximity", "TN0S", "mpc_die2", \
- "TN1E", "TN1F", "TN1G", "TN1S", "heatsink1", \
- "palm_rest", "memory_proximity", }
-
-#define ASMC_MB71_TEMPDESCS { "Enclosure Bottom 0", "Battery 1", "Battery 2", "CPU Package", "CPU Proximity", \
- "HDD Bay", "Northbridge Diode", "Northbridge Proximity", "TN0S", "MPC Die 2", \
- "TN1E", "TN1F", "TN1G", "TN1S", "Heatsink 1", \
- "Palm Rest", "Memory Proximity", }
-
-#define ASMC_MBP_TEMPS { "TB0T", "Th0H", "Th1H", "Tm0P", \
- "TG0H", "TG0P", "TG0T", NULL }
-
-#define ASMC_MBP_TEMPNAMES { "enclosure", "heatsink1", \
- "heatsink2", "memory", "graphics", \
- "graphicssink", "unknown", }
-
-#define ASMC_MBP_TEMPDESCS { "Enclosure Bottomside", \
- "Heatsink 1", "Heatsink 2", \
- "Memory Controller", \
- "Graphics Chip", "Graphics Heatsink", \
- "Unknown", }
-
-#define ASMC_MBP4_TEMPS { "TB0T", "Th0H", "Th1H", "Th2H", "Tm0P", \
- "TG0H", "TG0D", "TC0D", "TC0P", "Ts0P", \
- "TTF0", "TW0P", NULL }
-
-#define ASMC_MBP4_TEMPNAMES { "enclosure", "heatsink1", "heatsink2", \
- "heatsink3", "memory", "graphicssink", \
- "graphics", "cpu", "cpu2", "unknown1", \
- "unknown2", "wireless", }
-
-#define ASMC_MBP4_TEMPDESCS { "Enclosure Bottomside", \
- "Main Heatsink 1", "Main Heatsink 2", \
- "Main Heatsink 3", \
- "Memory Controller", \
- "Graphics Chip Heatsink", \
- "Graphics Chip Diode", \
- "CPU Temperature Diode", "CPU Point 2", \
- "Unknown", "Unknown", \
- "Wireless Module", }
-
-#define ASMC_MBP51_TEMPS { "TB0T", "TB1T", "TB2T", "TB3T", "TC0D", \
- "TC0F", "TC0P", "TG0D", "TG0F", "TG0H", \
- "TG0P", "TG0T", "TG1H", "TN0D", "TN0P", \
- "TTF0", "Th2H", "Tm0P", "Ts0P", "Ts0S", \
- NULL }
-
-#define ASMC_MBP51_TEMPNAMES { "enclosure_bottom_0", "enclosure_bottom_1", \
- "enclosure_bottom_2", "enclosure_bottom_3", \
- "cpu_diode", "cpu", \
- "cpu_pin", "gpu_diode", \
- "gpu", "gpu_heatsink", \
- "gpu_pin", "gpu_transistor", \
- "gpu_2_heatsink", "northbridge_diode", \
- "northbridge_pin", "unknown", \
- "heatsink_2", "memory_controller", \
- "pci_express_slot_pin", "pci_express_slot_unk" }
-
-#define ASMC_MBP51_TEMPDESCS { "Enclosure Bottom 0", "Enclosure Bottom 1", \
- "Enclosure Bottom 2", "Enclosure Bottom 3", \
- "CPU Diode", "CPU ???", \
- "CPU Pin", "GPU Diode", \
- "GPU ???", "GPU Heatsink", \
- "GPU Pin", "GPU Transistor", \
- "GPU 2 Heatsink", "Northbridge Diode", \
- "Northbridge Pin", "Unknown", \
- "Heatsink 2", "Memory Controller", \
- "PCI Express Slot Pin", "PCI Express Slot (unk)" }
-
-#define ASMC_MBP62_TEMPS { "TB0T", "TB1T", "TB2T", \
- "TC0C", "TC0D", "TC0P", \
- "TC1C", "TG0D", "TG0P", \
- "TG0T", "TMCD", "TP0P", \
- "TPCD", "Th1H", "Th2H", \
- "Tm0P", "Ts0P", "Ts0S" }
-
-#define ASMC_MBP62_TEMPNAMES { "enclosure_bottom_0", "enclosure_bottom_1", \
- "enclosure_bottom_2", "cpu0", \
- "cpu_diode", "cpu_proximity", \
- "cpu1", "gpu_diode", \
- "gpu_pin", "gpu_transistor", \
- "TMCD", "pch_controller_proximity", \
- "pch_die", "heatsink1", \
- "heatsink2", "memory-controller", \
- "palmrest", "memoryproximity" }
-
-#define ASMC_MBP62_TEMPDESCS { "Enclosure Bottom 0", "Enclosure Bottom 1", \
- "Enclosure Bottom 2", "CPU 0", \
- "CPU Diode", "CPU Proximity", \
- "CPU 1", "GPU Diode", \
- "GPU Pin", "GPU Transistor", \
- "TMCD", "PCH Controller Proximity", \
- "PCH Die", "Heat Sink 1", \
- "Heat Sink 2", "Memory Controller", \
- "Palm Rest", "Memory Proximity" }
-
-#define ASMC_MBP55_TEMPS { "TB0T", "TB1T", \
- "TB2T", "TB3T", \
- "TC0D", "TC0P", \
- "TN0D", "TN0P", \
- "TTF0", \
- "Th0H", "Th1H", "ThFH", \
- "Ts0P", "Ts0S", \
- NULL }
-
-#define ASMC_MBP55_TEMPNAMES { "enclosure_bottom_0", "enclosure_bottom_1", \
- "enclosure_bottom_2", "enclosure_bottom_3", \
- "cpu_diode", "cpu_pin", \
- "northbridge_diode", "northbridge_pin", \
- "unknown", \
- "heatsink_0", "heatsink_1", "heatsink_2", \
- "pci_express_slot_pin", "pci_express_slot_unk" }
-
-#define ASMC_MBP55_TEMPDESCS { "Enclosure Bottom 0", "Enclosure Bottom 1", \
- "Enclosure Bottom 2", "Enclosure Bottom 3", \
- "CPU Diode", "CPU Pin", \
- "Northbridge Diode", "Northbridge Pin", \
- "Unknown", \
- "Heatsink 0", "Heatsink 1", "Heatsink 2", \
- "PCI Express Slot Pin", "PCI Express Slot (unk)" }
-
-#define ASMC_MBP81_TEMPS { "TB0T", "TB1T", "TB2T", "TC0C", "TC0D", \
- "TC0E", "TC0F", "TC0P", "TC1C", "TC2C", \
- "TCFC", "TCGC", "TCSA", "TM0S", "TMBS", \
- "TP0P", "TPCD", "TW0P", "Th1H", "Ts0P", \
- "Ts0S", NULL }
-
-#define ASMC_MBP81_TEMPNAMES { "enclosure", "TB1T", "TB2T", "TC0C", "TC0D", \
- "TC0E", "TC0F", "TC0P", "TC1C", "TC2C", \
- "TCFC", "TCGC", "TCSA", "TM0S", "TMBS", \
- "TP0P", "TPCD", "wireless", "Th1H", "Ts0P", \
- "Ts0S" }
-
-#define ASMC_MBP81_TEMPDESCS { "Enclosure Bottomside", "TB1T", "TB2T", "TC0C", "TC0D", \
- "TC0E", "TC0F", "TC0P", "TC1C", "TC2C", \
- "TCFC", "TCGC", "TCSA", "TM0S", "TMBS", \
- "TP0P", "TPCD", "TW0P", "Th1H", "Ts0P", \
- "Ts0S" }
-
-#define ASMC_MBP82_TEMPS { "TB0T", "TB1T", "TB2T", "TC0C", "TC0D", \
- "TC0E", "TC0F", "TC0P", "TC1C", "TC2C", \
- "TC3C", "TC4C", "TCFC", "TCGC", "TCSA", \
- "TCTD", "TG0D", "TG0P", "THSP", "TM0S", \
- "TMBS", "TP0P", "TPCD", "TW0P", "Th1H", \
- "Th2H", "Tm0P", "Ts0P", "Ts0S", NULL }
-
-#define ASMC_MBP82_TEMPNAMES { "enclosure", "TB1T", "TB2T", "TC0C", "TC0D", \
- "TC0E", "TC0F", "TC0P", "TC1C", "TC2C", \
- "TC3C", "TC4C", "TCFC", "TCGC", "TCSA", \
- "TCTD", "graphics", "TG0P", "THSP", "TM0S", \
- "TMBS", "TP0P", "TPCD", "wireless", "Th1H", \
- "Th2H", "memory", "Ts0P", "Ts0S" }
-
-#define ASMC_MBP82_TEMPDESCS { "Enclosure Bottomside", "TB1T", "TB2T", "TC0C", "TC0D", \
- "TC0E", "TC0F", "TC0P", "TC1C", "TC2C", \
- "TC3C", "TC4C", "TCFC", "TCGC", "TCSA", \
- "TCTD", "TG0D", "TG0P", "THSP", "TM0S", \
- "TMBS", "TP0P", "TPCD", "TW0P", "Th1H", \
- "Th2H", "Tm0P", "Ts0P", "Ts0S" }
-
-#define ASMC_MBP83_TEMPS { "ALSL", "F0Ac", "F1Ac", "IB0R", "IC0R", \
- "ID0R", "IG0R", "IO0R", "PCPC", "PCPG", \
- "PCPT", "PD0R", "TB1T", "TB2T", "TC0C", \
- "TC0D", "TC0P", "TC1C", "TC2C", "TC3C", \
- "TC4C", "TG0D", "TG0P", "THSP", "TP0P", \
- "TPCD", "Th1H", "Th2H", "Tm0P", "Ts0P", \
- "VC0C", "VD0R", "VG0C", "VN0C", "VP0R", NULL }
-
-#define ASMC_MBP83_TEMPNAMES { "ambient_light", "fan_leftside", "fan_rightside", \
- "battery_current", "cpu_vcorevtt", "dc_current", \
- "gpu_voltage", "other", "cpu_package_core", \
- "cpu_package_gpu", "cpu_package_total", "dc_in", \
- "battery_1", "battery_2", "cpu_die_digital", \
- "cpu_die_analog", "cpu_proximity", "cpu_core_1", \
- "cpu_core_2", "cpu_core_3", "cpu_core_4", "gpu_die_analog", \
- "gpu_proximity", "thunderbolt", "platform_controller", \
- "pch_die_digital", "right_fin_stack", "left_fin_stack", \
- "dc_in_air_flow", "palm_rest", "cpu_vcore", "dc_in_voltage", \
- "gpu_vcore", "intel_gpu_vcore", "pbus_voltage" }
-
-#define ASMC_MBP83_TEMPDESCS { "Ambient Light", "Fan Leftside", "Fan Rightside", \
- "Battery BMON Current", "CPU VcoreVTT", "DC In AMON Current", \
- "GPU Voltage", "Other 5V 3V", "CPU Package Core", \
- "CPU Package GPU", "CPU Package Total", "DC In", \
- "Battery Sensor 1", "Battery Sensor 2", "CPU Die Digital", \
- "CPU Die Analog", "CPU Proximity", "CPU Core 1 DTS", \
- "CPU Core 2 DTS", "CPU Core 3 DTS", "CPU Core 4 DTS", \
- "GPU Die Analog", "GPU Proximity", "Thunderbolt Proximity", \
- "Platform Controller Hub", "PCH Die Digital", \
- "Right Fin Stack Proximity", "Left Fin Stack Proximity", \
- "DC In Proximity Air Flow", "Palm Rest", "CPU VCore", \
- "DC In Voltage", "GPU VCore", "Intel GPU VCore", "PBus Voltage" }
-
-#define ASMC_MBP91_TEMPS { "TA0P", "TB0T", "TB1T", "TB2T", "TC0E", \
- "TC0F", "TC0P", "TC1C", "TC2C", "TC3C", \
- "TC4C", "TCGC", "TCSA", "TCXC", "TG0D", \
- "TG0P", "TG1D", "TG1F", "TG1d", "TGTC", \
- "TGTD", "TM0P", "TM0S", "TP0P", "TPCD", \
- "Th1H", "Th2H", "Ts0P", "Ts0S", "Tsqf", NULL }
-
-#define ASMC_MBP91_TEMPNAMES { "ambient", "enclosure_bottom_1", "enclosure_bottom_2", \
- "enclosure_bottom_3", "cpu_die_peci_0", "cpu_die_peci_1", \
- "cpu_proximity", "cpu_core_1", "cpu_core_2", "cpu_core_3", \
- "cpu_core_4", "intel_gpu", "cpu_sys_agent", \
- "cpu_core_peci", "gpu_analog", \
- "gpu_proximity", "geforce_gpu_digital", "tg1f", \
- "gpu_2_die", "tgtc", "tgtd", "memory_proximity", \
- "mem_bank_a1", "platform_ctrl_hub", "pch_digital", \
- "main_heatsink_r", "main_heatsink_l", "palm_rest", \
- "bottom_skin", "tsqf" }
-
-#define ASMC_MBP91_TEMPDESCS { "Ambient", "Enclosure Bottom 1", "Enclosure Bottom 2", \
- "Enclosure Bottom 3", "CPU Die PECI 0", "CPU Die PECI 1", \
- "CPU Proximity", "CPU Core 1", "CPU Core 2", \
- "CPU Core 3", "CPU Core 4", "Intel GPU", \
- "CPU System Agent Core", "CPU Core - PECI", \
- "GPU Die - Analog", "GPU Proximity", \
- "GeForce GPU Die - Digital", "TG1F", "GPU 2 Die" \
- "TGTC", "TGTD", "Memory Proximity", \
- "Memory Bank A1", "Platform Controller Hub", "PCH Die - Digital", \
- "Main Heatsink Right", "Main Heatsink Left", "Palm Rest", \
- "Bottom Skin", "Tsqf" }
-
-#define ASMC_MBP92_TEMPS { "Ts0P", "Ts0S", "TA0P", "TB1T", "TB2T", \
- "TB0T", "TC1C", "TC2C", "TC0E", "TC0F", \
- "TC0J", "TC0P", "TCFC", "TCGC", "TCSA", \
- "TCTD", "TCXC", "TG1D", "TM0P", "TM0S", \
- "TPCD", NULL }
-
-#define ASMC_MBP92_TEMPNAMES { "Ts0P", "Ts0S", "TA0P", "TB1T", "TB2T", \
- "TB0T", "TC1C", "TC2C", "TC0E", "TC0F", \
- "TC0J", "TC0P", "TCFC", "TCGC", "TCSA", \
- "TCTD", "TCXC", "TG1D", "TM0P", "TM0S", \
- "TPCD" }
-
-#define ASMC_MBP92_TEMPDESCS { "Palm Rest", "Memory Proximity", "Airflow 1", \
- "Battery 1", "Battery 2", "Battery TS_MAX", \
- "CPU Core 1", "CPU Core 2", "CPU1", "CPU1", \
- "TC0J", "CPU 1 Proximity", "TCFC", \
- "PECI GPU", "PECI SA", "TCTD", "PECI CPU", \
- "GPU Die", "Memory Bank A1", "Memory Module A1", \
- "PCH Die" }
-
-#define ASMC_MBP112_TEMPS { "TB0T", "TB1T", "TB2T", "TBXT", "TC0E", \
- "TC0F", "TC0P", "TC1C", "TC2C", "TC3C", \
- "TC4C", "TCFC", "TCGC", "TCSA", "TCTD", \
- "TCXC", "TH0A", "TH0B", "TH0F", "TH0R", \
- "TH0V", "TH0a", "TH0b", "TH0c", "TM0P", \
- "TM0S", "TP0P", "TPCD", "TW0P", "Ta0P", \
- "TaSP", "Th1H", "Th2H", "Ts0P", "Ts0S", \
- "Ts1S", NULL }
-
-#define ASMC_MBP112_TEMPNAMES { "TB0T", "TB1T", "TB2T", "TBXT", "TC0E", \
- "TC0F", "TC0P", "TC1C", "TC2C", "TC3C", \
- "TC4C", "TCFC", "TCGC", "TCSA", "TCTD", \
- "TCXC", "TH0A", "TH0B", "TH0F", "TH0R", \
- "TH0V", "TH0a", "TH0b", "TH0c", "TM0P", \
- "TM0S", "TP0P", "TPCD", "TW0P", "Ta0P", \
- "TaSP", "Th1H", "Th2H", "Ts0P", "Ts0S", \
- "Ts1S" }
-
-#define ASMC_MBP112_TEMPDESCS { "TB0T", "TB1T", "TB2T", "TBXT", "TC0E", \
- "TC0F", "TC0P", "TC1C", "TC2C", "TC3C", \
- "TC4C", "TCFC", "TCGC", "TCSA", "TCTD", \
- "TCXC", "TH0A", "TH0B", "TH0F", "TH0R", \
- "TH0V", "TH0a", "TH0b", "TH0c", "TM0P", \
- "TM0S", "TP0P", "TPCD", "TW0P", "Ta0P", \
- "TaSP", "Th1H", "Th2H", "Ts0P", "Ts0S", \
- "Ts1S" }
-
-#define ASMC_MBP113_TEMPS { "TB0T", "TB1T", "TB2T", "TBXT", "TC0E", \
- "TC0F", "TC0P", "TC1C", "TC2C", "TC3C", \
- "TC4C", "TCFC", "TCGC", "TCSA", "TCTD", \
- "TCXC", "TG0D", "TG0P", "TG1D", "TG1F", \
- "TG1d", "TH0A", "TH0B", "TH0F", "TH0R", \
- "TH0V", "TH0a", "TH0b", "TH0c", "TM0P", \
- "TM0S", "TP0P", "TPCD", "TW0P", "Ta0P", \
- "TaSP", "Th1H", "Th2H", "Ts0P", "Ts0S", \
- "Ts1S", NULL }
-
-#define ASMC_MBP113_TEMPNAMES { "TB0T", "TB1T", "TB2T", "TBXT", "TC0E", \
- "TC0F", "TC0P", "TC1C", "TC2C", "TC3C", \
- "TC4C", "TCFC", "TCGC", "TCSA", "TCTD", \
- "TCXC", "TG0D", "TG0P", "TG1D", "TG1F", \
- "TG1d", "TH0A", "TH0B", "TH0F", "TH0R", \
- "TH0V", "TH0a", "TH0b", "TH0c", "TM0P", \
- "TM0S", "TP0P", "TPCD", "TW0P", "Ta0P", \
- "TaSP", "Th1H", "Th2H", "Ts0P", "Ts0S", \
- "Ts1S" }
-
-#define ASMC_MBP113_TEMPDESCS { "TB0T", "TB1T", "TB2T", "TBXT", "TC0E", \
- "TC0F", "TC0P", "TC1C", "TC2C", "TC3C", \
- "TC4C", "TCFC", "TCGC", "TCSA", "TCTD", \
- "TCXC", "TG0D", "TG0P", "TG1D", "TG1F", \
- "TG1d", "TH0A", "TH0B", "TH0F", "TH0R", \
- "TH0V", "TH0a", "TH0b", "TH0c", "TM0P", \
- "TM0S", "TP0P", "TPCD", "TW0P", "Ta0P", \
- "TaSP", "Th1H", "Th2H", "Ts0P", "Ts0S", \
- "Ts1S" }
-
-#define ASMC_MBP114_TEMPS { "IC0C", "ID0R", "IHDC", "IPBR", "IC0R", \
- "IO3R", "IO5R", "IM0C", "IC1C", "IC2C", \
- "IC3C", "ILDC", "IBLC", "IAPC", "IHSC", \
- "ICMC", "TC0P", "TP0P", "TM0P", \
- "Ta0P", "Th2H", "Th1H", "TW0P", "Ts0P", \
- "Ts1P", "TB0T", "TB1T", "TB2T", "TH0A", "TH0B", \
- "TC1C", "TC2C", "TC3C", "TC4C", "TCXC", \
- "TCGC", "TPCD", "TCSA", "VC0C", "VD0R", \
- "VP0R", "ALSL", "F0Ac", "F1Ac", "PCPC", \
- "PCPG", "PCPT", "PSTR", "PDTR", NULL }
-
-#define ASMC_MBP114_TEMPNAMES { "IC0C", "ID0R", "IHDC", "IPBR", "IC0R", \
- "IO3R", "IO5R", "IM0C", "IC1C", "IC2C", \
- "IC3C", "ILDC", "IBLC", "IAPC", "IHSC", \
- "ICMC", "TC0P", "TP0P", "TM0P", \
- "Ta0P", "Th2H", "Th1H", "TW0P", "Ts0P", \
- "Ts1P", "TB0T", "TB1T", "TB2T", "TH0A", "TH0B", \
- "TC1C", "TC2C", "TC3C", "TC4C", "TCXC", \
- "TCGC", "TPCD", "TCSA", "VC0C", "VD0R", \
- "VP0R", "ALSL", "F0Ac", "F1Ac", "PCPC", \
- "PCPG", "PCPT", "PSTR", "PDTR" }
-
-#define ASMC_MBP114_TEMPDESCS { "CPU High (CPU, I/O)", "DC In", "SSD", "Charger (BMON)", "CPU", \
- "Other 3.3V", "Other 5V", "Memory", "Platform Controller Hub Core", "CPU Load Current Monitor", \
- "CPU DDR", "LCD Panel", "LCD Backlight", "Airport", "Thunderbolt", \
- "S2", "CPU Proximity", "Platform Controller Hub", "Memory Proximity", "Air Flow Proximity", \
- "Left Fin Stack", "Right Fin Stack", "Airport Proximity", "Palm Rest", "Palm Rest Actuator", \
- "Battery Max", "Battery Sensor 1", "Battery Sensor 2", "SSD A", "SSD B", \
- "CPU Core 1", "CPU Core 2", "CPU Core 3", "CPU Core 4", "CPU PECI Die", \
- "Intel GPU", "Platform Controller Hub PECI", "CPU System Agent Core", "CPU VCore", "DC In", \
- "Pbus", "Ambient Light", "Leftside", "Rightside", "CPU Package Core", \
- "CPU Package GPU", "CPU Package Total", "System Total", "DC In" }
-
-/* MacBookPro11,5 - same as 11,4 but without IBLC, ICMC, and IC2C keys */
-#define ASMC_MBP115_TEMPS { "IC0C", "ID0R", "IHDC", "IPBR", "IC0R", \
- "IO3R", "IO5R", "IM0C", "IC1C", \
- "IC3C", "ILDC", "IAPC", "IHSC", \
- "TC0P", "TP0P", "TM0P", \
- "Ta0P", "Th2H", "Th1H", "TW0P", "Ts0P", \
- "Ts1P", "TB0T", "TB1T", "TB2T", "TH0A", "TH0B", \
- "TC1C", "TC2C", "TC3C", "TC4C", "TCXC", \
- "TCGC", "TPCD", "TCSA", "VC0C", "VD0R", \
- "VP0R", "ALSL", "F0Ac", "F1Ac", "PCPC", \
- "PCPG", "PCPT", "PSTR", "PDTR", NULL }
-
-
-#define ASMC_MBP115_TEMPNAMES { "IC0C", "ID0R", "IHDC", "IPBR", "IC0R", \
- "IO3R", "IO5R", "IM0C", "IC1C", \
- "IC3C", "ILDC", "IAPC", "IHSC", \
- "TC0P", "TP0P", "TM0P", \
- "Ta0P", "Th2H", "Th1H", "TW0P", "Ts0P", \
- "Ts1P", "TB0T", "TB1T", "TB2T", "TH0A", "TH0B", \
- "TC1C", "TC2C", "TC3C", "TC4C", "TCXC", \
- "TCGC", "TPCD", "TCSA", "VC0C", "VD0R", \
- "VP0R", "ALSL", "F0Ac", "F1Ac", "PCPC", \
- "PCPG", "PCPT", "PSTR", "PDTR" }
-
-#define ASMC_MBP115_TEMPDESCS { "CPU High (CPU, I/O)", "DC In", "SSD", "Charger (BMON)", "CPU", \
- "Other 3.3V", "Other 5V", "Memory", "Platform Controller Hub Core", \
- "CPU DDR", "LCD Panel", "Airport", "Thunderbolt", \
- "CPU Proximity", "Platform Controller Hub", "Memory Proximity", "Air Flow Proximity", \
- "Left Fin Stack", "Right Fin Stack", "Airport Proximity", "Palm Rest", "Palm Rest Actuator", \
- "Battery Max", "Battery Sensor 1", "Battery Sensor 2", "SSD A", "SSD B", \
- "CPU Core 1", "CPU Core 2", "CPU Core 3", "CPU Core 4", "CPU PECI Die", \
- "Intel GPU", "Platform Controller Hub PECI", "CPU System Agent Core", "CPU VCore", "DC In", \
- "Pbus", "Ambient Light", "Leftside", "Rightside", "CPU Package Core", \
- "CPU Package GPU", "CPU Package Total", "System Total", "DC In" }
-
-#define ASMC_MBP131_TEMPS { "TB0T", "TB1T", "TB2T", "TC0F", \
- "TC0P", "TC1C", "TC2C", "TCGC", \
- "TCSA", "TCXC", "Th1H", "TM0P", \
- "TPCD", "Ts0P", "Ts0S", "TaLC", \
- "Ts1P", NULL }
-
-#define ASMC_MBP131_TEMPNAMES { "battery", "battery_1", "battery_2", "cpu_die_peci", \
- "cpu_proximity", "cpu_core_1", "cpu_core_2", "intel_gpu", \
- "cpu_sys_agent", "cpu_core_peci", "right_fin_stack", "memory_proximity", \
- "platform_ctrl_hub", "trackpad", "bottom_skin", "air_flow", \
- "trackpad_act" }
-
-#define ASMC_MBP131_TEMPDESCS { "Battery", "Battery Sensor 1", "Battery Sensor 2", "CPU Die (PECI)", \
- "CPU Proximity", "CPU Core 1", "CPU Core 2", "Intel GPU", \
- "CPU System Agent Core (PECI)", "CPU Core (PECI)", "Right Fin Stack", "DDR3 Proximity", \
- "Platform Controller Hub Die", "Trackpad", "Bottom Skin", "Air Flow", \
- "Trackpad Actuator" }
-
-#define ASMC_MM_TEMPS { "TN0P", "TN1P", NULL }
-#define ASMC_MM_TEMPNAMES { "northbridge1", "northbridge2" }
-#define ASMC_MM_TEMPDESCS { "Northbridge Point 1", \
- "Northbridge Point 2" }
-
-#define ASMC_MM21_TEMPS { "TA0P", "TC0D", \
- "TC0H", "TC0P", \
- "TC1P", "TN0P", \
- "TN1P", NULL }
-
-#define ASMC_MM21_TEMPNAMES { "ambient_air", "cpu_die", \
- "cpu_heatsink", "cpu_proximity1", \
- "cpu_proximity2", "northbridge_proximity1", \
- "northbridge_proximity2", }
-
-#define ASMC_MM21_TEMPDESCS { "Ambient Air Temperature" \
- "CPU Die Core Temperature", \
- "CPU Heatsink Temperature", \
- "CPU Proximity 1 Temperature", \
- "CPU Proximity 2 Temperature", \
- "Northbridge Proximity 1 Temperature", \
- "Northbridge Proximity 2 Temperature", }
-
-#define ASMC_MM31_TEMPS { "TC0D", "TC0H", \
- "TC0P", "TH0P", \
- "TN0D", "TN0P", \
- "TW0P", NULL }
-
-#define ASMC_MM31_TEMPNAMES { "cpu0_die", "cpu0_heatsink", \
- "cpu0_proximity", "hdd_bay", \
- "northbridge_die", \
- "northbridge_proximity", \
- "wireless_proximity", }
-
-#define ASMC_MM31_TEMPDESCS { "CPU0 Die Core Temperature", \
- "CPU0 Heatsink Temperature", \
- "CPU0 Proximity Temperature", \
- "HDD Bay Temperature", \
- "Northbridge Die Core Temperature", \
- "Northbridge Proximity Temperature", \
- "Wireless Module Proximity Temperature", }
-
-#define ASMC_MM41_TEMPS { "TA0P", "TC0D", "TC0G", "TC0H", "TC0P", \
- "TC0p", "TCPG", "TH0G", "TH0P", "TH0p", \
- "TM0G", "TM0P", "TM0p", "TN0D", "TN0G", \
- "TN0P", "TN0p", "TN1D", "TN1E", "TN1F", \
- "TN1G", "TN1S", "TNPG", "TO0P", "TO0p", \
- "TW0P", "Tm0P", "Tp0C", NULL }
-
-#define ASMC_MM41_TEMPNAMES { "TA0P", "TC0D", "TC0G", "TC0H", "TC0P", \
- "TC0p", "TCPG", "TH0G", "TH0P", "TH0p", \
- "TM0G", "TM0P", "TM0p", "TN0D", "TN0G", \
- "TN0P", "TN0p", "TN1D", "TN1E", "TN1F", \
- "TN1G", "TN1S", "TNPG", "TO0P", "TO0p", \
- "TW0P", "Tm0P", "Tp0C", NULL }
-
-#define ASMC_MM41_TEMPDESCS { "TA0P", "TC0D", "TC0G", "TC0H", "TC0P", \
- "TC0p", "TCPG", "TH0G", "TH0P", "TH0p", \
- "TM0G", "TM0P", "TM0p", "TN0D", "TN0G", \
- "TN0P", "TN0p", "TN1D", "TN1E", "TN1F", \
- "TN1G", "TN1S", "TNPG", "TO0P", "TO0p", \
- "TW0P", "Tm0P", "Tp0C", NULL }
-
-#define ASMC_MM52_TEMPS { "TA0P", "TA1P", \
- "TC0D", "TC0P", \
- "TG0D", "TG1D", \
- "TG0P", "TG0M", \
- "TI0P", \
- "TM0S", "TMBS", \
- "TM0P", "TP0P", \
- "TPCD", "Tp0C", \
- "TW0P", NULL }
-
-#define ASMC_MM52_TEMPNAMES { "ambient_air_proximity", "ambient_cpu_pch_wireless_dimm", \
- "cpu_die", "cpu_proximity", \
- "gpu_diode1", "gpu_diode2", \
- "gpu_proximity", "gpu_integrated_switcher", \
- "thunderbolt_proximity", \
- "memory_slot1", "memory_slot2", \
- "memory_proximity", "pch_controller_proximity", \
- "pch_controller_die", "pwr_supply", \
- "wireless_proximity", }
-
-#define ASMC_MM52_TEMPDESCS { "Ambient Air Proximity Temperature", \
- "Combo Ambient CPU PCH Wireless DIMM Temperature", \
- "CPU Die Temperature", "CPU Proximity Temperature", \
- "GPU Diode 1 Temperature" , "GPU Diode 2 Temperature", \
- "GPU Proximity Temperature", \
- "Integrated Graphics/GPU Switcher Temperature", \
- "Thunderbolt Proximity Temperature", \
- "Memory Slot 1 Temperature", \
- "Memory Slot 2 Temperature", \
- "Memory Slots Proximity Temperature", \
- "Platform Controller Hub Proximity Temperature", \
- "Platform Controller Hub Die Temperature", \
- "Power Supply Temperature", \
- "Wireless Module Proximity Temperature", }
-
-#define ASMC_MM61_TEMPS { "TA0P", "TA1P", \
- "TC0D", "TC0G", "TC0P", "TCPG", \
- "TI0P", \
- "TM0S", "TMBS", "TM0P", \
- "TP0P", "TPCD", \
- "Tp0C", \
- "TW0P", NULL }
-
-#define ASMC_MM61_TEMPNAMES { "ambient_air_proximity", "ambient_cpu_pch_wireless_dimm", \
- "cpu_die", "TC0G", "cpu_proximity", "TCPG", \
- "thunderbolt_proximity", \
- "memory_slot1", "memory_slot2", "memory_proximity", \
- "pch_controller_proximity", "pch_controller_die", \
- "pwr_supply", \
- "wireless_proximity", NULL }
-
-#define ASMC_MM61_TEMPDESCS { "Ambient Air Proximity Temperature", \
- "Combo Ambient CPU PCH Wireless DIMM Temperature", \
- "CPU Die Temperature", \
- NULL, \
- "CPU Proximity Temperature", \
- NULL, \
- "Thunderbolt Proximity Temperature", \
- "Memory Slot 1 Temperature", \
- "Memory Slot 2 Temperature", \
- "Memory Slots Proximity Temperature", \
- "Platform Controller Hub Proximity Temperature", \
- "Platform Controller Hub Die Temperature", \
- "Power Supply Temperature", \
- "Wireless Module Proximity Temperature", NULL }
-
-#define ASMC_MM62_TEMPS { "TA0P", "TA1P", \
- "TC0D", "TC0G", "TC0P", "TCPG", \
- "TI0P", \
- "TM0S", "TMBS", "TM0P", \
- "TP0P", "TPCD", \
- "Tp0C", \
- "TW0P", NULL }
-
-#define ASMC_MM62_TEMPNAMES { "ambient_air_proximity", "ambient_cpu_pch_wireless_dimm", \
- "cpu_die", "TC0G", "cpu_proximity", "TCPG", \
- "thunderbolt_proximity", \
- "memory_slot1", "memory_slot2", "memory_proximity", \
- "pch_controller_proximity", "pch_controller_die", \
- "pwr_supply", \
- "wireless_proximity", NULL }
-
-#define ASMC_MM62_TEMPDESCS { "Ambient Air Proximity Temperature", \
- "Combo Ambient CPU PCH Wireless DIMM Temperature", \
- "CPU Die Temperature", \
- NULL, \
- "CPU Proximity Temperature", \
- NULL, \
- "Thunderbolt Proximity Temperature", \
- "Memory Slot 1 Temperature", \
- "Memory Slot 2 Temperature", \
- "Memory Slots Proximity Temperature", \
- "Platform Controller Hub Proximity Temperature", \
- "Platform Controller Hub Die Temperature", \
- "Power Supply Temperature", \
- "Wireless Module Proximity Temperature", NULL }
-
-#define ASMC_MM71_TEMPS { "TA0p", "TA1p", \
- "TA2p", "TC0c", \
- "TC0p", "TC1c", \
- "TCGc", "TCSc", \
- "TCXC", "TCXR", \
- "TM0p", "TPCd", \
- "TW0p", "Te0T", \
- "Tm0P", NULL }
-
-#define ASMC_MM71_TEMPNAMES { "ambient_air1", "ambient_air2", \
- "ambient_air3", "cpu_core1_peci", \
- "cpu_proximity", "cpu_core2_peci", \
- "intel_gpu", "cpu_sa_core_peci", \
- "cpu_core", "cpu_peci_dts", \
- "memory_proximity", "pch_controller_die", \
- "wireless_proximity", "thunderbolt_diode", \
- "logic_board", }
-
-#define ASMC_MM71_TEMPDESCS { "Ambient Air Temperature 1", \
- "Ambient Air Temperature 2", \
- "Ambient Air Temperature 3", \
- "CPU Core 1 PECI Temperature", "CPU Proximity Temperature", \
- "CPU Core 2 PECI Temperature", "Intel GPU Temperature", \
- "CPU System Agent Core PECI Temperature", \
- "CPU Core Temperature", "CPU PECI DTS Temperature", \
- "Memory Proximity Temperature", \
- "Platform Controller Hub Die Temperature", \
- "Wireless Module Proximity Temperature", \
- "Thunderbolt Diode Temperature", \
- "Logic Board temperature", }
-
-#define ASMC_MP1_TEMPS { "TA0P", \
- "TCAH", "TCBH", \
- "TC0P", "TC0C", "TC1C", \
- "TC2C", "TC3C", "THTG", \
- "TH0P", "TH1P", \
- "TH2P", "TH3P", \
- "TM0P", "TM1P", "TM2P", \
- "TM8P", "TM9P", "TMAP", \
- "TM0S", "TM1S", "TM2P", "TM3S", \
- "TM8S", "TM9S", "TMAS", "TMBS", \
- "TN0H", "TS0C", \
- "Tp0C", "Tp1C", "Tv0S", "Tv1S", NULL }
-
-#define ASMC_MP1_TEMPNAMES { "ambient", \
- "cpu_a_heatsink", "cpu_b_heatsink", \
- "cpu_a_proximity", "cpu_core0", "cpu_core1", \
- "cpu_core2", "cpu_core3", "THTG", \
- "hdd_bay0", "hdd_bay1", \
- "hdd_bay2", "hdd_bay3", \
- "memory_card_a_proximity0", \
- "memory_card_a_proximity1", \
- "memory_card_a_proximity2", \
- "memory_card_b_proximity0", \
- "memory_card_b_proximity1", \
- "memory_card_b_proximity2", \
- "memory_card_a_slot0", \
- "memory_card_a_slot1", \
- "memory_card_a_slot2", \
- "memory_card_a_slot3", \
- "memory_card_b_slot0", \
- "memory_card_b_slot1", \
- "memory_card_b_slot2", \
- "memory_card_b_slot3", \
- "mch_heatsink", "expansion_slots", \
- "power_supply_loc0", "power_supply_loc1", \
- "Tv0S", "Tv1S", }
-
-#define ASMC_MP1_TEMPDESCS { "Ambient Air", \
- "CPU A Heatsink", "CPU B Heatsink", \
- "CPU A Proximity", \
- "CPU Core 1", "CPU Core 2", \
- "CPU Core 3", "CPU Core 4", "THTG", \
- "Hard Drive Bay 1", "Hard Drive Bay 2", \
- "Hard Drive Bay 3", "Hard Drive Bay 4", \
- "Memory Riser A, Proximity 1", \
- "Memory Riser A, Proximity 2", \
- "Memory Riser A, Proximity 3", \
- "Memory Riser B, Proximity 1", \
- "Memory Riser B, Proximity 2", \
- "Memory Riser B, Proximity 3", \
- "Memory Riser A, Slot 1", \
- "Memory Riser A, Slot 2", \
- "Memory Riser A, Slot 3", \
- "Memory Riser A, Slot 4", \
- "Memory Riser B, Slot 1", \
- "Memory Riser B, Slot 2", \
- "Memory Riser B, Slot 3", \
- "Memory Riser B, Slot 4", \
- "MCH Heatsink", "Expansion Slots", \
- "Power Supply, Location 1", \
- "Power Supply, Location 2", \
- "Tv0S", "Tv1S", }
-
-#define ASMC_MP31_TEMPS { "TA0P", \
- "TC0C", "TC0D", "TC0P", \
- "TC1C", "TC1D", \
- "TC2C", "TC2D", \
- "TC3C", "TC3D", \
- "TCAG", "TCAH", "TCBG", "TCBH", \
- "TH0P", "TH1P", "TH2P", "TH3P", \
- "TM0P", "TM0S", "TM1P", "TM1S", \
- "TM2P", "TM2S", "TM3S", \
- "TM8P", "TM8S", "TM9P", "TM9S", \
- "TMAP", "TMAS", "TMBS", \
- "TN0C", "TN0D", "TN0H", \
- "TS0C", \
- "Tp0C", "Tp1C", \
- "Tv0S", "Tv1S", NULL }
-
-#define ASMC_MP31_TEMPNAMES { "ambient", \
- "cpu_core0", "cpu_diode0", "cpu_a_proximity", \
- "cpu_core1", "cpu_diode1", \
- "cpu_core2", "cpu_diode2", \
- "cpu_core3", "cpu_diode3", \
- "cpu_a_pkg", "cpu_a_heatsink", \
- "cpu_b_pkg", "cpu_b_heatsink", \
- "hdd_bay0", "hdd_bay1", \
- "hdd_bay2", "hdd_bay3", \
- "mem_riser_a_prox0", "mem_riser_a_slot0", \
- "mem_riser_a_prox1", "mem_riser_a_slot1", \
- "mem_riser_a_prox2", "mem_riser_a_slot2", \
- "mem_riser_a_slot3", \
- "mem_riser_b_prox0", "mem_riser_b_slot0", \
- "mem_riser_b_prox1", "mem_riser_b_slot1", \
- "mem_riser_b_prox2", "mem_riser_b_slot2", \
- "mem_riser_b_slot3", \
- "northbridge_core", "northbridge_diode", \
- "northbridge_heatsink", \
- "expansion_slots", \
- "power_supply0", "power_supply1", \
- "vrm0", "vrm1", }
-
-#define ASMC_MP31_TEMPDESCS { "Ambient Air", \
- "CPU Core 1", "CPU Diode 1", \
- "CPU A Proximity", \
- "CPU Core 2", "CPU Diode 2", \
- "CPU Core 3", "CPU Diode 3", \
- "CPU Core 4", "CPU Diode 4", \
- "CPU A Package", "CPU A Heatsink", \
- "CPU B Package", "CPU B Heatsink", \
- "Hard Drive Bay 1", "Hard Drive Bay 2", \
- "Hard Drive Bay 3", "Hard Drive Bay 4", \
- "Memory Riser A, Proximity 1", \
- "Memory Riser A, Slot 1", \
- "Memory Riser A, Proximity 2", \
- "Memory Riser A, Slot 2", \
- "Memory Riser A, Proximity 3", \
- "Memory Riser A, Slot 3", \
- "Memory Riser A, Slot 4", \
- "Memory Riser B, Proximity 1", \
- "Memory Riser B, Slot 1", \
- "Memory Riser B, Proximity 2", \
- "Memory Riser B, Slot 2", \
- "Memory Riser B, Proximity 3", \
- "Memory Riser B, Slot 3", \
- "Memory Riser B, Slot 4", \
- "Northbridge Core", "Northbridge Diode", \
- "Northbridge Heatsink", \
- "Expansion Slots", \
- "Power Supply 1", "Power Supply 2", \
- "VRM 1", "VRM 2", }
-
-#define ASMC_MP2_TEMPS { "TA0P", "TCAG", "TCAH", "TCBG", "TCBH", \
- "TC0C", "TC0D", "TC0P", "TC1C", "TC1D", \
- "TC2C", "TC2D", "TC3C", "TC3D", "THTG", \
- "TH0P", "TH1P", "TH2P", "TH3P", "TMAP", \
- "TMAS", "TMBS", "TM0P", "TM0S", "TM1P", \
- "TM1S", "TM2P", "TM2S", "TM3S", "TM8P", \
- "TM8S", "TM9P", "TM9S", "TN0H", "TS0C", \
- NULL }
-
-#define ASMC_MP2_TEMPNAMES { "TA0P", "TCAG", "TCAH", "TCBG", "TCBH", \
- "TC0C", "TC0D", "TC0P", "TC1C", "TC1D", \
- "TC2C", "TC2D", "TC3C", "TC3D", "THTG", \
- "TH0P", "TH1P", "TH2P", "TH3P", "TMAP", \
- "TMAS", "TMBS", "TM0P", "TM0S", "TM1P", \
- "TM1S", "TM2P", "TM2S", "TM3S", "TM8P", \
- "TM8S", "TM9P", "TM9S", "TN0H", "TS0C", }
-
-#define ASMC_MP2_TEMPDESCS { "TA0P", "TCAG", "TCAH", "TCBG", "TCBH", \
- "TC0C", "TC0D", "TC0P", "TC1C", "TC1D", \
- "TC2C", "TC2D", "TC3C", "TC3D", "THTG", \
- "TH0P", "TH1P", "TH2P", "TH3P", "TMAP", \
- "TMAS", "TMBS", "TM0P", "TM0S", "TM1P", \
- "TM1S", "TM2P", "TM2S", "TM3S", "TM8P", \
- "TM8S", "TM9P", "TM9S", "TN0H", "TS0C", }
-
-#define ASMC_MP5_TEMPS { "TA0P", "TCAC", "TCAD", "TCAG", "TCAH", \
- "TCAS", "TCBC", "TCBD", "TCBG", "TCBH", \
- "TCBS", "TH1F", "TH1P", "TH1V", "TH2F", \
- "TH2P", "TH2V", "TH3F", "TH3P", "TH3V", \
- "TH4F", "TH4P", "TH4V", "THPS", "THTG", \
- "TM1P", "TM2P", "TM2V", "TM3P", "TM3V", \
- "TM4P", "TM5P", "TM6P", "TM6V", "TM7P", \
- "TM7V", "TM8P", "TM8V", "TM9V", "TMA1", \
- "TMA2", "TMA3", "TMA4", "TMB1", "TMB2", \
- "TMB3", "TMB4", "TMHS", "TMLS", "TMPS", \
- "TMPV", "TMTG", "TN0D", "TN0H", "TNTG", \
- "Te1F", "Te1P", "Te1S", "Te2F", "Te2S", \
- "Te3F", "Te3S", "Te4F", "Te4S", "Te5F", \
- "Te5S", "TeGG", "TeGP", "TeRG", "TeRP", \
- "TeRV", "Tp0C", "Tp1C", "TpPS", "TpTG", \
- NULL }
-
-#define ASMC_MP5_TEMPNAMES { "ambient", "TCAC", "TCAD", "TCAG", "TCAH", \
- "TCAS", "TCBC", "TCBD", "TCBG", "TCBH", \
- "TCBS", "TH1F", "TH1P", "TH1V", "TH2F", \
- "TH2P", "TH2V", "TH3F", "TH3P", "TH3V", \
- "TH4F", "TH4P", "TH4V", "THPS", "THTG", \
- "TM1P", "TM2P", "TM2V", "TM3P", "TM3V", \
- "TM4P", "TM5P", "TM6P", "TM6V", "TM7P", \
- "TM7V", "TM8P", "TM8V", "TM9V", "ram_a1", \
- "ram_a2", "ram_a3", "ram_a4", "ram_b1", "ram_b2", \
- "ram_b3", "ram_b4", "TMHS", "TMLS", "TMPS", \
- "TMPV", "TMTG", "TN0D", "TN0H", "TNTG", \
- "Te1F", "Te1P", "Te1S", "Te2F", "Te2S", \
- "Te3F", "Te3S", "Te4F", "Te4S", "Te5F", \
- "Te5S", "TeGG", "TeGP", "TeRG", "TeRP", \
- "TeRV", "Tp0C", "Tp1C", "TpPS", "TpTG", }
-
-#define ASMC_MP5_TEMPDESCS { "TA0P", "TCAC", "TCAD", "TCAG", "TCAH", \
- "TCAS", "TCBC", "TCBD", "TCBG", "TCBH", \
- "TCBS", "TH1F", "TH1P", "TH1V", "TH2F", \
- "TH2P", "TH2V", "TH3F", "TH3P", "TH3V", \
- "TH4F", "TH4P", "TH4V", "THPS", "THTG", \
- "TM1P", "TM2P", "TM2V", "TM3P", "TM3V", \
- "TM4P", "TM5P", "TM6P", "TM6V", "TM7P", \
- "TM7V", "TM8P", "TM8V", "TM9V", "TMA1", \
- "TMA2", "TMA3", "TMA4", "TMB1", "TMB2", \
- "TMB3", "TMB4", "TMHS", "TMLS", "TMPS", \
- "TMPV", "TMTG", "TN0D", "TN0H", "TNTG", \
- "Te1F", "Te1P", "Te1S", "Te2F", "Te2S", \
- "Te3F", "Te3S", "Te4F", "Te4S", "Te5F", \
- "Te5S", "TeGG", "TeGP", "TeRG", "TeRP", \
- "TeRV", "Tp0C", "Tp1C", "TpPS", "TpTG", }
-
-#define ASMC_MP6_TEMPS { "TA0P", "TA1P", "TC0P", "TG0D", "TG0P", \
- "TG1D", "TG1P", "TM0P", "TM1P", NULL }
-
-#define ASMC_MP6_TEMPNAMES { "ambient_air_1", "ambient_air_2", \
- "cpu_proximity", "gpu_diode_1", \
- "gpu_proximity_1", "gpu_diode_2", \
- "gpu_proximity_2", "mem_proximity_1", \
- "mem_proximity_2" }
-
-#define ASMC_MP6_TEMPDESCS { "Ambient Air 1", "Ambient Air 2", \
- "CPU Proximity", "GPU Diode 1", \
- "GPU Proximity 1", "GPU Diode 2", \
- "GPU Proximity 2", "Memory Bank A", \
- "Memory Bank B" }
-
-#define ASMC_MBA_TEMPS { "TB0T", NULL }
-#define ASMC_MBA_TEMPNAMES { "enclosure" }
-#define ASMC_MBA_TEMPDESCS { "Enclosure Bottom" }
-
-#define ASMC_MBA3_TEMPS { "TB0T", "TB1T", "TB2T", \
- "TC0D", "TC0E", "TC0P", NULL }
-
-#define ASMC_MBA3_TEMPNAMES { "enclosure", "TB1T", "TB2T", \
- "TC0D", "TC0E", "TC0P" }
-
-#define ASMC_MBA3_TEMPDESCS { "Enclosure Bottom", "TB1T", "TB2T", \
- "TC0D", "TC0E", "TC0P" }
-
-#define ASMC_MBA4_TEMPS { "TB0T", "TB1T", "TB2T", "TC0C", \
- "TC0D", "TC0E", "TC0F", "TC0P", \
- "TC1C", "TC2C", "TCGC", "TCSA", \
- "TH0F", "TH0J", "TH0O", "TH0o", \
- "TM0P", "TPCD", "Ta0P", "Th1H", \
- "Tm0P", "Tm1P", "Ts0P", "Ts0S", \
- NULL }
-
-#define ASMC_MBA4_TEMPNAMES { "TB0T", "TB1T", "TB2T", "TC0C", \
- "TC0D", "TC0E", "TC0F", "TC0P", \
- "TC1C", "TC2C", "TCGC", "TCSA", \
- "TH0F", "TH0J", "TH0O", "TH0o", \
- "TM0P", "TPCD", "Ta0P", "Th1H", \
- "Tm0P", "Tm1P", "Ts0P", "Ts0S", \
- NULL }
-
-#define ASMC_MBA4_TEMPDESCS { "TB0T", "TB1T", "TB2T", "TC0C", \
- "TC0D", "TC0E", "TC0F", "TC0P", \
- "TC1C", "TC2C", "TCGC", "TCSA", \
- "TH0F", "TH0J", "TH0O", "TH0o", \
- "TM0P", "TPCD", "Ta0P", "Th1H", \
- "Tm0P", "Tm1P", "Ts0P", "Ts0S", \
- NULL }
-
-#define ASMC_MBA5_TEMPS { "TB0T", "TB1T", "TB2T", "TC0C", \
- "TC0D", "TC0E", "TC0F", "TC0P", \
- "TC1C", "TC2C", "TCGC", "TCSA", \
- "TCXC", "THSP", "TM0P", "TPCD", \
- "Ta0P", "Th1H", "Tm0P", "Tm1P", \
- "Ts0P", "Ts0S", NULL }
-
-#define ASMC_MBA5_TEMPNAMES { "enclosure1", "enclosure2", "enclosure3", "TC0C", \
- "cpudiode", "cputemp1", "cputemp2", "cpuproximity", \
- "cpucore1", "cpucore2", "cpupeci", "pecisa", \
- "TCXC", "THSP", "memorybank", "pchdie", \
- "Ta0P", "heatpipe", "mainboardproximity1", "mainboardproximity2", \
- "palmrest", "memoryproximity" }
-
-#define ASMC_MBA5_TEMPDESCS { "Enclosure Bottom 1", "Enclosure Bottom 2", "Enclosure Bottom 3", "TC0C",\
- "CPU Diode", "CPU Temp 1", "CPU Temp 2", "CPU Proximity", \
- "CPU Core 1", "CPU Core 2", "CPU Peci Core", "PECI SA", \
- "TCXC", "THSP", "Memory Bank A", "PCH Die", \
- "Ta0P", "Heatpipe", "Mainboard Proximity 1", "Mainboard Proximity 2", \
- "Palm Rest", "Memory Proximity" }
-
-/*
- * TODO: validate the temp zones for MBA 6.x !
- */
-#define ASMC_MBA6_TEMPS { "TB0T", "TB1T", "TB2T", \
- "TC0E", "TC0F", "TC0P", \
- "TC1C", "TC2C", "TCGC", "TCSA", \
- "TCXC", "THSP", "TM0P", "TPCD", \
- "Ta0P", "Th1H", "Tm0P", \
- "Ts0P", "Ts0S", NULL }
-
-#define ASMC_MBA6_TEMPNAMES { "enclosure1", "enclosure2", "enclosure3", \
- "cputemp1", "cputemp2", "cpuproximity", \
- "cpucore1", "cpucore2", "cpupeci", "pecisa", \
- "TCXC", "THSP", "memorybank", "pchdie", \
- "Ta0P", "heatpipe", "mainboardproximity1", \
- "palmrest", "memoryproximity" }
-
-#define ASMC_MBA6_TEMPDESCS { "Enclosure Bottom 1", "Enclosure Bottom 2", "Enclosure Bottom 3", \
- "CPU Temp 1", "CPU Temp 2", "CPU Proximity", \
- "CPU Core 1", "CPU Core 2", "CPU Peci Core", "PECI SA", \
- "TCXC", "THSP", "Memory Bank A", "PCH Die", \
- "Ta0P", "Heatpipe", "Mainboard Proximity 1", \
- "Palm Rest", "Memory Proximity" }
-
-
-#define ASMC_MBA7_TEMPS { "TB0T", "TB1T", "TB2T", \
- "TC0E", "TC0F", "TC0P", \
- "TC1C", "TC2C", \
- "TCGC", "TCSA", "TCXC", \
- "THSP", "TM0P", "TPCD", \
- "TW0P" "Ta0P", "Th1H", \
- "Tm0P", "Ts0P", "Ts0S", NULL }
-
-#define ASMC_MBA7_TEMPNAMES { "enclosure1", "enclosure2", "enclosure3", \
- "cputemp1", "cputemp2", "cpuproximity", \
- "cpucore1", "cpucore2", \
- "pecigpu", "pecisa", "pecicpu", \
- "thunderboltproximity", "memorybank", "pchdie", \
- "wirelessproximity", "airflowproximity", "heatpipe", \
- "mainboardproximity", "palmrest", "memoryproximity" }
-
-#define ASMC_MBA7_TEMPDESCS { "Enclosure Bottom 1", "Enclosure Bottom 2", "Enclosure Bottom 3", \
- "CPU Temp 1", "CPU Temp 2", "CPU Proximity", \
- "CPU Core 1", "CPU Core 2", \
- "PECI GPU", "PECI SA", "PECI CPU", \
- "Thunderbolt Proximity", "Memory Bank A", "PCH Die", \
- "Wireless Proximity", "Airflow Proxmity", "Heatpipe", \
- "Mainboard Proximity", "Palm Rest", "Memory Proximity" }
diff --git a/sys/dev/dpaa/bman.c b/sys/dev/dpaa/bman.c
index c275d2335eb8..3d1052f9ed9f 100644
--- a/sys/dev/dpaa/bman.c
+++ b/sys/dev/dpaa/bman.c
@@ -1,27 +1,7 @@
-/*-
- * Copyright (c) 2011-2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
+/*
+ * Copyright (c) 2026 Justin Hibbits
*
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON 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 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * SPDX-License-Identifier: BSD-2-Clause
*/
#include <sys/param.h>
@@ -29,6 +9,7 @@
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/lock.h>
+#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/proc.h>
@@ -36,63 +17,161 @@
#include <sys/rman.h>
#include <sys/sched.h>
+#include <machine/bus.h>
#include <machine/tlb.h>
#include "bman.h"
+#include "dpaa_common.h"
+#include "bman_var.h"
+
+#define BMAN_POOL_SWDET(n) (0x000 + 4 * (n))
+#define BMAN_POOL_HWDET(n) (0x100 + 4 * (n))
+#define BMAN_POOL_SWDXT(n) (0x200 + 4 * (n))
+#define BMAN_POOL_HWDXT(n) (0x300 + 4 * (n))
+#define FBPR_FP_LWIT 0x804
+#define BMAN_IP_REV_1 0x0bf8
+#define IP_MAJ_S 8
+#define IP_MAJ_M 0x0000ff00
+#define IP_MIN_M 0x000000ff
+#define BMAN_IP_REV_2 0x0bfc
+#define BMAN_FBPR_BARE 0x0c00
+#define BMAN_FBPR_BAR 0x0c04
+#define BMAN_FBPR_AR 0x0c10
+#define BMAN_LIODNR 0x0d08
+
+#define BMAN_POOL_CONTENT(n) (0x0600 + 4 * (n))
+#define BMAN_ECSR 0x0a00
+#define BMAN_ECIR 0x0a04
+#define ECIR_PORTAL(r) (((r) >> 24) & 0x0f)
+#define ECIR_VERB(r) (((r) >> 16) & 0x07)
+#define ECIR_R 0x00080000
+#define ECIR_POOL(r) ((r) & 0x3f)
+#define BMAN_CECR 0x0a34 /* Corruption Error Capture Register */
+#define BMAN_CEAR 0x0a38 /* Corruption Error Address Register */
+#define BMAN_AECR 0x0a34 /* Acces Error Capture Register */
+#define BMAN_AEAR 0x0a38 /* Acces Error Address Register */
+#define BMAN_ERR_ISR 0x0e00
+#define BMAN_ERR_IER 0x0e04
+#define BMAN_ERR_ISDR 0x0e08
+#define ERR_EMAI 0x00000040
+#define ERR_EMCI 0x00000020
+#define ERR_IVCI 0x00000010
+#define ERR_FLWI 0x00000008
+#define ERR_MBEI 0x00000004
+#define ERR_SBEI 0x00000002
+#define ERR_BSCN 0x00000001
+
+static MALLOC_DEFINE(M_BMAN, "bman", "DPAA Buffer Manager structures");
static struct bman_softc *bman_sc;
-extern t_Handle bman_portal_setup(struct bman_softc *bsc);
+static void
+bman_isr(void *arg)
+{
+ struct bman_softc *sc = arg;
+ uint32_t ier, isr, isr_bit;
+ uint32_t reg;
+
+ ier = bus_read_4(sc->sc_rres, BMAN_ERR_IER);
+ isr = bus_read_4(sc->sc_rres, BMAN_ERR_ISR);
+
+ isr_bit = (isr & ier);
+ if (isr_bit == 0)
+ goto end;
+
+ if (isr_bit & ERR_EMAI) {
+ device_printf(sc->sc_dev, "External memory access error\n");
+ reg = bus_read_4(sc->sc_rres, BMAN_AECR);
+ if (reg <= 63)
+ device_printf(sc->sc_dev, " pool %d\n", reg);
+ else
+ device_printf(sc->sc_dev, " FBPR free list\n");
+ reg = bus_read_4(sc->sc_rres, BMAN_AEAR);
+ device_printf(sc->sc_dev, " offset: %#x\n", reg);
+ }
+
+ if (isr_bit & ERR_EMCI) {
+ device_printf(sc->sc_dev, "External memory corruption error\n");
+ reg = bus_read_4(sc->sc_rres, BMAN_CECR);
+ if (reg <= 63)
+ device_printf(sc->sc_dev, " pool %d\n", reg);
+ else
+ device_printf(sc->sc_dev, " FBPR free list\n");
+ reg = bus_read_4(sc->sc_rres, BMAN_CEAR);
+ device_printf(sc->sc_dev, " offset: %#x\n", reg);
+ }
+ if (isr_bit & ERR_IVCI) {
+ reg = bus_read_4(sc->sc_rres, BMAN_ECIR);
+ device_printf(sc->sc_dev, "Invalid verb command\n");
+ device_printf(sc->sc_dev, "Portal: %d, ring: %s\n",
+ ECIR_POOL(reg), (reg & ECIR_R) ? "RCR" : "Command");
+ device_printf(sc->sc_dev, "verb: 0x%02x, pool: %d\n",
+ ECIR_VERB(reg), ECIR_POOL(reg));
+ }
+ if (isr_bit & (ERR_MBEI | ERR_SBEI)) {
+ if (isr_bit & ERR_MBEI)
+ device_printf(sc->sc_dev, "Multi-bit ECC error\n");
+ if (isr_bit & ERR_MBEI)
+ device_printf(sc->sc_dev, "Single-bit ECC error\n");
+ /* TODO: Add more error details for ECC errors. */
+ }
+
+end:
+ bus_write_4(sc->sc_rres, BMAN_ERR_ISR, isr);
+}
static void
-bman_exception(t_Handle h_App, e_BmExceptions exception)
+bman_get_version(struct bman_softc *sc)
{
- struct bman_softc *sc;
- const char *message;
+ uint32_t reg = bus_read_4(sc->sc_rres, BMAN_IP_REV_1);
- sc = h_App;
+ sc->sc_major = (reg & IP_MAJ_M) >> IP_MAJ_S;
+ sc->sc_minor = (reg & IP_MIN_M);
+}
- switch (exception) {
- case e_BM_EX_INVALID_COMMAND:
- message = "Invalid Command Verb";
- break;
- case e_BM_EX_FBPR_THRESHOLD:
- message = "FBPR pool exhaused. Consider increasing "
- "BMAN_MAX_BUFFERS";
- break;
- case e_BM_EX_SINGLE_ECC:
- message = "Single bit ECC error";
- break;
- case e_BM_EX_MULTI_ECC:
- message = "Multi bit ECC error";
- break;
- default:
- message = "Unknown error";
+static int
+bman_set_memory(struct bman_softc *sc, vm_paddr_t pa, vm_size_t size)
+{
+ vm_paddr_t bar_pa;
+ if ((pa & (size - 1)) != 0 || (size & (size - 1)) != 0) {
+ device_printf(sc->sc_dev,
+ "invalid memory configuration: pa: %#jx, size: %#jx\n",
+ (uintmax_t)pa, (uintmax_t)size);
+ return (ENXIO);
}
+ bar_pa = bus_read_4(sc->sc_rres, BMAN_FBPR_BARE);
+ bar_pa <<= 32;
+ bar_pa |= bus_read_4(sc->sc_rres, BMAN_FBPR_BAR);
+ if (bar_pa != 0 && bar_pa != pa) {
+ device_printf(sc->sc_dev,
+ "attempted to reinitialize BMan with different BAR\n");
+ return (ENOMEM);
+ } else if (bar_pa == pa)
+ return (0);
+
+ bus_write_4(sc->sc_rres, BMAN_FBPR_BARE, pa >> 32);
+ bus_write_4(sc->sc_rres, BMAN_FBPR_BAR, pa & 0xffffffff);
+ bus_write_4(sc->sc_rres, BMAN_FBPR_AR, ilog2(size) - 1);
- device_printf(sc->sc_dev, "BMAN Exception: %s.\n", message);
+ return (0);
}
int
bman_attach(device_t dev)
{
struct bman_softc *sc;
- t_BmRevisionInfo rev;
- t_Error error;
- t_BmParam bp;
+ vm_paddr_t bp_pa;
+ size_t bp_size;
+ int bp_count;
sc = device_get_softc(dev);
sc->sc_dev = dev;
bman_sc = sc;
- /* Check if MallocSmart allocator is ready */
- if (XX_MallocSmartInit() != E_OK)
- return (ENXIO);
-
/* Allocate resources */
sc->sc_rrid = 0;
- sc->sc_rres = bus_alloc_resource_anywhere(dev, SYS_RES_MEMORY,
- &sc->sc_rrid, BMAN_CCSR_SIZE, RF_ACTIVE);
+ sc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ sc->sc_rrid, RF_ACTIVE);
if (sc->sc_rres == NULL)
return (ENXIO);
@@ -102,36 +181,33 @@ bman_attach(device_t dev)
if (sc->sc_ires == NULL)
goto err;
- /* Initialize BMAN */
- memset(&bp, 0, sizeof(bp));
- bp.guestId = NCSW_MASTER_ID;
- bp.baseAddress = rman_get_bushandle(sc->sc_rres);
- bp.totalNumOfBuffers = BMAN_MAX_BUFFERS;
- bp.f_Exception = bman_exception;
- bp.h_App = sc;
- bp.errIrq = (uintptr_t)sc->sc_ires;
- bp.partBpidBase = 0;
- bp.partNumOfPools = BM_MAX_NUM_OF_POOLS;
+ bman_get_version(sc);
+ if (sc->sc_major == 2 && sc->sc_minor == 0)
+ bp_count = BMAN_MAX_POOLS_1023;
+ else
+ bp_count = BMAN_MAX_POOLS;
- sc->sc_bh = BM_Config(&bp);
- if (sc->sc_bh == NULL)
- goto err;
+ /* TODO: LIODN */
+ bus_write_4(sc->sc_rres, BMAN_LIODNR, 0);
- /* Warn if there is less than 5% free FPBR's in pool */
- error = BM_ConfigFbprThreshold(sc->sc_bh, (BMAN_MAX_BUFFERS / 8) / 20);
- if (error != E_OK)
- goto err;
+ sc->sc_vmem = vmem_create("BMan Pools", 0, bp_count, 1, 0, M_WAITOK);
- error = BM_Init(sc->sc_bh);
- if (error != E_OK)
- goto err;
+ /* Pool is reserved memory, so no need to track it ourselves. */
+ dpaa_map_private_memory(dev, 0, "fsl,bman-fbpr", &bp_pa, &bp_size);
+ bman_set_memory(sc, bp_pa, bp_size);
- error = BM_GetRevision(sc->sc_bh, &rev);
- if (error != E_OK)
- goto err;
+ /* Warn if FBPR drops below 5% total. */
+ bus_write_4(sc->sc_rres, FBPR_FP_LWIT, (bp_size / 8) / 20);
+
+ /* Clear interrupt status, and enable all interrupts. */
+ bus_write_4(sc->sc_rres, BMAN_ERR_ISR, 0xffffffff);
+ bus_write_4(sc->sc_rres, BMAN_ERR_IER, 0xffffffff);
+ bus_write_4(sc->sc_rres, BMAN_ERR_ISDR, 0);
- device_printf(dev, "Hardware version: %d.%d.\n",
- rev.majorRev, rev.minorRev);
+ /* Enable the IRQ line now. */
+ if (bus_setup_intr(dev, sc->sc_ires, INTR_TYPE_NET, NULL, bman_isr,
+ sc, &sc->sc_icookie) != 0)
+ goto err;
return (0);
@@ -147,9 +223,10 @@ bman_detach(device_t dev)
sc = device_get_softc(dev);
- if (sc->sc_bh != NULL)
- BM_Free(sc->sc_bh);
-
+ if (sc->sc_vmem != NULL)
+ vmem_destroy(sc->sc_vmem);
+ if (sc->sc_icookie != NULL)
+ bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie);
if (sc->sc_ires != NULL)
bus_release_resource(dev, SYS_RES_IRQ,
sc->sc_irid, sc->sc_ires);
@@ -186,179 +263,105 @@ bman_shutdown(device_t dev)
* BMAN API
*/
-t_Handle
-bman_pool_create(uint8_t *bpid, uint16_t bufferSize, uint16_t maxBuffers,
- uint16_t minBuffers, uint16_t allocBuffers, t_GetBufFunction *f_GetBuf,
- t_PutBufFunction *f_PutBuf, uint32_t dep_sw_entry, uint32_t dep_sw_exit,
- uint32_t dep_hw_entry, uint32_t dep_hw_exit,
- t_BmDepletionCallback *f_Depletion, t_Handle h_BufferPool,
- t_PhysToVirt *f_PhysToVirt, t_VirtToPhys *f_VirtToPhys)
+struct bman_pool *
+bman_new_pool(void)
{
- uint32_t thresholds[MAX_DEPLETION_THRESHOLDS];
struct bman_softc *sc;
- t_Handle pool, portal;
- t_BmPoolParam bpp;
- int error;
+ vmem_addr_t bpid;
+ struct bman_pool *pool;
sc = bman_sc;
pool = NULL;
- sched_pin();
-
- portal = bman_portal_setup(sc);
- if (portal == NULL)
- goto err;
-
- memset(&bpp, 0, sizeof(bpp));
- bpp.h_Bm = sc->sc_bh;
- bpp.h_BmPortal = portal;
- bpp.h_App = h_BufferPool;
- bpp.numOfBuffers = allocBuffers;
-
- bpp.bufferPoolInfo.h_BufferPool = h_BufferPool;
- bpp.bufferPoolInfo.f_GetBuf = f_GetBuf;
- bpp.bufferPoolInfo.f_PutBuf = f_PutBuf;
- bpp.bufferPoolInfo.f_PhysToVirt = f_PhysToVirt;
- bpp.bufferPoolInfo.f_VirtToPhys = f_VirtToPhys;
- bpp.bufferPoolInfo.bufferSize = bufferSize;
-
- pool = BM_POOL_Config(&bpp);
- if (pool == NULL)
- goto err;
-
- /*
- * Buffer context must be disabled on FreeBSD
- * as it could cause memory corruption.
- */
- BM_POOL_ConfigBuffContextMode(pool, 0);
-
- if (minBuffers != 0 || maxBuffers != 0) {
- error = BM_POOL_ConfigStockpile(pool, maxBuffers, minBuffers);
- if (error != E_OK)
- goto err;
- }
-
- if (f_Depletion != NULL) {
- thresholds[BM_POOL_DEP_THRESH_SW_ENTRY] = dep_sw_entry;
- thresholds[BM_POOL_DEP_THRESH_SW_EXIT] = dep_sw_exit;
- thresholds[BM_POOL_DEP_THRESH_HW_ENTRY] = dep_hw_entry;
- thresholds[BM_POOL_DEP_THRESH_HW_EXIT] = dep_hw_exit;
- error = BM_POOL_ConfigDepletion(pool, f_Depletion, thresholds);
- if (error != E_OK)
- goto err;
- }
-
- error = BM_POOL_Init(pool);
- if (error != E_OK)
- goto err;
+ if (vmem_alloc(sc->sc_vmem, 1, M_FIRSTFIT | M_NOWAIT, &bpid) != 0)
+ return (NULL);
- *bpid = BM_POOL_GetId(pool);
- sc->sc_bpool_cpu[*bpid] = PCPU_GET(cpuid);
+ pool = malloc(sizeof(*pool), M_BMAN, M_WAITOK | M_ZERO);
- sched_unpin();
+ pool->bpid = bpid;
return (pool);
-
-err:
- if (pool != NULL)
- BM_POOL_Free(pool);
-
- sched_unpin();
-
- return (NULL);
}
-int
-bman_pool_destroy(t_Handle pool)
+struct bman_pool *
+bman_pool_create(uint8_t *bpid, uint16_t buffer_size, uint16_t max_buffers,
+ uint32_t dep_sw_entry, uint32_t dep_sw_exit,
+ uint32_t dep_hw_entry, uint32_t dep_hw_exit,
+ bm_depletion_handler dep_cb, void *arg)
{
struct bman_softc *sc;
+ struct bman_pool *bp;
sc = bman_sc;
- thread_lock(curthread);
- sched_bind(curthread, sc->sc_bpool_cpu[BM_POOL_GetId(pool)]);
- thread_unlock(curthread);
+ bp = bman_new_pool();
+ if (bpid != NULL)
+ *bpid = bp->bpid;
+
+ if (dep_cb) {
+ bp->dep_cb = dep_cb;
+ bus_write_4(sc->sc_rres, BMAN_POOL_SWDET(bp->bpid),
+ dep_sw_entry);
+ bus_write_4(sc->sc_rres, BMAN_POOL_SWDXT(bp->bpid),
+ dep_sw_exit);
+ bus_write_4(sc->sc_rres, BMAN_POOL_HWDET(bp->bpid),
+ dep_hw_entry);
+ bus_write_4(sc->sc_rres, BMAN_POOL_HWDXT(bp->bpid),
+ dep_hw_exit);
+ bp->arg = arg;
+ bman_portal_enable_scn(DPCPU_GET(bman_affine_portal), bp);
+ }
- BM_POOL_Free(pool);
+ return (bp);
+}
- thread_lock(curthread);
- sched_unbind(curthread);
- thread_unlock(curthread);
+int
+bman_pool_destroy(struct bman_pool *pool)
+{
+ /* Need to error, or print a warning, if the pool isn't empty */
+ if (bman_count(pool) != 0)
+ return (EBUSY);
+ vmem_free(bman_sc->sc_vmem, pool->bpid, 1);
+ free(pool, M_BMAN);
return (0);
}
int
-bman_pool_fill(t_Handle pool, uint16_t nbufs)
+bman_put_buffers(struct bman_pool *pool, struct bman_buffer *buffers, int count)
{
- struct bman_softc *sc;
- t_Handle portal;
+ struct bman_portal_softc *portal;
int error;
- sc = bman_sc;
- sched_pin();
+ critical_enter();
- portal = bman_portal_setup(sc);
+ portal = DPCPU_GET(bman_affine_portal);
if (portal == NULL) {
- sched_unpin();
+ critical_exit();
return (EIO);
}
- error = BM_POOL_FillBufs(pool, portal, nbufs);
-
- sched_unpin();
-
- return ((error == E_OK) ? 0 : EIO);
-}
-
-void *
-bman_get_buffer(t_Handle pool)
-{
- struct bman_softc *sc;
- t_Handle portal;
- void *buffer;
-
- sc = bman_sc;
- sched_pin();
-
- portal = bman_portal_setup(sc);
- if (portal == NULL) {
- sched_unpin();
- return (NULL);
+ while (count > 0) {
+ int c = min(count, 8);
+ error = bman_release(pool, buffers, c);
+ buffers += c;
+ count -= c;
}
- buffer = BM_POOL_GetBuf(pool, portal);
+ critical_exit();
- sched_unpin();
-
- return (buffer);
+ return (error);
}
-int
-bman_put_buffer(t_Handle pool, void *buffer)
+uint32_t
+bman_get_bpid(struct bman_pool *pool)
{
- struct bman_softc *sc;
- t_Handle portal;
- int error;
-
- sc = bman_sc;
- sched_pin();
-
- portal = bman_portal_setup(sc);
- if (portal == NULL) {
- sched_unpin();
- return (EIO);
- }
-
- error = BM_POOL_PutBuf(pool, portal, buffer);
-
- sched_unpin();
-
- return ((error == E_OK) ? 0 : EIO);
+ return (pool->bpid);
}
uint32_t
-bman_count(t_Handle pool)
+bman_count(struct bman_pool *pool)
{
- return (BM_POOL_GetCounter(pool, e_BM_POOL_COUNTERS_CONTENT));
+ return (bus_read_4(bman_sc->sc_rres, BMAN_POOL_CONTENT(pool->bpid)));
}
+
diff --git a/sys/dev/dpaa/bman.h b/sys/dev/dpaa/bman.h
index 01c09489890c..118c6f5938bc 100644
--- a/sys/dev/dpaa/bman.h
+++ b/sys/dev/dpaa/bman.h
@@ -1,3 +1,9 @@
+/*
+ * Copyright (c) 2026 Justin Hibbits
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
/*-
* Copyright (c) 2011-2012 Semihalf.
* All rights reserved.
@@ -27,29 +33,16 @@
#ifndef _BMAN_H
#define _BMAN_H
+#include <sys/vmem.h>
#include <machine/vmparam.h>
-#include <contrib/ncsw/inc/Peripherals/bm_ext.h>
-
/*
* BMAN Configuration
*/
-/* Maximum number of buffers in all BMAN pools */
-#define BMAN_MAX_BUFFERS 4096
-
/*
* Portal definitions
*/
-#define BMAN_CE_PA(base) (base)
-#define BMAN_CI_PA(base) ((base) + 0x100000)
-
-#define BMAN_PORTAL_CE_PA(base, n) \
- (BMAN_CE_PA(base) + ((n) * BMAN_PORTAL_CE_SIZE))
-#define BMAN_PORTAL_CI_PA(base, n) \
- (BMAN_CI_PA(base) + ((n) * BMAN_PORTAL_CI_SIZE))
-
-#define BMAN_CCSR_SIZE 0x1000
struct bman_softc {
device_t sc_dev; /* device handle */
@@ -57,129 +50,42 @@ struct bman_softc {
struct resource *sc_rres; /* register resource */
int sc_irid; /* interrupt rid */
struct resource *sc_ires; /* interrupt resource */
+ void *sc_icookie;
+ vmem_t *sc_vmem; /* resource pool */
+ int sc_major;
+ int sc_minor;
+};
- bool sc_regs_mapped[MAXCPU]; /* register mapping status */
+struct bman_buffer {
+ uint16_t bpid;
+ uint16_t buf_hi;
+ uint32_t buf_lo;
+} __aligned(8);
- t_Handle sc_bh; /* BMAN handle */
- t_Handle sc_bph[MAXCPU]; /* BMAN portal handles */
- vm_paddr_t sc_bp_pa; /* BMAN portals PA */
- unsigned int sc_bpool_cpu[BM_MAX_NUM_OF_POOLS];
-};
+struct bman_pool;
+struct bman_buffer;
-/*
- * External API
- */
+typedef void (*bm_depletion_handler)(void *, bool);
/*
- * @brief Function to create BMAN pool.
- *
- * @param bpid The pointer to variable where Buffer Pool ID will be
- * stored.
- *
- * @param bufferSize The size of buffers in newly created pool.
- *
- * @param maxBuffers The maximum number of buffers in software stockpile.
- * Set to 0 if software stockpile should not be created.
- *
- * @param minBuffers The minimum number of buffers in software stockpile.
- * Set to 0 if software stockpile should not be created.
- *
- * @param allocBuffers The number of buffers to preallocate during pool
- * creation.
- *
- * @param f_GetBuf The buffer allocating function. Called only by
- * bman_pool_create() and bman_pool_fill().
- *
- * @param f_PutBuf The buffer freeing function. Called only by
- * bman_pool_destroy().
- *
- * @param dep_sw_entry The software portal depletion entry threshold.
- * Set to 0 if depletion should not be signaled on
- * software portal.
- *
- * @param dep_sw_exit The software portal depletion exit threshold.
- * Set to 0 if depletion should not be signaled on
- * software portal.
- *
- * @param dep_hw_entry The hardware portal depletion entry threshold.
- * Set to 0 if depletion should not be signaled on
- * hardware portal.
- *
- * @param dep_hw_exit The hardware portal depletion exit threshold.
- * Set to 0 if depletion should not be signaled on
- * hardware portal.
- *
- * @param f_Depletion The software portal depletion notification function.
- * Set to NULL if depletion notification is not used.
- *
- * @param h_BufferPool The user provided buffer pool context passed to
- * f_GetBuf, f_PutBuf and f_Depletion functions.
- *
- * @param f_PhysToVirt The PA to VA translation function. Set to NULL if
- * default one should be used.
- *
- * @param f_VirtToPhys The VA to PA translation function. Set to NULL if
- * default one should be used.
- *
- * @returns Handle to newly created BMAN pool or NULL on error.
- *
- * @cautions If pool uses software stockpile, all accesses to given
- * pool must be protected by lock. Even if only hardware
- * portal depletion notification is used, the caller must
- * provide valid @p f_Depletion function.
+ * External API
*/
-t_Handle bman_pool_create(uint8_t *bpid, uint16_t bufferSize,
- uint16_t maxBuffers, uint16_t minBuffers, uint16_t allocBuffers,
- t_GetBufFunction *f_GetBuf, t_PutBufFunction *f_PutBuf,
- uint32_t dep_sw_entry, uint32_t dep_sw_exit, uint32_t dep_hw_entry,
- uint32_t dep_hw_exit, t_BmDepletionCallback *f_Depletion,
- t_Handle h_BufferPool, t_PhysToVirt *f_PhysToVirt,
- t_VirtToPhys *f_VirtToPhys);
-/*
- * @brief Fill pool with buffers.
- *
- * The bman_pool_fill() function fills the BMAN pool with buffers. The buffers
- * are allocated through f_GetBuf function (see bman_pool_create() description).
- *
- * @param pool The BMAN pool handle.
- * @param nbufs The number of buffers to allocate. To maximize
- * performance this value should be multiple of 8.
- *
- * @returns Zero on success or error code on failure.
- */
-int bman_pool_fill(t_Handle pool, uint16_t nbufs);
+struct bman_pool *bman_new_pool(void);
+struct bman_pool *bman_pool_create(uint8_t *bpid, uint16_t buffer_size,
+ uint16_t max_buffers, uint32_t dep_sw_entry, uint32_t dep_sw_exit, uint32_t
+ dep_hw_entry, uint32_t dep_hw_exit, bm_depletion_handler dep_cb, void *arg);
/*
* @brief Destroy pool.
*
- * The bman_pool_destroy() function destroys the BMAN pool. Buffers for pool
- * are free through f_PutBuf function (see bman_pool_create() description).
- *
- * @param pool The BMAN pool handle.
- *
- * @returns Zero on success or error code on failure.
- */
-int bman_pool_destroy(t_Handle pool);
-
-/*
- * @brief Get a buffer from BMAN pool.
+ * The bman_pool_destroy() function destroys the BMAN pool.
+ * The buffer pool must be empty.
*
* @param pool The BMAN pool handle.
- *
- * @returns Pointer to the buffer or NULL if pool is empty.
+ * @return 0 on success, EBUSY if the pool is not empty.
*/
-void *bman_get_buffer(t_Handle pool);
-
-/*
- * @brief Put a buffer to BMAN pool.
- *
- * @param pool The BMAN pool handle.
- * @param buffer The pointer to buffer.
- *
- * @returns Zero on success or error code on failure.
- */
-int bman_put_buffer(t_Handle pool, void *buffer);
+int bman_pool_destroy(struct bman_pool *pool);
/*
* @brief Count free buffers in given pool.
@@ -188,7 +94,25 @@ int bman_put_buffer(t_Handle pool, void *buffer);
*
* @returns Number of free buffers in pool.
*/
-uint32_t bman_count(t_Handle pool);
+uint32_t bman_count(struct bman_pool *pool);
+
+int bman_put_buffers(struct bman_pool *, struct bman_buffer *, int);
+static inline int
+bman_put_buffer(struct bman_pool *p, vm_paddr_t buf, int bpid)
+{
+ struct bman_buffer b = {
+ .bpid = bpid,
+ .buf_hi = ((uintptr_t)buf) >> 32,
+ .buf_lo = ((uintptr_t)buf) & 0xffffffff
+ };
+ return (bman_put_buffers(p, &b, 1));
+}
+
+int bman_acquire(struct bman_pool *, struct bman_buffer *, uint8_t);
+
+int bman_create_affine_portal(device_t, vm_offset_t, vm_offset_t, int);
+void bman_destroy_affine_portal(int);
+uint32_t bman_get_bpid(struct bman_pool *);
/*
* Bus i/f
diff --git a/sys/dev/dpaa/bman_fdt.c b/sys/dev/dpaa/bman_fdt.c
index 330db7b89715..c77d58cf118d 100644
--- a/sys/dev/dpaa/bman_fdt.c
+++ b/sys/dev/dpaa/bman_fdt.c
@@ -40,6 +40,7 @@
#include <dev/ofw/ofw_subr.h>
#include "bman.h"
+#include "bman_var.h"
#include "portals.h"
#define FBMAN_DEVSTR "Freescale Buffer Manager"
@@ -59,12 +60,7 @@ static device_method_t bman_methods[] = {
DEVMETHOD_END
};
-static driver_t bman_driver = {
- "bman",
- bman_methods,
- sizeof(struct bman_softc),
-};
-
+DEFINE_CLASS_0(bman, bman_driver, bman_methods, sizeof(struct bman_softc));
EARLY_DRIVER_MODULE(bman, simplebus, bman_driver, 0, 0, BUS_PASS_SUPPORTDEV);
static int
@@ -82,144 +78,46 @@ bman_fdt_probe(device_t dev)
/*
* BMAN Portals
*/
-#define BMAN_PORT_DEVSTR "Freescale Buffer Manager - Portals"
+#define BMAN_PORT_DEVSTR "Freescale Buffer Manager - Portal"
-static device_probe_t bman_portals_fdt_probe;
-static device_attach_t bman_portals_fdt_attach;
+static int portal_ncpus;
+static device_probe_t bman_portal_fdt_probe;
+static device_attach_t bman_portal_fdt_attach;
-static device_method_t bm_portals_methods[] = {
+static device_method_t bman_portal_methods[] = {
/* Device interface */
- DEVMETHOD(device_probe, bman_portals_fdt_probe),
- DEVMETHOD(device_attach, bman_portals_fdt_attach),
- DEVMETHOD(device_detach, bman_portals_detach),
+ DEVMETHOD(device_probe, bman_portal_fdt_probe),
+ DEVMETHOD(device_attach, bman_portal_fdt_attach),
+ DEVMETHOD(device_detach, bman_portal_detach),
DEVMETHOD_END
};
-static driver_t bm_portals_driver = {
- "bman-portals",
- bm_portals_methods,
- sizeof(struct dpaa_portals_softc),
-};
-
-EARLY_DRIVER_MODULE(bman_portals, ofwbus, bm_portals_driver, 0, 0,
- BUS_PASS_BUS);
-
-static void
-get_addr_props(phandle_t node, uint32_t *addrp, uint32_t *sizep)
-{
-
- *addrp = 2;
- *sizep = 1;
- OF_getencprop(node, "#address-cells", addrp, sizeof(*addrp));
- OF_getencprop(node, "#size-cells", sizep, sizeof(*sizep));
-}
+DEFINE_CLASS_0(bman_portal, bman_portal_driver, bman_portal_methods,
+ sizeof(struct bman_portal_softc));
+EARLY_DRIVER_MODULE(bman_portal, simplebus, bman_portal_driver, 0, 0,
+ BUS_PASS_SUPPORTDEV + BUS_PASS_ORDER_MIDDLE);
static int
-bman_portals_fdt_probe(device_t dev)
+bman_portal_fdt_probe(device_t dev)
{
- phandle_t node;
-
- if (ofw_bus_is_compatible(dev, "simple-bus")) {
- node = ofw_bus_get_node(dev);
- for (node = OF_child(node); node > 0; node = OF_peer(node)) {
- if (ofw_bus_node_is_compatible(node, "fsl,bman-portal"))
- break;
- }
- if (node <= 0)
- return (ENXIO);
- } else if (!ofw_bus_is_compatible(dev, "fsl,bman-portals"))
+ if (!ofw_bus_is_compatible(dev, "fsl,bman-portal"))
return (ENXIO);
device_set_desc(dev, BMAN_PORT_DEVSTR);
-
return (BUS_PROBE_DEFAULT);
}
static int
-bman_portals_fdt_attach(device_t dev)
+bman_portal_fdt_attach(device_t dev)
{
- struct dpaa_portals_softc *sc;
- struct resource_list_entry *rle;
- phandle_t node, child, cpu_node;
- vm_paddr_t portal_pa;
- vm_size_t portal_size;
- uint32_t addr, size;
- ihandle_t cpu;
- int cpu_num, cpus, intr_rid;
- struct dpaa_portals_devinfo di;
- struct ofw_bus_devinfo ofw_di = {};
+ int portal_cpu = portal_ncpus;
- cpus = 0;
- sc = device_get_softc(dev);
- sc->sc_dev = dev;
-
- node = ofw_bus_get_node(dev);
- get_addr_props(node, &addr, &size);
-
- /* Find portals tied to CPUs */
- for (child = OF_child(node); child != 0; child = OF_peer(child)) {
- if (cpus >= mp_ncpus)
- break;
- if (!ofw_bus_node_is_compatible(child, "fsl,bman-portal")) {
- continue;
- }
- /* Checkout related cpu */
- if (OF_getprop(child, "cpu-handle", (void *)&cpu,
- sizeof(cpu)) > 0) {
- cpu_node = OF_instance_to_package(cpu);
- /* Acquire cpu number */
- if (OF_getencprop(cpu_node, "reg", &cpu_num, sizeof(cpu_num)) <= 0) {
- device_printf(dev, "Could not retrieve CPU number.\n");
- return (ENXIO);
- }
- } else
- cpu_num = cpus;
-
- cpus++;
-
- if (ofw_bus_gen_setup_devinfo(&ofw_di, child) != 0) {
- device_printf(dev, "could not set up devinfo\n");
- continue;
- }
-
- resource_list_init(&di.di_res);
- if (ofw_bus_reg_to_rl(dev, child, addr, size, &di.di_res)) {
- device_printf(dev, "%s: could not process 'reg' "
- "property\n", ofw_di.obd_name);
- ofw_bus_gen_destroy_devinfo(&ofw_di);
- continue;
- }
- if (ofw_bus_intr_to_rl(dev, child, &di.di_res, &intr_rid)) {
- device_printf(dev, "%s: could not process "
- "'interrupts' property\n", ofw_di.obd_name);
- resource_list_free(&di.di_res);
- ofw_bus_gen_destroy_devinfo(&ofw_di);
- continue;
- }
- di.di_intr_rid = intr_rid;
-
- ofw_reg_to_paddr(child, 0, &portal_pa, &portal_size, NULL);
- rle = resource_list_find(&di.di_res, SYS_RES_MEMORY, 0);
-
- if (sc->sc_dp_pa == 0)
- sc->sc_dp_pa = portal_pa - rle->start;
-
- portal_size = rle->end + 1;
- rle = resource_list_find(&di.di_res, SYS_RES_MEMORY, 1);
- portal_size = ulmax(rle->end + 1, portal_size);
- sc->sc_dp_size = ulmax(sc->sc_dp_size, portal_size);
-
- if (dpaa_portal_alloc_res(dev, &di, cpu_num))
- goto err;
- }
+ /* Don't attach to more portals than we have CPUs */
+ if (mp_ncpus == portal_ncpus)
+ return (ENXIO);
- ofw_bus_gen_destroy_devinfo(&ofw_di);
+ portal_ncpus++;
- return (bman_portals_attach(dev));
-err:
- resource_list_free(&di.di_res);
- ofw_bus_gen_destroy_devinfo(&ofw_di);
- bman_portals_detach(dev);
- return (ENXIO);
+ return (bman_portal_attach(dev, portal_cpu));
}
diff --git a/sys/dev/dpaa/bman_portals.c b/sys/dev/dpaa/bman_portals.c
index 10c788410e1c..b0c8200c1880 100644
--- a/sys/dev/dpaa/bman_portals.c
+++ b/sys/dev/dpaa/bman_portals.c
@@ -1,27 +1,7 @@
-/*-
- * Copyright (c) 2012 Semihalf.
- * All rights reserved.
+/*
+ * Copyright (c) 2026 Justin Hibbits
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON 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 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * SPDX-License-Identifier: BSD-2-Clause
*/
#include "opt_platform.h"
@@ -30,6 +10,8 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
+#include <sys/cpuset.h>
+#include <sys/interrupt.h>
#include <sys/lock.h>
#include <sys/module.h>
#include <sys/mutex.h>
@@ -46,132 +28,300 @@
#include <powerpc/mpc85xx/mpc85xx.h>
#include "bman.h"
+#include "bman_var.h"
#include "portals.h"
-t_Handle bman_portal_setup(struct bman_softc *);
+#define BCSP_CFG 0x0100
+#define CFG_RPM_M 0x00000003
+#define CFG_RPM_PI 0x00000000
+#define CFG_RPM_PE 0x00000001
+#define CFG_RPM_VBM 0x00000002
+#define BCSP_SCN0 0x0200
+#define BCSP_SCN1 0x0204
+#define BCSP_ISR 0x0e00
+#define BCSP_IER 0x0e04
+#define BCSP_ISDR 0x0e08
+#define INTR_RCDI 0x00000004
+#define INTR_RCRI 0x00000002
+#define INTR_BSCN 0x00000001
+
+#define BMAN_CE_CR 0x0000
+#define BMAN_CE_RR0 0x0100
+#define BMAN_CE_RR1 0x0140
+#define BMAN_CE_RR(n) (BMAN_CE_RR0 + 0x40 * (n))
+#define BMAN_CE_RCR 0x1000
+#define BCSP_RCR_PI_CENA 0x3000
+#define BCSP_RCR_CI_CENA 0x3100
+#define BCSP_RCR_PI_CINH 0x000
+#define BCSP_RCR_CI_CINH 0x004
+
+#define BMAN_MC_VERB_VBIT 0x80
+#define BMAN_MC_VERB_ACQUIRE 0x10
+#define BMAN_MC_VERB_QUERY 0x40
+#define BMAN_RCR_VERB_BPID0 0x20
+#define BMAN_RCR_VERB_BPID_BUF 0x30
+
+struct bman_mc_command {
+ uint8_t verb;
+ uint8_t cd;
+ uint8_t rsvd[62];
+};
+
+union bman_mc_result {
+ struct {
+ uint8_t verb;
+ uint8_t cd;
+ uint8_t rsvd[62];
+ };
+ struct {
+ uint64_t rsvd_q1[5];
+ uint64_t bp_as;
+ uint64_t rsvd_q2;
+ uint64_t bp_ds;
+ };
+ struct bman_buffer bufs[8];
+};
+
+struct bman_rcr_entry {
+ union {
+ struct {
+ uint8_t verb;
+ uint8_t bpid;
+ uint8_t rsvd[62];
+ };
+ struct bman_buffer bufs[8];
+ };
+};
+
+static void bman_portal_isr(void *arg);
+
+static union bman_mc_result *bman_mc_send(struct bman_portal_softc *p,
+ uint8_t verb, uint8_t cd);
-struct dpaa_portals_softc *bp_sc;
+DPCPU_DEFINE(struct bman_portal_softc *, bman_affine_portal);
+
+DPAA_RING(bman_rcr, 8, BCSP_RCR_PI_CENA, BCSP_RCR_CI_CENA,
+ BCSP_RCR_PI_CINH, BCSP_RCR_CI_CINH);
+
+static uint32_t
+bm_ci_read(struct bman_portal_softc *sc, bus_size_t off)
+{
+ return (bus_read_4(sc->sc_base.sc_mres[1], off));
+}
+
+static void
+bm_ci_write(struct bman_portal_softc *sc, bus_size_t off, uint32_t val)
+{
+ bus_write_4(sc->sc_base.sc_mres[1], off, val);
+}
int
-bman_portals_attach(device_t dev)
+bman_portal_attach(device_t dev, int cpu)
{
- struct dpaa_portals_softc *sc;
+ struct bman_portal_softc *sc = device_get_softc(dev);
- sc = bp_sc = device_get_softc(dev);
-
- /* Map bman portal to physical address space */
- if (law_enable(OCP85XX_TGTIF_BMAN, sc->sc_dp_pa, sc->sc_dp_size)) {
- bman_portals_detach(dev);
- return (ENXIO);
- }
- /* Set portal properties for XX_VirtToPhys() */
- XX_PortalSetInfo(dev);
+ sc->sc_base.sc_cpu = cpu;
+ dpaa_portal_alloc_res(dev, cpu);
+
+ bm_ci_write(sc, BCSP_ISDR, 0);
+ bm_ci_write(sc, BCSP_IER, INTR_RCRI | INTR_BSCN);
+ bus_setup_intr(dev, sc->sc_base.sc_ires, INTR_TYPE_NET | INTR_MPSAFE,
+ NULL, bman_portal_isr, sc, &sc->sc_base.sc_intr_cookie);
+ bus_bind_intr(dev, sc->sc_base.sc_ires, cpu);
+
+ /* Select valid-bit mode for rings */
+ bus_write_4(sc->sc_base.sc_mres[1], BCSP_CFG, CFG_RPM_VBM);
+ /* Disable pool depletion notifications. */
+ bm_ci_write(sc, BCSP_SCN0, 0);
+ bm_ci_write(sc, BCSP_SCN1, 0);
+
+ DPCPU_ID_SET(cpu, bman_affine_portal, sc);
+
+ sc->sc_rcr.ring =
+ (struct bman_rcr_entry *)(sc->sc_base.sc_ce_va + BMAN_CE_RCR);
+ bman_rcr_ring_init(&sc->sc_rcr, &sc->sc_base);
+ /* Starting MC polarity is always 1 */
+ sc->mc.polarity = BMAN_MC_VERB_VBIT;
- bus_attach_children(dev);
return (0);
}
int
-bman_portals_detach(device_t dev)
+bman_portal_detach(device_t dev)
{
- struct dpaa_portals_softc *sc;
+ struct bman_portal_softc *sc;
int i;
- bp_sc = NULL;
sc = device_get_softc(dev);
- for (i = 0; i < ARRAY_SIZE(sc->sc_dp); i++) {
- if (sc->sc_dp[i].dp_ph != NULL) {
- thread_lock(curthread);
- sched_bind(curthread, i);
- thread_unlock(curthread);
- BM_PORTAL_Free(sc->sc_dp[i].dp_ph);
+ /* TODO: Unmap TLB regions */
+ thread_lock(curthread);
+ sched_bind(curthread, sc->sc_base.sc_cpu);
+ thread_unlock(curthread);
- thread_lock(curthread);
- sched_unbind(curthread);
- thread_unlock(curthread);
- }
+ if (sc->sc_base.sc_ires != NULL)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_base.sc_ires);
- if (sc->sc_dp[i].dp_ires != NULL) {
- XX_DeallocIntr((uintptr_t)sc->sc_dp[i].dp_ires);
- bus_release_resource(dev, SYS_RES_IRQ,
- sc->sc_dp[i].dp_irid, sc->sc_dp[i].dp_ires);
- }
- }
- for (i = 0; i < ARRAY_SIZE(sc->sc_rres); i++) {
- if (sc->sc_rres[i] != NULL)
+ for (i = 0; i < nitems(sc->sc_base.sc_mres); i++) {
+ if (sc->sc_base.sc_mres[i] != NULL)
bus_release_resource(dev, SYS_RES_MEMORY,
- sc->sc_rrid[i],
- sc->sc_rres[i]);
+ i, sc->sc_base.sc_mres[i]);
}
+ thread_lock(curthread);
+ sched_unbind(curthread);
+ thread_unlock(curthread);
+
return (0);
}
-t_Handle
-bman_portal_setup(struct bman_softc *bsc)
+static uint64_t
+bman_query(struct bman_portal_softc *sc, bool depletion)
{
- struct dpaa_portals_softc *sc;
- t_BmPortalParam bpp;
- t_Handle portal;
- unsigned int cpu;
- uintptr_t p;
+ union bman_mc_result *mc_res;
+ uint64_t res;
- /* Return NULL if we're not ready or while detach */
- if (bp_sc == NULL)
- return (NULL);
+ critical_enter();
+ mc_res = bman_mc_send(sc, BMAN_MC_VERB_QUERY, 0);
+ if (mc_res == NULL)
+ goto err;
- sc = bp_sc;
+ if (depletion)
+ res = mc_res->bp_ds;
+ else
+ res = mc_res->bp_as;
+ critical_exit();
- sched_pin();
- portal = NULL;
- cpu = PCPU_GET(cpuid);
+ return (res);
- /* Check if portal is ready */
- while (atomic_cmpset_acq_ptr((uintptr_t *)&sc->sc_dp[cpu].dp_ph,
- 0, -1) == 0) {
- p = atomic_load_acq_ptr((uintptr_t *)&sc->sc_dp[cpu].dp_ph);
+err:
+ critical_exit();
+ device_printf(sc->sc_base.sc_dev, "Timeout querying depltetion\n");
+ return (0);
+}
- /* Return if portal is already initialized */
- if (p != 0 && p != -1) {
- sched_unpin();
- return ((t_Handle)p);
- }
+static void
+bman_portal_isr(void *arg)
+{
+ struct bman_portal_softc *sc = arg;
+ uint32_t intrs;
+
+ intrs = bm_ci_read(sc, BCSP_ISR);
- /* Not inititialized and "owned" by another thread */
- sched_relinquish(curthread);
+ /* Release Command Ring interrupt. */
+ if (intrs & INTR_RCRI) {
+ bman_rcr_update(&sc->sc_rcr, &sc->sc_base);
+ }
+ /* Buffer Pool State Change Notification. */
+ if (intrs & INTR_BSCN) {
+ struct bman_pool *pool;
+ uint64_t res = bman_query(sc, true);
+ if (__predict_true(res != 0)) {
+ int idx = flsll(res);
+ pool = sc->sc_pools[64 - idx];
+ KASSERT(pool != NULL,
+ ("state change on unassociated bpid %d\n", idx));
+ pool->dep_cb(pool->arg, true);
+ }
}
- /* Map portal registers */
- dpaa_portal_map_registers(sc);
+ bm_ci_write(sc, BCSP_ISR, intrs);
+}
- /* Configure and initialize portal */
- bpp.ceBaseAddress = rman_get_bushandle(sc->sc_rres[0]);
- bpp.ciBaseAddress = rman_get_bushandle(sc->sc_rres[1]);
- bpp.h_Bm = bsc->sc_bh;
- bpp.swPortalId = cpu;
- bpp.irq = (uintptr_t)sc->sc_dp[cpu].dp_ires;
+/* RCR */
- portal = BM_PORTAL_Config(&bpp);
- if (portal == NULL)
- goto err;
+int
+bman_release(struct bman_pool *pool, const struct bman_buffer *bufs,
+ uint8_t count)
+{
+ struct bman_portal_softc *portal;
+ struct bman_rcr_entry *rcr;
- if (BM_PORTAL_Init(portal) != E_OK)
- goto err;
+ if (count > 8)
+ return (EINVAL);
- atomic_store_rel_ptr((uintptr_t *)&sc->sc_dp[cpu].dp_ph, (uintptr_t)portal);
-
- sched_unpin();
+ critical_enter();
+ portal = DPCPU_GET(bman_affine_portal);
+ rcr = bman_rcr_start(&portal->sc_rcr, &portal->sc_base);
+ bzero(rcr, sizeof(*rcr));
- return (portal);
+ /* This should be safe, because bpid must be less than 256. */
+ for (int i = 0; i < count; i++)
+ rcr->bufs[i] = bufs[i];
+ rcr->bufs[0].bpid = pool->bpid;
+ bman_rcr_commit(&portal->sc_rcr, BMAN_RCR_VERB_BPID0 | count);
+ critical_exit();
-err:
- if (portal != NULL)
- BM_PORTAL_Free(portal);
+ return (0);
+}
+
+/* MC commands */
+/* Assumes pinned */
+static union bman_mc_result *
+bman_mc_send(struct bman_portal_softc *p, uint8_t verb, uint8_t cd)
+{
+ int res_idx;
+ struct bman_mc_command *command;
+ union bman_mc_result *rr;
+ uintptr_t ce_va = p->sc_base.sc_ce_va;
+
+ command = (struct bman_mc_command *)(ce_va + BMAN_CE_CR);
+ dpaa_zero_line(command);
+ command->cd = cd;
+ dpaa_lw_barrier();
+ command->verb = verb | p->mc.polarity;
+ res_idx = (p->mc.polarity ? 1 : 0);
+ p->mc.polarity ^= BMAN_MC_VERB_VBIT;
+ dpaa_flush_line(command);
- atomic_store_rel_ptr((uintptr_t *)&sc->sc_dp[cpu].dp_ph, 0);
- sched_unpin();
+ rr = (union bman_mc_result *)(ce_va + BMAN_CE_RR(res_idx));
+ for (;;) {
+ if (rr->verb != 0)
+ break;
+ dpaa_flush_line(rr);
+ }
+ return (rr);
+}
+
+int
+bman_acquire(struct bman_pool *pool, struct bman_buffer *bufs, uint8_t count)
+{
+ union bman_mc_result *rr;
+
+ if (count > 8 || count == 0)
+ return (EINVAL);
+ critical_enter();
+ rr = bman_mc_send(DPCPU_GET(bman_affine_portal),
+ BMAN_MC_VERB_ACQUIRE | count,
+ pool->bpid);
+ critical_exit();
+
+ if (rr == NULL)
+ return (ETIMEDOUT);
+ if ((rr->verb & ~BMAN_MC_VERB_VBIT) == 0)
+ return (ENOMEM);
+
+ memcpy(bufs, rr, count * sizeof(*bufs));
+
+ return (0);
+}
+
+/*
+ * Enable pool state change notifications on this portal. This requires the
+ * pool to already be configured with the callback to handle state changes.
+ */
+void
+bman_portal_enable_scn(struct bman_portal_softc *sc, struct bman_pool *pool)
+{
+ uint32_t reg, reg_ptr;
- return (NULL);
+ if (pool->bpid >= 32)
+ reg_ptr = BCSP_SCN1;
+ else
+ reg_ptr = BCSP_SCN0;
+ reg = bm_ci_read(sc, reg_ptr);
+ reg |= (1 << (31 - pool->bpid));
+ bm_ci_write(sc, reg_ptr, reg);
+ sc->sc_pools[pool->bpid] = pool;
}
diff --git a/sys/dev/dpaa/bman_var.h b/sys/dev/dpaa/bman_var.h
new file mode 100644
index 000000000000..91484da61ac3
--- /dev/null
+++ b/sys/dev/dpaa/bman_var.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2026 Justin Hibbits
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef BMAN_VAR_H
+#define BMAN_VAR_H
+
+#include "dpaa_common.h"
+#include "portals.h"
+
+#define BMAN_MAX_POOLS 64
+#define BMAN_MAX_POOLS_1023 8
+
+DPAA_RING_DECLARE(bman_rcr);
+
+struct bman_mc {
+ uint8_t polarity;
+ bool busy;
+};
+
+struct bman_portal_softc {
+ struct dpaa_portal_softc sc_base;
+
+ struct bman_mc mc;
+ struct bman_rcr_ring sc_rcr;
+ struct bman_pool *sc_pools[BMAN_MAX_POOLS];
+};
+
+struct bman_pool {
+ uint32_t bpid;
+ bm_depletion_handler dep_cb;
+ void *arg;
+};
+
+DPCPU_DECLARE(struct bman_portal_softc *, bman_affine_portal);
+
+int bman_release(struct bman_pool *pool, const struct bman_buffer *bufs,
+ uint8_t count);
+
+void bman_portal_enable_scn(struct bman_portal_softc *, struct bman_pool *);
+
+#endif
diff --git a/sys/dev/dpaa/dpaa_common.c b/sys/dev/dpaa/dpaa_common.c
new file mode 100644
index 000000000000..c5055231298b
--- /dev/null
+++ b/sys/dev/dpaa/dpaa_common.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2026 Justin Hibbits
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "dpaa_common.h"
+
+#define FDT_REG_CELLS 4
+int
+dpaa_map_private_memory(device_t dev, int idx, const char *compat,
+ vm_paddr_t *addrp, size_t *sizep)
+{
+ phandle_t node;
+ pcell_t cells[idx + 1];
+ pcell_t *cell_alloc;
+ int addr_cells, size_cells;
+ uint64_t tmp;
+ u_long align, base, size;
+ vm_paddr_t alloc_base;
+ vm_size_t alloc_range_size;
+ ssize_t alloc_size;
+ void *reserved;
+ int rv;
+
+ node = ofw_bus_get_node(dev);
+ if (OF_getencprop(node, "memory-region", cells, sizeof(cells)) <= 0)
+ return (ENXIO);
+
+ node = OF_node_from_xref(cells[idx]);
+ /* If the memory is already reserved, we just need to return it. */
+ if (fdt_regsize(node, &base, &size) == 0)
+ goto success;
+
+ rv = fdt_addrsize_cells(OF_parent(node), &addr_cells, &size_cells);
+ if (rv != 0)
+ return (rv);
+
+ if (OF_getprop(node, "alignment", &tmp, sizeof(tmp)) <= 0)
+ return (ENXIO);
+
+ align = fdt_data_get(&tmp, addr_cells);
+ if (OF_getprop(node, "size", &tmp, sizeof(tmp)) <= 0)
+ return (ENXIO);
+ size = fdt_data_get(&tmp, size_cells);
+
+ alloc_size =
+ OF_getencprop_alloc(node, "alloc-ranges", (void **)&cell_alloc);
+ if (alloc_size < 0)
+ return (ENXIO);
+
+ alloc_size /= sizeof(pcell_t);
+ for (int i = 0; i < alloc_size; i += (addr_cells + size_cells)) {
+ alloc_base = fdt_data_get(&cell_alloc[i], addr_cells);
+ alloc_range_size =
+ fdt_data_get(&cell_alloc[i + addr_cells], size_cells);
+ reserved = contigmalloc(size, M_DEVBUF, M_NOWAIT | M_ZERO,
+ alloc_base, alloc_base + alloc_range_size, align, 0);
+ if (reserved != NULL)
+ break;
+ }
+ if (reserved == NULL)
+ return (ENOMEM);
+ /* Flush the cache (zeroed memory) because it won't be touched later. */
+ cpu_flush_dcache(reserved, size);
+ base = pmap_kextract((vm_offset_t)reserved);
+
+success:
+ *addrp = base;
+ *sizep = size;
+
+ return (0);
+}
diff --git a/sys/dev/dpaa/dpaa_common.h b/sys/dev/dpaa/dpaa_common.h
new file mode 100644
index 000000000000..8fa43a034ef5
--- /dev/null
+++ b/sys/dev/dpaa/dpaa_common.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2026 Justin Hibbits
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef DPAA_COMMON_H
+#define DPAA_COMMON_H
+
+#include <machine/atomic.h>
+
+int dpaa_map_private_memory(device_t dev, int idx, const char *compat,
+ vm_paddr_t *addrp, size_t *sizep);
+
+struct dpaa_fd {
+ uint64_t liodn:8;
+ uint64_t bpid:8;
+ uint64_t eliodn:4;
+ uint64_t _rsvd1:4;
+ uint64_t addr:40;
+ uint32_t format:3;
+ uint32_t offset:9;
+ uint32_t length:20;
+ uint32_t cmd_stat;
+} __packed;
+
+#define DPAA_FD_FORMAT_SHORT_MBSF 4
+
+#define DPAA_FD_RX_STATUS_DCL4C 0x10000000
+#define DPAA_FD_RX_STATUS_DME 0x01000000
+#define DPAA_FD_RX_STATUS_IPRE_M 0x00300000
+#define DPAA_FD_RX_STATUS_FPE 0x00080000
+#define DPAA_FD_RX_STATUS_FSE 0x00040000
+#define DPAA_FD_RX_STATUS_DIS 0x00020000
+#define DPAA_FD_RX_STATUS_EOF 0x00008000
+#define DPAA_FD_RX_STATUS_NSS 0x00004000
+#define DPAA_FD_RX_STATUS_KSO 0x00002000
+#define DPAA_FD_RX_STATUS_FCL_M 0x00000c00
+#define DPAA_FD_RX_STATUS_IPP 0x00000200
+#define DPAA_FD_RX_STATUS_FLM 0x00000100
+#define DPAA_FD_RX_STATUS_PTE 0x00000080
+#define DPAA_FD_RX_STATUS_ISP 0x00000040
+#define DPAA_FD_RX_STATUS_PHE 0x00000020
+#define DPAA_FD_RX_STATUS_FRDR 0x00000010
+#define DPAA_FD_RX_STATUS_BLE 0x00000008
+#define DPAA_FD_RX_STATUS_L4CV 0x00000004
+#define DPAA_FD_RX_STATUS_IPR 0x00000001
+
+#define DPAA_FD_TX_CMD_RPD 0x40000000
+#define DPAA_FD_TX_CMD_DTC 0x10000000
+#define DPAA_FD_TX_STATUS_UFD 0x04000000
+#define DPAA_FD_TX_STATUS_LGE 0x02000000
+#define DPAA_FD_TX_STATUS_DME 0x01000000
+
+/* Most of the above are error flags, but some aren't */
+#define DPAA_FD_CMD_STAT_ERR_M 0x010ce3e8
+#define DPAA_FD_TX_STAT_ERR_M 0x03000000
+
+#define DPAA_FD_GET_ADDR(fd) ((void *)PHYS_TO_DMAP(fd->addr))
+
+struct dpaa_sgte {
+ uint64_t addr;
+ uint32_t extension:1;
+ uint32_t final:1;
+ uint32_t length:30;
+ uint16_t bpid;
+ uint16_t offset;
+} __packed;
+struct qman_fqr;
+
+
+#define DPAA_NUM_OF_SG_TABLE_ENTRY 16
+
+/*
+ * Ring API infrastructure
+ *
+ * BMan and QMan both use cache-enabled rings. Abstract this away to a more
+ * generalized interface to reduce code copying.
+ *
+ * Requirements:
+ * - Before calling <ring>_init() the ring base (ring->ring) must be initialized
+ * to the base of the ring.
+ */
+#define DPAA_RING_DECLARE(pfx) \
+ struct pfx##_ring { \
+ struct pfx##_entry *ring; \
+ struct pfx##_entry *cursor; \
+ uint8_t vbit; \
+ uint8_t avail; \
+ uint8_t ci; \
+ uint8_t ithresh; \
+ }
+
+/*
+ * Ring functions:
+ *
+ * ring_cyc_diff() -- get the (circular) difference of `l - f`
+ * ring_ring_init() -- Set up the ring structures. Portal must be
+ * initialized beforehand, and ring->ring must be nonzero.
+ * ring_CARRYCLEAR() -- stealth math to do circular roll-over
+ * ring_INC() -- Increment the cursor within the ring
+ * ring_update() -- Update ring entry availability count
+ * ring_start() -- Reserve the next entry in the ring if available.
+ * ring_commit() -- Commit the reserved ring entry by setting the verb and
+ * AVB bit
+ */
+#define DPAA_RING(pfx,sz,pi_e,ci_e,pi_i,ci_i) \
+static inline int \
+pfx##_cyc_diff(uint8_t size, uint8_t f, uint8_t l) \
+{ \
+ if (f <= l) \
+ return (uint8_t)(l - f); \
+ return (uint8_t)(l + size - f); \
+} \
+static inline void \
+pfx##_ring_init(struct pfx##_ring *ring, struct dpaa_portal_softc *portal)\
+{ \
+ uint32_t pi = *(uint32_t*)(portal->sc_ci_va + pi_i) & (sz - 1); \
+ uint32_t ci = *(uint32_t*)(portal->sc_ci_va + ci_i); \
+ ring->ci = ci & (sz - 1); \
+ ring->vbit = !!(ci & sz) << 7; \
+ ring->cursor = ring->ring + pi; \
+ ring->avail = sz - 1 - pfx##_cyc_diff(sz, ring->ci, pi); \
+} \
+static inline void * \
+pfx##_CARRYCLEAR(struct pfx##_entry *p) \
+{ \
+ return ((void *)((uintptr_t)p & (~(uintptr_t)(sz << 6)))); \
+} \
+static inline void \
+pfx##_INC(struct pfx##_ring *ring) \
+{ \
+ struct pfx##_entry *partial = ring->cursor + 1; \
+ ring->cursor = pfx##_CARRYCLEAR(partial); \
+ if (partial != ring->cursor) \
+ ring->vbit ^= 0x80; \
+} \
+static inline uint8_t \
+pfx##_update(struct pfx##_ring *ring, struct dpaa_portal_softc *portal) \
+{ \
+ uint8_t diff, old_ci = ring->ci; \
+ ring->ci = *(uint32_t*)(portal->sc_ci_va + ci_i) & (sz - 1); \
+ diff = pfx##_cyc_diff(sz, old_ci, ring->ci); \
+ ring->avail += diff; \
+ return (diff); \
+} \
+static inline struct pfx##_entry * __unused \
+pfx##_start(struct pfx##_ring *ring, struct dpaa_portal_softc *portal) \
+{ \
+ if (ring->avail <= 1) { \
+ pfx##_update(ring, portal); \
+ if (ring->avail == 0) \
+ return (NULL); \
+ } \
+ dpaa_zero_line(ring->cursor); \
+ return (ring->cursor); \
+} \
+static inline void __unused \
+pfx##_commit(struct pfx##_ring *ring, uint8_t verb) \
+{ \
+ struct pfx##_entry *entry = ring->cursor; \
+ dpaa_lw_barrier(); \
+ entry->verb = verb | ring->vbit; \
+ dpaa_flush_line(entry); \
+ pfx##_INC(ring); \
+ ring->avail--; \
+} struct hack
+
+#ifdef __powerpc__
+static inline void
+dpaa_flush_line(void *line)
+{
+ __asm __volatile ("dcbf 0, %0" :: "r"(line) : "memory");
+}
+
+static inline void
+dpaa_zero_line(void *line)
+{
+ __asm __volatile ("dcbz 0, %0" :: "r"(line) : "memory");
+}
+
+static inline void
+dpaa_touch_line(void *line)
+{
+ __asm __volatile ("dcbt 0, %0" :: "r"(line) : "memory");
+}
+
+static inline void
+dpaa_lw_barrier(void)
+{
+ powerpc_lwsync();
+}
+#endif
+
+#endif
diff --git a/sys/dev/dpaa/dpaa_eth.c b/sys/dev/dpaa/dpaa_eth.c
new file mode 100644
index 000000000000..6424a6e0b0c3
--- /dev/null
+++ b/sys/dev/dpaa/dpaa_eth.c
@@ -0,0 +1,719 @@
+/*-
+ * Copyright (c) 2026 Justin Hibbits
+ * Copyright (c) 2012 Semihalf.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON 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 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/smp.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+#include <net/if_arp.h>
+#include <netinet/ip.h>
+#include <netinet/ip6.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include "miibus_if.h"
+
+#include "bman.h"
+#include "dpaa_common.h"
+#include "dpaa_eth.h"
+#include "fman.h"
+#include "fman_parser.h"
+#include "fman_port.h"
+#include "fman_if.h"
+#include "fman_port_if.h"
+#include "if_dtsec.h"
+#include "qman.h"
+#include "qman_var.h"
+#include "qman_portal_if.h"
+
+
+#define DPAA_ETH_LOCK(sc) mtx_lock(&(sc)->sc_lock)
+#define DPAA_ETH_UNLOCK(sc) mtx_unlock(&(sc)->sc_lock)
+#define DPAA_ETH_LOCK_ASSERT(sc) mtx_assert(&(sc)->sc_lock, MA_OWNED)
+
+/**
+ * @group dTSEC RM private defines.
+ * @{
+ */
+#define DTSEC_BPOOLS_USED (1)
+#define DTSEC_MAX_TX_QUEUE_LEN 256
+
+struct dpaa_eth_frame_info {
+ struct mbuf *fi_mbuf;
+ struct fman_internal_context fi_ic;
+ struct dpaa_sgte fi_sgt[DPAA_NUM_OF_SG_TABLE_ENTRY];
+};
+
+enum dpaa_eth_pool_params {
+ DTSEC_RM_POOL_RX_LOW_MARK = 16,
+ DTSEC_RM_POOL_RX_HIGH_MARK = 64,
+ DTSEC_RM_POOL_RX_MAX_SIZE = 256,
+
+ DTSEC_RM_POOL_FI_LOW_MARK = 16,
+ DTSEC_RM_POOL_FI_HIGH_MARK = 64,
+ DTSEC_RM_POOL_FI_MAX_SIZE = 256,
+};
+
+#define DTSEC_RM_FQR_RX_CHANNEL 0x401
+#define DTSEC_RM_FQR_TX_CONF_CHANNEL 0
+enum dpaa_eth_fq_params {
+ DTSEC_RM_FQR_RX_WQ = 1,
+ DTSEC_RM_FQR_TX_WQ = 1,
+ DTSEC_RM_FQR_TX_CONF_WQ = 1
+};
+/** @} */
+
+
+/**
+ * @group dTSEC Frame Info routines.
+ * @{
+ */
+void
+dpaa_eth_fi_pool_free(struct dpaa_eth_softc *sc)
+{
+
+ if (sc->sc_fi_zone != NULL)
+ uma_zdestroy(sc->sc_fi_zone);
+}
+
+int
+dpaa_eth_fi_pool_init(struct dpaa_eth_softc *sc)
+{
+
+ snprintf(sc->sc_fi_zname, sizeof(sc->sc_fi_zname), "%s: Frame Info",
+ device_get_nameunit(sc->sc_dev));
+
+ sc->sc_fi_zone = uma_zcreate(sc->sc_fi_zname,
+ sizeof(struct dpaa_eth_frame_info), NULL, NULL, NULL, NULL,
+ UMA_ALIGN_PTR, 0);
+
+ return (0);
+}
+
+static struct dpaa_eth_frame_info *
+dpaa_eth_fi_alloc(struct dpaa_eth_softc *sc)
+{
+ struct dpaa_eth_frame_info *fi;
+
+ fi = uma_zalloc(sc->sc_fi_zone, M_NOWAIT | M_ZERO);
+
+ return (fi);
+}
+
+static void
+dpaa_eth_fi_free(struct dpaa_eth_softc *sc, struct dpaa_eth_frame_info *fi)
+{
+
+ uma_zfree(sc->sc_fi_zone, fi);
+}
+/** @} */
+
+
+/**
+ * @group dTSEC FMan PORT routines.
+ * @{
+ */
+int
+dpaa_eth_fm_port_rx_init(struct dpaa_eth_softc *sc)
+{
+ struct fman_port_params params;
+ int error;
+
+ params.dflt_fqid = sc->sc_rx_fqid;
+ params.err_fqid = sc->sc_rx_fqid;
+ params.rx_params.num_pools = 1;
+ params.rx_params.bpools[0].bpid = bman_get_bpid(sc->sc_rx_pool);
+ params.rx_params.bpools[0].size = MCLBYTES;
+ error = FMAN_PORT_CONFIG(sc->sc_rx_port, &params);
+ error = FMAN_PORT_INIT(sc->sc_rx_port);
+ if (error != 0) {
+ device_printf(sc->sc_dev, "couldn't initialize FM Port RX.\n");
+ return (ENXIO);
+ }
+
+ return (0);
+}
+
+int
+dpaa_eth_fm_port_tx_init(struct dpaa_eth_softc *sc)
+{
+ struct fman_port_params params;
+ int error;
+
+ params.dflt_fqid = sc->sc_tx_conf_fqid;
+ params.err_fqid = sc->sc_tx_conf_fqid;
+
+ error = FMAN_PORT_CONFIG(sc->sc_tx_port, &params);
+ error = FMAN_PORT_INIT(sc->sc_tx_port);
+ if (error != 0) {
+ device_printf(sc->sc_dev, "couldn't initialize FM Port TX.\n");
+ return (ENXIO);
+ }
+
+ return (0);
+}
+/** @} */
+
+
+/**
+ * @group dTSEC buffer pools routines.
+ * @{
+ */
+static int
+dpaa_eth_pool_rx_put_buffer(struct dpaa_eth_softc *sc, uint8_t *buffer,
+ void *context)
+{
+
+ uma_zfree(sc->sc_rx_zone, buffer);
+
+ return (0);
+}
+
+static int
+dtsec_add_buffers(struct dpaa_eth_softc *sc, int count)
+{
+ struct bman_buffer bufs[8] = {};
+ int err;
+ int c;
+
+ while (count > 0) {
+ c = min(8, count);
+ for (int i = 0; i < c; i++) {
+ void *b;
+ vm_paddr_t pa;
+
+ b = uma_zalloc(sc->sc_rx_zone, M_NOWAIT);
+ if (b == NULL)
+ return (ENOMEM);
+ pa = pmap_kextract((vm_offset_t)b);
+ bufs[i].buf_hi = (pa >> 32);
+ bufs[i].buf_lo = (pa & 0xffffffff);
+ }
+
+ err = bman_put_buffers(sc->sc_rx_pool, bufs, c);
+ if (err != 0)
+ return (err);
+ count -= c;
+ }
+
+ return (0);
+}
+
+static void
+dpaa_eth_pool_rx_depleted(void *h_App, bool in)
+{
+ struct dpaa_eth_softc *sc;
+ unsigned int count;
+
+ sc = h_App;
+
+ if (!in)
+ return;
+
+ while (1) {
+ count = bman_count(sc->sc_rx_pool);
+ if (count > DTSEC_RM_POOL_RX_HIGH_MARK)
+ return;
+
+ /* Can only release 8 buffers at a time */
+ count = min(DTSEC_RM_POOL_RX_HIGH_MARK - count + 8, 8);
+ if (dtsec_add_buffers(sc, count) != 0)
+ return;
+ }
+}
+
+void
+dpaa_eth_pool_rx_free(struct dpaa_eth_softc *sc)
+{
+
+ if (sc->sc_rx_pool != NULL)
+ bman_pool_destroy(sc->sc_rx_pool);
+
+ if (sc->sc_rx_zone != NULL)
+ uma_zdestroy(sc->sc_rx_zone);
+}
+
+int
+dpaa_eth_pool_rx_init(struct dpaa_eth_softc *sc)
+{
+
+ /* MCLBYTES must be less than PAGE_SIZE */
+ CTASSERT(MCLBYTES < PAGE_SIZE);
+
+ snprintf(sc->sc_rx_zname, sizeof(sc->sc_rx_zname), "%s: RX Buffers",
+ device_get_nameunit(sc->sc_dev));
+
+ sc->sc_rx_zone = uma_zcreate(sc->sc_rx_zname, MCLBYTES, NULL,
+ NULL, NULL, NULL, MCLBYTES - 1, 0);
+
+ sc->sc_rx_pool = bman_pool_create(&sc->sc_rx_bpid, MCLBYTES,
+ DTSEC_RM_POOL_RX_MAX_SIZE, DTSEC_RM_POOL_RX_LOW_MARK,
+ DTSEC_RM_POOL_RX_HIGH_MARK, 0, 0, dpaa_eth_pool_rx_depleted, sc);
+ if (sc->sc_rx_pool == NULL) {
+ device_printf(sc->sc_dev, "NULL rx pool somehow\n");
+ dpaa_eth_pool_rx_free(sc);
+ return (EIO);
+ }
+
+ dtsec_add_buffers(sc, DTSEC_RM_POOL_RX_HIGH_MARK);
+
+ return (0);
+}
+/** @} */
+
+
+/**
+ * @group dTSEC Frame Queue Range routines.
+ * @{
+ */
+static void
+dpaa_eth_fq_mext_free(struct mbuf *m)
+{
+ struct dpaa_eth_softc *sc;
+ void *buffer;
+
+ buffer = m->m_ext.ext_arg1;
+ sc = m->m_ext.ext_arg2;
+ if (bman_count(sc->sc_rx_pool) <= DTSEC_RM_POOL_RX_MAX_SIZE)
+ bman_put_buffer(sc->sc_rx_pool,
+ pmap_kextract((vm_offset_t)buffer), sc->sc_rx_bpid);
+ else
+ dpaa_eth_pool_rx_put_buffer(sc, buffer, NULL);
+}
+
+static int
+dpaa_eth_update_csum_flags(struct qman_fd *frame,
+ struct fman_parse_result *prs, struct mbuf *m)
+{
+ uint16_t l3r = be16toh(prs->l3r);
+
+ /* TODO: nested protocols? */
+ if ((l3r & L3R_FIRST_IP_M) != 0) {
+ m->m_pkthdr.csum_flags |= CSUM_L3_CALC;
+ if ((l3r & L3R_FIRST_ERROR) == 0)
+ m->m_pkthdr.csum_flags |= CSUM_L3_VALID;
+ }
+ if (frame->cmd_stat & DPAA_FD_RX_STATUS_L4CV) {
+ m->m_pkthdr.csum_flags |= CSUM_L4_CALC;
+ m->m_pkthdr.csum_data = 0xffff;
+ if ((prs->l4r & L4R_TYPE_M) != 0 &&
+ (prs->l4r & L4R_ERR) == 0)
+ m->m_pkthdr.csum_flags |= CSUM_L4_VALID;
+ }
+
+ return (0);
+}
+
+static int
+dpaa_eth_fq_rx_callback(device_t portal, struct qman_fq *fq,
+ struct qman_fd *frame, void *app)
+{
+ struct dpaa_eth_softc *sc;
+ struct mbuf *m;
+ struct fman_internal_context *frame_ic;
+ void *frame_va;
+
+ m = NULL;
+ sc = app;
+
+ frame_va = DPAA_FD_GET_ADDR(frame);
+ frame_ic = frame_va; /* internal context at head of the frame */
+ /* Only simple (single- or multi-) frames are supported. */
+ KASSERT(frame->format == 0 || frame->format == 4,
+ ("%s(): Got unsupported frame format 0x%02X!", __func__,
+ frame->format));
+
+ if ((frame->cmd_stat & DPAA_FD_CMD_STAT_ERR_M) != 0) {
+ device_printf(sc->sc_dev, "RX error: 0x%08X\n",
+ frame->cmd_stat);
+ goto err;
+ }
+
+ m = m_gethdr(M_NOWAIT, MT_HEADER);
+ if (m == NULL)
+ goto err;
+
+ if (frame->format == 0) {
+ /* Single-frame format */
+ m_extadd(m, (char *)frame_va + frame->offset, frame->length,
+ dpaa_eth_fq_mext_free, frame_va, sc, 0, EXT_NET_DRV);
+ } else {
+ struct dpaa_sgte *sgt =
+ (struct dpaa_sgte *)(char *)frame_va + frame->offset;
+ /* Simple multi-frame format */
+ for (int i = 0; i < DPAA_NUM_OF_SG_TABLE_ENTRY; i++) {
+ if (sgt[i].length > 0)
+ m_extadd(m, PHYS_TO_DMAP(sgt[i].addr),
+ sgt[i].length, dpaa_eth_fq_mext_free,
+ PHYS_TO_DMAP(sgt[i].addr), sc, 0,
+ EXT_NET_DRV);
+ if (sgt[i].final)
+ break;
+ }
+ /* Free the SGT buffer, it's no longer needed. */
+ bman_put_buffer(sc->sc_rx_pool, frame->addr, sc->sc_rx_bpid);
+ }
+
+ if (if_getcapenable(sc->sc_ifnet) & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6))
+ dpaa_eth_update_csum_flags(frame, &frame_ic->prs, m);
+
+ m->m_pkthdr.rcvif = sc->sc_ifnet;
+ m->m_len = frame->length;
+ m_fixhdr(m);
+
+ if_input(sc->sc_ifnet, m);
+
+ return (1);
+
+err:
+ bman_put_buffer(sc->sc_rx_pool, frame->addr, sc->sc_rx_bpid);
+ if (m != NULL)
+ m_freem(m);
+
+ return (1);
+}
+
+static int
+dpaa_eth_fq_tx_confirm_callback(device_t portal, struct qman_fq *fq,
+ struct qman_fd *frame, void *app)
+{
+ struct dpaa_eth_frame_info *fi;
+ struct dpaa_eth_softc *sc;
+ unsigned int qlen;
+ struct dpaa_sgte *sgt0;
+
+ sc = app;
+
+ if ((frame->cmd_stat & DPAA_FD_TX_STAT_ERR_M) != 0)
+ device_printf(sc->sc_dev, "TX error: 0x%08X\n",
+ frame->cmd_stat);
+
+ /*
+ * We are storing struct dpaa_eth_frame_info in first entry
+ * of scatter-gather table.
+ */
+ sgt0 = (struct dpaa_sgte *)PHYS_TO_DMAP(frame->addr + frame->offset);
+ fi = (struct dpaa_eth_frame_info *)PHYS_TO_DMAP(sgt0->addr);
+
+ /* Free transmitted frame */
+ m_freem(fi->fi_mbuf);
+ dpaa_eth_fi_free(sc, fi);
+
+ qlen = qman_fq_get_counter(sc->sc_tx_conf_fq, QMAN_COUNTER_FRAME);
+
+ if (qlen == 0) {
+ DPAA_ETH_LOCK(sc);
+
+ if (sc->sc_tx_fq_full) {
+ sc->sc_tx_fq_full = 0;
+ dpaa_eth_if_start_locked(sc);
+ }
+
+ DPAA_ETH_UNLOCK(sc);
+ }
+
+ return (1);
+}
+
+void
+dpaa_eth_fq_rx_free(struct dpaa_eth_softc *sc)
+{
+ int cpu;
+
+ if (sc->sc_rx_fq)
+ qman_fq_free(sc->sc_rx_fq);
+ if (sc->sc_rx_channel != 0) {
+ CPU_FOREACH(cpu) {
+ device_t portal = DPCPU_ID_GET(cpu, qman_affine_portal);
+ QMAN_PORTAL_STATIC_DEQUEUE_RM_CHANNEL(portal,
+ sc->sc_rx_channel);
+ }
+ qman_free_channel(sc->sc_rx_channel);
+ }
+}
+
+int
+dpaa_eth_fq_rx_init(struct dpaa_eth_softc *sc)
+{
+ void *fq;
+ int error;
+ int cpu;
+
+ /* Default Frame Queue */
+ if (sc->sc_rx_channel == 0)
+ sc->sc_rx_channel = qman_alloc_channel();
+ fq = qman_fq_create(1, sc->sc_rx_channel, DTSEC_RM_FQR_RX_WQ,
+ false, 0, false, false, true, false, 0, 0, 0);
+ if (fq == NULL) {
+ device_printf(sc->sc_dev,
+ "could not create default RX queue\n");
+ return (EIO);
+ }
+
+ CPU_FOREACH(cpu) {
+ device_t portal = DPCPU_ID_GET(cpu, qman_affine_portal);
+ QMAN_PORTAL_STATIC_DEQUEUE_CHANNEL(portal, sc->sc_rx_channel);
+ }
+
+ sc->sc_rx_fq = fq;
+ sc->sc_rx_fqid = qman_fq_get_fqid(fq);
+
+ error = qman_fq_register_cb(fq, dpaa_eth_fq_rx_callback, sc);
+ if (error != 0) {
+ device_printf(sc->sc_dev, "could not register RX callback\n");
+ dpaa_eth_fq_rx_free(sc);
+ return (EIO);
+ }
+
+ return (0);
+}
+
+void
+dpaa_eth_fq_tx_free(struct dpaa_eth_softc *sc)
+{
+
+ if (sc->sc_tx_fq)
+ qman_fq_free(sc->sc_tx_fq);
+
+ if (sc->sc_tx_conf_fq)
+ qman_fq_free(sc->sc_tx_conf_fq);
+}
+
+int
+dpaa_eth_fq_tx_init(struct dpaa_eth_softc *sc)
+{
+ int error;
+ void *fq;
+
+ /* TX Frame Queue */
+ fq = qman_fq_create(1, sc->sc_port_tx_qman_chan,
+ DTSEC_RM_FQR_TX_WQ, false, 0, false, false, true, false, 0, 0, 0);
+ if (fq == NULL) {
+ device_printf(sc->sc_dev, "could not create default TX queue"
+ "\n");
+ return (EIO);
+ }
+
+ sc->sc_tx_fq = fq;
+
+ if (sc->sc_rx_channel == 0)
+ sc->sc_rx_channel = qman_alloc_channel();
+ /* TX Confirmation Frame Queue */
+ fq = qman_fq_create(1, sc->sc_rx_channel,
+ DTSEC_RM_FQR_TX_CONF_WQ, false, 0, false, false, true, false, 0, 0,
+ 0);
+ if (fq == NULL) {
+ device_printf(sc->sc_dev, "could not create TX confirmation "
+ "queue\n");
+ dpaa_eth_fq_tx_free(sc);
+ return (EIO);
+ }
+
+ sc->sc_tx_conf_fq = fq;
+ sc->sc_tx_conf_fqid = qman_fq_get_fqid(fq);
+
+ error = qman_fq_register_cb(fq, dpaa_eth_fq_tx_confirm_callback, sc);
+ if (error != 0) {
+ device_printf(sc->sc_dev, "could not register TX confirmation "
+ "callback\n");
+ dpaa_eth_fq_tx_free(sc);
+ return (EIO);
+ }
+
+ return (0);
+}
+/** @} */
+
+/* Returns the cmd_stat field for the frame descriptor */
+static uint32_t
+dpaa_eth_tx_add_csum(struct dpaa_eth_frame_info *fi)
+{
+ struct mbuf *m = fi->fi_mbuf;
+ struct fman_parse_result *prs = &fi->fi_ic.prs;
+ uint32_t csum_flags = m->m_pkthdr.csum_flags;
+ uint8_t ether_size = ETHER_HDR_LEN;
+
+ if ((csum_flags & CSUM_FLAGS_TX) == 0)
+ return (0);
+
+ if (m->m_flags & M_VLANTAG)
+ ether_size += ETHER_VLAN_ENCAP_LEN;
+ if (csum_flags & CSUM_IP)
+ prs->l3r = L3R_FIRST_IPV4;
+ if (csum_flags & CSUM_IP_UDP) {
+ prs->l4r = L4R_TYPE_UDP;
+ prs->l4_off = ether_size + sizeof(struct ip);
+ } else if (csum_flags & CSUM_IP_TCP) {
+ prs->l4r = L4R_TYPE_TCP;
+ prs->l4_off = ether_size + sizeof(struct ip);
+ } else if (csum_flags & CSUM_IP6_UDP) {
+ prs->l3r = L3R_FIRST_IPV6;
+ prs->l4r = L4R_TYPE_UDP;
+ prs->l4_off = ether_size + sizeof(struct ip6_hdr);
+ } else if (csum_flags & CSUM_IP6_TCP) {
+ prs->l3r = L3R_FIRST_IPV6;
+ prs->l4r = L4R_TYPE_TCP;
+ prs->l4_off = ether_size + sizeof(struct ip6_hdr);
+ }
+
+ prs->ip_off[0] = ether_size;
+
+ return (DPAA_FD_TX_CMD_RPD | DPAA_FD_TX_CMD_DTC);
+}
+
+/**
+ * @group dTSEC IFnet routines.
+ * @{
+ */
+void
+dpaa_eth_if_start_locked(struct dpaa_eth_softc *sc)
+{
+ vm_size_t dsize, psize, ssize;
+ struct dpaa_eth_frame_info *fi;
+ unsigned int qlen, i;
+ struct mbuf *m0, *m;
+ vm_offset_t vaddr;
+ struct dpaa_fd fd;
+
+ DPAA_ETH_LOCK_ASSERT(sc);
+ /* TODO: IFF_DRV_OACTIVE */
+
+ if ((sc->sc_mii->mii_media_status & IFM_ACTIVE) == 0)
+ return;
+
+ if ((if_getdrvflags(sc->sc_ifnet) & IFF_DRV_RUNNING) != IFF_DRV_RUNNING)
+ return;
+
+ while (!if_sendq_empty(sc->sc_ifnet)) {
+ /* Check length of the TX queue */
+ qlen = qman_fq_get_counter(sc->sc_tx_fq, QMAN_COUNTER_FRAME);
+
+ if (qlen >= DTSEC_MAX_TX_QUEUE_LEN) {
+ sc->sc_tx_fq_full = 1;
+ return;
+ }
+
+ fi = dpaa_eth_fi_alloc(sc);
+ if (fi == NULL)
+ return;
+
+ m0 = if_dequeue(sc->sc_ifnet);
+ if (m0 == NULL) {
+ dpaa_eth_fi_free(sc, fi);
+ return;
+ }
+
+ i = 0;
+ m = m0;
+ psize = 0;
+ dsize = 0;
+ fi->fi_mbuf = m0;
+ while (m && i < DPAA_NUM_OF_SG_TABLE_ENTRY) {
+ if (m->m_len == 0)
+ continue;
+
+ /*
+ * First entry in scatter-gather table is used to keep
+ * pointer to frame info structure.
+ */
+ fi->fi_sgt[i].addr = pmap_kextract((vm_offset_t)fi);
+ i++;
+
+ dsize = m->m_len;
+ vaddr = (vm_offset_t)m->m_data;
+ while (dsize > 0 && i < DPAA_NUM_OF_SG_TABLE_ENTRY) {
+ ssize = PAGE_SIZE - (vaddr & PAGE_MASK);
+ if (m->m_len < ssize)
+ ssize = m->m_len;
+
+ fi->fi_sgt[i].addr = pmap_kextract(vaddr);
+ fi->fi_sgt[i].length = ssize;
+
+ fi->fi_sgt[i].extension = 0;
+ fi->fi_sgt[i].final = 0;
+ fi->fi_sgt[i].bpid = 0;
+ fi->fi_sgt[i].offset = 0;
+
+ dsize -= ssize;
+ vaddr += ssize;
+ psize += ssize;
+ i++;
+ }
+
+ if (dsize > 0)
+ break;
+
+ m = m->m_next;
+ }
+
+ /* Check if SG table was constructed properly */
+ if (m != NULL || dsize != 0) {
+ dpaa_eth_fi_free(sc, fi);
+ m_freem(m0);
+ continue;
+ }
+
+ fi->fi_sgt[i - 1].final = 1;
+
+ fd.addr = pmap_kextract((vm_offset_t)&fi->fi_ic);
+ fd.length = psize;
+ fd.format = DPAA_FD_FORMAT_SHORT_MBSF;
+
+ fd.liodn = 0;
+ fd.bpid = 0;
+ fd.eliodn = 0;
+ fd.offset = offsetof(struct dpaa_eth_frame_info, fi_sgt) -
+ offsetof(struct dpaa_eth_frame_info, fi_ic);
+ fd.cmd_stat = dpaa_eth_tx_add_csum(fi);
+
+ DPAA_ETH_UNLOCK(sc);
+ if (qman_fq_enqueue(sc->sc_tx_fq, &fd) != 0) {
+ dpaa_eth_fi_free(sc, fi);
+ m_freem(m0);
+ }
+ DPAA_ETH_LOCK(sc);
+ }
+}
+/** @} */
diff --git a/sys/dev/dpaa/dpaa_eth.h b/sys/dev/dpaa/dpaa_eth.h
new file mode 100644
index 000000000000..7832b4dd7bff
--- /dev/null
+++ b/sys/dev/dpaa/dpaa_eth.h
@@ -0,0 +1,116 @@
+/*-
+ * Copyright (c) 2012 Semihalf.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON 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 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef DPAA_ETH_H_
+#define DPAA_ETH_H_
+
+struct dpaa_eth_softc {
+ /* XXX MII bus requires that struct ifnet is first!!! */
+ if_t sc_ifnet;
+
+ device_t sc_dev;
+ struct resource *sc_mem;
+ struct mtx sc_lock;
+
+ int sc_mac_enet_mode;
+
+ /* RX Pool */
+ struct bman_pool *sc_rx_pool;
+ uint8_t sc_rx_bpid;
+ uma_zone_t sc_rx_zone;
+ char sc_rx_zname[64];
+
+ /* RX Frame Queue */
+ struct qman_fq *sc_rx_fq;
+ uint32_t sc_rx_fqid;
+
+ /* TX Frame Queue */
+ struct qman_fq *sc_tx_fq;
+ bool sc_tx_fq_full;
+ struct qman_fq *sc_tx_conf_fq;
+ uint32_t sc_tx_conf_fqid;
+
+ /* Methods */
+ int (*sc_port_rx_init)
+ (struct dpaa_eth_softc *sc, int unit);
+ int (*sc_port_tx_init)
+ (struct dpaa_eth_softc *sc, int unit);
+ void (*sc_start_locked)
+ (struct dpaa_eth_softc *sc);
+
+ /* dTSEC data */
+ uint8_t sc_eth_id; /* Ethernet ID within its frame manager */
+ uintptr_t sc_mac_mem_offset;
+ int sc_mac_mdio_irq;
+ uint8_t sc_mac_addr[6];
+ int sc_port_rx_hw_id;
+ int sc_port_tx_hw_id;
+ uint32_t sc_port_tx_qman_chan;
+ int sc_phy_addr;
+ bool sc_hidden;
+ device_t sc_mdio;
+ int sc_rev_major;
+ int sc_rev_minor;
+
+ device_t sc_rx_port;
+ device_t sc_tx_port;
+
+ int sc_rx_channel;
+
+ /* MII data */
+ struct mii_data *sc_mii;
+ device_t sc_mii_dev;
+ struct mtx sc_mii_lock;
+
+ struct callout sc_tick_callout;
+
+ /* Frame Info Zone */
+ uma_zone_t sc_fi_zone;
+ char sc_fi_zname[64];
+};
+
+/**
+ * @group dTSEC Regular Mode API.
+ * @{
+ */
+int dpaa_eth_fm_port_rx_init(struct dpaa_eth_softc *sc);
+int dpaa_eth_fm_port_tx_init(struct dpaa_eth_softc *sc);
+
+void dpaa_eth_if_start_locked(struct dpaa_eth_softc *sc);
+
+int dpaa_eth_pool_rx_init(struct dpaa_eth_softc *sc);
+void dpaa_eth_pool_rx_free(struct dpaa_eth_softc *sc);
+
+int dpaa_eth_fi_pool_init(struct dpaa_eth_softc *sc);
+void dpaa_eth_fi_pool_free(struct dpaa_eth_softc *sc);
+
+int dpaa_eth_fq_rx_init(struct dpaa_eth_softc *sc);
+int dpaa_eth_fq_tx_init(struct dpaa_eth_softc *sc);
+void dpaa_eth_fq_rx_free(struct dpaa_eth_softc *sc);
+void dpaa_eth_fq_tx_free(struct dpaa_eth_softc *sc);
+/** @} */
+
+#endif /* DPAA_ETH_H_ */
diff --git a/sys/dev/dpaa/fman.c b/sys/dev/dpaa/fman.c
index 393c28487ba9..b94c05fd7dbf 100644
--- a/sys/dev/dpaa/fman.c
+++ b/sys/dev/dpaa/fman.c
@@ -1,27 +1,7 @@
-/*-
- * Copyright (c) 2011-2012 Semihalf.
- * All rights reserved.
+/*
+ * Copyright (c) 2026 Justin Hibbits
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON 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 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * SPDX-License-Identifier: BSD-2-Clause
*/
#include <sys/param.h>
@@ -33,6 +13,7 @@
#include <sys/malloc.h>
#include <dev/fdt/simplebus.h>
+#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
@@ -40,50 +21,140 @@
#include "opt_platform.h"
-#include <contrib/ncsw/inc/Peripherals/fm_ext.h>
-#include <contrib/ncsw/inc/Peripherals/fm_muram_ext.h>
-#include <contrib/ncsw/inc/ncsw_ext.h>
-#include <contrib/ncsw/integrations/fman_ucode.h>
+#include <powerpc/mpc85xx/mpc85xx.h>
#include "fman.h"
+#define FMAN_BMI_OFFSET 0x80000
+#define FMAN_QMI_OFFSET 0x80400
+#define FMAN_KG_OFFSET 0xc1000
+#define FMAN_DMA_OFFSET 0xc2000
+#define FMAN_FPM_OFFSET 0xc3000
+#define FMAN_IMEM_OFFSET 0xc4000
+#define FMAN_HWP_OFFSET 0xc7000
+#define FMAN_CGP_OFFSET 0xdb000
+
+#define FM_IP_REV_1 (FMAN_FPM_OFFSET + 0x0c4)
+#define IP_REV_1_MAJ_M 0x0000ff00
+#define IP_REV_1_MAJ_S 8
+#define IP_REV_1_MIN_M 0x000000ff
+#define FM_RSTC (FMAN_FPM_OFFSET + 0x0cc)
+#define FM_RSTC_FM_RESET 0x80000000
+
+#define FMBM_INIT (FMAN_BMI_OFFSET + 0x000)
+#define INIT_STR 0x80000000
+#define FMBM_CFG1 (FMAN_BMI_OFFSET + 0x0004)
+#define FBPS_M 0x07ff0000
+#define FBPS_S 16
+#define FBPO_M 0x000007ff
+#define FMBM_CFG2 (FMAN_BMI_OFFSET + 0x0008)
+#define TNTSKS_M 0x007f0000
+#define TNTSKS_S 16
+#define FMBM_IEVR (FMAN_BMI_OFFSET + 0x0020)
+#define IEVR_SPEC 0x80000000
+#define IEVR_LEC 0x40000000
+#define IEVR_STEC 0x20000000
+#define IEVR_DEC 0x10000000
+#define FMBM_IER (FMAN_BMI_OFFSET + 0x0024)
+#define IER_SPECE 0x80000000
+#define IER_LECE 0x40000000
+#define IER_STECE 0x20000000
+#define IER_DECE 0x10000000
+#define FMBM_PP(n) (FMAN_BMI_OFFSET + 0x104 + ((n - 1) * 4))
+#define PP_MXT_M 0x3f000000
+#define PP_MXT_S 24
+#define PP_EXT_M 0x000f0000
+#define PP_EXT_S 16
+#define PP_MXD_M 0x00000f00
+#define PP_MXD_S 8
+#define PP_EXD_M 0x0000000f
+#define FMBM_PFS(n) (FMAN_BMI_OFFSET + 0x204 + ((n - 1) * 4))
+#define PFS_EXBS_M 0x03ff0000
+#define PFS_EXBS_S 16
+#define PFS_IFSZ_M 0x000003ff
+#define FMQM_GC (FMAN_QMI_OFFSET + 0x000)
+#define GC_STEN 0x10000000
+#define GC_ENQ_THR_S 8
+#define GC_ENQ_THR_M 0x00003f00
+#define GC_DEQ_THR_M 0x0000003f
+#define FMQM_EIE (FMAN_QMI_OFFSET + 0x008)
+#define EIE_DEE 0x80000000
+#define EIE_DFUPE 0x40000000
+#define FMQM_EIEN (FMAN_QMI_OFFSET + 0x00c)
+#define EIEN_DEE 0x80000000
+#define EIEN_DFUPE 0x40000000
+#define FMQM_IE
+#define IRAM_ADDR (FMAN_IMEM_OFFSET + 0x000)
+#define IADD_AIE 0x80000000
+#define IRAM_DATA (FMAN_IMEM_OFFSET + 0x004)
+#define IRAM_READY (FMAN_IMEM_OFFSET + 0x0c)
+#define IREADY_READY 0x80000000
+
+#define FMPR_RPIMAC (FMAN_HWP_OFFSET + 0x844)
+#define HWP_RPIMAC_PEN 0x00000001
+
+#define FMDM_SR (FMAN_DMA_OFFSET + 0x000)
+#define SR_CMDQNE 0x10000000
+#define SR_BER 0x08000000
+#define SR_RDB_ECC 0x04000000
+#define SR_WRB_SECC 0x02000000
+#define FMDM_MR (FMAN_DMA_OFFSET + 0x004)
+#define MR_CEN_M 0x0000e000
+#define MR_CEN_S 13
+#define FMDM_SETR (FMAN_DMA_OFFSET + 0x010)
+#define FMDM_EBCR (FMAN_DMA_OFFSET + 0x2c)
+#define FMDM_PLRn(n) (FMAN_DMA_OFFSET + 0x060 + (4 * (n / 2)))
+#define PLRN_LIODN_M(n) (0xfff << PLRN_LIODN_S(n))
+#define PLRN_LIODN_S(n) ((n & 1) ? 0 : 16)
+
+#define FMFP_TSC1 (FMAN_FPM_OFFSET + 0x060)
+#define TSC1_TEN 0x80000000
+#define FMFP_TSC2 (FMAN_FPM_OFFSET + 0x064)
+#define TSC2_TSIV_INT_S 16
+#define FM_RCR (FMAN_FPM_OFFSET + 0x070)
+#define RCR_FEE 0x80000000
+#define RCR_IEE 0x40000000
+#define RCR_MET 0x20000000
+#define RCR_IET 0x10000000
+#define RCR_SFE 0x08000000
+#define FMFP_EE (FMAN_FPM_OFFSET + 0x0dc)
+#define EE_DECC 0x80000000
+#define EE_STL 0x40000000
+#define EE_SECC 0x20000000
+#define EE_RFM 0x00010000
+#define EE_DECC_EN 0x00008000
+#define EE_STL_EN 0x00004000
+#define EE_SECC_EN 0x00002000
+#define EE_EHM 0x00000008
+#define EE_CER 0x00000002
+#define EE_DER 0x00000001
+#define FMFP_CEV0 (FMAN_FPM_OFFSET + 0x0e0)
+#define FMFP_CEV1 (FMAN_FPM_OFFSET + 0x0e4)
+#define FMFP_CEV2 (FMAN_FPM_OFFSET + 0x0e8)
+#define FMFP_CEV3 (FMAN_FPM_OFFSET + 0x0ec)
+
+/* DMA constants */
+#define DMA_CAM_UNITS 8
+#define DMA_CAM_SIZE 64
+#define DMA_CAM_ALIGN 64
+
+
+/* Timestamp counter */
+#define FM_TIMESTAMP_1US_BIT 8
static MALLOC_DEFINE(M_FMAN, "fman", "fman devices information");
+static void fman_intr(void *arg);
+
/**
* @group FMan private defines.
* @{
*/
-enum fman_irq_enum {
- FMAN_IRQ_NUM = 0,
- FMAN_ERR_IRQ_NUM = 1
-};
-
-enum fman_mu_ram_map {
- FMAN_MURAM_OFF = 0x0,
- FMAN_MURAM_SIZE = 0x28000
-};
-
-struct fman_config {
- device_t fman_device;
- uintptr_t mem_base_addr;
- uintptr_t irq_num;
- uintptr_t err_irq_num;
- uint8_t fm_id;
- t_FmExceptionsCallback *exception_callback;
- t_FmBusErrorCallback *bus_error_callback;
-};
/**
* @group FMan private methods/members.
* @{
*/
-/**
- * Frame Manager firmware.
- * We use the same firmware for both P3041 and P2041 devices.
- */
-const uint32_t fman_firmware[] = FMAN_UC_IMG;
-const uint32_t fman_firmware_size = sizeof(fman_firmware);
int
fman_activate_resource(device_t bus, device_t child, struct resource *res)
@@ -125,7 +196,7 @@ fman_release_resource(device_t bus, device_t child, struct resource *res)
passthrough = (device_get_parent(child) != bus);
rl = BUS_GET_RESOURCE_LIST(bus, child);
if (rman_get_type(res) != SYS_RES_IRQ) {
- if ((rman_get_flags(res) & RF_ACTIVE) != 0 ){
+ if ((rman_get_flags(res) & RF_ACTIVE) != 0) {
rv = bus_deactivate_resource(child, res);
if (rv != 0)
return (rv);
@@ -209,202 +280,400 @@ fman_alloc_resource(device_t bus, device_t child, int type, int rid,
return (NULL);
}
+
static int
-fman_fill_ranges(phandle_t node, struct simplebus_softc *sc)
+fman_get_revision_major(struct fman_softc *sc)
{
- int host_address_cells;
- cell_t *base_ranges;
- ssize_t nbase_ranges;
- int err;
- int i, j, k;
+ uint32_t reg;
- err = OF_searchencprop(OF_parent(node), "#address-cells",
- &host_address_cells, sizeof(host_address_cells));
- if (err <= 0)
- return (-1);
+ reg = bus_read_4(sc->mem_res, FM_IP_REV_1);
- nbase_ranges = OF_getproplen(node, "ranges");
- if (nbase_ranges < 0)
- return (-1);
- sc->nranges = nbase_ranges / sizeof(cell_t) /
- (sc->acells + host_address_cells + sc->scells);
- if (sc->nranges == 0)
- return (0);
+ return ((reg & IP_REV_1_MAJ_M) >> IP_REV_1_MAJ_S);
+}
- sc->ranges = malloc(sc->nranges * sizeof(sc->ranges[0]),
- M_DEVBUF, M_WAITOK);
- base_ranges = malloc(nbase_ranges, M_DEVBUF, M_WAITOK);
- OF_getencprop(node, "ranges", base_ranges, nbase_ranges);
+static int
+fman_get_revision_minor(struct fman_softc *sc)
+{
+ uint32_t reg;
- for (i = 0, j = 0; i < sc->nranges; i++) {
- sc->ranges[i].bus = 0;
- for (k = 0; k < sc->acells; k++) {
- sc->ranges[i].bus <<= 32;
- sc->ranges[i].bus |= base_ranges[j++];
- }
- sc->ranges[i].host = 0;
- for (k = 0; k < host_address_cells; k++) {
- sc->ranges[i].host <<= 32;
- sc->ranges[i].host |= base_ranges[j++];
- }
- sc->ranges[i].size = 0;
- for (k = 0; k < sc->scells; k++) {
- sc->ranges[i].size <<= 32;
- sc->ranges[i].size |= base_ranges[j++];
+ reg = bus_read_4(sc->mem_res, FM_IP_REV_1);
+
+ return ((reg & IP_REV_1_MIN_M));
+}
+
+static void
+fman_fill_soc_params(struct fman_softc *sc)
+{
+
+ switch (sc->sc_revision_major) {
+ case 2:
+ sc->bmi_max_fifo_size = 160 * 1024;
+ sc->iram_size = 64 * 1024;
+ sc->dma_thresh_max_commq = 31;
+ sc->dma_thresh_max_buf = 127;
+ sc->qmi_max_tnums = 64;
+ sc->qmi_def_tnums_thresh = 48;
+ sc->bmi_max_tasks = 128;
+ sc->max_open_dmas = 32;
+ sc->dma_cam_num_entries = 32;
+ sc->port_cgs = 256;
+ sc->rx_ports = 5;
+ sc->total_fifo_size = 100 * 1024;
+ break;
+ case 3:
+ sc->bmi_max_fifo_size = 160 * 1024;
+ sc->iram_size = 64 * 1024;
+ sc->dma_thresh_max_commq = 31;
+ sc->dma_thresh_max_buf = 127;
+ sc->qmi_max_tnums = 64;
+ sc->qmi_def_tnums_thresh = 48;
+ sc->bmi_max_tasks = 128;
+ sc->max_open_dmas = 32;
+ sc->dma_cam_num_entries = 32;
+ sc->port_cgs = 256;
+ sc->rx_ports = 6;
+ sc->total_fifo_size = 136 * 1024;
+ break;
+ case 6:
+ sc->dma_thresh_max_commq = 31;
+ sc->dma_thresh_max_buf = 127;
+ sc->qmi_max_tnums = 64;
+ sc->qmi_def_tnums_thresh = 48;
+ sc->dma_cam_num_entries = 64;
+ sc->port_cgs = 256;
+ switch (sc->sc_revision_minor) {
+ case 1:
+ case 4:
+ sc->bmi_max_fifo_size = 192 * 1024;
+ sc->bmi_max_tasks = 64;
+ sc->max_open_dmas = 32;
+ sc->rx_ports = 5;
+ sc->total_fifo_size = 156 * 1024;
+ if (sc->sc_revision_minor == 1)
+ sc->iram_size = 32 * 1024;
+ else
+ sc->iram_size = 64 * 1024;
+ break;
+ case 0:
+ case 2:
+ case 3:
+ sc->bmi_max_fifo_size = 384 * 1024;
+ sc->bmi_max_tasks = 128;
+ sc->max_open_dmas = 84;
+ sc->rx_ports = 8;
+ sc->iram_size = 64 * 1024;
+ sc->total_fifo_size = 295 * 1024;
+ break;
+ default:
+ device_printf(sc->sc_base.dev,
+ "Unsupported FManv3 revision: %d\n",
+ sc->sc_revision_minor);
+ break;
}
+ break;
+ default:
+ device_printf(sc->sc_base.dev,
+ "Unsupported FMan version: %d\n", sc->sc_revision_major);
+ break;
}
-
- free(base_ranges, M_DEVBUF);
- return (sc->nranges);
}
-static t_Handle
-fman_init(struct fman_softc *sc, struct fman_config *cfg)
+static int
+fman_reset(struct fman_softc *sc)
{
- phandle_t node;
- t_FmParams fm_params;
- t_Handle muram_handle, fm_handle;
- t_Error error;
- t_FmRevisionInfo revision_info;
- uint16_t clock;
- uint32_t tmp, mod;
+ unsigned int count;
+
+ if (sc->sc_revision_major < 6) {
+ bus_write_4(sc->mem_res, FM_RSTC, FM_RSTC_FM_RESET);
+ count = 100;
+ do {
+ DELAY(1);
+ } while ((bus_read_4(sc->mem_res, FM_RSTC) & FM_RSTC_FM_RESET) &&
+ --count);
+ if (count == 0)
+ return (EBUSY);
+ return (0);
+ } else {
+#ifdef __powerpc__
+ phandle_t node;
+ u_long base, size;
+ uint32_t devdisr2;
+#define GUTS_DEVDISR2 0x0074
+#define DEVDISR2_FMAN1 0xfcc00000
+#define DEVDISR2_FMAN2 0x000fcc00
+
+ node = ofw_bus_get_node(device_get_parent(sc->sc_base.dev));
+ node = fdt_find_compatible(node, "fsl,qoriq-device-config-2.0",
+ false);
- /* MURAM configuration */
- muram_handle = FM_MURAM_ConfigAndInit(cfg->mem_base_addr +
- FMAN_MURAM_OFF, FMAN_MURAM_SIZE);
- if (muram_handle == NULL) {
- device_printf(cfg->fman_device, "couldn't init FM MURAM module"
- "\n");
- return (NULL);
+ if (node == 0) {
+ device_printf(sc->sc_base.dev,
+ "missing device-config node in FDT. Cannot reset FMAN");
+ return (0);
+ }
+ fdt_regsize(node, &base, &size);
+
+ devdisr2 = ccsr_read4(ccsrbar_va + base + GUTS_DEVDISR2);
+ if (sc->fm_id == 0)
+ ccsr_write4(ccsrbar_va + base + GUTS_DEVDISR2,
+ devdisr2 & ~DEVDISR2_FMAN1);
+ else
+ ccsr_write4(ccsrbar_va + base + GUTS_DEVDISR2,
+ devdisr2 & ~DEVDISR2_FMAN2);
+#endif
+ bus_write_4(sc->mem_res, FM_RSTC, FM_RSTC_FM_RESET);
+ count = 100;
+ do {
+ DELAY(1);
+ } while ((bus_read_4(sc->mem_res, FM_RSTC) & FM_RSTC_FM_RESET) &&
+ --count);
+#ifdef __powerpc__
+ ccsr_write4(ccsrbar_va + base + GUTS_DEVDISR2, devdisr2);
+#endif
+ if (count == 0)
+ return (EBUSY);
+ return (0);
}
- sc->muram_handle = muram_handle;
+}
- /* Fill in FM configuration */
- fm_params.fmId = cfg->fm_id;
- /* XXX we support only one partition thus each fman has master id */
- fm_params.guestId = NCSW_MASTER_ID;
+static int
+fman_clear_iram(struct fman_softc *sc)
+{
+#ifdef notyet
+ int i;
- fm_params.baseAddr = cfg->mem_base_addr;
- fm_params.h_FmMuram = muram_handle;
+ /*
+ * TODO: Allow clearing the IRAM and loading new firmware. Currently
+ * this is not supported, so assume that there's already firmware
+ * loaded, and don't clear it just yet.
+ */
+ bus_write_4(sc->mem_res, IRAM_ADDR, IADD_AIE);
+ for (i = 0; i < 100 && bus_read_4(sc->mem_res, IRAM_ADDR) != IADD_AIE; i++)
+ DELAY(1);
- /* Get FMan clock in Hz */
- if ((tmp = fman_get_clock(sc)) == 0)
- return (NULL);
+ if (i == 100)
+ return (EBUSY);
- /* Convert FMan clock to MHz */
- clock = (uint16_t)(tmp / 1000000);
- mod = tmp % 1000000;
+ for (i = 0; i < sc->iram_size / 4; i++)
+ bus_write_4(sc->mem_res, IRAM_DATA, 0xffffffff);
- if (mod >= 500000)
- ++clock;
+ bus_write_4(sc->mem_res, IRAM_ADDR, sc->iram_size - 4);
+ for (i = 0; i < 100 &&
+ bus_read_4(sc->mem_res, IRAM_DATA) != 0xffffffff; i++)
+ DELAY(1);
- fm_params.fmClkFreq = clock;
- fm_params.f_Exception = cfg->exception_callback;
- fm_params.f_BusError = cfg->bus_error_callback;
- fm_params.h_App = cfg->fman_device;
- fm_params.irq = cfg->irq_num;
- fm_params.errIrq = cfg->err_irq_num;
+ if (i == 100)
+ return (EBUSY);
+#endif
- fm_params.firmware.size = fman_firmware_size;
- fm_params.firmware.p_Code = (uint32_t*)fman_firmware;
+ return (0);
+}
- fm_handle = FM_Config(&fm_params);
- if (fm_handle == NULL) {
- device_printf(cfg->fman_device, "couldn't configure FM "
- "module\n");
- goto err;
- }
+static int
+fman_dma_init(struct fman_softc *sc)
+{
+ vmem_addr_t addr;
+ uint32_t reg;
+ int err;
- FM_ConfigResetOnInit(fm_handle, TRUE);
+ reg = bus_read_4(sc->mem_res, FMDM_SR);
+ bus_write_4(sc->mem_res, FMDM_SR, reg | SR_BER);
+ reg = bus_read_4(sc->mem_res, FMDM_MR) & ~MR_CEN_M;
+ reg |= ((sc->dma_cam_num_entries / DMA_CAM_UNITS) - 1) << MR_CEN_S;
+ bus_write_4(sc->mem_res, FMDM_MR, reg);
- error = FM_Init(fm_handle);
- if (error != E_OK) {
- device_printf(cfg->fman_device, "couldn't init FM module\n");
- goto err2;
- }
+ err = vmem_xalloc(sc->muram_vmem,
+ sc->dma_cam_num_entries * DMA_CAM_SIZE, DMA_CAM_ALIGN, 0, 0,
+ VMEM_ADDR_MIN, VMEM_ADDR_MAX, M_BESTFIT | M_WAITOK, &addr);
+ if (err != 0)
+ device_printf(sc->sc_base.dev,
+ "failed to allocate DMA buffer\n");
+ reg = addr;
+ bus_write_4(sc->mem_res, FMDM_EBCR, reg);
+ return (0);
+}
- error = FM_GetRevision(fm_handle, &revision_info);
- if (error != E_OK) {
- device_printf(cfg->fman_device, "couldn't get FM revision\n");
- goto err2;
- }
+static int
+fman_bmi_init(struct fman_softc *sc)
+{
+ uint32_t reg;
- device_printf(cfg->fman_device, "Hardware version: %d.%d.\n",
- revision_info.majorRev, revision_info.minorRev);
+ reg = sc->bmi_fifo_base / FMAN_BMI_FIFO_ALIGN;
+ reg |= (sc->total_fifo_size / FMAN_BMI_FIFO_UNITS - 1) << FBPS_S;
+ bus_write_4(sc->mem_res, FMBM_CFG1, reg);
- /* Initialize the simplebus part of things */
- simplebus_init(sc->sc_base.dev, 0);
+ reg = ((sc->bmi_max_tasks - 1) << TNTSKS_S) & TNTSKS_M;
+ //bus_write_4(sc->mem_res, FMBM_CFG2, reg);
- node = ofw_bus_get_node(sc->sc_base.dev);
- fman_fill_ranges(node, &sc->sc_base);
- sc->rman.rm_type = RMAN_ARRAY;
- sc->rman.rm_descr = "FMan range";
- rman_init_from_resource(&sc->rman, sc->mem_res);
- for (node = OF_child(node); node > 0; node = OF_peer(node)) {
- simplebus_add_device(sc->sc_base.dev, node, 0, NULL, -1, NULL);
- }
+ bus_write_4(sc->mem_res, FMBM_IEVR,
+ IEVR_SPEC | IEVR_LEC | IEVR_STEC | IEVR_DEC);
- return (fm_handle);
+ bus_write_4(sc->mem_res, FMBM_IER,
+ IER_SPECE | IER_LECE | IER_STECE | IER_DECE);
-err2:
- FM_Free(fm_handle);
-err:
- FM_MURAM_Free(muram_handle);
- return (NULL);
+ return (0);
}
-static void
-fman_exception_callback(t_Handle app_handle, e_FmExceptions exception)
+static int
+fman_qmi_init(struct fman_softc *sc)
{
- struct fman_softc *sc;
-
- sc = app_handle;
- device_printf(sc->sc_base.dev, "FMan exception occurred.\n");
+ bus_write_4(sc->mem_res, FMQM_EIE, EIE_DEE | EIE_DFUPE);
+ bus_write_4(sc->mem_res, FMQM_EIEN, EIEN_DEE | EIEN_DFUPE);
+ return (0);
}
static void
-fman_error_callback(t_Handle app_handle, e_FmPortType port_type,
- uint8_t port_id, uint64_t addr, uint8_t tnum, uint16_t liodn)
+fman_hwp_init(struct fman_softc *sc)
{
- struct fman_softc *sc;
-
- sc = app_handle;
- device_printf(sc->sc_base.dev, "FMan error occurred.\n");
+ /* Start up the parser */
+ bus_write_4(sc->mem_res, FMPR_RPIMAC, HWP_RPIMAC_PEN);
}
-/** @} */
+static int
+fman_enable(struct fman_softc *sc)
+{
+ bus_write_4(sc->mem_res, FMBM_INIT, INIT_STR);
+ bus_write_4(sc->mem_res, FMQM_GC, 0xc0000000 |
+ GC_STEN | (sc->qmi_def_tnums_thresh << GC_ENQ_THR_S) |
+ sc->qmi_def_tnums_thresh);
-/**
- * @group FMan driver interface.
- * @{
+ return (0);
+}
+
+/*
+ * Enable timestamp counting. Matching Freescale's reference code, generate the
+ * timestamp incrementer to be roughly 256MHz, such that bit 23 would update
+ * every microsecond.
*/
+static int
+fman_enable_timestamp(struct fman_softc *sc)
+{
+ uint64_t frac;
+ uint32_t clock = fman_get_clock(sc) / 1000000;
+ uint32_t intgr, tmp;
+ uint32_t ts_freq = 1 << FM_TIMESTAMP_1US_BIT;
-int
-fman_get_handle(device_t dev, t_Handle *fmh)
+ intgr = ts_freq / clock;
+
+ frac = ((uint64_t)ts_freq << 16) - ((uint64_t)intgr << 16) * clock;
+ frac = (frac % clock ? 1 : 0) + (frac / clock);
+
+ tmp = (intgr << TSC2_TSIV_INT_S) | (uint32_t)frac;
+
+ bus_write_4(sc->mem_res, FMFP_TSC2, tmp);
+ bus_write_4(sc->mem_res, FMFP_TSC1, TSC1_TEN);
+
+ return (0);
+}
+
+static int
+fman_keygen_init(struct fman_softc *sc)
{
- struct fman_softc *sc = device_get_softc(dev);
+ /* TODO: keygen */
+ return (0);
+}
+
+static int
+fman_fpm_init(struct fman_softc *sc)
+{
+ /* Clear all events, and enable interrupts. */
+ bus_write_4(sc->mem_res, FMFP_EE,
+ EE_DECC | EE_STL | EE_SECC | EE_EHM |
+ EE_DECC_EN | EE_STL_EN | EE_SECC_EN);
+
+ bus_write_4(sc->mem_res, FMFP_CEV0, 0xffffffff);
+ bus_write_4(sc->mem_res, FMFP_CEV1, 0xffffffff);
+ bus_write_4(sc->mem_res, FMFP_CEV2, 0xffffffff);
+ bus_write_4(sc->mem_res, FMFP_CEV3, 0xffffffff);
- *fmh = sc->fm_handle;
+ bus_write_4(sc->mem_res, FM_RCR, RCR_FEE | RCR_IEE);
return (0);
}
-int
-fman_get_muram_handle(device_t dev, t_Handle *muramh)
+static int
+fman_init(struct fman_softc *sc)
{
- struct fman_softc *sc = device_get_softc(dev);
+ vmem_addr_t base_addr;
+ sc->sc_revision_major = fman_get_revision_major(sc);
+ sc->sc_revision_minor = fman_get_revision_minor(sc);
+
+ if (bootverbose)
+ device_printf(sc->sc_base.dev, "Hardware version: %d.%d.\n",
+ sc->sc_revision_major, sc->sc_revision_minor);
+
+ fman_fill_soc_params(sc);
+ bus_set_region_4(sc->mem_res, FMAN_CGP_OFFSET, 0, sc->port_cgs / 4);
+
+ if (fman_reset(sc) != 0)
+ goto err;
+
+ if (fman_clear_iram(sc) != 0)
+ goto err;
+
+ if (fman_dma_init(sc) != 0)
+ goto err;
- *muramh = sc->muram_handle;
+ fman_fpm_init(sc);
+
+ vmem_alloc(sc->muram_vmem, sc->total_fifo_size, M_BESTFIT | M_WAITOK,
+ &base_addr);
+ sc->bmi_fifo_base = base_addr;
+
+ fman_bmi_init(sc);
+ fman_qmi_init(sc);
+ fman_hwp_init(sc);
+ if (fman_keygen_init(sc) != 0)
+ goto err;
+
+ if (fman_enable(sc) != 0)
+ goto err;
+
+ fman_enable_timestamp(sc);
return (0);
+err:
+ return (ENXIO);
}
-int
-fman_get_bushandle(device_t dev, vm_offset_t *fm_base)
+void
+fman_get_revision(device_t dev, int *major, int *minor)
{
struct fman_softc *sc = device_get_softc(dev);
- *fm_base = rman_get_bushandle(sc->mem_res);
+ if (major)
+ *major = sc->sc_revision_major;
+ if (minor)
+ *minor = sc->sc_revision_minor;
+}
+
+/** @} */
+
+static int
+fman_init_muram(struct fman_softc *sc)
+{
+ u_long base, size;
+ phandle_t node;
+
+ node = ofw_bus_get_node(sc->sc_base.dev);
+ for (node = OF_child(node); node != 0; node = OF_peer(node)) {
+ char compat[255];
+
+ if (OF_getprop(node, "compatible", compat, sizeof(compat)) < 0)
+ continue;
+ if (strcmp(compat, "fsl,fman-muram") == 0)
+ break;
+ }
+ if (node == 0) {
+ device_printf(sc->sc_base.dev, "no muram node\n");
+ return (ENXIO);
+ }
+ if (fdt_regsize(node, &base, &size) != 0) {
+ device_printf(sc->sc_base.dev, "failed to get muram reg\n");
+ return (ENXIO);
+ }
+ sc->muram_vmem = vmem_create("MURAM",
+ base, size, 1, 0, M_WAITOK);
return (0);
}
@@ -413,20 +682,18 @@ int
fman_attach(device_t dev)
{
struct fman_softc *sc;
- struct fman_config cfg;
pcell_t qchan_range[2];
+ pcell_t cell;
phandle_t node;
sc = device_get_softc(dev);
sc->sc_base.dev = dev;
- /* Check if MallocSmart allocator is ready */
- if (XX_MallocSmartInit() != E_OK) {
- device_printf(dev, "could not initialize smart allocator.\n");
- return (ENXIO);
- }
-
+ cell = 0;
node = ofw_bus_get_node(dev);
+ OF_getencprop(node, "cell-index", &cell, sizeof(cell));
+ sc->fm_id = cell;
+
if (OF_getencprop(node, "fsl,qman-channel-range", qchan_range,
sizeof(qchan_range)) <= 0) {
device_printf(dev, "Missing QMan channel range property!\n");
@@ -450,6 +717,12 @@ fman_attach(device_t dev)
goto err;
}
+ if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET | INTR_MPSAFE,
+ NULL, fman_intr, sc, &sc->irq_cookie) != 0) {
+ device_printf(dev, "error setting up interrupt handler.\n");
+ goto err;
+ }
+
sc->err_irq_rid = 1;
sc->err_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
&sc->err_irq_rid, RF_ACTIVE | RF_SHAREABLE);
@@ -458,20 +731,19 @@ fman_attach(device_t dev)
goto err;
}
- /* Set FMan configuration */
- cfg.fman_device = dev;
- cfg.fm_id = device_get_unit(dev);
- cfg.mem_base_addr = rman_get_bushandle(sc->mem_res);
- cfg.irq_num = (uintptr_t)sc->irq_res;
- cfg.err_irq_num = (uintptr_t)sc->err_irq_res;
- cfg.exception_callback = fman_exception_callback;
- cfg.bus_error_callback = fman_error_callback;
+ /* Initialize the simplebus part of things */
+ sc->rman.rm_type = RMAN_ARRAY;
+ sc->rman.rm_descr = "FMan range";
+ rman_init_from_resource(&sc->rman, sc->mem_res);
+ simplebus_attach_impl(sc->sc_base.dev);
+
+ if (fman_init_muram(sc) != 0)
+ goto err;
+
+ /* TODO: Interrupts... */
- sc->fm_handle = fman_init(sc, &cfg);
- if (sc->fm_handle == NULL) {
- device_printf(dev, "could not be configured\n");
+ if (fman_init(sc) != 0)
goto err;
- }
bus_attach_children(dev);
return (0);
@@ -485,16 +757,14 @@ int
fman_detach(device_t dev)
{
struct fman_softc *sc;
+ int rv;
- sc = device_get_softc(dev);
+ rv = simplebus_detach(dev);
- if (sc->muram_handle) {
- FM_MURAM_Free(sc->muram_handle);
- }
+ if (rv != 0)
+ return (rv);
- if (sc->fm_handle) {
- FM_Free(sc->fm_handle);
- }
+ sc = device_get_softc(dev);
if (sc->mem_res) {
bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid,
@@ -511,6 +781,9 @@ fman_detach(device_t dev)
sc->err_irq_res);
}
+ if (sc->muram_vmem != NULL)
+ vmem_destroy(sc->muram_vmem);
+
return (0);
}
@@ -535,21 +808,152 @@ fman_shutdown(device_t dev)
return (0);
}
+static void
+fman_intr(void *arg)
+{
+ /* TODO: All FMAN interrupts */
+}
+
int
fman_qman_channel_id(device_t dev, int port)
{
struct fman_softc *sc;
- int qman_port_id[] = {0x31, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e,
- 0x2f, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
int i;
sc = device_get_softc(dev);
- for (i = 0; i < sc->qman_chan_count; i++) {
- if (qman_port_id[i] == port)
- return (sc->qman_chan_base + i);
+ if (sc->sc_revision_major >= 6) {
+ static const int qman_port_id[] = {
+ 0x30, 0x31, 0x28, 0x29, 0x2a, 0x2b,
+ 0x2c, 0x2d, 0x02, 0x03, 0x04, 0x05, 0x07, 0x07
+ };
+ for (i = 0; i < sc->qman_chan_count; i++) {
+ if (qman_port_id[i] == port)
+ return (sc->qman_chan_base + i);
+ }
+ } else {
+ static const int qman_port_id[] = {
+ 0x31, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x01,
+ 0x02, 0x03, 0x04, 0x05, 0x07, 0x07
+ };
+ for (i = 0; i < sc->qman_chan_count; i++) {
+ if (qman_port_id[i] == port)
+ return (sc->qman_chan_base + i);
+ }
}
return (0);
}
+size_t
+fman_get_bmi_max_fifo_size(device_t dev)
+{
+ struct fman_softc *sc = device_get_softc(dev);
+
+ return (sc->bmi_max_fifo_size);
+}
+
+int
+fman_reset_mac(device_t dev, int mac_id)
+{
+ struct fman_softc *sc = device_get_softc(dev);
+ int timeout = 100;
+ uint32_t mask;
+
+ if (mac_id < 0 || mac_id > 9)
+ return (EINVAL);
+
+ /* MAC bits start at bit 1 for MAC0, and go down */
+ mask = (1 << (30 - mac_id));
+ bus_write_4(sc->mem_res, FM_RSTC, mask);
+ while ((bus_read_4(sc->mem_res, FM_RSTC) & mask) && --timeout)
+ DELAY(10);
+
+ if (timeout == 0)
+ return (EIO);
+
+ return (0);
+}
+
+static int
+fman_set_port_tasks(struct fman_softc *sc, int port_id,
+ uint8_t tasks, uint8_t extra)
+{
+ uint32_t reg;
+
+ reg = bus_read_4(sc->mem_res, FMBM_PP(port_id));
+
+ reg &= ~(PP_MXT_M | PP_EXT_M);
+ reg |= ((uint32_t)(tasks - 1) << PP_MXT_S) |
+ ((uint32_t)extra << PP_EXT_S);
+ bus_write_4(sc->mem_res, FMBM_PP(port_id), reg);
+
+ return (0);
+}
+
+static int
+fman_set_port_fifo_size(struct fman_softc *sc, int port_id,
+ uint32_t fifo_size, uint32_t extra)
+{
+ uint32_t reg;
+
+ reg = (fifo_size / FMAN_BMI_FIFO_UNITS - 1) |
+ ((extra / FMAN_BMI_FIFO_UNITS) << PFS_EXBS_S);
+
+ /* TODO: Make sure fifo size doesn't overrun */
+ /* See Linux driver, fman set_size_of_fifo */
+
+ bus_write_4(sc->mem_res, FMBM_PFS(port_id), reg);
+ return (0);
+}
+
+static int
+fman_set_port_dmas(struct fman_softc *sc, int port_id,
+ int open_dmas, int extra_dmas)
+{
+ /* TODO: set port DMAs */
+ return (0);
+}
+
+static void
+fman_set_port_liodn(struct fman_softc *sc, int port_id, uint32_t liodn)
+{
+ uint32_t reg;
+
+ reg = bus_read_4(sc->mem_res, FMDM_PLRn(port_id));
+ reg &= ~PLRN_LIODN_M(port_id);
+ reg |= liodn << PLRN_LIODN_S(port_id);
+ bus_write_4(sc->mem_res, FMDM_PLRn(port_id), reg);
+}
+
+int
+fman_set_port_params(device_t dev, struct fman_port_init_params *params)
+{
+ struct fman_softc *sc = device_get_softc(dev);
+ int error;
+
+ error = fman_set_port_tasks(sc, params->port_id,
+ params->num_tasks, params->extra_tasks);
+
+ if (error != 0)
+ return (error);
+
+ if (!params->is_rx_port) {
+ }
+ error = fman_set_port_fifo_size(sc, params->port_id, params->fifo_size,
+ params->extra_fifo_size);
+
+ if (error != 0)
+ return (error);
+
+ error = fman_set_port_dmas(sc, params->port_id,
+ params->open_dmas, params->extra_dmas);
+
+ if (error != 0)
+ return (error);
+
+ fman_set_port_liodn(sc, params->port_id, params->liodn);
+
+ return (0);
+}
+
/** @} */
diff --git a/sys/dev/dpaa/fman.h b/sys/dev/dpaa/fman.h
index a2ada5e16ffb..a0af1b36b5a3 100644
--- a/sys/dev/dpaa/fman.h
+++ b/sys/dev/dpaa/fman.h
@@ -28,6 +28,23 @@
#define FMAN_H_
#include <dev/fdt/simplebus.h>
+#include <sys/vmem.h>
+
+#define FMAN_BMI_FIFO_UNITS 0x100
+#define FMAN_BMI_FIFO_ALIGN 0x100
+
+#define FM_FD_ERR_DMA 0x01000000
+#define FM_FD_ERR_FPE 0x00080000
+#define FM_FD_ERR_FSE 0x00040000
+#define FM_FD_ERR_DIS 0x00020000
+#define FM_FD_ERR_EOF 0x00008000
+#define FM_FD_ERR_NSS 0x00004000
+#define FM_FD_ERR_KSO 0x00002000
+#define FM_FD_ERR_IPP 0x00000200
+#define FM_FD_ERR_PTE 0x00000080
+#define FM_FD_ERR_ISP 0x00000040
+#define FM_FD_ERR_PHE 0x00000020
+#define FM_FD_ERR_BLE 0x00000008
/**
* FMan driver instance data.
@@ -38,22 +55,91 @@ struct fman_softc {
struct resource *irq_res;
struct resource *err_irq_res;
struct rman rman;
+ vmem_t *muram_vmem;
int mem_rid;
int irq_rid;
int err_irq_rid;
+ void *irq_cookie;
int qman_chan_base;
int qman_chan_count;
+ int fm_id;
+
+ int sc_revision_major;
+ int sc_revision_minor;
+
+ uint16_t clock;
+ bool timestamps;
+
+ uint32_t iram_size;
+ uint32_t dma_thresh_max_commq;
+ uint32_t dma_thresh_max_buf;
+ uint32_t dma_cam_num_entries;
+ uint32_t max_open_dmas;
+
+ uint32_t qmi_max_tnums;
+ uint32_t qmi_def_tnums_thresh;
+
+ uint32_t bmi_max_tasks;
+ uint32_t bmi_max_fifo_size;
+ uint32_t bmi_fifo_base;
- t_Handle fm_handle;
- t_Handle muram_handle;
+ uint32_t port_cgs;
+ uint32_t rx_ports;
+ uint32_t total_fifo_size;
+
+ uint32_t qman_channel_base;
+ uint32_t qman_channels;
+};
+
+struct fman_port_init_params {
+ int port_id;
+ bool is_rx_port;
+ uint8_t num_tasks;
+ uint8_t extra_tasks;
+ uint8_t open_dmas;
+ uint8_t extra_dmas;
+ uint32_t fifo_size;
+ uint32_t extra_fifo_size;
+ uint8_t deq_pipeline_size;
+ uint16_t max_frame_length;
+ uint16_t liodn;
};
+struct fman_parse_result {
+ uint8_t lpid;
+ uint8_t shimr;
+ uint16_t l2r;
+ uint16_t l3r;
+ uint8_t l4r;
+ uint8_t cpid;
+ uint16_t nxthdr;
+ uint16_t cksum;
+ uint32_t lcv;
+ uint8_t shim_off[2];
+ uint8_t ip_pid_off;
+ uint8_t eth_off;
+ uint8_t llc_snap_off;
+ uint8_t vlan_tic_off[2];
+ uint8_t last_e_type_off;
+ uint8_t pppoe_off;
+ uint8_t mpls_off[2];
+ uint8_t ip_off[2];
+ uint8_t gre_off;
+ uint8_t l4_off;
+ uint8_t nxthdr_off;
+};
+
+struct fman_internal_context {
+ struct fman_parse_result prs;
+ uint64_t timestamp;
+ uint64_t hash;
+};
/**
- * @group QMan bus interface.
+ * @group FMan bus interface.
* @{
*/
-struct resource * fman_alloc_resource(device_t bus, device_t child, int type,
+struct resource *fman_alloc_resource(device_t bus, device_t child, int type,
int rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags);
int fman_activate_resource(device_t bus, device_t child,
struct resource *res);
@@ -66,11 +152,16 @@ int fman_shutdown(device_t dev);
int fman_read_ivar(device_t dev, device_t child, int index,
uintptr_t *result);
int fman_qman_channel_id(device_t, int);
+void fman_get_revision(device_t, int *, int *);
/** @} */
uint32_t fman_get_clock(struct fman_softc *sc);
-int fman_get_handle(device_t dev, t_Handle *fmh);
-int fman_get_muram_handle(device_t dev, t_Handle *muramh);
int fman_get_bushandle(device_t dev, vm_offset_t *fm_base);
+size_t fman_get_bmi_max_fifo_size(device_t);
+int fman_reset_mac(device_t, int);
+int fman_set_port_params(device_t dev, struct fman_port_init_params *params);
+int fman_qman_channel_id(device_t, int);
+int fman_set_mac_intr_handler(device_t, int, driver_intr_t, void *);
+int fman_set_mac_err_handler(device_t, int, driver_intr_t, void *);
#endif /* FMAN_H_ */
diff --git a/sys/dev/dpaa/fman_fdt.c b/sys/dev/dpaa/fman_fdt.c
index 4d3723b6de4d..88f08269f086 100644
--- a/sys/dev/dpaa/fman_fdt.c
+++ b/sys/dev/dpaa/fman_fdt.c
@@ -34,10 +34,8 @@
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
-#include <contrib/ncsw/inc/ncsw_ext.h>
-#include <contrib/ncsw/inc/enet_ext.h>
-
#include "fman.h"
+#include "fman_if.h"
#define FFMAN_DEVSTR "Freescale Frame Manager"
@@ -56,6 +54,12 @@ static device_method_t fman_methods[] = {
DEVMETHOD(bus_alloc_resource, fman_alloc_resource),
DEVMETHOD(bus_activate_resource, fman_activate_resource),
DEVMETHOD(bus_release_resource, fman_release_resource),
+
+ DEVMETHOD(fman_get_revision, fman_get_revision),
+ DEVMETHOD(fman_reset_mac, fman_reset_mac),
+ DEVMETHOD(fman_set_port_params, fman_set_port_params),
+ DEVMETHOD(fman_get_qman_channel_id, fman_qman_channel_id),
+
DEVMETHOD_END
};
@@ -92,8 +96,8 @@ fman_get_clock(struct fman_softc *sc)
if ((OF_getprop(node, "clock-frequency", &fman_clock,
sizeof(fman_clock)) <= 0) || (fman_clock == 0)) {
- device_printf(dev, "could not acquire correct frequency "
- "from DTS\n");
+ device_printf(dev,
+ "could not acquire correct frequency from DTS\n");
return (0);
}
diff --git a/sys/dev/dpaa/fman_if.m b/sys/dev/dpaa/fman_if.m
new file mode 100644
index 000000000000..e7412ca64195
--- /dev/null
+++ b/sys/dev/dpaa/fman_if.m
@@ -0,0 +1,38 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2026 Justin Hibbits
+
+#include <machine/bus.h>
+#include <dev/dpaa/fman.h>
+
+/**
+ * @brief DPAA FMan interface
+ *
+ */
+INTERFACE fman;
+
+METHOD void get_revision {
+ device_t dev;
+ int *major;
+ int *minor;
+};
+
+METHOD size_t get_bmi_max_fifo_size {
+ device_t dev;
+};
+
+METHOD int get_qman_channel_id {
+ device_t dev;
+ int port_id;
+};
+
+METHOD int reset_mac {
+ device_t dev;
+ int mac_id;
+};
+
+METHOD int set_port_params {
+ device_t dev;
+ struct fman_port_init_params *params;
+};
diff --git a/sys/dev/dpaa/fman_mdio.c b/sys/dev/dpaa/fman_mdio.c
index 8df716fc5571..d32b13ad0a79 100644
--- a/sys/dev/dpaa/fman_mdio.c
+++ b/sys/dev/dpaa/fman_mdio.c
@@ -46,17 +46,15 @@
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
-#include <contrib/ncsw/inc/Peripherals/fm_ext.h>
-
#include "fman.h"
#include "miibus_if.h"
#define MDIO_LOCK() mtx_lock(&sc->sc_lock)
#define MDIO_UNLOCK() mtx_unlock(&sc->sc_lock)
-#define MDIO_WRITE4(sc,r,v) \
- bus_space_write_4(&bs_be_tag, sc->sc_handle, sc->sc_offset + r, v)
+#define MDIO_WRITE4(sc, r, v) \
+ bus_write_4(sc->sc_res, r, v)
#define MDIO_READ4(sc, r) \
- bus_space_read_4(&bs_be_tag, sc->sc_handle, sc->sc_offset + r)
+ bus_read_4(sc->sc_res, r)
#define MDIO_MIIMCFG 0x0
#define MDIO_MIIMCOM 0x4
@@ -76,8 +74,7 @@ static int pqmdio_miibus_writereg(device_t dev, int phy, int reg, int value);
struct pqmdio_softc {
struct mtx sc_lock;
- bus_space_handle_t sc_handle;
- int sc_offset;
+ struct resource *sc_res;
};
static device_method_t pqmdio_methods[] = {
@@ -123,13 +120,10 @@ static int
pqmdio_fdt_attach(device_t dev)
{
struct pqmdio_softc *sc;
- rman_res_t start, count;
sc = device_get_softc(dev);
- fman_get_bushandle(device_get_parent(dev), &sc->sc_handle);
- bus_get_resource(dev, SYS_RES_MEMORY, 0, &start, &count);
- sc->sc_offset = start;
+ sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 0, RF_ACTIVE);
OF_device_register_xref(OF_xref_from_node(ofw_bus_get_node(dev)), dev);
diff --git a/sys/dev/dpaa/fman_muram.c b/sys/dev/dpaa/fman_muram.c
new file mode 100644
index 000000000000..a3df993dbb98
--- /dev/null
+++ b/sys/dev/dpaa/fman_muram.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2026 Justin Hibbits
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <sys/malloc.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+
+#include "opt_platform.h"
+
+#include <powerpc/mpc85xx/mpc85xx.h>
+
+#include "fman.h"
+
+struct fman_muram_softc {
+ struct resource *sc_mem;
+ vmem_t sc_vmem;
+};
+
+static int
+fman_muram_probe(device_t dev)
+{
+ if (!ofw_bus_is_compatible(dev, "fsl,fman-muram"))
+ return (ENXIO);
+
+ device_set_desc(dev, "FMan MURAM");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+fman_muram_attach(device_t dev)
+{
+ struct fman_muram_softc *sc = device_get_softc(dev);
+
+ sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 0,
+ RF_ACTIVE | RF_SHAREABLE);
+
+ if (sc->sc_mem == NULL) {
+ device_printf(dev, "cannot allocate memory\n");
+ return (ENXIO);
+ }
+ sc->sc_vmem = vmem_create("MURAM", rman_get_bushandle(sc->sc_mem),
+ rman_get_size(sc->sc_mem),
+}
+
+static device_method_t muram_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, fman_muram_probe),
+ DEVMETHOD(device_attach, fman_muram_attach),
+ DEVMETHOD(device_detach, fman_muram_detach),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(fman_muram, fman_muram_driver, muram_methods,
+ sizeof(struct fman_muram_softc));
+EARLY_DRIVER_MODULE(fman_muram, fman, fman_muram_driver, 0, 0,
+ BUS_PASS_SUPPORTDEV);
diff --git a/sys/dev/dpaa/fman_parser.h b/sys/dev/dpaa/fman_parser.h
new file mode 100644
index 000000000000..aff95b1ae9d9
--- /dev/null
+++ b/sys/dev/dpaa/fman_parser.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2026 Justin Hibbits
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef DPAA_FMAN_PARSER_H
+#define DPAA_FMAN_PARSER_H
+
+#define FMAN_PARSE_RESULT_OFF 32
+#define L3R_FIRST_IPV4 0x8000
+#define L3R_FIRST_IPV6 0x4000
+#define L3R_FIRST_IP_M (L3R_FIRST_IPV4 | L3R_FIRST_IPV6)
+#define L3R_LAST_IPV4 0x8000
+#define L3R_LAST_IPV6 0x4000
+#define L3R_LAST_IP_M (L3R_LAST_IPV4 | L3R_LAST_IPV6)
+#define L3R_FIRST_ERROR 0x2000
+#define L3R_LAST_ERROR 0x0080
+#define L4R_TYPE_M 0xe0
+#define L4R_TYPE_TCP 0x20
+#define L4R_TYPE_UDP 0x40
+#define L4R_TYPE_IPSEC 0x60
+#define L4R_TYPE_SCTP 0x80
+#define L4R_DCCP 0xa0
+#define L4R_ERR 0x10
+
+#endif
diff --git a/sys/dev/dpaa/fman_port.c b/sys/dev/dpaa/fman_port.c
new file mode 100644
index 000000000000..384d13a7b3a7
--- /dev/null
+++ b/sys/dev/dpaa/fman_port.c
@@ -0,0 +1,697 @@
+/*
+ * Copyright (c) 2026 Justin Hibbits
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <machine/bus.h>
+#include "fman.h"
+#include "fman_parser.h"
+#include "fman_port.h"
+#include "fman_if.h"
+#include "fman_port_if.h"
+
+struct fman_port_rsrc {
+ uint32_t num;
+ uint32_t extra;
+};
+
+#define MAX_BM_POOLS 64
+struct fman_port_softc {
+ device_t sc_dev;
+ struct resource *sc_mem;
+ int sc_port_id;
+ int sc_port_speed;
+ int sc_port_type;
+
+ int sc_revision_major;
+ int sc_revision_minor;
+
+ int sc_max_frame_length;
+ int sc_bm_max_pools;
+ int sc_max_port_fifo_size;
+ int sc_qman_channel_id;
+
+ int sc_deq_byte_count;
+ int sc_deq_high_priority;
+ int sc_tx_deq_pipeline_depth;
+
+ int sc_default_fqid;
+ int sc_err_fqid;
+ int pcd_base_fqid;
+ int pcd_fqs_count;
+
+ int sc_max_ext_portals;
+ int sc_max_sub_portals;
+
+ struct fman_port_rsrc sc_open_dmas;
+ struct fman_port_rsrc sc_tasks;
+ struct fman_port_rsrc sc_fifo_bufs;
+
+ struct fman_port_buffer_pool sc_bpools[FMAN_PORT_MAX_POOLS];
+};
+
+#define TX_10G_PORT_BASE 0x30
+#define RX_10G_PORT_BASE 0x10
+
+#define FMAN_PORT_TYPE_TX 0
+#define FMAN_PORT_TYPE_RX 1
+
+#define PORT_RX 0x01
+#define PORT_TX 0x02
+#define PORT_V3 0x04
+
+#define FMBM_RCFG 0x000
+#define BMI_PORT_CFG_EN 0x80000000
+#define FMBM_RST 0x004
+#define FMBM_RDA 0x008
+#define RDA_WOPT 0x00100000
+#define FMBM_RFP 0x00c
+#define FMBM_RFED 0x010
+#define BMI_RX_FRAME_END_CUT_SHIFT 16
+#define FMBM_RICP 0x014 /* Counts are units of 16 bytes */
+#define RICP_ICEOF_M 0x001f0000
+#define RICP_ICEOF_S 16
+#define RICP_ICIOF_M 0x00000f00
+#define RICP_ICIOF_S 8
+#define RICP_ICSZ_S 0x0000001f
+#define FMBM_RIM 0x018
+#define FMBM_REBM 0x01c
+#define REBM_BSM_M 0x01ff0000
+#define REBM_BSM_S 16
+#define REBM_BEM_M 0x000001ff
+#define FMBM_RFNE 0x020
+#define FMBM_RFCA 0x024
+#define RFCA_OR 0x80000000
+#define RFCA_COLOR 0x0c000000
+#define RFCA_SYNC 0x03000000
+#define RFCA_SYNC_REQ 0x02000000
+#define RFCA_MR 0x003f0000
+#define RFCA_MR_DEF 0x003c0000
+#define FMBM_RFPNE 0x028
+#define FMBM_RETH 0x038
+#define RETH_ETHE 0x80000000 /* Excessive Threshold Enable */
+#define FMBM_RFQID 0x060
+#define FMBM_REFQID 0x064
+#define FMBM_RFSDM 0x068
+#define FMBM_RFSEM 0x06c
+#define FMBM_RFENE 0x070
+#define FMBM_REBMPI(i) (0x100 + (4 * (i)))
+#define REBMPI_VAL 0x80000000
+#define REBMPI_ACE 0x40000000
+#define REBMPI_BPID_S 16
+#define FMBM_RSTC 0x0200
+#define RSTC_EN 0x80000000
+
+#define FMBM_TCFG 0x000
+#define FMBM_TST 0x004
+#define FMBM_TDA 0x008
+#define FMBM_TFP 0x00c
+#define BMI_FIFO_PIPELINE_DEPTH_SHIFT 12
+#define FMBM_TFED 0x010
+#define FMBM_TICP 0x014
+#define TICP_ICEOF_M 0x001f0000
+#define TICP_ICEOF_S 16
+#define TICP_ICIOF_M 0x00000f00
+#define TICP_ICIOF_S 8
+#define TICP_ICSZ_S 0x0000001f
+#define FMBM_TFDNE 0x018
+#define FMBM_TFCA 0x01c
+#define TFCA_MR_DEF 0
+#define TFCA_ATTR_ORDER 0x80000000
+#define FMBM_TCFQID 0x020
+#define FMBM_TEFQID 0x024
+#define FMBM_TFENE 0x028
+#define FMBM_TFNE 0x070
+#define TFNE_EBD 0x80000000
+
+#define FMQM_PNC 0x400
+#define PNC_EN 0x80000000
+#define PNC_STEN 0x80000000
+#define FMQM_PNS 0x404
+#define PNS_DEQ_FD_BSY 0x20000000
+#define FMQM_PNEN 0x41c
+#define FMQM_PNDN 0x42c
+#define FMQM_PNDC 0x430
+#define QMI_DEQ_CFG_PRI 0x80000000
+#define QMI_DEQ_CFG_TYPE1 0x10000000
+#define QMI_DEQ_CFG_TYPE2 0x20000000
+#define QMI_DEQ_CFG_TYPE3 0x30000000
+#define QMI_DEQ_CFG_PREFETCH_PARTIAL 0x01000000
+#define QMI_DEQ_CFG_PREFETCH_FULL 0x03000000
+#define QMI_DEQ_CFG_SP_MASK 0xf
+#define QMI_DEQ_CFG_SP_SHIFT 20
+
+#define HWP_PCAC 0xbf8
+#define HWP_PCAC_PSTOP 0x00000001
+#define HWP_HXS_PCAC_PSTAT 0x00000100
+#define HWP_HXS_SSA(x) (0x800 + x * 2 * sizeof(uint32_t))
+#define HWP_HXS_LCV(x) (0x800 + (x * 2 + 1) * sizeof(uint32_t))
+#define HWP_HXS_TCP 0xA
+#define HWP_HXS_UDP 0xB
+#define HXS_SH_PAD_REM 0x80000000
+#define HWP_HXS_COUNT 16
+
+#define PORT_MAX_FRAME_LENGTH 9600
+
+#define NIA_ORDER_RESTORE 0x00800000
+#define NIA_ENG_BMI 0x00500000
+#define NIA_ENG_QMI_DEQ 0x00580000
+#define NIA_ENG_QMI_ENQ 0x00540000
+#define NIA_ENG_HWP 0x00440000
+#define NIA_ENG_HWK 0x00480000
+#define NIA_BMI_AC_TX_RELEASE 0x000002c0
+#define NIA_BMI_AC_TX 0x00000274
+#define NIA_BMI_AC_RELEASE 0x000000c0
+#define NIA_BMI_AC_ENQ_FRAME 0x00000002
+#define NIA_BMI_AC_FETCH_ALLFRAME 0x0000020c
+
+#define BMI_RX_ERR (FM_FD_ERR_DMA | FM_FD_ERR_FPE | \
+ FM_FD_ERR_FSE | FM_FD_ERR_DIS | \
+ FM_FD_ERR_EOF | FM_FD_ERR_NSS | \
+ FM_FD_ERR_KSO | FM_FD_ERR_IPP | \
+ FM_FD_ERR_PTE | FM_FD_ERR_PHE | \
+ FM_FD_ERR_BLE)
+
+/* Default configurations */
+#define DEFAULT_RX_CUT_END_BYTES 4
+
+static struct ofw_compat_data compats[] = {
+ { "fsl,fman-v2-port-rx", PORT_RX },
+ { "fsl,fman-v2-port-tx", PORT_TX },
+ { "fsl,fman-v3-port-rx", PORT_V3 | PORT_RX },
+ { "fsl,fman-v3-port-tx", PORT_V3 | PORT_TX },
+ { NULL, 0 }
+};
+
+static int
+fman_port_probe(device_t dev)
+{
+ if (ofw_bus_search_compatible(dev, compats)->ocd_str == NULL)
+ return (ENXIO);
+
+ device_set_desc(dev, "FMan port");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+fman_port_attach(device_t dev)
+{
+ struct fman_port_softc *sc;
+ phandle_t node;
+ pcell_t cell;
+ uintptr_t compat_data =
+ ofw_bus_search_compatible(dev, compats)->ocd_data;
+ int port_speed = 1000;
+ int port_type;
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+
+ node = ofw_bus_get_node(dev);
+ if (OF_getencprop(node, "cell-index", &cell, sizeof(cell)) < 0) {
+ device_printf(dev, "No cell-index property");
+ return (ENXIO);
+ }
+
+ sc->sc_port_id = cell;
+
+ sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 0,
+ RF_ACTIVE | RF_SHAREABLE);
+
+ if (sc->sc_mem == NULL) {
+ device_printf(dev, "failed to allocate MMIO");
+ return (ENXIO);
+ }
+
+ FMAN_GET_REVISION(device_get_parent(dev),
+ &sc->sc_revision_major, &sc->sc_revision_minor);
+
+ if ((compat_data & PORT_TX) == PORT_TX)
+ port_type = FMAN_PORT_TYPE_TX;
+ else
+ port_type = FMAN_PORT_TYPE_RX;
+
+ if ((compat_data & PORT_V3) == PORT_V3) {
+ if (OF_hasprop(node, "fsl,fman-10g-port"))
+ port_speed = 10000;
+ } else {
+ if ((compat_data & PORT_TX) &&
+ sc->sc_port_id > TX_10G_PORT_BASE)
+ port_speed = 10000;
+ else if ((compat_data & PORT_RX) &&
+ sc->sc_port_id > RX_10G_PORT_BASE)
+ port_speed = 10000;
+ }
+
+ if (sc->sc_port_speed == 10000) {
+ sc->sc_deq_high_priority = true;
+ sc->sc_deq_byte_count = 0x1400;
+ } else {
+ sc->sc_deq_high_priority = false;
+ sc->sc_deq_byte_count = 0x0400;
+ }
+
+ sc->sc_port_type = port_type;
+ sc->sc_port_speed = port_speed;
+
+ sc->sc_bm_max_pools = MAX_BM_POOLS;
+ sc->sc_max_frame_length = PORT_MAX_FRAME_LENGTH;
+
+ if (port_type == FMAN_PORT_TYPE_TX)
+ sc->sc_qman_channel_id =
+ FMAN_GET_QMAN_CHANNEL_ID(device_get_parent(dev),
+ sc->sc_port_id);
+
+ OF_device_register_xref(OF_xref_from_node(ofw_bus_get_node(dev)), dev);
+
+ return (0);
+}
+
+static int
+fman_port_detach(device_t dev)
+{
+ struct fman_port_softc *sc = device_get_softc(dev);
+
+ if (sc->sc_mem != NULL)
+ bus_release_resource(dev, sc->sc_mem);
+
+ return (0);
+}
+
+static int
+fman_port_config(device_t dev, struct fman_port_params *params)
+{
+ struct fman_port_softc *sc = device_get_softc(dev);
+
+ sc->sc_default_fqid = params->dflt_fqid;
+ sc->sc_err_fqid = params->err_fqid;
+
+ sc->sc_max_port_fifo_size =
+ FMAN_GET_BMI_MAX_FIFO_SIZE(device_get_parent(dev));
+ switch (sc->sc_revision_major) {
+ case 2:
+ case 3:
+ sc->sc_max_ext_portals = 4;
+ sc->sc_max_sub_portals = 12;
+ break;
+ case 6:
+ sc->sc_max_ext_portals = 8;
+ sc->sc_max_sub_portals = 16;
+ break;
+ }
+ if (sc->sc_revision_major >= 6 &&
+ sc->sc_port_type == FMAN_PORT_TYPE_TX && sc->sc_port_speed == 1000)
+ /* Errata A005127 workaround */
+ bus_write_4(sc->sc_mem, FMBM_TFP, 0x00001013);
+
+ sc->sc_tasks.extra = 0;
+
+ switch (sc->sc_port_speed) {
+ case 10000:
+ if (sc->sc_revision_major < 6) {
+ sc->sc_tasks.num = 16;
+ if (sc->sc_port_type == FMAN_PORT_TYPE_RX)
+ sc->sc_tasks.extra = 8;
+ } else
+ sc->sc_tasks.num = 14;
+ break;
+ case 1000:
+ if (sc->sc_revision_major >= 6)
+ sc->sc_tasks.num = 4;
+ else {
+ sc->sc_tasks.num = 3;
+ if (sc->sc_port_type == FMAN_PORT_TYPE_RX)
+ sc->sc_tasks.extra = 2;
+ }
+ break;
+ default:
+ sc->sc_tasks.num = 0;
+ break;
+ }
+
+ /* Open DMAs */
+ if (sc->sc_revision_major >= 6) {
+ sc->sc_open_dmas.extra = 0;
+ if (sc->sc_port_speed == 10000) {
+ if (sc->sc_port_type == FMAN_PORT_TYPE_TX)
+ sc->sc_open_dmas.num = 12;
+ else
+ sc->sc_open_dmas.num = 8;
+ } else {
+ if (sc->sc_port_type == FMAN_PORT_TYPE_TX)
+ sc->sc_open_dmas.num = 3;
+ else
+ sc->sc_open_dmas.num = 2;
+ }
+ } else {
+ if (sc->sc_port_speed == 10000) {
+ sc->sc_open_dmas.num = 8;
+ sc->sc_open_dmas.num = 8;
+ } else {
+ sc->sc_open_dmas.num = 1;
+ sc->sc_open_dmas.extra = 1;
+ }
+ }
+
+ /* FIFO bufs */
+ if (sc->sc_revision_major >= 6) {
+ if (sc->sc_port_type == FMAN_PORT_TYPE_TX)
+ if (sc->sc_port_speed == 10000)
+ sc->sc_fifo_bufs.num = 64;
+ else
+ sc->sc_fifo_bufs.num = 50;
+ else
+ if (sc->sc_port_speed == 10000)
+ sc->sc_fifo_bufs.num = 96;
+ else
+ sc->sc_fifo_bufs.num = 50;
+ } else {
+ if (sc->sc_port_type == FMAN_PORT_TYPE_TX)
+ if (sc->sc_port_speed == 10000)
+ sc->sc_fifo_bufs.num = 48;
+ else
+ sc->sc_fifo_bufs.num = 44;
+ else
+ if (sc->sc_port_speed == 10000)
+ sc->sc_fifo_bufs.num = 48;
+ else
+ sc->sc_fifo_bufs.num = 45;
+ }
+
+ sc->sc_fifo_bufs.extra = 0;
+ sc->sc_fifo_bufs.num *= FMAN_BMI_FIFO_UNITS;
+
+ if (sc->sc_port_type == FMAN_PORT_TYPE_RX)
+ for (int i = 0; i < params->rx_params.num_pools; i++)
+ sc->sc_bpools[i] = params->rx_params.bpools[i];
+
+ /* TODO: buf_margins? See fman_sp_build_buffer_struct */
+
+ return (0);
+}
+
+static int
+fman_port_init_bmi_rx(struct fman_port_softc *sc)
+{
+ uint32_t reg;
+
+ /* TODO: Sort the buffer pool list. */
+ /* TODO: Backup pools */
+ /* TODO: Depletion mode */
+ for (int i = 0; i < FMAN_PORT_MAX_POOLS; i++) {
+ /* Initialize the external pool info */
+ if (sc->sc_bpools[i].size != 0) {
+ bus_write_4(sc->sc_mem, FMBM_REBMPI(i),
+ REBMPI_VAL | REBMPI_ACE |
+ (sc->sc_bpools[i].bpid << REBMPI_BPID_S) |
+ sc->sc_bpools[i].size);
+ } else
+ /* Mark invalid if zero */
+ bus_write_4(sc->sc_mem, FMBM_REBMPI(i), 0);
+ }
+
+ bus_write_4(sc->sc_mem, FMBM_RDA, RDA_WOPT);
+
+ bus_write_4(sc->sc_mem, FMBM_RFCA,
+ RFCA_OR | RFCA_SYNC_REQ | RFCA_MR_DEF);
+
+ bus_write_4(sc->sc_mem, FMBM_RFPNE,
+ NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME);
+ bus_write_4(sc->sc_mem, FMBM_RFENE,
+ NIA_ENG_QMI_ENQ | NIA_ORDER_RESTORE);
+
+ bus_write_4(sc->sc_mem, FMBM_RFQID, sc->sc_default_fqid);
+ bus_write_4(sc->sc_mem, FMBM_REFQID, sc->sc_err_fqid);
+
+ if (sc->sc_revision_major < 6)
+ bus_write_4(sc->sc_mem, FMBM_RETH, RETH_ETHE);
+
+ /* Errata A006320 makes CFED field bad */
+ if (sc->sc_revision_major == 6 && (sc->sc_revision_minor == 0))
+ /* These are under errata A006320 */;
+ else
+ bus_write_4(sc->sc_mem, FMBM_RFED,
+ DEFAULT_RX_CUT_END_BYTES << BMI_RX_FRAME_END_CUT_SHIFT);
+
+ /* Insert internal context ahead of the frame */
+ reg = sizeof(struct fman_internal_context) << REBM_BSM_S;
+ bus_write_4(sc->sc_mem, FMBM_REBM, reg);
+ reg = howmany(FMAN_PARSE_RESULT_OFF, 0x10) << RICP_ICIOF_S;
+ reg |= howmany(sizeof(struct fman_internal_context), 0x10);
+ bus_write_4(sc->sc_mem, FMBM_RICP, reg);
+
+ bus_write_4(sc->sc_mem, FMBM_RFNE, NIA_ENG_HWP);
+ bus_write_4(sc->sc_mem, FMBM_RFSDM, FM_FD_ERR_DIS);
+ bus_write_4(sc->sc_mem, FMBM_RFSEM, BMI_RX_ERR & ~FM_FD_ERR_DIS);
+
+ return (0);
+}
+
+static int
+fman_port_init_bmi_tx(struct fman_port_softc *sc)
+{
+ uint32_t reg;
+ int depth;
+
+ bus_write_4(sc->sc_mem, FMBM_TCFG, 0);
+ bus_write_4(sc->sc_mem, FMBM_TDA, 0);
+ bus_write_4(sc->sc_mem, FMBM_TFED, 0);
+ if (sc->sc_port_speed == 10000)
+ depth = 4;
+ else if (sc->sc_revision_major >= 6)
+ depth = 2;
+ else
+ depth = 1;
+ sc->sc_tx_deq_pipeline_depth = depth;
+ reg = ((depth - 1) << BMI_FIFO_PIPELINE_DEPTH_SHIFT) | 0x13;
+ bus_write_4(sc->sc_mem, FMBM_TFP, reg);
+
+ /* Default color: green */
+ bus_write_4(sc->sc_mem, FMBM_TFCA,
+ TFCA_MR_DEF | TFCA_ATTR_ORDER);
+
+ bus_write_4(sc->sc_mem, FMBM_TFDNE, NIA_ENG_QMI_DEQ);
+ bus_write_4(sc->sc_mem, FMBM_TFENE,
+ NIA_ENG_QMI_ENQ | NIA_ORDER_RESTORE);
+
+ /* Insert internal context ahead of the frame */
+ reg = howmany(FMAN_PARSE_RESULT_OFF, 0x10) << TICP_ICIOF_S;
+ reg |= howmany(sizeof(struct fman_internal_context), 0x10);
+ bus_write_4(sc->sc_mem, FMBM_TICP, reg);
+
+ if (sc->sc_revision_major >= 6)
+ bus_write_4(sc->sc_mem, FMBM_TFNE,
+ (sc->sc_default_fqid == 0 ? TFNE_EBD : 0) |
+ NIA_BMI_AC_FETCH_ALLFRAME);
+ bus_write_4(sc->sc_mem, FMBM_TCFQID, sc->sc_default_fqid);
+ bus_write_4(sc->sc_mem, FMBM_TEFQID, sc->sc_err_fqid);
+
+ return (0);
+}
+
+static int
+fman_port_init_hwp(struct fman_port_softc *sc)
+{
+ int i;
+
+ /* Stop the parser so we can initialize it for our uses */
+ bus_write_4(sc->sc_mem, HWP_PCAC, HWP_PCAC_PSTOP);
+
+ for (i = 0; i < 100 &&
+ (bus_read_4(sc->sc_mem, HWP_PCAC) & HWP_HXS_PCAC_PSTAT) != 0; i++) {
+ DELAY(10);
+ }
+ if (i == 100) {
+ device_printf(sc->sc_dev, "Timeout stopping HW parser\n");
+ return (ENXIO);
+ }
+
+ /* set the parser examination config */
+ for (i = 0; i < HWP_HXS_COUNT; i++) {
+ bus_write_4(sc->sc_mem, HWP_HXS_SSA(i), 0);
+ bus_write_4(sc->sc_mem, HWP_HXS_LCV(i), 0xffffffff);
+ }
+ bus_write_4(sc->sc_mem, HWP_HXS_SSA(HWP_HXS_TCP), HXS_SH_PAD_REM);
+ bus_write_4(sc->sc_mem, HWP_HXS_SSA(HWP_HXS_UDP), HXS_SH_PAD_REM);
+
+ /* Re-enable the parser */
+ bus_write_4(sc->sc_mem, HWP_PCAC, 0);
+
+ return (0);
+}
+
+static int
+fman_port_init_qmi(struct fman_port_softc *sc)
+{
+ uint32_t reg;
+
+ if (sc->sc_port_type == FMAN_PORT_TYPE_RX) {
+ bus_write_4(sc->sc_mem, FMQM_PNEN,
+ NIA_ENG_BMI | NIA_BMI_AC_RELEASE);
+ return (0);
+ }
+
+ /* TX port */
+ bus_write_4(sc->sc_mem, FMQM_PNDN,
+ NIA_ENG_BMI | NIA_BMI_AC_TX);
+ /* TX port */
+ bus_write_4(sc->sc_mem, FMQM_PNEN,
+ NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE);
+
+ reg = 0;
+
+ if (sc->sc_deq_high_priority)
+ reg |= QMI_DEQ_CFG_PRI;
+
+ reg |= QMI_DEQ_CFG_TYPE1;
+ reg |= QMI_DEQ_CFG_PREFETCH_FULL;
+ reg |= (sc->sc_qman_channel_id & QMI_DEQ_CFG_SP_MASK) << QMI_DEQ_CFG_SP_SHIFT;
+ reg |= sc->sc_deq_byte_count;
+ bus_write_4(sc->sc_mem, FMQM_PNDC, reg);
+
+ return (0);
+}
+
+static int
+fman_port_init(device_t dev)
+{
+ struct fman_port_init_params params;
+ struct fman_port_softc *sc = device_get_softc(dev);
+ int err;
+
+ if (sc->sc_port_type == FMAN_PORT_TYPE_RX) {
+ /* Set up RX buffers and fifo */
+ }
+ params.port_id = sc->sc_port_id;
+ params.is_rx_port = (sc->sc_port_type == FMAN_PORT_TYPE_RX);
+ params.num_tasks = sc->sc_tasks.num;
+ params.extra_tasks = sc->sc_tasks.extra;
+ params.open_dmas = sc->sc_open_dmas.num;
+ params.extra_dmas = sc->sc_open_dmas.extra;
+ params.fifo_size = sc->sc_fifo_bufs.num;
+ params.extra_fifo_size = sc->sc_fifo_bufs.extra;
+ params.max_frame_length = sc->sc_max_frame_length;
+ params.deq_pipeline_size = sc->sc_tx_deq_pipeline_depth;
+
+ /* TODO: verify_size_of_fifo() from Linux driver */
+ err = FMAN_SET_PORT_PARAMS(device_get_parent(dev), &params);
+
+ if (err != 0)
+ return (err);
+
+ if (sc->sc_port_type == FMAN_PORT_TYPE_TX)
+ err = fman_port_init_bmi_tx(sc);
+ else {
+ err = fman_port_init_bmi_rx(sc);
+ if (err == 0)
+ fman_port_init_hwp(sc);
+ }
+
+ if (err != 0)
+ return (err);
+
+ err = fman_port_init_qmi(sc);
+
+ /* TODO: keygen here */
+
+ return (err);
+}
+
+static int
+fman_port_disable(device_t dev)
+{
+ struct fman_port_softc *sc;
+ uint32_t reg;
+ int count;
+
+ sc = device_get_softc(dev);
+
+ switch (sc->sc_port_type) {
+ case FMAN_PORT_TYPE_TX:
+ reg = bus_read_4(sc->sc_mem, FMQM_PNC);
+ bus_write_4(sc->sc_mem, FMQM_PNC, reg & ~PNC_EN);
+ for (count = 0; count < 100; count++) {
+ DELAY(10);
+ reg = bus_read_4(sc->sc_mem, FMQM_PNS);
+ if (!(reg & PNS_DEQ_FD_BSY))
+ break;
+ }
+ if (count == 100)
+ device_printf(sc->sc_dev, "Timeout stopping QMI\n");
+ reg = bus_read_4(sc->sc_mem, FMBM_TCFG);
+ bus_write_4(sc->sc_mem, FMBM_TCFG, reg & ~BMI_PORT_CFG_EN);
+ for (count = 0; count < 100; count++) {
+ DELAY(10);
+ reg = bus_read_4(sc->sc_mem, FMBM_TST);
+ if (!(reg & PNS_DEQ_FD_BSY))
+ break;
+ }
+ if (count == 100)
+ device_printf(sc->sc_dev, "Timeout stopping BMI");
+ break;
+ case FMAN_PORT_TYPE_RX:
+ reg = bus_read_4(sc->sc_mem, FMBM_RCFG);
+ bus_write_4(sc->sc_mem, FMBM_RCFG, reg & ~BMI_PORT_CFG_EN);
+ for (count = 0; count < 100; count++) {
+ DELAY(10);
+ reg = bus_read_4(sc->sc_mem, FMBM_RST);
+ if (!(reg & PNS_DEQ_FD_BSY))
+ break;
+ }
+ if (count == 100)
+ device_printf(sc->sc_dev, "Timeout stopping BMI");
+ break;
+ }
+
+ return (0);
+}
+
+static int
+fman_port_enable(device_t dev)
+{
+ struct fman_port_softc *sc;
+ uint32_t reg;
+
+ sc = device_get_softc(dev);
+ switch (sc->sc_port_type) {
+ case FMAN_PORT_TYPE_TX:
+ reg = bus_read_4(sc->sc_mem, FMQM_PNC);
+ bus_write_4(sc->sc_mem, FMQM_PNC, reg | PNC_EN | PNC_STEN);
+ reg = bus_read_4(sc->sc_mem, FMBM_TCFG);
+ bus_write_4(sc->sc_mem, FMBM_TCFG, reg | BMI_PORT_CFG_EN);
+ break;
+ case FMAN_PORT_TYPE_RX:
+ reg = bus_read_4(sc->sc_mem, FMBM_RCFG);
+ bus_write_4(sc->sc_mem, FMQM_PNC, reg | PNC_EN | PNC_STEN);
+ bus_write_4(sc->sc_mem, FMBM_RCFG, reg | BMI_PORT_CFG_EN);
+ bus_write_4(sc->sc_mem, FMBM_RSTC, RSTC_EN);
+ break;
+ }
+
+ return (0);
+}
+
+static device_method_t fman_port_methods[] = {
+ DEVMETHOD(device_probe, fman_port_probe),
+ DEVMETHOD(device_attach, fman_port_attach),
+ DEVMETHOD(device_detach, fman_port_detach),
+
+ DEVMETHOD(fman_port_config, fman_port_config),
+ DEVMETHOD(fman_port_init, fman_port_init),
+ DEVMETHOD(fman_port_enable, fman_port_enable),
+ DEVMETHOD(fman_port_disable, fman_port_disable),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(fman_port, fman_port_driver, fman_port_methods,
+ sizeof(struct fman_port_softc));
+EARLY_DRIVER_MODULE(fman_port, fman, fman_port_driver, 0, 0,
+ BUS_PASS_SUPPORTDEV + BUS_PASS_ORDER_MIDDLE);
diff --git a/sys/dev/dpaa/fman_port.h b/sys/dev/dpaa/fman_port.h
new file mode 100644
index 000000000000..8803c5e5f7c9
--- /dev/null
+++ b/sys/dev/dpaa/fman_port.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2026 Justin Hibbits
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef DPAA_FMAN_PORT_H
+#define DPAA_FMAN_PORT_H
+
+#define FMAN_PORT_MAX_POOLS 4
+struct fman_port_buffer_pool {
+ uint8_t bpid;
+ uint16_t size;
+};
+
+struct fman_port_params {
+ uint32_t dflt_fqid; /* Must not be 0 */
+ uint32_t err_fqid;
+ union {
+ struct {
+ int num_pools;
+ struct fman_port_buffer_pool bpools[FMAN_PORT_MAX_POOLS];
+ } rx_params;
+ struct {
+ } tx_params;
+ };
+};
+
+#endif
diff --git a/sys/dev/dpaa/fman_port_if.m b/sys/dev/dpaa/fman_port_if.m
new file mode 100644
index 000000000000..fe6159340c2c
--- /dev/null
+++ b/sys/dev/dpaa/fman_port_if.m
@@ -0,0 +1,33 @@
+#
+# Copyright (c) 2026 Justin Hibbits
+#
+# SPDX-License-Identifier: BSD-2-Clause
+
+#include <machine/bus.h>
+#include <dev/dpaa/fman_port.h>
+
+/**
+ * @brief DPAA FMan Port interface
+ *
+ */
+INTERFACE fman_port;
+
+/**
+ * @brief Configure the port for a specific purpose
+ */
+METHOD int config {
+ device_t dev;
+ struct fman_port_params *params;
+};
+
+METHOD int init {
+ device_t dev;
+};
+
+METHOD int disable {
+ device_t dev;
+};
+
+METHOD int enable {
+ device_t dev;
+};
diff --git a/sys/dev/dpaa/fman_xmdio.c b/sys/dev/dpaa/fman_xmdio.c
new file mode 100644
index 000000000000..521c30860dc5
--- /dev/null
+++ b/sys/dev/dpaa/fman_xmdio.c
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2026 Justin Hibbits
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/resource.h>
+#include <sys/socket.h>
+
+#include <machine/bus.h>
+
+#include <net/if.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+#include <net/if_var.h>
+
+#include <dev/mdio/mdio.h>
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "fman.h"
+#include "miibus_if.h"
+#include "mdio_if.h"
+
+#define MDIO_LOCK() mtx_lock(&sc->sc_lock)
+#define MDIO_UNLOCK() mtx_unlock(&sc->sc_lock)
+#define MDIO_WRITE4(sc, r, v) \
+ bus_write_4(sc->sc_res, r, v)
+#define MDIO_READ4(sc, r) \
+ bus_read_4(sc->sc_res, r)
+
+#define MDIO_CFG 0x30
+#define CFG_ENC45 0x00000040
+#define MDIO_STAT 0x30
+#define STAT_BUSY 0x80000000
+#define STAT_MDIO_RD_ER 0x00000002
+#define MDIO_CTL 0x34
+#define CTL_READ 0x00008000
+#define MDIO_DATA 0x38
+#define MDIO_ADDR 0x3c
+
+static int xmdio_fdt_probe(device_t dev);
+static int xmdio_fdt_attach(device_t dev);
+static int xmdio_detach(device_t dev);
+static int xmdio_miibus_readreg(device_t dev, int phy, int reg);
+static int xmdio_miibus_writereg(device_t dev, int phy, int reg, int value);
+static int xmdio_mdio_readextreg(device_t dev, int phy, int devad, int reg);
+static int xmdio_mdio_writeextreg(device_t dev, int phy, int devad, int reg,
+ int val);
+
+struct xmdio_softc {
+ struct mtx sc_lock;
+ struct resource *sc_res;
+};
+
+static struct ofw_compat_data mdio_compat_data[] = {
+ {"fsl,fman-memac-mdio", 0},
+ {"fsl,fman-xmdio", 0},
+ {NULL, 0}
+};
+
+static device_method_t xmdio_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, xmdio_fdt_probe),
+ DEVMETHOD(device_attach, xmdio_fdt_attach),
+ DEVMETHOD(device_detach, xmdio_detach),
+ DEVMETHOD(bus_add_child, bus_generic_add_child),
+
+ /* MII interface */
+ DEVMETHOD(miibus_readreg, xmdio_miibus_readreg),
+ DEVMETHOD(miibus_writereg, xmdio_miibus_writereg),
+
+ /* MDIO interface */
+ DEVMETHOD(mdio_readreg, xmdio_miibus_readreg),
+ DEVMETHOD(mdio_writereg, xmdio_miibus_writereg),
+ DEVMETHOD(mdio_readextreg, xmdio_mdio_readextreg),
+ DEVMETHOD(mdio_writeextreg, xmdio_mdio_writeextreg),
+
+ DEVMETHOD_END
+};
+
+static driver_t xmdio_driver = {
+ "xmdio",
+ xmdio_methods,
+ sizeof(struct xmdio_softc),
+};
+
+EARLY_DRIVER_MODULE(xmdio, fman, xmdio_driver, 0, 0,
+ BUS_PASS_SUPPORTDEV);
+DRIVER_MODULE(miibus, xmdio, miibus_driver, 0, 0);
+DRIVER_MODULE(mdio, xmdio, mdio_driver, 0, 0);
+MODULE_DEPEND(xmdio, miibus, 1, 1, 1);
+
+static int
+xmdio_fdt_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_search_compatible(dev, mdio_compat_data)->ocd_str)
+ return (ENXIO);
+
+ device_set_desc(dev, "Freescale XGMAC MDIO");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+xmdio_fdt_attach(device_t dev)
+{
+ struct xmdio_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 0, RF_ACTIVE);
+
+ OF_device_register_xref(OF_xref_from_node(ofw_bus_get_node(dev)), dev);
+
+ mtx_init(&sc->sc_lock, device_get_nameunit(dev), "XMDIO lock",
+ MTX_DEF);
+
+ return (0);
+}
+
+static int
+xmdio_detach(device_t dev)
+{
+ struct xmdio_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ mtx_destroy(&sc->sc_lock);
+
+ return (0);
+}
+
+static void
+set_clause45(struct xmdio_softc *sc)
+{
+ uint32_t reg;
+
+ reg = MDIO_READ4(sc, MDIO_CFG);
+ MDIO_WRITE4(sc, MDIO_CFG, reg | CFG_ENC45);
+}
+
+static void
+set_clause22(struct xmdio_softc *sc)
+{
+ uint32_t reg;
+
+ reg = MDIO_READ4(sc, MDIO_CFG);
+ MDIO_WRITE4(sc, MDIO_CFG, reg & ~CFG_ENC45);
+}
+
+static int
+xmdio_wait_no_busy(struct xmdio_softc *sc)
+{
+ uint32_t count, val;
+
+ for (count = 1000; count > 0; count--) {
+ val = MDIO_READ4(sc, MDIO_CFG);
+ if ((val & STAT_BUSY) == 0)
+ break;
+ DELAY(1);
+ }
+
+ if (count == 0)
+ return (0xffff);
+
+ return (0);
+}
+
+int
+xmdio_miibus_readreg(device_t dev, int phy, int reg)
+{
+ struct xmdio_softc *sc;
+ int rv;
+ uint32_t ctl;
+
+ sc = device_get_softc(dev);
+
+ MDIO_LOCK();
+
+ set_clause22(sc);
+ ctl = (phy << 5) | reg;
+ MDIO_WRITE4(sc, MDIO_CTL, ctl | CTL_READ);
+
+ MDIO_READ4(sc, MDIO_CTL);
+
+ if (xmdio_wait_no_busy(sc))
+ rv = 0xffff;
+ else
+ rv = MDIO_READ4(sc, MDIO_DATA);
+
+ MDIO_WRITE4(sc, MDIO_CTL, 0);
+ MDIO_UNLOCK();
+
+ return (rv);
+}
+
+int
+xmdio_miibus_writereg(device_t dev, int phy, int reg, int value)
+{
+ struct xmdio_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ MDIO_LOCK();
+ set_clause22(sc);
+ /* Stop the MII management read cycle */
+ MDIO_WRITE4(sc, MDIO_CTL, (phy << 5) | reg);
+
+ MDIO_WRITE4(sc, MDIO_DATA, value);
+
+ /* Wait till MII management write is complete */
+ xmdio_wait_no_busy(sc);
+ MDIO_UNLOCK();
+
+ return (0);
+}
+
+static int
+xmdio_mdio_readextreg(device_t dev, int phy, int devad, int reg)
+{
+ struct xmdio_softc *sc;
+ int rv;
+ uint32_t ctl;
+
+ sc = device_get_softc(dev);
+
+ MDIO_LOCK();
+
+ set_clause45(sc);
+ ctl = (phy << 5) | devad;
+ MDIO_WRITE4(sc, MDIO_CTL, ctl);
+ MDIO_WRITE4(sc, MDIO_ADDR, reg);
+ xmdio_wait_no_busy(sc);
+ MDIO_WRITE4(sc, MDIO_CTL, ctl | CTL_READ);
+ MDIO_READ4(sc, MDIO_CTL);
+
+ xmdio_wait_no_busy(sc);
+
+ if (MDIO_READ4(sc, MDIO_STAT) & STAT_MDIO_RD_ER)
+ rv = 0xffff;
+ else
+ rv = MDIO_READ4(sc, MDIO_DATA);
+
+ MDIO_WRITE4(sc, MDIO_CTL, 0);
+ MDIO_UNLOCK();
+
+ return (rv);
+}
+
+static int
+xmdio_mdio_writeextreg(device_t dev, int phy, int devad, int reg, int val)
+{
+ struct xmdio_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ MDIO_LOCK();
+ set_clause45(sc);
+ /* Stop the MII management read cycle */
+ MDIO_WRITE4(sc, MDIO_CTL, (phy << 5) | devad);
+
+ MDIO_WRITE4(sc, MDIO_DATA, val);
+
+ /* Wait till MII management write is complete */
+ xmdio_wait_no_busy(sc);
+ MDIO_UNLOCK();
+
+ return (0);
+}
+
diff --git a/sys/dev/dpaa/if_dtsec.c b/sys/dev/dpaa/if_dtsec.c
index a5f9955061a4..0d886abc5345 100644
--- a/sys/dev/dpaa/if_dtsec.c
+++ b/sys/dev/dpaa/if_dtsec.c
@@ -54,184 +54,54 @@
#include "miibus_if.h"
-#include <contrib/ncsw/inc/integrations/dpaa_integration_ext.h>
-#include <contrib/ncsw/inc/Peripherals/fm_mac_ext.h>
-#include <contrib/ncsw/inc/Peripherals/fm_port_ext.h>
-#include <contrib/ncsw/inc/flib/fsl_fman_dtsec.h>
-#include <contrib/ncsw/inc/xx_ext.h>
-
+#include "dpaa_eth.h"
#include "fman.h"
+#include "fman_port.h"
#include "if_dtsec.h"
-#include "if_dtsec_im.h"
-#include "if_dtsec_rm.h"
+
+#include "fman_if.h"
+#include "fman_port_if.h"
#define DTSEC_MIN_FRAME_SIZE 64
#define DTSEC_MAX_FRAME_SIZE 9600
#define DTSEC_REG_MAXFRM 0x110
-#define DTSEC_REG_GADDR(i) (0x0a0 + 4*(i))
+#define DTSEC_REG_IGADDR(i) (0x080 + 4 * (i))
+#define DTSEC_REG_GADDR(i) (0x0a0 + 4 * (i))
-/**
- * @group dTSEC private defines.
- * @{
- */
-/**
- * dTSEC FMan MAC exceptions info struct.
- */
-struct dtsec_fm_mac_ex_str {
- const int num;
- const char *str;
-};
-/** @} */
+#define DTSEC_ECNTRL 0x014
+#define ECNTRL_R100M 0x00000008
+#define DTSEC_TCTRL 0x040
+#define TCTRL_GTS 0x00000020
+#define DTSEC_RCTRL 0x050
+#define RCTRL_CFA 0x00008000
+#define RCTRL_GHTX 0x00000400
+#define RCTRL_GRS 0x00000020
+#define RCTRL_MPROM 0x00000008
+#define DTSEC_MACCFG1 0x100
+#define DTSEC_MACCFG2 0x104
+#define MACCFG_IF_M 0x00000300
+#define MACCFG_IF_10_100 0x00000100
+#define MACCFG_IF_1G 0x00000200
+#define MACCFG_FULLDUPLEX 0x00000001
+#define DTSEC_MACSTNADDR1 0x140
+#define DTSEC_MACSTNADDR2 0x144
+static void dtsec_if_init_locked(struct dtsec_softc *sc);
/**
* @group FMan MAC routines.
* @{
*/
-#define DTSEC_MAC_EXCEPTIONS_END (-1)
-
-/**
- * FMan MAC exceptions.
- */
-static const struct dtsec_fm_mac_ex_str dtsec_fm_mac_exceptions[] = {
- { e_FM_MAC_EX_10G_MDIO_SCAN_EVENTMDIO, "MDIO scan event" },
- { e_FM_MAC_EX_10G_MDIO_CMD_CMPL, "MDIO command completion" },
- { e_FM_MAC_EX_10G_REM_FAULT, "Remote fault" },
- { e_FM_MAC_EX_10G_LOC_FAULT, "Local fault" },
- { e_FM_MAC_EX_10G_1TX_ECC_ER, "Transmit frame ECC error" },
- { e_FM_MAC_EX_10G_TX_FIFO_UNFL, "Transmit FIFO underflow" },
- { e_FM_MAC_EX_10G_TX_FIFO_OVFL, "Receive FIFO overflow" },
- { e_FM_MAC_EX_10G_TX_ER, "Transmit frame error" },
- { e_FM_MAC_EX_10G_RX_FIFO_OVFL, "Receive FIFO overflow" },
- { e_FM_MAC_EX_10G_RX_ECC_ER, "Receive frame ECC error" },
- { e_FM_MAC_EX_10G_RX_JAB_FRM, "Receive jabber frame" },
- { e_FM_MAC_EX_10G_RX_OVRSZ_FRM, "Receive oversized frame" },
- { e_FM_MAC_EX_10G_RX_RUNT_FRM, "Receive runt frame" },
- { e_FM_MAC_EX_10G_RX_FRAG_FRM, "Receive fragment frame" },
- { e_FM_MAC_EX_10G_RX_LEN_ER, "Receive payload length error" },
- { e_FM_MAC_EX_10G_RX_CRC_ER, "Receive CRC error" },
- { e_FM_MAC_EX_10G_RX_ALIGN_ER, "Receive alignment error" },
- { e_FM_MAC_EX_1G_BAB_RX, "Babbling receive error" },
- { e_FM_MAC_EX_1G_RX_CTL, "Receive control (pause frame) interrupt" },
- { e_FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET, "Graceful transmit stop "
- "complete" },
- { e_FM_MAC_EX_1G_BAB_TX, "Babbling transmit error" },
- { e_FM_MAC_EX_1G_TX_CTL, "Transmit control (pause frame) interrupt" },
- { e_FM_MAC_EX_1G_TX_ERR, "Transmit error" },
- { e_FM_MAC_EX_1G_LATE_COL, "Late collision" },
- { e_FM_MAC_EX_1G_COL_RET_LMT, "Collision retry limit" },
- { e_FM_MAC_EX_1G_TX_FIFO_UNDRN, "Transmit FIFO underrun" },
- { e_FM_MAC_EX_1G_MAG_PCKT, "Magic Packet detected when dTSEC is in "
- "Magic Packet detection mode" },
- { e_FM_MAC_EX_1G_MII_MNG_RD_COMPLET, "MII management read completion" },
- { e_FM_MAC_EX_1G_MII_MNG_WR_COMPLET, "MII management write completion" },
- { e_FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET, "Graceful receive stop "
- "complete" },
- { e_FM_MAC_EX_1G_TX_DATA_ERR, "Internal data error on transmit" },
- { e_FM_MAC_EX_1G_RX_DATA_ERR, "Internal data error on receive" },
- { e_FM_MAC_EX_1G_1588_TS_RX_ERR, "Time-Stamp Receive Error" },
- { e_FM_MAC_EX_1G_RX_MIB_CNT_OVFL, "MIB counter overflow" },
- { DTSEC_MAC_EXCEPTIONS_END, "" }
-};
-
-static const char *
-dtsec_fm_mac_ex_to_str(e_FmMacExceptions exception)
-{
- int i;
-
- for (i = 0; dtsec_fm_mac_exceptions[i].num != exception &&
- dtsec_fm_mac_exceptions[i].num != DTSEC_MAC_EXCEPTIONS_END; ++i)
- ;
-
- if (dtsec_fm_mac_exceptions[i].num == DTSEC_MAC_EXCEPTIONS_END)
- return ("<Unknown Exception>");
-
- return (dtsec_fm_mac_exceptions[i].str);
-}
-
-static void
-dtsec_fm_mac_mdio_event_callback(t_Handle h_App,
- e_FmMacExceptions exception)
-{
- struct dtsec_softc *sc;
-
- sc = h_App;
- device_printf(sc->sc_dev, "MDIO event %i: %s.\n", exception,
- dtsec_fm_mac_ex_to_str(exception));
-}
-
-static void
-dtsec_fm_mac_exception_callback(t_Handle app, e_FmMacExceptions exception)
-{
- struct dtsec_softc *sc;
-
- sc = app;
- device_printf(sc->sc_dev, "MAC exception %i: %s.\n", exception,
- dtsec_fm_mac_ex_to_str(exception));
-}
-
-static void
-dtsec_fm_mac_free(struct dtsec_softc *sc)
-{
- if (sc->sc_mach == NULL)
- return;
-
- FM_MAC_Disable(sc->sc_mach, e_COMM_MODE_RX_AND_TX);
- FM_MAC_Free(sc->sc_mach);
- sc->sc_mach = NULL;
-}
static int
dtsec_fm_mac_init(struct dtsec_softc *sc, uint8_t *mac)
{
- t_FmMacParams params;
- t_Error error;
-
- memset(&params, 0, sizeof(params));
- memcpy(&params.addr, mac, sizeof(params.addr));
-
- params.baseAddr = rman_get_bushandle(sc->sc_mem);
- params.enetMode = sc->sc_mac_enet_mode;
- params.macId = sc->sc_eth_id;
- params.mdioIrq = sc->sc_mac_mdio_irq;
- params.f_Event = dtsec_fm_mac_mdio_event_callback;
- params.f_Exception = dtsec_fm_mac_exception_callback;
- params.h_App = sc;
- params.h_Fm = sc->sc_fmh;
+ FMAN_GET_REVISION(device_get_parent(sc->sc_base.sc_dev), &sc->sc_base.sc_rev_major,
+ &sc->sc_base.sc_rev_minor);
- sc->sc_mach = FM_MAC_Config(&params);
- if (sc->sc_mach == NULL) {
- device_printf(sc->sc_dev, "couldn't configure FM_MAC module.\n"
- );
+ if (FMAN_RESET_MAC(device_get_parent(sc->sc_base.sc_dev), sc->sc_base.sc_eth_id) != 0)
return (ENXIO);
- }
-
- error = FM_MAC_ConfigResetOnInit(sc->sc_mach, TRUE);
- if (error != E_OK) {
- device_printf(sc->sc_dev, "couldn't enable reset on init "
- "feature.\n");
- dtsec_fm_mac_free(sc);
- return (ENXIO);
- }
-
- /* Do not inform about pause frames */
- error = FM_MAC_ConfigException(sc->sc_mach, e_FM_MAC_EX_1G_RX_CTL,
- FALSE);
- if (error != E_OK) {
- device_printf(sc->sc_dev, "couldn't disable pause frames "
- "exception.\n");
- dtsec_fm_mac_free(sc);
- return (ENXIO);
- }
-
- error = FM_MAC_Init(sc->sc_mach);
- if (error != E_OK) {
- device_printf(sc->sc_dev, "couldn't initialize FM_MAC module."
- "\n");
- dtsec_fm_mac_free(sc);
- return (ENXIO);
- }
return (0);
}
@@ -239,87 +109,6 @@ dtsec_fm_mac_init(struct dtsec_softc *sc, uint8_t *mac)
/**
- * @group FMan PORT routines.
- * @{
- */
-static const char *
-dtsec_fm_port_ex_to_str(e_FmPortExceptions exception)
-{
-
- switch (exception) {
- case e_FM_PORT_EXCEPTION_IM_BUSY:
- return ("IM: RX busy");
- default:
- return ("<Unknown Exception>");
- }
-}
-
-void
-dtsec_fm_port_rx_exception_callback(t_Handle app,
- e_FmPortExceptions exception)
-{
- struct dtsec_softc *sc;
-
- sc = app;
- device_printf(sc->sc_dev, "RX exception: %i: %s.\n", exception,
- dtsec_fm_port_ex_to_str(exception));
-}
-
-void
-dtsec_fm_port_tx_exception_callback(t_Handle app,
- e_FmPortExceptions exception)
-{
- struct dtsec_softc *sc;
-
- sc = app;
- device_printf(sc->sc_dev, "TX exception: %i: %s.\n", exception,
- dtsec_fm_port_ex_to_str(exception));
-}
-
-e_FmPortType
-dtsec_fm_port_rx_type(enum eth_dev_type type)
-{
- switch (type) {
- case ETH_DTSEC:
- return (e_FM_PORT_TYPE_RX);
- case ETH_10GSEC:
- return (e_FM_PORT_TYPE_RX_10G);
- default:
- return (e_FM_PORT_TYPE_DUMMY);
- }
-}
-
-e_FmPortType
-dtsec_fm_port_tx_type(enum eth_dev_type type)
-{
-
- switch (type) {
- case ETH_DTSEC:
- return (e_FM_PORT_TYPE_TX);
- case ETH_10GSEC:
- return (e_FM_PORT_TYPE_TX_10G);
- default:
- return (e_FM_PORT_TYPE_DUMMY);
- }
-}
-
-static void
-dtsec_fm_port_free_both(struct dtsec_softc *sc)
-{
- if (sc->sc_rxph) {
- FM_PORT_Free(sc->sc_rxph);
- sc->sc_rxph = NULL;
- }
-
- if (sc->sc_txph) {
- FM_PORT_Free(sc->sc_txph);
- sc->sc_txph = NULL;
- }
-}
-/** @} */
-
-
-/**
* @group IFnet routines.
* @{
*/
@@ -332,7 +121,7 @@ dtsec_set_mtu(struct dtsec_softc *sc, unsigned int mtu)
DTSEC_LOCK_ASSERT(sc);
if (mtu >= DTSEC_MIN_FRAME_SIZE && mtu <= DTSEC_MAX_FRAME_SIZE) {
- bus_write_4(sc->sc_mem, DTSEC_REG_MAXFRM, mtu);
+ bus_write_4(sc->sc_base.sc_mem, DTSEC_REG_MAXFRM, mtu);
return (mtu);
}
@@ -342,9 +131,10 @@ dtsec_set_mtu(struct dtsec_softc *sc, unsigned int mtu)
static u_int
dtsec_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
{
- struct dtsec_softc *sc = arg;
+ uint32_t h, *hashtable = arg;
- FM_MAC_AddHashMacAddr(sc->sc_mach, (t_EnetAddr *)LLADDR(sdl));
+ h = (ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN) >> 24) & 0xFF;
+ hashtable[(h >> 5)] |= 1 << (0x1F - (h & 0x1F));
return (1);
}
@@ -352,18 +142,52 @@ dtsec_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
static void
dtsec_setup_multicast(struct dtsec_softc *sc)
{
+ uint32_t hashtable[8] = {};
int i;
- if (if_getflags(sc->sc_ifnet) & IFF_ALLMULTI) {
+ if (if_getflags(sc->sc_base.sc_ifnet) & IFF_ALLMULTI) {
for (i = 0; i < 8; i++)
- bus_write_4(sc->sc_mem, DTSEC_REG_GADDR(i), 0xFFFFFFFF);
+ bus_write_4(sc->sc_base.sc_mem, DTSEC_REG_GADDR(i), 0xFFFFFFFF);
+ bus_write_4(sc->sc_base.sc_mem, DTSEC_RCTRL,
+ bus_read_4(sc->sc_base.sc_mem, DTSEC_RCTRL) | RCTRL_MPROM);
return;
}
+ bus_write_4(sc->sc_base.sc_mem, DTSEC_RCTRL,
+ bus_read_4(sc->sc_base.sc_mem, DTSEC_RCTRL) & ~RCTRL_MPROM);
+
+ if_foreach_llmaddr(sc->sc_base.sc_ifnet, dtsec_hash_maddr, hashtable);
+ for (i = 0; i < 8; i++)
+ bus_write_4(sc->sc_base.sc_mem, DTSEC_REG_GADDR(i),
+ hashtable[i]);
+}
+
+static void
+dtsec_if_graceful_stop(struct dtsec_softc *sc)
+{
+ bus_write_4(sc->sc_base.sc_mem, DTSEC_RCTRL,
+ bus_read_4(sc->sc_base.sc_mem, DTSEC_RCTRL) | RCTRL_GRS);
+ if (sc->sc_base.sc_rev_major == 2)
+ DELAY(100);
+ else
+ DELAY(10);
- fman_dtsec_reset_filter_table(rman_get_virtual(sc->sc_mem),
- true, false);
- if_foreach_llmaddr(sc->sc_ifnet, dtsec_hash_maddr, sc);
+ bus_write_4(sc->sc_base.sc_mem, DTSEC_TCTRL,
+ bus_read_4(sc->sc_base.sc_mem, DTSEC_TCTRL) | TCTRL_GTS);
+}
+
+static void
+dtsec_if_graceful_start(struct dtsec_softc *sc)
+{
+ bus_write_4(sc->sc_base.sc_mem, DTSEC_RCTRL,
+ bus_read_4(sc->sc_base.sc_mem, DTSEC_RCTRL) & ~RCTRL_GRS);
+ if (sc->sc_base.sc_rev_major == 2)
+ DELAY(100);
+ else
+ DELAY(10);
+
+ bus_write_4(sc->sc_base.sc_mem, DTSEC_TCTRL,
+ bus_read_4(sc->sc_base.sc_mem, DTSEC_TCTRL) & ~TCTRL_GTS);
}
static int
@@ -373,24 +197,22 @@ dtsec_if_enable_locked(struct dtsec_softc *sc)
DTSEC_LOCK_ASSERT(sc);
- error = FM_MAC_Enable(sc->sc_mach, e_COMM_MODE_RX_AND_TX);
- if (error != E_OK)
- return (EIO);
+ dtsec_if_graceful_start(sc);
- error = FM_PORT_Enable(sc->sc_rxph);
- if (error != E_OK)
+ error = FMAN_PORT_ENABLE(sc->sc_base.sc_rx_port);
+ if (error != 0)
return (EIO);
- error = FM_PORT_Enable(sc->sc_txph);
- if (error != E_OK)
+ error = FMAN_PORT_ENABLE(sc->sc_base.sc_tx_port);
+ if (error != 0)
return (EIO);
dtsec_setup_multicast(sc);
- if_setdrvflagbits(sc->sc_ifnet, IFF_DRV_RUNNING, 0);
+ if_setdrvflagbits(sc->sc_base.sc_ifnet, IFF_DRV_RUNNING, 0);
/* Refresh link state */
- dtsec_miibus_statchg(sc->sc_dev);
+ dtsec_miibus_statchg(sc->sc_base.sc_dev);
return (0);
}
@@ -402,19 +224,17 @@ dtsec_if_disable_locked(struct dtsec_softc *sc)
DTSEC_LOCK_ASSERT(sc);
- error = FM_MAC_Disable(sc->sc_mach, e_COMM_MODE_RX_AND_TX);
- if (error != E_OK)
- return (EIO);
+ dtsec_if_graceful_stop(sc);
- error = FM_PORT_Disable(sc->sc_rxph);
- if (error != E_OK)
+ error = FMAN_PORT_DISABLE(sc->sc_base.sc_rx_port);
+ if (error != 0)
return (EIO);
- error = FM_PORT_Disable(sc->sc_txph);
- if (error != E_OK)
+ error = FMAN_PORT_DISABLE(sc->sc_base.sc_tx_port);
+ if (error != 0)
return (EIO);
- if_setdrvflagbits(sc->sc_ifnet, 0, IFF_DRV_RUNNING);
+ if_setdrvflagbits(sc->sc_base.sc_ifnet, 0, IFF_DRV_RUNNING);
return (0);
}
@@ -443,9 +263,10 @@ dtsec_if_ioctl(if_t ifp, u_long command, caddr_t data)
case SIOCSIFFLAGS:
DTSEC_LOCK(sc);
- if (if_getflags(sc->sc_ifnet) & IFF_UP)
- error = dtsec_if_enable_locked(sc);
- else
+ if (if_getflags(ifp) & IFF_UP) {
+ if (!(if_getdrvflags(ifp) & IFF_DRV_RUNNING))
+ dtsec_if_init_locked(sc);
+ } else
error = dtsec_if_disable_locked(sc);
DTSEC_UNLOCK(sc);
@@ -453,7 +274,7 @@ dtsec_if_ioctl(if_t ifp, u_long command, caddr_t data)
case SIOCGIFMEDIA:
case SIOCSIFMEDIA:
- error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii->mii_media,
+ error = ifmedia_ioctl(ifp, ifr, &sc->sc_base.sc_mii->mii_media,
command);
break;
@@ -474,8 +295,8 @@ dtsec_if_tick(void *arg)
/* TODO */
DTSEC_LOCK(sc);
- mii_tick(sc->sc_mii);
- callout_reset(&sc->sc_tick_callout, hz, dtsec_if_tick, sc);
+ mii_tick(sc->sc_base.sc_mii);
+ callout_reset(&sc->sc_base.sc_tick_callout, hz, dtsec_if_tick, sc);
DTSEC_UNLOCK(sc);
}
@@ -487,30 +308,38 @@ dtsec_if_deinit_locked(struct dtsec_softc *sc)
DTSEC_LOCK_ASSERT(sc);
DTSEC_UNLOCK(sc);
- callout_drain(&sc->sc_tick_callout);
+ callout_drain(&sc->sc_base.sc_tick_callout);
DTSEC_LOCK(sc);
}
static void
+dtsec_if_set_macaddr(struct dtsec_softc *sc, const char *addr)
+{
+ uint32_t reg;
+
+ reg = (addr[5] << 24) | (addr[4] << 16) | (addr[3] << 8) | addr[2];
+ bus_write_4(sc->sc_base.sc_mem, DTSEC_MACSTNADDR1, reg);
+ reg = (addr[1] << 24) | (addr[0] << 16);
+ bus_write_4(sc->sc_base.sc_mem, DTSEC_MACSTNADDR2, reg);
+}
+
+static void
dtsec_if_init_locked(struct dtsec_softc *sc)
{
int error;
+ const char *macaddr;
DTSEC_LOCK_ASSERT(sc);
- /* Set MAC address */
- error = FM_MAC_ModifyMacAddr(sc->sc_mach,
- (t_EnetAddr *)if_getlladdr(sc->sc_ifnet));
- if (error != E_OK) {
- device_printf(sc->sc_dev, "couldn't set MAC address.\n");
- goto err;
- }
+ macaddr = if_getlladdr(sc->sc_base.sc_ifnet);
+ dtsec_if_set_macaddr(sc, macaddr);
/* Start MII polling */
- if (sc->sc_mii)
- callout_reset(&sc->sc_tick_callout, hz, dtsec_if_tick, sc);
+ if (sc->sc_base.sc_mii)
+ callout_reset(&sc->sc_base.sc_tick_callout, hz,
+ dtsec_if_tick, sc);
- if (if_getflags(sc->sc_ifnet) & IFF_UP) {
+ if (if_getflags(sc->sc_base.sc_ifnet) & IFF_UP) {
error = dtsec_if_enable_locked(sc);
if (error != 0)
goto err;
@@ -524,7 +353,7 @@ dtsec_if_init_locked(struct dtsec_softc *sc)
err:
dtsec_if_deinit_locked(sc);
- device_printf(sc->sc_dev, "initialization error.\n");
+ device_printf(sc->sc_base.sc_dev, "initialization error.\n");
return;
}
@@ -547,7 +376,7 @@ dtsec_if_start(if_t ifp)
sc = if_getsoftc(ifp);
DTSEC_LOCK(sc);
- sc->sc_start_locked(sc);
+ dpaa_eth_if_start_locked(&sc->sc_base);
DTSEC_UNLOCK(sc);
}
@@ -569,7 +398,7 @@ dtsec_ifmedia_upd(if_t ifp)
struct dtsec_softc *sc = if_getsoftc(ifp);
DTSEC_LOCK(sc);
- mii_mediachg(sc->sc_mii);
+ mii_mediachg(sc->sc_base.sc_mii);
DTSEC_UNLOCK(sc);
return (0);
@@ -582,10 +411,10 @@ dtsec_ifmedia_sts(if_t ifp, struct ifmediareq *ifmr)
DTSEC_LOCK(sc);
- mii_pollstat(sc->sc_mii);
+ mii_pollstat(sc->sc_base.sc_mii);
- ifmr->ifm_active = sc->sc_mii->mii_media_active;
- ifmr->ifm_status = sc->sc_mii->mii_media_status;
+ ifmr->ifm_active = sc->sc_base.sc_mii->mii_media_active;
+ ifmr->ifm_status = sc->sc_base.sc_mii->mii_media_status;
DTSEC_UNLOCK(sc);
}
@@ -596,118 +425,75 @@ dtsec_ifmedia_sts(if_t ifp, struct ifmediareq *ifmr)
* @group dTSEC bus interface.
* @{
*/
-static void
-dtsec_configure_mode(struct dtsec_softc *sc)
-{
- char tunable[64];
-
- snprintf(tunable, sizeof(tunable), "%s.independent_mode",
- device_get_nameunit(sc->sc_dev));
-
- sc->sc_mode = DTSEC_MODE_REGULAR;
- TUNABLE_INT_FETCH(tunable, &sc->sc_mode);
-
- if (sc->sc_mode == DTSEC_MODE_REGULAR) {
- sc->sc_port_rx_init = dtsec_rm_fm_port_rx_init;
- sc->sc_port_tx_init = dtsec_rm_fm_port_tx_init;
- sc->sc_start_locked = dtsec_rm_if_start_locked;
- } else {
- sc->sc_port_rx_init = dtsec_im_fm_port_rx_init;
- sc->sc_port_tx_init = dtsec_im_fm_port_tx_init;
- sc->sc_start_locked = dtsec_im_if_start_locked;
- }
-
- device_printf(sc->sc_dev, "Configured for %s mode.\n",
- (sc->sc_mode == DTSEC_MODE_REGULAR) ? "regular" : "independent");
-}
int
dtsec_attach(device_t dev)
{
struct dtsec_softc *sc;
- device_t parent;
+ cell_t ports[2];
+ phandle_t node;
int error;
if_t ifp;
sc = device_get_softc(dev);
- parent = device_get_parent(dev);
- sc->sc_dev = dev;
- sc->sc_mac_mdio_irq = NO_IRQ;
-
- /* Check if MallocSmart allocator is ready */
- if (XX_MallocSmartInit() != E_OK)
- return (ENXIO);
+ sc->sc_base.sc_dev = dev;
+ node = ofw_bus_get_node(dev);
/* Init locks */
- mtx_init(&sc->sc_lock, device_get_nameunit(dev),
+ mtx_init(&sc->sc_base.sc_lock, device_get_nameunit(dev),
"DTSEC Global Lock", MTX_DEF);
- mtx_init(&sc->sc_mii_lock, device_get_nameunit(dev),
+ mtx_init(&sc->sc_base.sc_mii_lock, device_get_nameunit(dev),
"DTSEC MII Lock", MTX_DEF);
/* Init callouts */
- callout_init(&sc->sc_tick_callout, CALLOUT_MPSAFE);
+ callout_init(&sc->sc_base.sc_tick_callout, CALLOUT_MPSAFE);
- /* Read configuraton */
- if ((error = fman_get_handle(parent, &sc->sc_fmh)) != 0)
- return (error);
-
- if ((error = fman_get_muram_handle(parent, &sc->sc_muramh)) != 0)
- return (error);
-
- if ((error = fman_get_bushandle(parent, &sc->sc_fm_base)) != 0)
- return (error);
-
- /* Configure working mode */
- dtsec_configure_mode(sc);
+ /* Create RX buffer pool */
+ error = dpaa_eth_pool_rx_init(&sc->sc_base);
+ if (error != 0)
+ return (EIO);
- /* If we are working in regular mode configure BMAN and QMAN */
- if (sc->sc_mode == DTSEC_MODE_REGULAR) {
- /* Create RX buffer pool */
- error = dtsec_rm_pool_rx_init(sc);
- if (error != 0)
- return (EIO);
+ /* Create RX frame queue range */
+ error = dpaa_eth_fq_rx_init(&sc->sc_base);
+ if (error != 0)
+ return (EIO);
- /* Create RX frame queue range */
- error = dtsec_rm_fqr_rx_init(sc);
- if (error != 0)
- return (EIO);
+ /* Create frame info pool */
+ error = dpaa_eth_fi_pool_init(&sc->sc_base);
+ if (error != 0)
+ return (EIO);
- /* Create frame info pool */
- error = dtsec_rm_fi_pool_init(sc);
- if (error != 0)
- return (EIO);
+ /* Create TX frame queue range */
+ error = dpaa_eth_fq_tx_init(&sc->sc_base);
+ if (error != 0)
+ return (EIO);
- /* Create TX frame queue range */
- error = dtsec_rm_fqr_tx_init(sc);
- if (error != 0)
- return (EIO);
+ if (OF_getencprop(node, "fsl,fman-ports", ports, sizeof(ports)) < 0) {
+ device_printf(dev, "missing ports in device tree\n");
+ return (ENXIO);
}
-
/* Init FMan MAC module. */
- error = dtsec_fm_mac_init(sc, sc->sc_mac_addr);
+ error = dtsec_fm_mac_init(sc, sc->sc_base.sc_mac_addr);
if (error != 0) {
dtsec_detach(dev);
return (ENXIO);
}
- /* Init FMan TX port */
- error = sc->sc_port_tx_init(sc, device_get_unit(sc->sc_dev));
- if (error != 0) {
- dtsec_detach(dev);
- return (ENXIO);
- }
+ sc->sc_base.sc_rx_port = OF_device_from_xref(ports[0]);
+ sc->sc_base.sc_tx_port = OF_device_from_xref(ports[1]);
+ dpaa_eth_fm_port_rx_init(&sc->sc_base);
+ dpaa_eth_fm_port_tx_init(&sc->sc_base);
- /* Init FMan RX port */
- error = sc->sc_port_rx_init(sc, device_get_unit(sc->sc_dev));
- if (error != 0) {
+ if (sc->sc_base.sc_rx_port == NULL || sc->sc_base.sc_tx_port == NULL) {
+ device_printf(dev, "invalid ports");
dtsec_detach(dev);
return (ENXIO);
}
/* Create network interface for upper layers */
- ifp = sc->sc_ifnet = if_alloc(IFT_ETHER);
+ ifp = sc->sc_base.sc_ifnet = if_alloc(IFT_ETHER);
if_setsoftc(ifp, sc);
if_setflags(ifp, IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST);
@@ -716,11 +502,12 @@ dtsec_attach(device_t dev)
if_setioctlfn(ifp, dtsec_if_ioctl);
if_setsendqlen(ifp, IFQ_MAXLEN);
- if (sc->sc_phy_addr >= 0)
- if_initname(ifp, device_get_name(sc->sc_dev),
- device_get_unit(sc->sc_dev));
+ if (sc->sc_base.sc_phy_addr >= 0)
+ if_initname(ifp, device_get_name(sc->sc_base.sc_dev),
+ device_get_unit(sc->sc_base.sc_dev));
else
- if_initname(ifp, "dtsec_phy", device_get_unit(sc->sc_dev));
+ if_initname(ifp, "dtsec_phy",
+ device_get_unit(sc->sc_base.sc_dev));
/* TODO */
#if 0
@@ -732,18 +519,18 @@ dtsec_attach(device_t dev)
if_setcapenable(ifp, if_getcapabilities(ifp));
/* Attach PHY(s) */
- error = mii_attach(sc->sc_dev, &sc->sc_mii_dev, ifp, dtsec_ifmedia_upd,
- dtsec_ifmedia_sts, BMSR_DEFCAPMASK, sc->sc_phy_addr,
- MII_OFFSET_ANY, 0);
+ error = mii_attach(sc->sc_base.sc_dev, &sc->sc_base.sc_mii_dev,
+ ifp, dtsec_ifmedia_upd, dtsec_ifmedia_sts, BMSR_DEFCAPMASK,
+ sc->sc_base.sc_phy_addr, MII_OFFSET_ANY, 0);
if (error) {
- device_printf(sc->sc_dev, "attaching PHYs failed: %d\n", error);
- dtsec_detach(sc->sc_dev);
+ device_printf(sc->sc_base.sc_dev,
+ "attaching PHYs failed: %d\n", error);
+ dtsec_detach(sc->sc_base.sc_dev);
return (error);
}
- sc->sc_mii = device_get_softc(sc->sc_mii_dev);
/* Attach to stack */
- ether_ifattach(ifp, sc->sc_mac_addr);
+ ether_ifattach(ifp, sc->sc_base.sc_mac_addr);
return (0);
}
@@ -755,7 +542,7 @@ dtsec_detach(device_t dev)
if_t ifp;
sc = device_get_softc(dev);
- ifp = sc->sc_ifnet;
+ ifp = sc->sc_base.sc_ifnet;
if (device_is_attached(dev)) {
ether_ifdetach(ifp);
@@ -765,28 +552,23 @@ dtsec_detach(device_t dev)
DTSEC_UNLOCK(sc);
}
- if (sc->sc_ifnet) {
- if_free(sc->sc_ifnet);
- sc->sc_ifnet = NULL;
+ if (sc->sc_base.sc_ifnet) {
+ if_free(sc->sc_base.sc_ifnet);
+ sc->sc_base.sc_ifnet = NULL;
}
- if (sc->sc_mode == DTSEC_MODE_REGULAR) {
- /* Free RX/TX FQRs */
- dtsec_rm_fqr_rx_free(sc);
- dtsec_rm_fqr_tx_free(sc);
+ /* Free RX/TX FQRs */
+ dpaa_eth_fq_rx_free(&sc->sc_base);
+ dpaa_eth_fq_tx_free(&sc->sc_base);
- /* Free frame info pool */
- dtsec_rm_fi_pool_free(sc);
+ /* Free frame info pool */
+ dpaa_eth_fi_pool_free(&sc->sc_base);
- /* Free RX buffer pool */
- dtsec_rm_pool_rx_free(sc);
- }
-
- dtsec_fm_mac_free(sc);
- dtsec_fm_port_free_both(sc);
+ /* Free RX buffer pool */
+ dpaa_eth_pool_rx_free(&sc->sc_base);
/* Destroy lock */
- mtx_destroy(&sc->sc_lock);
+ mtx_destroy(&sc->sc_base.sc_lock);
return (0);
}
@@ -825,7 +607,7 @@ dtsec_miibus_readreg(device_t dev, int phy, int reg)
sc = device_get_softc(dev);
- return (MIIBUS_READREG(sc->sc_mdio, phy, reg));
+ return (MIIBUS_READREG(sc->sc_base.sc_mdio, phy, reg));
}
int
@@ -836,43 +618,49 @@ dtsec_miibus_writereg(device_t dev, int phy, int reg, int value)
sc = device_get_softc(dev);
- return (MIIBUS_WRITEREG(sc->sc_mdio, phy, reg, value));
+ return (MIIBUS_WRITEREG(sc->sc_base.sc_mdio, phy, reg, value));
}
void
dtsec_miibus_statchg(device_t dev)
{
struct dtsec_softc *sc;
- e_EnetSpeed speed;
+ uint32_t reg;
bool duplex;
- int error;
+ int speed;
sc = device_get_softc(dev);
DTSEC_LOCK_ASSERT(sc);
- duplex = ((sc->sc_mii->mii_media_active & IFM_GMASK) == IFM_FDX);
+ duplex = ((sc->sc_base.sc_mii->mii_media_active & IFM_GMASK) == IFM_FDX);
- switch (IFM_SUBTYPE(sc->sc_mii->mii_media_active)) {
+ switch (IFM_SUBTYPE(sc->sc_base.sc_mii->mii_media_active)) {
case IFM_1000_T:
case IFM_1000_SX:
- speed = e_ENET_SPEED_1000;
- break;
-
- case IFM_100_TX:
- speed = e_ENET_SPEED_100;
- break;
-
- case IFM_10_T:
- speed = e_ENET_SPEED_10;
+ if (!duplex) {
+ device_printf(sc->sc_base.sc_dev,
+ "Only full-duplex supported for 1Gbps speeds");
+ return;
+ }
+ speed = MACCFG_IF_1G;
break;
default:
- speed = e_ENET_SPEED_10;
+ speed = MACCFG_IF_10_100;
}
- error = FM_MAC_AdjustLink(sc->sc_mach, speed, duplex);
- if (error != E_OK)
- device_printf(sc->sc_dev, "error while adjusting MAC speed.\n");
+ reg = bus_read_4(sc->sc_base.sc_mem, DTSEC_MACCFG2);
+ reg &= ~(MACCFG_IF_M | MACCFG_FULLDUPLEX);
+
+ if (duplex)
+ reg |= MACCFG_FULLDUPLEX;
+ reg |= speed;
+ bus_write_4(sc->sc_base.sc_mem, DTSEC_MACCFG2, reg);
+
+ reg = bus_read_4(sc->sc_base.sc_mem, DTSEC_ECNTRL) & ~ECNTRL_R100M;
+ if (IFM_SUBTYPE(sc->sc_base.sc_mii->mii_media_active) == IFM_100_TX)
+ reg |= ECNTRL_R100M;
+ bus_write_4(sc->sc_base.sc_mem, DTSEC_ECNTRL, reg);
}
/** @} */
diff --git a/sys/dev/dpaa/if_dtsec.h b/sys/dev/dpaa/if_dtsec.h
index 4de0b776e9f5..7e0cb52a2400 100644
--- a/sys/dev/dpaa/if_dtsec.h
+++ b/sys/dev/dpaa/if_dtsec.h
@@ -34,11 +34,11 @@
#define DTSEC_MODE_REGULAR 0
#define DTSEC_MODE_INDEPENDENT 1
-#define DTSEC_LOCK(sc) mtx_lock(&(sc)->sc_lock)
-#define DTSEC_UNLOCK(sc) mtx_unlock(&(sc)->sc_lock)
-#define DTSEC_LOCK_ASSERT(sc) mtx_assert(&(sc)->sc_lock, MA_OWNED)
-#define DTSEC_MII_LOCK(sc) mtx_lock(&(sc)->sc_mii_lock)
-#define DTSEC_MII_UNLOCK(sc) mtx_unlock(&(sc)->sc_mii_lock)
+#define DTSEC_LOCK(sc) mtx_lock(&(sc)->sc_base.sc_lock)
+#define DTSEC_UNLOCK(sc) mtx_unlock(&(sc)->sc_base.sc_lock)
+#define DTSEC_LOCK_ASSERT(sc) mtx_assert(&(sc)->sc_base.sc_lock, MA_OWNED)
+#define DTSEC_MII_LOCK(sc) mtx_lock(&(sc)->sc_base.sc_mii_lock)
+#define DTSEC_MII_UNLOCK(sc) mtx_unlock(&(sc)->sc_base.sc_mii_lock)
enum eth_dev_type {
ETH_DTSEC = 0x1,
@@ -46,97 +46,13 @@ enum eth_dev_type {
};
struct dtsec_softc {
- /* XXX MII bus requires that struct ifnet is first!!! */
- if_t sc_ifnet;
-
- device_t sc_dev;
- struct resource *sc_mem;
- struct mtx sc_lock;
- int sc_mode;
-
- /* Methods */
- int (*sc_port_rx_init)
- (struct dtsec_softc *sc, int unit);
- int (*sc_port_tx_init)
- (struct dtsec_softc *sc, int unit);
- void (*sc_start_locked)
- (struct dtsec_softc *sc);
-
- /* dTSEC data */
+ struct dpaa_eth_softc sc_base;
enum eth_dev_type sc_eth_dev_type;
- uint8_t sc_eth_id; /* Ethernet ID within its frame manager */
- uintptr_t sc_mac_mem_offset;
- e_EnetMode sc_mac_enet_mode;
- int sc_mac_mdio_irq;
- uint8_t sc_mac_addr[6];
- int sc_port_rx_hw_id;
- int sc_port_tx_hw_id;
- uint32_t sc_port_tx_qman_chan;
- int sc_phy_addr;
- bool sc_hidden;
- device_t sc_mdio;
-
- /* Params from fman_bus driver */
- vm_offset_t sc_fm_base;
- t_Handle sc_fmh;
- t_Handle sc_muramh;
-
- t_Handle sc_mach;
- t_Handle sc_rxph;
- t_Handle sc_txph;
-
- /* MII data */
- struct mii_data *sc_mii;
- device_t sc_mii_dev;
- struct mtx sc_mii_lock;
-
- struct callout sc_tick_callout;
-
- /* RX Pool */
- t_Handle sc_rx_pool;
- uint8_t sc_rx_bpid;
- uma_zone_t sc_rx_zone;
- char sc_rx_zname[64];
-
- /* RX Frame Queue */
- t_Handle sc_rx_fqr;
- uint32_t sc_rx_fqid;
-
- /* TX Frame Queue */
- t_Handle sc_tx_fqr;
- bool sc_tx_fqr_full;
- t_Handle sc_tx_conf_fqr;
- uint32_t sc_tx_conf_fqid;
-
- /* Frame Info Zone */
- uma_zone_t sc_fi_zone;
- char sc_fi_zname[64];
};
/** @} */
/**
- * @group dTSEC FMan PORT API.
- * @{
- */
-enum dtsec_fm_port_params {
- FM_PORT_LIODN_BASE = 0,
- FM_PORT_LIODN_OFFSET = 0,
- FM_PORT_MEM_ID = 0,
- FM_PORT_MEM_ATTR = MEMORY_ATTR_CACHEABLE,
- FM_PORT_BUFFER_SIZE = MCLBYTES,
-};
-
-e_FmPortType dtsec_fm_port_rx_type(enum eth_dev_type type);
-void dtsec_fm_port_rx_exception_callback(t_Handle app,
- e_FmPortExceptions exception);
-void dtsec_fm_port_tx_exception_callback(t_Handle app,
- e_FmPortExceptions exception);
-e_FmPortType dtsec_fm_port_tx_type(enum eth_dev_type type);
-/** @} */
-
-
-/**
* @group dTSEC bus interface.
* @{
*/
diff --git a/sys/dev/dpaa/if_dtsec_fdt.c b/sys/dev/dpaa/if_dtsec_fdt.c
index 441ff9c96c50..85b1998015d5 100644
--- a/sys/dev/dpaa/if_dtsec_fdt.c
+++ b/sys/dev/dpaa/if_dtsec_fdt.c
@@ -48,9 +48,7 @@
#include "miibus_if.h"
-#include <contrib/ncsw/inc/Peripherals/fm_port_ext.h>
-#include <contrib/ncsw/inc/xx_ext.h>
-
+#include "dpaa_eth.h"
#include "if_dtsec.h"
#include "fman.h"
@@ -123,7 +121,7 @@ dtsec_fdt_attach(device_t dev)
enet_node = ofw_bus_get_node(dev);
if (OF_getprop(enet_node, "local-mac-address",
- (void *)sc->sc_mac_addr, 6) == -1) {
+ (void *)sc->sc_base.sc_mac_addr, 6) == -1) {
device_printf(dev,
"Could not load local-mac-addr property from DTS\n");
return (ENXIO);
@@ -135,17 +133,17 @@ dtsec_fdt_attach(device_t dev)
else if (ofw_bus_is_compatible(dev, "fsl,fman-xgec") != 0)
sc->sc_eth_dev_type = ETH_10GSEC;
else
- return(ENXIO);
+ return (ENXIO);
/* Get PHY address */
- if (OF_getprop(enet_node, "phy-handle", (void *)&phy_node,
+ if (OF_getprop(enet_node, "tbi-handle", (void *)&phy_node,
sizeof(phy_node)) <= 0)
return (ENXIO);
phy_node = OF_node_from_xref(phy_node);
- if (OF_getprop(phy_node, "reg", (void *)&sc->sc_phy_addr,
- sizeof(sc->sc_phy_addr)) <= 0)
+ if (OF_getprop(phy_node, "reg", (void *)&sc->sc_base.sc_phy_addr,
+ sizeof(sc->sc_base.sc_phy_addr)) <= 0)
return (ENXIO);
phy_dev = OF_device_from_xref(OF_parent(phy_node));
@@ -155,12 +153,12 @@ dtsec_fdt_attach(device_t dev)
return (ENXIO);
}
- sc->sc_mdio = phy_dev;
+ sc->sc_base.sc_mdio = phy_dev;
/* Get MAC memory offset in SoC */
rid = 0;
- sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
- if (sc->sc_mem == NULL)
+ sc->sc_base.sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (sc->sc_base.sc_mem == NULL)
return (ENXIO);
/* Get PHY connection type */
@@ -168,20 +166,10 @@ dtsec_fdt_attach(device_t dev)
sizeof(phy_type)) <= 0)
return (ENXIO);
- if (!strcmp(phy_type, "sgmii"))
- sc->sc_mac_enet_mode = e_ENET_MODE_SGMII_1000;
- else if (!strcmp(phy_type, "rgmii"))
- sc->sc_mac_enet_mode = e_ENET_MODE_RGMII_1000;
- else if (!strcmp(phy_type, "xgmii"))
- /* We set 10 Gigabit mode flag however we don't support it */
- sc->sc_mac_enet_mode = e_ENET_MODE_XGMII_10000;
- else
- return (ENXIO);
-
if (OF_getencprop(enet_node, "cell-index",
(void *)&mac_id, sizeof(mac_id)) <= 0)
return (ENXIO);
- sc->sc_eth_id = mac_id;
+ sc->sc_base.sc_eth_id = mac_id;
/* Get RX/TX port handles */
if (OF_getprop(enet_node, "fsl,fman-ports", (void *)fman_rxtx_node,
@@ -194,32 +182,17 @@ dtsec_fdt_attach(device_t dev)
if (fman_rxtx_node[1] == 0)
return (ENXIO);
- fman_rxtx_node[0] = OF_instance_to_package(fman_rxtx_node[0]);
- fman_rxtx_node[1] = OF_instance_to_package(fman_rxtx_node[1]);
-
- if (ofw_bus_node_is_compatible(fman_rxtx_node[0],
- "fsl,fman-v2-port-rx") == 0)
- return (ENXIO);
-
- if (ofw_bus_node_is_compatible(fman_rxtx_node[1],
- "fsl,fman-v2-port-tx") == 0)
- return (ENXIO);
-
- /* Get RX port HW id */
- if (OF_getprop(fman_rxtx_node[0], "reg", (void *)&sc->sc_port_rx_hw_id,
- sizeof(sc->sc_port_rx_hw_id)) <= 0)
- return (ENXIO);
+ sc->sc_base.sc_rx_port = OF_device_from_xref(fman_rxtx_node[0]);
+ sc->sc_base.sc_tx_port = OF_device_from_xref(fman_rxtx_node[1]);
- /* Get TX port HW id */
- if (OF_getprop(fman_rxtx_node[1], "reg", (void *)&sc->sc_port_tx_hw_id,
- sizeof(sc->sc_port_tx_hw_id)) <= 0)
+ if (sc->sc_base.sc_rx_port == NULL || sc->sc_base.sc_tx_port == NULL)
return (ENXIO);
if (OF_getprop(fman_rxtx_node[1], "cell-index", &fman_tx_cell,
sizeof(fman_tx_cell)) <= 0)
return (ENXIO);
/* Get QMan channel */
- sc->sc_port_tx_qman_chan = fman_qman_channel_id(device_get_parent(dev),
+ sc->sc_base.sc_port_tx_qman_chan = fman_qman_channel_id(device_get_parent(dev),
fman_tx_cell);
return (dtsec_attach(dev));
diff --git a/sys/dev/dpaa/if_dtsec_im.c b/sys/dev/dpaa/if_dtsec_im.c
deleted file mode 100644
index 0711275790c3..000000000000
--- a/sys/dev/dpaa/if_dtsec_im.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/*-
- * Copyright (c) 2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON 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 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/bus.h>
-#include <sys/rman.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/socket.h>
-#include <sys/sysctl.h>
-#include <sys/sockio.h>
-
-#include <net/ethernet.h>
-#include <net/if.h>
-#include <net/if_dl.h>
-#include <net/if_media.h>
-#include <net/if_types.h>
-#include <net/if_arp.h>
-
-#include <dev/mii/mii.h>
-#include <dev/mii/miivar.h>
-
-#include "miibus_if.h"
-
-#include <contrib/ncsw/inc/integrations/dpaa_integration_ext.h>
-#include <contrib/ncsw/inc/Peripherals/fm_mac_ext.h>
-#include <contrib/ncsw/inc/Peripherals/fm_port_ext.h>
-#include <contrib/ncsw/inc/xx_ext.h>
-
-#include "fman.h"
-#include "if_dtsec.h"
-#include "if_dtsec_im.h"
-
-
-/**
- * @group dTSEC FMan PORT routines.
- * @{
- */
-static e_RxStoreResponse
-dtsec_im_fm_port_rx_callback(t_Handle app, uint8_t *data, uint16_t length,
- uint16_t status, uint8_t position, t_Handle buf_context)
-{
- struct dtsec_softc *sc;
- struct mbuf *m;
-
- /* TODO STATUS / Position checking */
- sc = app;
-
- m = m_devget(data, length, 0, sc->sc_ifnet, NULL);
- if (m)
- if_input(sc->sc_ifnet, m);
-
- XX_FreeSmart(data);
-
- return (e_RX_STORE_RESPONSE_CONTINUE);
-}
-
-static void
-dtsec_im_fm_port_tx_conf_callback(t_Handle app, uint8_t *data, uint16_t status,
- t_Handle buf_context)
-{
-
- /* TODO: Check status */
- XX_FreeSmart(data);
-}
-
-static uint8_t *
-dtsec_im_fm_port_rx_get_buf(t_Handle buffer_pool, t_Handle *buf_context_handle)
-{
- struct dtsec_softc *sc;
- uint8_t *buffer;
-
- sc = buffer_pool;
-
- buffer = XX_MallocSmart(FM_PORT_BUFFER_SIZE, 0, sizeof(void *));
- if (!buffer)
- device_printf(sc->sc_dev, "couldn't allocate RX buffer.\n");
-
- return (buffer);
-}
-
-static t_Error
-dtsec_im_fm_port_rx_put_buf(t_Handle buffer_pool, uint8_t *buffer,
- t_Handle buf_context)
-{
-
- XX_FreeSmart(buffer);
- return (E_OK);
-}
-
-int
-dtsec_im_fm_port_rx_init(struct dtsec_softc *sc, int unit)
-{
- t_FmPortParams params;
- t_BufferPoolInfo *pool_params;
- t_FmPortImRxTxParams *im_params;
- t_Error error;
-
- memset(&params, 0, sizeof(params));
-
- params.baseAddr = sc->sc_fm_base + sc->sc_port_rx_hw_id;
- params.h_Fm = sc->sc_fmh;
- params.portType = dtsec_fm_port_rx_type(sc->sc_eth_dev_type);
- params.portId = sc->sc_eth_id;
- params.independentModeEnable = TRUE;
- params.liodnBase = FM_PORT_LIODN_BASE;
- params.f_Exception = dtsec_fm_port_rx_exception_callback;
- params.h_App = sc;
-
- im_params = &params.specificParams.imRxTxParams;
- im_params->h_FmMuram = sc->sc_muramh;
- im_params->liodnOffset = FM_PORT_LIODN_OFFSET;
- im_params->dataMemId = FM_PORT_MEM_ID;
- im_params->dataMemAttributes = FM_PORT_MEM_ATTR;
- im_params->f_RxStore = dtsec_im_fm_port_rx_callback;
-
- pool_params = &params.specificParams.imRxTxParams.rxPoolParams;
- pool_params->h_BufferPool = sc;
- pool_params->f_GetBuf = dtsec_im_fm_port_rx_get_buf;
- pool_params->f_PutBuf = dtsec_im_fm_port_rx_put_buf;
- pool_params->bufferSize = FM_PORT_BUFFER_SIZE;
-
- sc->sc_rxph = FM_PORT_Config(&params);
- if (sc->sc_rxph == NULL) {
- device_printf(sc->sc_dev, "couldn't configure FM Port RX.\n");
- return (ENXIO);
- }
-
- error = FM_PORT_Init(sc->sc_rxph);
- if (error != E_OK) {
- device_printf(sc->sc_dev, "couldn't initialize FM Port RX.\n");
- FM_PORT_Free(sc->sc_rxph);
- return (ENXIO);
- }
-
- if (bootverbose)
- device_printf(sc->sc_dev, "RX hw port 0x%02x initialized.\n",
- sc->sc_port_rx_hw_id);
-
- return (0);
-}
-
-int
-dtsec_im_fm_port_tx_init(struct dtsec_softc *sc, int unit)
-{
- t_FmPortParams params;
- t_FmPortImRxTxParams *im_params;
- t_Error error;
-
- memset(&params, 0, sizeof(params));
-
- params.baseAddr = sc->sc_fm_base + sc->sc_port_tx_hw_id;
- params.h_Fm = sc->sc_fmh;
- params.portType = dtsec_fm_port_tx_type(sc->sc_eth_dev_type);
- params.portId = unit;
- params.independentModeEnable = TRUE;
- params.liodnBase = FM_PORT_LIODN_BASE;
- params.f_Exception = dtsec_fm_port_tx_exception_callback;
- params.h_App = sc;
-
- im_params = &params.specificParams.imRxTxParams;
- im_params->h_FmMuram = sc->sc_muramh;
- im_params->liodnOffset = FM_PORT_LIODN_OFFSET;
- im_params->dataMemId = FM_PORT_MEM_ID;
- im_params->dataMemAttributes = FM_PORT_MEM_ATTR;
- im_params->f_TxConf = dtsec_im_fm_port_tx_conf_callback;
-
- sc->sc_txph = FM_PORT_Config(&params);
- if (sc->sc_txph == NULL) {
- device_printf(sc->sc_dev, "couldn't configure FM Port TX.\n");
- return (ENXIO);
- }
-
- error = FM_PORT_Init(sc->sc_txph);
- if (error != E_OK) {
- device_printf(sc->sc_dev, "couldn't initialize FM Port TX.\n");
- FM_PORT_Free(sc->sc_txph);
- return (ENXIO);
- }
-
- if (bootverbose)
- device_printf(sc->sc_dev, "TX hw port 0x%02x initialized.\n",
- sc->sc_port_tx_hw_id);
-
- return (0);
-}
-/** @} */
-
-
-/**
- * @group dTSEC IFnet routines.
- * @{
- */
-void
-dtsec_im_if_start_locked(struct dtsec_softc *sc)
-{
- uint8_t *buffer;
- uint16_t length;
- struct mbuf *m;
- int error;
-
- DTSEC_LOCK_ASSERT(sc);
- /* TODO: IFF_DRV_OACTIVE */
-
- if ((sc->sc_mii->mii_media_status & IFM_ACTIVE) == 0)
- return;
-
- if ((if_getdrvflags(sc->sc_ifnet) & IFF_DRV_RUNNING) != IFF_DRV_RUNNING)
- return;
-
- while (!if_sendq_empty(sc->sc_ifnet)) {
- m = if_dequeue(sc->sc_ifnet);
- if (m == NULL)
- break;
-
- length = m_length(m, NULL);
- buffer = XX_MallocSmart(length, 0, sizeof(void *));
- if (!buffer) {
- m_freem(m);
- break;
- }
-
- m_copydata(m, 0, length, buffer);
- m_freem(m);
-
- error = FM_PORT_ImTx(sc->sc_txph, buffer, length, TRUE, buffer);
- if (error != E_OK) {
- /* TODO: Ring full */
- XX_FreeSmart(buffer);
- break;
- }
- }
-}
-/** @} */
diff --git a/sys/dev/dpaa/if_dtsec_im.h b/sys/dev/dpaa/if_dtsec_im.h
deleted file mode 100644
index e1c8f2a3c0c2..000000000000
--- a/sys/dev/dpaa/if_dtsec_im.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*-
- * Copyright (c) 2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON 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 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef IF_DTSEC_IM_H_
-#define IF_DTSEC_IM_H_
-
-/**
- * @group dTSEC Independent Mode API.
- * @{
- */
-int dtsec_im_fm_port_tx_init(struct dtsec_softc *sc, int unit);
-int dtsec_im_fm_port_rx_init(struct dtsec_softc *sc, int unit);
-void dtsec_im_if_start_locked(struct dtsec_softc *sc);
-/** @} */
-
-#endif /* IF_DTSEC_IM_H_ */
diff --git a/sys/dev/dpaa/if_dtsec_rm.c b/sys/dev/dpaa/if_dtsec_rm.c
deleted file mode 100644
index 0b9f8e0ae6c7..000000000000
--- a/sys/dev/dpaa/if_dtsec_rm.c
+++ /dev/null
@@ -1,651 +0,0 @@
-/*-
- * Copyright (c) 2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON 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 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/bus.h>
-#include <sys/rman.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/socket.h>
-#include <sys/sysctl.h>
-#include <sys/sockio.h>
-
-#include <net/ethernet.h>
-#include <net/if.h>
-#include <net/if_dl.h>
-#include <net/if_media.h>
-#include <net/if_types.h>
-#include <net/if_arp.h>
-
-#include <dev/mii/mii.h>
-#include <dev/mii/miivar.h>
-
-#include "miibus_if.h"
-
-#include <contrib/ncsw/inc/integrations/dpaa_integration_ext.h>
-#include <contrib/ncsw/inc/Peripherals/fm_ext.h>
-#include <contrib/ncsw/inc/Peripherals/fm_mac_ext.h>
-#include <contrib/ncsw/inc/Peripherals/fm_port_ext.h>
-#include <contrib/ncsw/inc/xx_ext.h>
-
-#include "fman.h"
-#include "bman.h"
-#include "qman.h"
-#include "if_dtsec.h"
-#include "if_dtsec_rm.h"
-
-
-/**
- * @group dTSEC RM private defines.
- * @{
- */
-#define DTSEC_BPOOLS_USED (1)
-#define DTSEC_MAX_TX_QUEUE_LEN 256
-
-struct dtsec_rm_frame_info {
- struct mbuf *fi_mbuf;
- t_DpaaSGTE fi_sgt[DPAA_NUM_OF_SG_TABLE_ENTRY];
-};
-
-enum dtsec_rm_pool_params {
- DTSEC_RM_POOL_RX_LOW_MARK = 16,
- DTSEC_RM_POOL_RX_HIGH_MARK = 64,
- DTSEC_RM_POOL_RX_MAX_SIZE = 256,
-
- DTSEC_RM_POOL_FI_LOW_MARK = 16,
- DTSEC_RM_POOL_FI_HIGH_MARK = 64,
- DTSEC_RM_POOL_FI_MAX_SIZE = 256,
-};
-
-#define DTSEC_RM_FQR_RX_CHANNEL e_QM_FQ_CHANNEL_POOL1
-#define DTSEC_RM_FQR_TX_CONF_CHANNEL e_QM_FQ_CHANNEL_SWPORTAL0
-enum dtsec_rm_fqr_params {
- DTSEC_RM_FQR_RX_WQ = 1,
- DTSEC_RM_FQR_TX_WQ = 1,
- DTSEC_RM_FQR_TX_CONF_WQ = 1
-};
-/** @} */
-
-
-/**
- * @group dTSEC Frame Info routines.
- * @{
- */
-void
-dtsec_rm_fi_pool_free(struct dtsec_softc *sc)
-{
-
- if (sc->sc_fi_zone != NULL)
- uma_zdestroy(sc->sc_fi_zone);
-}
-
-int
-dtsec_rm_fi_pool_init(struct dtsec_softc *sc)
-{
-
- snprintf(sc->sc_fi_zname, sizeof(sc->sc_fi_zname), "%s: Frame Info",
- device_get_nameunit(sc->sc_dev));
-
- sc->sc_fi_zone = uma_zcreate(sc->sc_fi_zname,
- sizeof(struct dtsec_rm_frame_info), NULL, NULL, NULL, NULL,
- UMA_ALIGN_PTR, 0);
-
- return (0);
-}
-
-static struct dtsec_rm_frame_info *
-dtsec_rm_fi_alloc(struct dtsec_softc *sc)
-{
- struct dtsec_rm_frame_info *fi;
-
- fi = uma_zalloc(sc->sc_fi_zone, M_NOWAIT);
-
- return (fi);
-}
-
-static void
-dtsec_rm_fi_free(struct dtsec_softc *sc, struct dtsec_rm_frame_info *fi)
-{
-
- uma_zfree(sc->sc_fi_zone, fi);
-}
-/** @} */
-
-
-/**
- * @group dTSEC FMan PORT routines.
- * @{
- */
-int
-dtsec_rm_fm_port_rx_init(struct dtsec_softc *sc, int unit)
-{
- t_FmPortParams params;
- t_FmPortRxParams *rx_params;
- t_FmExtPools *pool_params;
- t_Error error;
-
- memset(&params, 0, sizeof(params));
-
- params.baseAddr = sc->sc_fm_base + sc->sc_port_rx_hw_id;
- params.h_Fm = sc->sc_fmh;
- params.portType = dtsec_fm_port_rx_type(sc->sc_eth_dev_type);
- params.portId = sc->sc_eth_id;
- params.independentModeEnable = false;
- params.liodnBase = FM_PORT_LIODN_BASE;
- params.f_Exception = dtsec_fm_port_rx_exception_callback;
- params.h_App = sc;
-
- rx_params = &params.specificParams.rxParams;
- rx_params->errFqid = sc->sc_rx_fqid;
- rx_params->dfltFqid = sc->sc_rx_fqid;
- rx_params->liodnOffset = 0;
-
- pool_params = &rx_params->extBufPools;
- pool_params->numOfPoolsUsed = DTSEC_BPOOLS_USED;
- pool_params->extBufPool->id = sc->sc_rx_bpid;
- pool_params->extBufPool->size = FM_PORT_BUFFER_SIZE;
-
- sc->sc_rxph = FM_PORT_Config(&params);
- if (sc->sc_rxph == NULL) {
- device_printf(sc->sc_dev, "couldn't configure FM Port RX.\n");
- return (ENXIO);
- }
-
- error = FM_PORT_Init(sc->sc_rxph);
- if (error != E_OK) {
- device_printf(sc->sc_dev, "couldn't initialize FM Port RX.\n");
- FM_PORT_Free(sc->sc_rxph);
- return (ENXIO);
- }
-
- if (bootverbose)
- device_printf(sc->sc_dev, "RX hw port 0x%02x initialized.\n",
- sc->sc_port_rx_hw_id);
-
- return (0);
-}
-
-int
-dtsec_rm_fm_port_tx_init(struct dtsec_softc *sc, int unit)
-{
- t_FmPortParams params;
- t_FmPortNonRxParams *tx_params;
- t_Error error;
-
- memset(&params, 0, sizeof(params));
-
- params.baseAddr = sc->sc_fm_base + sc->sc_port_tx_hw_id;
- params.h_Fm = sc->sc_fmh;
- params.portType = dtsec_fm_port_tx_type(sc->sc_eth_dev_type);
- params.portId = sc->sc_eth_id;
- params.independentModeEnable = false;
- params.liodnBase = FM_PORT_LIODN_BASE;
- params.f_Exception = dtsec_fm_port_tx_exception_callback;
- params.h_App = sc;
-
- tx_params = &params.specificParams.nonRxParams;
- tx_params->errFqid = sc->sc_tx_conf_fqid;
- tx_params->dfltFqid = sc->sc_tx_conf_fqid;
- tx_params->qmChannel = sc->sc_port_tx_qman_chan;
-#ifdef FM_OP_PARTITION_ERRATA_FMANx8
- tx_params->opLiodnOffset = 0;
-#endif
-
- sc->sc_txph = FM_PORT_Config(&params);
- if (sc->sc_txph == NULL) {
- device_printf(sc->sc_dev, "couldn't configure FM Port TX.\n");
- return (ENXIO);
- }
-
- error = FM_PORT_Init(sc->sc_txph);
- if (error != E_OK) {
- device_printf(sc->sc_dev, "couldn't initialize FM Port TX.\n");
- FM_PORT_Free(sc->sc_txph);
- return (ENXIO);
- }
-
- if (bootverbose)
- device_printf(sc->sc_dev, "TX hw port 0x%02x initialized.\n",
- sc->sc_port_tx_hw_id);
-
- return (0);
-}
-/** @} */
-
-
-/**
- * @group dTSEC buffer pools routines.
- * @{
- */
-static t_Error
-dtsec_rm_pool_rx_put_buffer(t_Handle h_BufferPool, uint8_t *buffer,
- t_Handle context)
-{
- struct dtsec_softc *sc;
-
- sc = h_BufferPool;
- uma_zfree(sc->sc_rx_zone, buffer);
-
- return (E_OK);
-}
-
-static uint8_t *
-dtsec_rm_pool_rx_get_buffer(t_Handle h_BufferPool, t_Handle *context)
-{
- struct dtsec_softc *sc;
- uint8_t *buffer;
-
- sc = h_BufferPool;
- buffer = uma_zalloc(sc->sc_rx_zone, M_NOWAIT);
-
- return (buffer);
-}
-
-static void
-dtsec_rm_pool_rx_depleted(t_Handle h_App, bool in)
-{
- struct dtsec_softc *sc;
- unsigned int count;
-
- sc = h_App;
-
- if (!in)
- return;
-
- while (1) {
- count = bman_count(sc->sc_rx_pool);
- if (count > DTSEC_RM_POOL_RX_HIGH_MARK)
- return;
-
- bman_pool_fill(sc->sc_rx_pool, DTSEC_RM_POOL_RX_HIGH_MARK);
- }
-}
-
-void
-dtsec_rm_pool_rx_free(struct dtsec_softc *sc)
-{
-
- if (sc->sc_rx_pool != NULL)
- bman_pool_destroy(sc->sc_rx_pool);
-
- if (sc->sc_rx_zone != NULL)
- uma_zdestroy(sc->sc_rx_zone);
-}
-
-int
-dtsec_rm_pool_rx_init(struct dtsec_softc *sc)
-{
-
- /* FM_PORT_BUFFER_SIZE must be less than PAGE_SIZE */
- CTASSERT(FM_PORT_BUFFER_SIZE < PAGE_SIZE);
-
- snprintf(sc->sc_rx_zname, sizeof(sc->sc_rx_zname), "%s: RX Buffers",
- device_get_nameunit(sc->sc_dev));
-
- sc->sc_rx_zone = uma_zcreate(sc->sc_rx_zname, FM_PORT_BUFFER_SIZE, NULL,
- NULL, NULL, NULL, FM_PORT_BUFFER_SIZE - 1, 0);
-
- sc->sc_rx_pool = bman_pool_create(&sc->sc_rx_bpid, FM_PORT_BUFFER_SIZE,
- 0, 0, DTSEC_RM_POOL_RX_MAX_SIZE, dtsec_rm_pool_rx_get_buffer,
- dtsec_rm_pool_rx_put_buffer, DTSEC_RM_POOL_RX_LOW_MARK,
- DTSEC_RM_POOL_RX_HIGH_MARK, 0, 0, dtsec_rm_pool_rx_depleted, sc, NULL,
- NULL);
- if (sc->sc_rx_pool == NULL) {
- device_printf(sc->sc_dev, "NULL rx pool somehow\n");
- dtsec_rm_pool_rx_free(sc);
- return (EIO);
- }
-
- return (0);
-}
-/** @} */
-
-
-/**
- * @group dTSEC Frame Queue Range routines.
- * @{
- */
-static void
-dtsec_rm_fqr_mext_free(struct mbuf *m)
-{
- struct dtsec_softc *sc;
- void *buffer;
-
- buffer = m->m_ext.ext_arg1;
- sc = m->m_ext.ext_arg2;
- if (bman_count(sc->sc_rx_pool) <= DTSEC_RM_POOL_RX_MAX_SIZE)
- bman_put_buffer(sc->sc_rx_pool, buffer);
- else
- dtsec_rm_pool_rx_put_buffer(sc, buffer, NULL);
-}
-
-static e_RxStoreResponse
-dtsec_rm_fqr_rx_callback(t_Handle app, t_Handle fqr, t_Handle portal,
- uint32_t fqid_off, t_DpaaFD *frame)
-{
- struct dtsec_softc *sc;
- struct mbuf *m;
- void *frame_va;
-
- m = NULL;
- sc = app;
-
- frame_va = DPAA_FD_GET_ADDR(frame);
- KASSERT(DPAA_FD_GET_FORMAT(frame) == e_DPAA_FD_FORMAT_TYPE_SHORT_SBSF,
- ("%s(): Got unsupported frame format 0x%02X!", __func__,
- DPAA_FD_GET_FORMAT(frame)));
-
- KASSERT(DPAA_FD_GET_OFFSET(frame) == 0,
- ("%s(): Only offset 0 is supported!", __func__));
-
- if (DPAA_FD_GET_STATUS(frame) != 0) {
- device_printf(sc->sc_dev, "RX error: 0x%08X\n",
- DPAA_FD_GET_STATUS(frame));
- goto err;
- }
-
- m = m_gethdr(M_NOWAIT, MT_HEADER);
- if (m == NULL)
- goto err;
-
- m_extadd(m, frame_va, FM_PORT_BUFFER_SIZE,
- dtsec_rm_fqr_mext_free, frame_va, sc, 0,
- EXT_NET_DRV);
-
- m->m_pkthdr.rcvif = sc->sc_ifnet;
- m->m_len = DPAA_FD_GET_LENGTH(frame);
- m_fixhdr(m);
-
- if_input(sc->sc_ifnet, m);
-
- return (e_RX_STORE_RESPONSE_CONTINUE);
-
-err:
- bman_put_buffer(sc->sc_rx_pool, frame_va);
- if (m != NULL)
- m_freem(m);
-
- return (e_RX_STORE_RESPONSE_CONTINUE);
-}
-
-static e_RxStoreResponse
-dtsec_rm_fqr_tx_confirm_callback(t_Handle app, t_Handle fqr, t_Handle portal,
- uint32_t fqid_off, t_DpaaFD *frame)
-{
- struct dtsec_rm_frame_info *fi;
- struct dtsec_softc *sc;
- unsigned int qlen;
- t_DpaaSGTE *sgt0;
-
- sc = app;
-
- if (DPAA_FD_GET_STATUS(frame) != 0)
- device_printf(sc->sc_dev, "TX error: 0x%08X\n",
- DPAA_FD_GET_STATUS(frame));
-
- /*
- * We are storing struct dtsec_rm_frame_info in first entry
- * of scatter-gather table.
- */
- sgt0 = DPAA_FD_GET_ADDR(frame);
- fi = DPAA_SGTE_GET_ADDR(sgt0);
-
- /* Free transmitted frame */
- m_freem(fi->fi_mbuf);
- dtsec_rm_fi_free(sc, fi);
-
- qlen = qman_fqr_get_counter(sc->sc_tx_conf_fqr, 0,
- e_QM_FQR_COUNTERS_FRAME);
-
- if (qlen == 0) {
- DTSEC_LOCK(sc);
-
- if (sc->sc_tx_fqr_full) {
- sc->sc_tx_fqr_full = 0;
- dtsec_rm_if_start_locked(sc);
- }
-
- DTSEC_UNLOCK(sc);
- }
-
- return (e_RX_STORE_RESPONSE_CONTINUE);
-}
-
-void
-dtsec_rm_fqr_rx_free(struct dtsec_softc *sc)
-{
-
- if (sc->sc_rx_fqr)
- qman_fqr_free(sc->sc_rx_fqr);
-}
-
-int
-dtsec_rm_fqr_rx_init(struct dtsec_softc *sc)
-{
- t_Error error;
- t_Handle fqr;
-
- /* Default Frame Queue */
- fqr = qman_fqr_create(1, DTSEC_RM_FQR_RX_CHANNEL, DTSEC_RM_FQR_RX_WQ,
- false, 0, false, false, true, false, 0, 0, 0);
- if (fqr == NULL) {
- device_printf(sc->sc_dev, "could not create default RX queue"
- "\n");
- return (EIO);
- }
-
- sc->sc_rx_fqr = fqr;
- sc->sc_rx_fqid = qman_fqr_get_base_fqid(fqr);
-
- error = qman_fqr_register_cb(fqr, dtsec_rm_fqr_rx_callback, sc);
- if (error != E_OK) {
- device_printf(sc->sc_dev, "could not register RX callback\n");
- dtsec_rm_fqr_rx_free(sc);
- return (EIO);
- }
-
- return (0);
-}
-
-void
-dtsec_rm_fqr_tx_free(struct dtsec_softc *sc)
-{
-
- if (sc->sc_tx_fqr)
- qman_fqr_free(sc->sc_tx_fqr);
-
- if (sc->sc_tx_conf_fqr)
- qman_fqr_free(sc->sc_tx_conf_fqr);
-}
-
-int
-dtsec_rm_fqr_tx_init(struct dtsec_softc *sc)
-{
- t_Error error;
- t_Handle fqr;
-
- /* TX Frame Queue */
- fqr = qman_fqr_create(1, sc->sc_port_tx_qman_chan,
- DTSEC_RM_FQR_TX_WQ, false, 0, false, false, true, false, 0, 0, 0);
- if (fqr == NULL) {
- device_printf(sc->sc_dev, "could not create default TX queue"
- "\n");
- return (EIO);
- }
-
- sc->sc_tx_fqr = fqr;
-
- /* TX Confirmation Frame Queue */
- fqr = qman_fqr_create(1, DTSEC_RM_FQR_TX_CONF_CHANNEL,
- DTSEC_RM_FQR_TX_CONF_WQ, false, 0, false, false, true, false, 0, 0,
- 0);
- if (fqr == NULL) {
- device_printf(sc->sc_dev, "could not create TX confirmation "
- "queue\n");
- dtsec_rm_fqr_tx_free(sc);
- return (EIO);
- }
-
- sc->sc_tx_conf_fqr = fqr;
- sc->sc_tx_conf_fqid = qman_fqr_get_base_fqid(fqr);
-
- error = qman_fqr_register_cb(fqr, dtsec_rm_fqr_tx_confirm_callback, sc);
- if (error != E_OK) {
- device_printf(sc->sc_dev, "could not register TX confirmation "
- "callback\n");
- dtsec_rm_fqr_tx_free(sc);
- return (EIO);
- }
-
- return (0);
-}
-/** @} */
-
-
-/**
- * @group dTSEC IFnet routines.
- * @{
- */
-void
-dtsec_rm_if_start_locked(struct dtsec_softc *sc)
-{
- vm_size_t dsize, psize, ssize;
- struct dtsec_rm_frame_info *fi;
- unsigned int qlen, i;
- struct mbuf *m0, *m;
- vm_offset_t vaddr;
- t_DpaaFD fd;
-
- DTSEC_LOCK_ASSERT(sc);
- /* TODO: IFF_DRV_OACTIVE */
-
- if ((sc->sc_mii->mii_media_status & IFM_ACTIVE) == 0)
- return;
-
- if ((if_getdrvflags(sc->sc_ifnet) & IFF_DRV_RUNNING) != IFF_DRV_RUNNING)
- return;
-
- while (!if_sendq_empty(sc->sc_ifnet)) {
- /* Check length of the TX queue */
- qlen = qman_fqr_get_counter(sc->sc_tx_fqr, 0,
- e_QM_FQR_COUNTERS_FRAME);
-
- if (qlen >= DTSEC_MAX_TX_QUEUE_LEN) {
- sc->sc_tx_fqr_full = 1;
- return;
- }
-
- fi = dtsec_rm_fi_alloc(sc);
- if (fi == NULL)
- return;
-
- m0 = if_dequeue(sc->sc_ifnet);
- if (m0 == NULL) {
- dtsec_rm_fi_free(sc, fi);
- return;
- }
-
- i = 0;
- m = m0;
- psize = 0;
- dsize = 0;
- fi->fi_mbuf = m0;
- while (m && i < DPAA_NUM_OF_SG_TABLE_ENTRY) {
- if (m->m_len == 0)
- continue;
-
- /*
- * First entry in scatter-gather table is used to keep
- * pointer to frame info structure.
- */
- DPAA_SGTE_SET_ADDR(&fi->fi_sgt[i], (void *)fi);
- DPAA_SGTE_SET_LENGTH(&fi->fi_sgt[i], 0);
-
- DPAA_SGTE_SET_EXTENSION(&fi->fi_sgt[i], 0);
- DPAA_SGTE_SET_FINAL(&fi->fi_sgt[i], 0);
- DPAA_SGTE_SET_BPID(&fi->fi_sgt[i], 0);
- DPAA_SGTE_SET_OFFSET(&fi->fi_sgt[i], 0);
- i++;
-
- dsize = m->m_len;
- vaddr = (vm_offset_t)m->m_data;
- while (dsize > 0 && i < DPAA_NUM_OF_SG_TABLE_ENTRY) {
- ssize = PAGE_SIZE - (vaddr & PAGE_MASK);
- if (m->m_len < ssize)
- ssize = m->m_len;
-
- DPAA_SGTE_SET_ADDR(&fi->fi_sgt[i],
- (void *)vaddr);
- DPAA_SGTE_SET_LENGTH(&fi->fi_sgt[i], ssize);
-
- DPAA_SGTE_SET_EXTENSION(&fi->fi_sgt[i], 0);
- DPAA_SGTE_SET_FINAL(&fi->fi_sgt[i], 0);
- DPAA_SGTE_SET_BPID(&fi->fi_sgt[i], 0);
- DPAA_SGTE_SET_OFFSET(&fi->fi_sgt[i], 0);
-
- dsize -= ssize;
- vaddr += ssize;
- psize += ssize;
- i++;
- }
-
- if (dsize > 0)
- break;
-
- m = m->m_next;
- }
-
- /* Check if SG table was constructed properly */
- if (m != NULL || dsize != 0) {
- dtsec_rm_fi_free(sc, fi);
- m_freem(m0);
- continue;
- }
-
- DPAA_SGTE_SET_FINAL(&fi->fi_sgt[i-1], 1);
-
- DPAA_FD_SET_ADDR(&fd, fi->fi_sgt);
- DPAA_FD_SET_LENGTH(&fd, psize);
- DPAA_FD_SET_FORMAT(&fd, e_DPAA_FD_FORMAT_TYPE_SHORT_MBSF);
-
- fd.liodn = 0;
- fd.bpid = 0;
- fd.elion = 0;
- DPAA_FD_SET_OFFSET(&fd, 0);
- DPAA_FD_SET_STATUS(&fd, 0);
-
- DTSEC_UNLOCK(sc);
- if (qman_fqr_enqueue(sc->sc_tx_fqr, 0, &fd) != E_OK) {
- dtsec_rm_fi_free(sc, fi);
- m_freem(m0);
- }
- DTSEC_LOCK(sc);
- }
-}
-/** @} */
diff --git a/sys/dev/dpaa/if_dtsec_rm.h b/sys/dev/dpaa/if_dtsec_rm.h
deleted file mode 100644
index 28f779a11386..000000000000
--- a/sys/dev/dpaa/if_dtsec_rm.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*-
- * Copyright (c) 2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON 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 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef IF_DTSEC_RM_H_
-#define IF_DTSEC_RM_H_
-
-/**
- * @group dTSEC Regular Mode API.
- * @{
- */
-int dtsec_rm_fm_port_rx_init(struct dtsec_softc *sc, int unit);
-int dtsec_rm_fm_port_tx_init(struct dtsec_softc *sc, int unit);
-
-void dtsec_rm_if_start_locked(struct dtsec_softc *sc);
-
-int dtsec_rm_pool_rx_init(struct dtsec_softc *sc);
-void dtsec_rm_pool_rx_free(struct dtsec_softc *sc);
-
-int dtsec_rm_fi_pool_init(struct dtsec_softc *sc);
-void dtsec_rm_fi_pool_free(struct dtsec_softc *sc);
-
-int dtsec_rm_fqr_rx_init(struct dtsec_softc *sc);
-int dtsec_rm_fqr_tx_init(struct dtsec_softc *sc);
-void dtsec_rm_fqr_rx_free(struct dtsec_softc *sc);
-void dtsec_rm_fqr_tx_free(struct dtsec_softc *sc);
-/** @} */
-
-#endif /* IF_DTSEC_RM_H_ */
diff --git a/sys/dev/dpaa/if_memac.c b/sys/dev/dpaa/if_memac.c
new file mode 100644
index 000000000000..6d0fa3f5e337
--- /dev/null
+++ b/sys/dev/dpaa/if_memac.c
@@ -0,0 +1,820 @@
+/*
+ * Copyright (c) 2026 Justin Hibbits
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/sockio.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+#include <net/if_arp.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/openfirm.h>
+
+#include "miibus_if.h"
+
+#include "dpaa_eth.h"
+#include "fman.h"
+#include "fman_port.h"
+#include "if_memac.h"
+
+#include "fman_if.h"
+#include "fman_port_if.h"
+
+#define MEMAC_MIN_FRAME_SIZE 64
+#define MEMAC_MAX_FRAME_SIZE 32736
+
+#define MEMAC_COMMAND_CONFIG 0x008
+#define COMMAND_CONFIG_RXSTP 0x20000000
+#define COMMAND_CONFIG_NO_LEN_CHK 0x00020000
+#define COMMAND_CONFIG_SWR 0x00001000
+#define COMMAND_CONFIG_TXP 0x00000800
+#define COMMAND_CONFIG_CRC 0x00000040
+#define COMMAND_CONFIG_PROMISC 0x00000010
+#define COMMAND_CONFIG_RX_EN 0x00000002
+#define COMMAND_CONFIG_TX_EN 0x00000001
+#define MEMAC_MAC_ADDR_0 0x00c
+#define MEMAC_MAC_ADDR_1 0x010
+#define MEMAC_REG_MAXFRM 0x14
+#define MEMAC_REG_TX_FIFO_SECTIONS 0x020
+#define TX_FIFO_SECTIONS_TX_EMPTY_M 0xffff0000
+#define TX_FIFO_SECTIONS_TX_EMPTY_S 16
+#define TX_FIFO_SECTIONS_TX_AVAIL_M 0x0000ffff
+
+#define HASHTABLE_CTRL 0x02c
+#define CTRL_MCAST 0x00000100
+#define CTRL_HASH_ADDR_M 0x0000003f
+#define HASHTABLE_SIZE 64
+#define MEMAC_IEVENT 0x040
+#define IEVENT_RX_EMPTY 0x00000040
+#define IEVENT_TX_EMPTY 0x00000020
+#define MEMAC_CL01_PAUSE_QUANTA 0x054
+#define MEMAC_IF_MODE 0x300
+#define IF_MODE_ENA 0x00008000
+#define IF_MODE_SSP_M 0x00006000
+#define IF_MODE_SSP_100MB 0x00000000
+#define IF_MODE_SSP_10MB 0x00002000
+#define IF_MODE_SSP_1GB 0x00004000
+#define IF_MODE_SFD 0x00001000
+#define IF_MODE_MSG 0x00000200
+#define IF_MODE_HG 0x00000100
+#define IF_MODE_HD 0x00000040
+#define IF_MODE_RLP 0x00000020
+#define IF_MODE_RG 0x00000004
+#define IF_MODE_IFMODE_M 0x00000003
+#define IF_MODE_IFMODE_XGMII 0x00000000
+#define IF_MODE_IFMODE_MII 0x00000001
+#define IF_MODE_IFMODE_GMII 0x00000002
+
+#define DEFAULT_PAUSE_QUANTA 0xf000
+
+#define DPAA_CSUM_TX_OFFLOAD (CSUM_IP | CSUM_DELAY_DATA | CSUM_DELAY_DATA_IPV6)
+
+
+/**
+ * @group FMan MAC routines.
+ * @{
+ */
+#define MEMAC_MAC_EXCEPTIONS_END (-1)
+
+static void memac_if_init_locked(struct memac_softc *sc);
+
+static int
+memac_fm_mac_init(struct memac_softc *sc, uint8_t *mac)
+{
+ uint32_t reg;
+
+ FMAN_GET_REVISION(device_get_parent(sc->sc_base.sc_dev), &sc->sc_base.sc_rev_major,
+ &sc->sc_base.sc_rev_minor);
+
+ if (FMAN_RESET_MAC(device_get_parent(sc->sc_base.sc_dev), sc->sc_base.sc_eth_id) != 0)
+ return (ENXIO);
+
+ reg = bus_read_4(sc->sc_base.sc_mem, MEMAC_COMMAND_CONFIG);
+ reg |= COMMAND_CONFIG_SWR;
+ bus_write_4(sc->sc_base.sc_mem, MEMAC_COMMAND_CONFIG, reg);
+
+ while (bus_read_4(sc->sc_base.sc_mem, MEMAC_COMMAND_CONFIG) & COMMAND_CONFIG_SWR)
+ ;
+
+ /* TODO: TX_FIFO_SECTIONS */
+ /* TODO: CL01 pause quantum */
+ bus_write_4(sc->sc_base.sc_mem, MEMAC_COMMAND_CONFIG,
+ COMMAND_CONFIG_NO_LEN_CHK | COMMAND_CONFIG_TXP | COMMAND_CONFIG_CRC);
+
+ reg = bus_read_4(sc->sc_base.sc_mem, MEMAC_IF_MODE);
+ reg &= ~(IF_MODE_IFMODE_M | IF_MODE_RG);
+ switch (sc->sc_base.sc_mac_enet_mode) {
+ case MII_CONTYPE_RGMII:
+ reg |= IF_MODE_RG;
+ /* FALLTHROUGH */
+ case MII_CONTYPE_GMII:
+ case MII_CONTYPE_SGMII:
+ case MII_CONTYPE_QSGMII:
+ reg |= IF_MODE_IFMODE_GMII;
+ break;
+ case MII_CONTYPE_RMII:
+ reg |= IF_MODE_RG;
+ /* FALLTHROUGH */
+ case MII_CONTYPE_MII:
+ reg |= IF_MODE_IFMODE_MII;
+ break;
+ }
+
+ bus_write_4(sc->sc_base.sc_mem, MEMAC_IF_MODE, reg);
+
+ return (0);
+}
+/** @} */
+
+
+/**
+ * @group IFnet routines.
+ * @{
+ */
+static int
+memac_set_mtu(struct memac_softc *sc, unsigned int mtu)
+{
+
+ mtu += ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN + ETHER_CRC_LEN;
+
+ MEMAC_LOCK_ASSERT(sc);
+
+ if (mtu >= MEMAC_MIN_FRAME_SIZE && mtu <= MEMAC_MAX_FRAME_SIZE) {
+ bus_write_4(sc->sc_base.sc_mem, MEMAC_REG_MAXFRM, mtu);
+ return (mtu);
+ }
+
+ return (0);
+}
+
+static u_int
+memac_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct memac_softc *sc = arg;
+ uint8_t *addr = LLADDR(sdl);
+ uint32_t hash = 0;
+ uint8_t a, h;
+
+ /* Hash is 6 bits, composed if [XOR{47:40},XOR{39:32},....] */
+ for (int i = 0; i < 6; i++) {
+ a = addr[i];
+ h = 0;
+ for (int j = 0; j < 8; j++, a >>= 1) {
+ h ^= (a & 0x1);
+ }
+ hash |= (h << i);
+ }
+ bus_write_4(sc->sc_base.sc_mem, HASHTABLE_CTRL, hash | CTRL_MCAST);
+
+ return (1);
+}
+
+static void
+memac_setup_multicast(struct memac_softc *sc)
+{
+
+ if (if_getflags(sc->sc_base.sc_ifnet) & IFF_ALLMULTI) {
+ for (int i = 0; i < HASHTABLE_SIZE; i++)
+ bus_write_4(sc->sc_base.sc_mem,
+ HASHTABLE_CTRL, CTRL_MCAST | i);
+ } else {
+ /* Clear the hash table */
+ for (int i = 0; i < HASHTABLE_SIZE; i++)
+ bus_write_4(sc->sc_base.sc_mem,
+ HASHTABLE_CTRL, i);
+ }
+
+ if_foreach_llmaddr(sc->sc_base.sc_ifnet, memac_hash_maddr, sc);
+}
+
+static void
+memac_setup_promisc(struct memac_softc *sc)
+{
+ uint32_t reg;
+
+ reg = bus_read_4(sc->sc_base.sc_mem, MEMAC_COMMAND_CONFIG);
+ reg &= ~COMMAND_CONFIG_PROMISC;
+
+ if ((if_getflags(sc->sc_base.sc_ifnet) & IFF_PROMISC) != 0)
+ bus_write_4(sc->sc_base.sc_mem, MEMAC_COMMAND_CONFIG,
+ reg | COMMAND_CONFIG_PROMISC);
+}
+
+static void
+memac_if_graceful_stop(struct memac_softc *sc)
+{
+ struct resource *regs = sc->sc_base.sc_mem;
+ uint32_t reg;
+
+ reg = bus_read_4(regs, MEMAC_COMMAND_CONFIG);
+ reg |= COMMAND_CONFIG_RXSTP;
+
+ bus_write_4(regs, MEMAC_COMMAND_CONFIG, reg);
+ while ((bus_read_4(regs, MEMAC_IEVENT) & IEVENT_RX_EMPTY) == 0)
+ ;
+ reg &= COMMAND_CONFIG_RX_EN;
+ bus_write_4(regs, MEMAC_COMMAND_CONFIG, reg);
+
+ while ((bus_read_4(regs, MEMAC_IEVENT) & IEVENT_TX_EMPTY) == 0)
+ ;
+ bus_write_4(regs, MEMAC_COMMAND_CONFIG, reg & ~COMMAND_CONFIG_TX_EN);
+}
+
+static void
+memac_mac_enable(struct memac_softc *sc)
+{
+ uint32_t reg = bus_read_4(sc->sc_base.sc_mem, MEMAC_COMMAND_CONFIG);
+
+ reg |= (COMMAND_CONFIG_RX_EN | COMMAND_CONFIG_TX_EN);
+
+ bus_write_4(sc->sc_base.sc_mem, MEMAC_COMMAND_CONFIG, reg);
+}
+
+static int
+memac_if_enable_locked(struct memac_softc *sc)
+{
+ int error;
+
+ MEMAC_LOCK_ASSERT(sc);
+
+ memac_set_mtu(sc, if_getmtu(sc->sc_base.sc_ifnet));
+ memac_mac_enable(sc);
+
+ error = FMAN_PORT_ENABLE(sc->sc_base.sc_rx_port);
+ if (error != 0)
+ return (EIO);
+
+ error = FMAN_PORT_ENABLE(sc->sc_base.sc_tx_port);
+ if (error != 0)
+ return (EIO);
+
+ bus_write_4(sc->sc_base.sc_mem, MEMAC_IEVENT, 0);
+ memac_setup_multicast(sc);
+ memac_setup_promisc(sc);
+
+ if_setdrvflagbits(sc->sc_base.sc_ifnet, IFF_DRV_RUNNING, 0);
+
+ /* Refresh link state */
+ memac_miibus_statchg(sc->sc_base.sc_dev);
+
+ return (0);
+}
+
+static int
+memac_if_disable_locked(struct memac_softc *sc)
+{
+ int error;
+
+ MEMAC_LOCK_ASSERT(sc);
+
+ error = FMAN_PORT_DISABLE(sc->sc_base.sc_tx_port);
+ if (error != 0)
+ return (EIO);
+
+ memac_if_graceful_stop(sc);
+
+ error = FMAN_PORT_DISABLE(sc->sc_base.sc_rx_port);
+ if (error != 0)
+ return (EIO);
+
+ if_setdrvflagbits(sc->sc_base.sc_ifnet, 0, IFF_DRV_RUNNING);
+
+ return (0);
+}
+
+static int
+memac_if_ioctl(if_t ifp, u_long command, caddr_t data)
+{
+ struct memac_softc *sc;
+ struct ifreq *ifr;
+ uint32_t changed;
+ int error;
+
+ sc = if_getsoftc(ifp);
+ ifr = (struct ifreq *)data;
+ error = 0;
+
+ /* Basic functionality to achieve media status reports */
+ switch (command) {
+ case SIOCSIFMTU:
+ MEMAC_LOCK(sc);
+ if (memac_set_mtu(sc, ifr->ifr_mtu))
+ if_setmtu(ifp, ifr->ifr_mtu);
+ else
+ error = EINVAL;
+ MEMAC_UNLOCK(sc);
+ break;
+ case SIOCSIFFLAGS:
+ MEMAC_LOCK(sc);
+ if (if_getflags(ifp) & IFF_UP) {
+ if (!(if_getdrvflags(ifp) & IFF_DRV_RUNNING))
+ memac_if_init_locked(sc);
+ } else if (if_getdrvflags(ifp) & IFF_DRV_RUNNING)
+ error = memac_if_disable_locked(sc);
+
+ MEMAC_UNLOCK(sc);
+ break;
+
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ if (if_getflags(sc->sc_base.sc_ifnet) & IFF_UP) {
+ MEMAC_LOCK(sc);
+ memac_setup_multicast(sc);
+ MEMAC_UNLOCK(sc);
+ }
+ break;
+
+ case SIOCSIFCAP:
+ changed = if_getcapenable(ifp) ^ ifr->ifr_reqcap;
+ if ((changed & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6)) != 0)
+ if_togglecapenable(ifp,
+ IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6);
+ if ((changed & (IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6)) != 0) {
+ if_togglecapenable(ifp,
+ IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6);
+ if_togglehwassist(ifp, DPAA_CSUM_TX_OFFLOAD);
+ }
+ break;
+
+ case SIOCGIFMEDIA:
+ case SIOCSIFMEDIA:
+ error = ifmedia_ioctl(ifp, ifr, &sc->sc_base.sc_mii->mii_media,
+ command);
+ break;
+
+ default:
+ error = ether_ioctl(ifp, command, data);
+ }
+
+ return (error);
+}
+
+static void
+memac_if_tick(void *arg)
+{
+ struct memac_softc *sc;
+
+ sc = arg;
+
+ /* TODO */
+ MEMAC_LOCK(sc);
+
+ mii_tick(sc->sc_base.sc_mii);
+ callout_reset(&sc->sc_base.sc_tick_callout, hz, memac_if_tick, sc);
+
+ MEMAC_UNLOCK(sc);
+}
+
+static void
+memac_if_deinit_locked(struct memac_softc *sc)
+{
+
+ MEMAC_LOCK_ASSERT(sc);
+
+ MEMAC_UNLOCK(sc);
+ callout_drain(&sc->sc_base.sc_tick_callout);
+ MEMAC_LOCK(sc);
+}
+
+static void
+memac_if_set_macaddr(struct memac_softc *sc, const char *addr)
+{
+ uint32_t reg;
+
+ reg = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
+ bus_write_4(sc->sc_base.sc_mem, MEMAC_MAC_ADDR_0, reg);
+ reg = (addr[5] << 8) | (addr[4]);
+ bus_write_4(sc->sc_base.sc_mem, MEMAC_MAC_ADDR_1, reg);
+}
+
+static void
+memac_if_init_locked(struct memac_softc *sc)
+{
+ int error;
+ const char *macaddr;
+
+ MEMAC_LOCK_ASSERT(sc);
+
+ macaddr = if_getlladdr(sc->sc_base.sc_ifnet);
+ memac_if_set_macaddr(sc, macaddr);
+
+ /* Start MII polling */
+ if (sc->sc_base.sc_mii)
+ callout_reset(&sc->sc_base.sc_tick_callout, hz,
+ memac_if_tick, sc);
+
+ if (if_getflags(sc->sc_base.sc_ifnet) & IFF_UP) {
+ error = memac_if_enable_locked(sc);
+ if (error != 0)
+ goto err;
+ } else {
+ error = memac_if_disable_locked(sc);
+ if (error != 0)
+ goto err;
+ }
+
+ if_link_state_change(sc->sc_base.sc_ifnet, LINK_STATE_UP);
+
+ bus_write_4(sc->sc_base.sc_mem, MEMAC_CL01_PAUSE_QUANTA,
+ DEFAULT_PAUSE_QUANTA);
+
+ return;
+
+err:
+ memac_if_deinit_locked(sc);
+ device_printf(sc->sc_base.sc_dev, "initialization error.\n");
+ return;
+}
+
+static void
+memac_if_init(void *data)
+{
+ struct memac_softc *sc;
+
+ sc = data;
+
+ MEMAC_LOCK(sc);
+ memac_if_init_locked(sc);
+ MEMAC_UNLOCK(sc);
+}
+
+static void
+memac_if_start(if_t ifp)
+{
+ struct memac_softc *sc;
+
+ sc = if_getsoftc(ifp);
+ MEMAC_LOCK(sc);
+ dpaa_eth_if_start_locked(&sc->sc_base);
+ MEMAC_UNLOCK(sc);
+}
+
+static void
+memac_if_watchdog(if_t ifp)
+{
+ /* TODO */
+}
+/** @} */
+
+
+/**
+ * @group IFmedia routines.
+ * @{
+ */
+static int
+memac_ifmedia_upd(if_t ifp)
+{
+ struct memac_softc *sc = if_getsoftc(ifp);
+
+ return (0);
+ MEMAC_LOCK(sc);
+ mii_mediachg(sc->sc_base.sc_mii);
+ MEMAC_UNLOCK(sc);
+
+ return (0);
+}
+
+static void
+memac_ifmedia_fixed_sts(if_t ifp, struct ifmediareq *ifmr)
+{
+ struct memac_softc *sc = if_getsoftc(ifp);
+
+ MEMAC_LOCK(sc);
+ ifmr->ifm_count = 1;
+ ifmr->ifm_mask = 0;
+ ifmr->ifm_status = IFM_AVALID | IFM_ACTIVE;
+ ifmr->ifm_current = ifmr->ifm_active =
+ sc->sc_base.sc_mii->mii_media.ifm_cur->ifm_media;
+ ifmr->ifm_active = ifmr->ifm_current;
+
+ /*
+ * In non-PHY usecases, we need to signal link state up, otherwise
+ * certain things requiring a link event (e.g async DHCP client) from
+ * devd do not happen.
+ */
+ if (if_getlinkstate(ifp) == LINK_STATE_UNKNOWN) {
+ if_link_state_change(ifp, LINK_STATE_UP);
+ }
+
+ /* We assume the link is static, as in a peer switch. */
+
+ MEMAC_UNLOCK(sc);
+
+ return;
+}
+
+static void
+memac_ifmedia_sts(if_t ifp, struct ifmediareq *ifmr)
+{
+ struct memac_softc *sc = if_getsoftc(ifp);
+
+ MEMAC_LOCK(sc);
+
+ mii_pollstat(sc->sc_base.sc_mii);
+
+ ifmr->ifm_active = sc->sc_base.sc_mii->mii_media_active;
+ ifmr->ifm_status = sc->sc_base.sc_mii->mii_media_status;
+
+ MEMAC_UNLOCK(sc);
+}
+/** @} */
+
+
+/**
+ * @group dTSEC bus interface.
+ * @{
+ */
+
+int
+memac_attach(device_t dev)
+{
+ struct memac_softc *sc;
+ int error;
+ if_t ifp;
+
+ sc = device_get_softc(dev);
+
+ sc->sc_base.sc_dev = dev;
+
+ /* Init locks */
+ mtx_init(&sc->sc_base.sc_lock, device_get_nameunit(dev),
+ "mEMAC Global Lock", MTX_DEF);
+
+ mtx_init(&sc->sc_base.sc_mii_lock, device_get_nameunit(dev),
+ "mEMAC MII Lock", MTX_DEF);
+
+ /* Init callouts */
+ callout_init(&sc->sc_base.sc_tick_callout, CALLOUT_MPSAFE);
+
+ /* Create RX buffer pool */
+ error = dpaa_eth_pool_rx_init(&sc->sc_base);
+ if (error != 0)
+ return (EIO);
+
+ /* Create RX frame queue range */
+ error = dpaa_eth_fq_rx_init(&sc->sc_base);
+ if (error != 0)
+ return (EIO);
+
+ /* Create frame info pool */
+ error = dpaa_eth_fi_pool_init(&sc->sc_base);
+ if (error != 0)
+ return (EIO);
+
+ /* Create TX frame queue range */
+ error = dpaa_eth_fq_tx_init(&sc->sc_base);
+ if (error != 0)
+ return (EIO);
+
+ /* Init FMan MAC module. */
+ error = memac_fm_mac_init(sc, sc->sc_base.sc_mac_addr);
+ if (error != 0) {
+ memac_detach(dev);
+ return (ENXIO);
+ }
+
+ dpaa_eth_fm_port_rx_init(&sc->sc_base);
+ dpaa_eth_fm_port_tx_init(&sc->sc_base);
+
+ /* Create network interface for upper layers */
+ ifp = sc->sc_base.sc_ifnet = if_alloc(IFT_ETHER);
+ if_setsoftc(ifp, sc);
+
+ if_setflags(ifp, IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST);
+ if_setinitfn(ifp, memac_if_init);
+ if_setstartfn(ifp, memac_if_start);
+ if_setioctlfn(ifp, memac_if_ioctl);
+ if_setsendqlen(ifp, IFQ_MAXLEN);
+ if_setsendqready(ifp);
+
+ if (sc->sc_base.sc_phy_addr >= 0)
+ if_initname(ifp, device_get_name(sc->sc_base.sc_dev),
+ device_get_unit(sc->sc_base.sc_dev));
+ else
+ if_initname(ifp, "memac_phy",
+ device_get_unit(sc->sc_base.sc_dev));
+
+
+ if_setcapabilities(ifp, IFCAP_JUMBO_MTU |
+ IFCAP_VLAN_MTU | IFCAP_VLAN_HWCSUM |
+ IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6 |
+ IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6);
+ if_setcapenable(ifp, if_getcapabilities(ifp));
+ if_sethwassist(ifp, DPAA_CSUM_TX_OFFLOAD);
+
+ /* Attach PHY(s) */
+ if (!sc->sc_fixed_link) {
+ error = mii_attach(sc->sc_base.sc_dev, &sc->sc_base.sc_mii_dev,
+ ifp, memac_ifmedia_upd, memac_ifmedia_sts, BMSR_DEFCAPMASK,
+ sc->sc_base.sc_phy_addr, MII_OFFSET_ANY, 0);
+ if (error) {
+ device_printf(sc->sc_base.sc_dev,
+ "attaching PHYs failed: %d\n", error);
+ memac_detach(sc->sc_base.sc_dev);
+ return (error);
+ }
+ sc->sc_base.sc_mii = device_get_softc(sc->sc_base.sc_mii_dev);
+ } else {
+ phandle_t node;
+ uint32_t type = IFM_ETHER;
+ uint32_t speed;
+
+ node = ofw_bus_find_child(ofw_bus_get_node(dev), "fixed-link");
+ if (OF_getencprop(node, "speed", &speed, sizeof(speed)) <= 0) {
+ device_printf(dev,
+ "fixed link has no speed property\n");
+ memac_detach(sc->sc_base.sc_dev);
+ return (ENXIO);
+ }
+ switch (speed) {
+ case 10:
+ type |= IFM_10_T;
+ break;
+ case 100:
+ type |= IFM_100_TX;
+ break;
+ case 1000:
+ type |= IFM_1000_T;
+ break;
+ case 2500:
+ type |= IFM_2500_T;
+ break;
+ case 5000:
+ type |= IFM_5000_T;
+ break;
+ case 10000:
+ type |= IFM_10G_T;
+ break;
+ }
+ if (OF_hasprop(node, "full-duplex"))
+ type |= IFM_FDX;
+ sc->sc_base.sc_mii = malloc(sizeof(*sc->sc_base.sc_mii),
+ M_DEVBUF, M_WAITOK | M_ZERO);
+ ifmedia_init(&sc->sc_base.sc_mii->mii_media, 0,
+ memac_ifmedia_upd, memac_ifmedia_fixed_sts);
+ ifmedia_add(&sc->sc_base.sc_mii->mii_media, type, 0, NULL);
+ ifmedia_set(&sc->sc_base.sc_mii->mii_media, type);
+ }
+
+ /* Attach to stack */
+ ether_ifattach(ifp, sc->sc_base.sc_mac_addr);
+
+ return (0);
+}
+
+int
+memac_detach(device_t dev)
+{
+ struct memac_softc *sc;
+ if_t ifp;
+
+ sc = device_get_softc(dev);
+ ifp = sc->sc_base.sc_ifnet;
+
+ if (device_is_attached(dev)) {
+ ether_ifdetach(ifp);
+ /* Shutdown interface */
+ MEMAC_LOCK(sc);
+ memac_if_deinit_locked(sc);
+ MEMAC_UNLOCK(sc);
+ }
+
+ if (sc->sc_base.sc_ifnet) {
+ if_free(sc->sc_base.sc_ifnet);
+ sc->sc_base.sc_ifnet = NULL;
+ }
+
+ /* Free RX/TX FQRs */
+ dpaa_eth_fq_rx_free(&sc->sc_base);
+ dpaa_eth_fq_tx_free(&sc->sc_base);
+
+ /* Free frame info pool */
+ dpaa_eth_fi_pool_free(&sc->sc_base);
+
+ /* Free RX buffer pool */
+ dpaa_eth_pool_rx_free(&sc->sc_base);
+
+ /* Destroy lock */
+ mtx_destroy(&sc->sc_base.sc_lock);
+
+ return (0);
+}
+
+int
+memac_suspend(device_t dev)
+{
+
+ return (0);
+}
+
+int
+memac_resume(device_t dev)
+{
+
+ return (0);
+}
+
+int
+memac_shutdown(device_t dev)
+{
+
+ return (0);
+}
+/** @} */
+
+
+/**
+ * @group MII bus interface.
+ * @{
+ */
+int
+memac_miibus_readreg(device_t dev, int phy, int reg)
+{
+ struct memac_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ return (MIIBUS_READREG(sc->sc_base.sc_mdio, phy, reg));
+}
+
+int
+memac_miibus_writereg(device_t dev, int phy, int reg, int value)
+{
+
+ struct memac_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ return (MIIBUS_WRITEREG(sc->sc_base.sc_mdio, phy, reg, value));
+}
+
+void
+memac_miibus_statchg(device_t dev)
+{
+ struct memac_softc *sc;
+ uint32_t reg;
+ bool duplex;
+ int speed;
+
+ sc = device_get_softc(dev);
+
+ MEMAC_LOCK_ASSERT(sc);
+
+ duplex = ((sc->sc_base.sc_mii->mii_media_active & IFM_GMASK) == IFM_FDX);
+
+ switch (IFM_SUBTYPE(sc->sc_base.sc_mii->mii_media_active)) {
+ case IFM_AUTO:
+ speed = IF_MODE_ENA;
+ break;
+ case IFM_1000_T:
+ case IFM_1000_SX:
+ if (!duplex) {
+ device_printf(sc->sc_base.sc_dev,
+ "Only full-duplex supported for 1Gbps speeds");
+ return;
+ }
+ speed = IF_MODE_SSP_1GB;
+ break;
+
+ case IFM_100_TX:
+ speed = IF_MODE_SSP_100MB;
+ break;
+ default:
+ speed = IF_MODE_SSP_10MB;
+ break;
+ }
+
+ reg = bus_read_4(sc->sc_base.sc_mem, MEMAC_IF_MODE);
+ reg &= ~(IF_MODE_ENA | IF_MODE_SSP_M | IF_MODE_SFD);
+ reg |= 0x2;
+
+ if (duplex)
+ reg |= IF_MODE_SFD;
+ else
+ reg |= IF_MODE_HD;
+ reg |= speed;
+ bus_write_4(sc->sc_base.sc_mem, MEMAC_IF_MODE, reg);
+}
+/** @} */
diff --git a/sys/dev/dpaa/if_memac.h b/sys/dev/dpaa/if_memac.h
new file mode 100644
index 000000000000..98942abaf79c
--- /dev/null
+++ b/sys/dev/dpaa/if_memac.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2026 Justin Hibbits
+ * Copyright (c) 2011-2012 Semihalf.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef IF_MEMAC_H_
+#define IF_MEMAC_H_
+
+/**
+ * @group dTSEC common API.
+ * @{
+ */
+#define MEMAC_MODE_REGULAR 0
+
+#define MEMAC_LOCK(sc) mtx_lock(&(sc)->sc_base.sc_lock)
+#define MEMAC_UNLOCK(sc) mtx_unlock(&(sc)->sc_base.sc_lock)
+#define MEMAC_LOCK_ASSERT(sc) mtx_assert(&(sc)->sc_base.sc_lock, MA_OWNED)
+#define MEMAC_MII_LOCK(sc) mtx_lock(&(sc)->sc_base.sc_mii_lock)
+#define MEMAC_MII_UNLOCK(sc) mtx_unlock(&(sc)->sc_base.sc_mii_lock)
+
+enum eth_dev_type {
+ ETH_MEMAC = 0x1,
+ ETH_10GSEC = 0x2
+};
+
+struct memac_softc {
+ struct dpaa_eth_softc sc_base;
+ bool sc_fixed_link;
+};
+/** @} */
+
+
+/**
+ * @group dTSEC bus interface.
+ * @{
+ */
+int memac_attach(device_t dev);
+int memac_detach(device_t dev);
+int memac_suspend(device_t dev);
+int memac_resume(device_t dev);
+int memac_shutdown(device_t dev);
+int memac_miibus_readreg(device_t dev, int phy, int reg);
+int memac_miibus_writereg(device_t dev, int phy, int reg,
+ int value);
+void memac_miibus_statchg(device_t dev);
+/** @} */
+
+#endif /* IF_MEMAC_H_ */
diff --git a/sys/dev/dpaa/if_memac_fdt.c b/sys/dev/dpaa/if_memac_fdt.c
new file mode 100644
index 000000000000..f136608a906c
--- /dev/null
+++ b/sys/dev/dpaa/if_memac_fdt.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2026 Justin Hibbits
+ * Copyright (c) 2012 Semihalf.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/socket.h>
+
+#include <machine/bus.h>
+
+#include <powerpc/mpc85xx/mpc85xx.h>
+
+#include <net/if.h>
+#include <net/if_media.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+#include <dev/mii/mii_fdt.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/openfirm.h>
+
+#include "miibus_if.h"
+
+#include "dpaa_eth.h"
+#include "if_memac.h"
+#include "fman.h"
+
+
+static int memac_fdt_probe(device_t dev);
+static int memac_fdt_attach(device_t dev);
+
+static device_method_t memac_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, memac_fdt_probe),
+ DEVMETHOD(device_attach, memac_fdt_attach),
+ DEVMETHOD(device_detach, memac_detach),
+
+ DEVMETHOD(device_shutdown, memac_shutdown),
+ DEVMETHOD(device_suspend, memac_suspend),
+ DEVMETHOD(device_resume, memac_resume),
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_driver_added, bus_generic_driver_added),
+
+ /* MII interface */
+ DEVMETHOD(miibus_readreg, memac_miibus_readreg),
+ DEVMETHOD(miibus_writereg, memac_miibus_writereg),
+ DEVMETHOD(miibus_statchg, memac_miibus_statchg),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(memac, memac_driver, memac_methods, sizeof(struct memac_softc));
+
+DRIVER_MODULE(memac, fman, memac_driver, 0, 0);
+DRIVER_MODULE(miibus, memac, miibus_driver, 0, 0);
+MODULE_DEPEND(memac, ether, 1, 1, 1);
+MODULE_DEPEND(memac, miibus, 1, 1, 1);
+
+static int
+memac_fdt_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "fsl,fman-memac"))
+ return (ENXIO);
+
+ device_set_desc(dev,
+ "Freescale Multirate Ethernet Media Access Controller");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+memac_fdt_attach(device_t dev)
+{
+ struct memac_softc *sc;
+ device_t phy_dev;
+ phandle_t enet_node, phy_node;
+ phandle_t fman_rxtx_node[2];
+ pcell_t fman_tx_cell, mac_id;
+
+ sc = device_get_softc(dev);
+ enet_node = ofw_bus_get_node(dev);
+
+ if (OF_getprop(enet_node, "local-mac-address",
+ (void *)sc->sc_base.sc_mac_addr, 6) == -1) {
+ device_printf(dev,
+ "Could not load local-mac-addr property from DTS\n");
+ return (ENXIO);
+ }
+
+ /* Get PHY connection type */
+ sc->sc_base.sc_mac_enet_mode = mii_fdt_get_contype(enet_node);
+
+ sc->sc_fixed_link = OF_hasprop(enet_node, "fixed-link") ||
+ (ofw_bus_find_child(enet_node, "fixed-link") != 0);
+ if (!sc->sc_fixed_link) {
+ OF_getprop(enet_node, "phy-handle", &phy_node, sizeof(phy_node));
+ phy_node = OF_node_from_xref(phy_node);
+
+ if (OF_getencprop(phy_node, "reg", (void *)&sc->sc_base.sc_phy_addr,
+ sizeof(sc->sc_base.sc_phy_addr)) <= 0)
+ return (ENXIO);
+
+ phy_dev = OF_device_from_xref(OF_xref_from_node(OF_parent(phy_node)));
+
+ if (phy_dev == NULL) {
+ device_printf(dev, "No PHY found.\n");
+ return (ENXIO);
+ }
+
+ sc->sc_base.sc_mdio = phy_dev;
+ }
+
+ /* Get MAC memory offset in SoC */
+ sc->sc_base.sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 0, RF_ACTIVE);
+ if (sc->sc_base.sc_mem == NULL)
+ return (ENXIO);
+
+ sc->sc_base.sc_mac_enet_mode = mii_fdt_get_contype(enet_node);
+
+ if (sc->sc_base.sc_mac_enet_mode == MII_CONTYPE_UNKNOWN) {
+ device_printf(dev, "unknown MII type, defaulting to SGMII\n");
+ sc->sc_base.sc_mac_enet_mode = MII_CONTYPE_SGMII;
+ }
+
+ if (OF_getencprop(enet_node, "cell-index",
+ (void *)&mac_id, sizeof(mac_id)) <= 0)
+ return (ENXIO);
+ sc->sc_base.sc_eth_id = mac_id;
+
+ /* Get RX/TX port handles */
+ if (OF_getencprop(enet_node, "fsl,fman-ports", (void *)fman_rxtx_node,
+ sizeof(fman_rxtx_node)) <= 0)
+ return (ENXIO);
+
+ if (fman_rxtx_node[0] == 0)
+ return (ENXIO);
+
+ if (fman_rxtx_node[1] == 0)
+ return (ENXIO);
+
+ sc->sc_base.sc_rx_port = OF_device_from_xref(fman_rxtx_node[0]);
+ sc->sc_base.sc_tx_port = OF_device_from_xref(fman_rxtx_node[1]);
+
+ if (sc->sc_base.sc_rx_port == NULL || sc->sc_base.sc_tx_port == NULL)
+ return (ENXIO);
+
+ fman_rxtx_node[1] = OF_node_from_xref(fman_rxtx_node[1]);
+ if (OF_getencprop(fman_rxtx_node[1], "cell-index", &fman_tx_cell,
+ sizeof(fman_tx_cell)) <= 0)
+ return (ENXIO);
+ /* Get QMan channel */
+ sc->sc_base.sc_port_tx_qman_chan = fman_qman_channel_id(device_get_parent(dev),
+ fman_tx_cell);
+
+ return (memac_attach(dev));
+}
diff --git a/sys/dev/dpaa/portals.h b/sys/dev/dpaa/portals.h
index a2d6294f3d8e..ef550b09a726 100644
--- a/sys/dev/dpaa/portals.h
+++ b/sys/dev/dpaa/portals.h
@@ -24,39 +24,30 @@
* SUCH DAMAGE.
*/
-typedef struct dpaa_portal {
- int dp_irid; /* interrupt rid */
- struct resource *dp_ires; /* interrupt resource */
+#ifndef DPAA_PORTALS_H
+#define DPAA_PORTALS_H
- bool dp_regs_mapped; /* register mapping status */
-
- t_Handle dp_ph; /* portal's handle */
- vm_paddr_t dp_ce_pa; /* portal's CE area PA */
- vm_paddr_t dp_ci_pa; /* portal's CI area PA */
- uint32_t dp_ce_size; /* portal's CE area size */
- uint32_t dp_ci_size; /* portal's CI area size */
- uintptr_t dp_intr_num; /* portal's intr. number */
-} dpaa_portal_t;
-
-struct dpaa_portals_softc {
+struct dpaa_portal_softc {
device_t sc_dev; /* device handle */
- vm_paddr_t sc_dp_pa; /* portal's PA */
- uint32_t sc_dp_size; /* portal's size */
- int sc_rrid[2]; /* memory rid */
- struct resource *sc_rres[2]; /* memory resource */
- dpaa_portal_t sc_dp[MAXCPU];
-};
-
-struct dpaa_portals_devinfo {
- struct resource_list di_res;
- int di_intr_rid;
+ vm_paddr_t sc_ce_pa; /* portal's CE PA */
+ vm_offset_t sc_ce_va;
+ vm_paddr_t sc_ci_pa; /* portal's CI PA */
+ vm_offset_t sc_ci_va;
+ int sc_cpu;
+ uint32_t sc_ce_size; /* portal's CE size */
+ uint32_t sc_ci_size; /* portal's CI size */
+ struct resource *sc_mres[2]; /* memory resource */
+ struct resource *sc_ires; /* Interrupt */
+ void *sc_intr_cookie;
+ bool sc_regs_mapped; /* register mapping status */
};
-int bman_portals_attach(device_t);
-int bman_portals_detach(device_t);
+int bman_portal_attach(device_t, int);
+int bman_portal_detach(device_t);
-int qman_portals_attach(device_t);
-int qman_portals_detach(device_t);
+int qman_portal_attach(device_t, int);
+int qman_portal_detach(device_t);
-int dpaa_portal_alloc_res(device_t, struct dpaa_portals_devinfo *, int);
-void dpaa_portal_map_registers(struct dpaa_portals_softc *);
+int dpaa_portal_alloc_res(device_t, int);
+void dpaa_portal_map_registers(struct dpaa_portal_softc *);
+#endif
diff --git a/sys/dev/dpaa/portals_common.c b/sys/dev/dpaa/portals_common.c
index ed8e577694f2..c4501af05889 100644
--- a/sys/dev/dpaa/portals_common.c
+++ b/sys/dev/dpaa/portals_common.c
@@ -41,127 +41,46 @@
#include <machine/resource.h>
#include <machine/tlb.h>
-#include <contrib/ncsw/inc/error_ext.h>
-#include <contrib/ncsw/inc/xx_ext.h>
-
#include "portals.h"
int
-dpaa_portal_alloc_res(device_t dev, struct dpaa_portals_devinfo *di, int cpu)
+dpaa_portal_alloc_res(device_t dev, int cpu)
{
- struct dpaa_portals_softc *sc = device_get_softc(dev);
- struct resource_list_entry *rle;
- int err;
- struct resource_list *res;
+ struct dpaa_portal_softc *sc = device_get_softc(dev);
- /* Check if MallocSmart allocator is ready */
- if (XX_MallocSmartInit() != E_OK)
+ sc->sc_mres[0] = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ 0, RF_ACTIVE);
+ if (sc->sc_mres[0] == NULL) {
+ device_printf(dev,
+ "Could not allocate cache enabled memory.\n");
return (ENXIO);
-
- res = &di->di_res;
-
- /*
- * Allocate memory.
- * Reserve only one pair of CE/CI virtual memory regions
- * for all CPUs, in order to save the space.
- */
- if (sc->sc_rres[0] == NULL) {
- /* Cache enabled area */
- rle = resource_list_find(res, SYS_RES_MEMORY, 0);
- sc->sc_rrid[0] = 0;
- sc->sc_rres[0] = bus_alloc_resource(dev,
- SYS_RES_MEMORY, &sc->sc_rrid[0], rle->start + sc->sc_dp_pa,
- rle->end + sc->sc_dp_pa, rle->count, RF_ACTIVE);
- if (sc->sc_rres[0] == NULL) {
- device_printf(dev,
- "Could not allocate cache enabled memory.\n");
- return (ENXIO);
- }
- tlb1_set_entry(rman_get_bushandle(sc->sc_rres[0]),
- rle->start + sc->sc_dp_pa, rle->count, _TLB_ENTRY_MEM);
- /* Cache inhibited area */
- rle = resource_list_find(res, SYS_RES_MEMORY, 1);
- sc->sc_rrid[1] = 1;
- sc->sc_rres[1] = bus_alloc_resource(dev,
- SYS_RES_MEMORY, &sc->sc_rrid[1], rle->start + sc->sc_dp_pa,
- rle->end + sc->sc_dp_pa, rle->count, RF_ACTIVE);
- if (sc->sc_rres[1] == NULL) {
- device_printf(dev,
- "Could not allocate cache inhibited memory.\n");
- bus_release_resource(dev, SYS_RES_MEMORY,
- sc->sc_rrid[0], sc->sc_rres[0]);
- return (ENXIO);
- }
- tlb1_set_entry(rman_get_bushandle(sc->sc_rres[1]),
- rle->start + sc->sc_dp_pa, rle->count, _TLB_ENTRY_IO);
- sc->sc_dp[cpu].dp_regs_mapped = 1;
}
- /* Acquire portal's CE_PA and CI_PA */
- rle = resource_list_find(res, SYS_RES_MEMORY, 0);
- sc->sc_dp[cpu].dp_ce_pa = rle->start + sc->sc_dp_pa;
- sc->sc_dp[cpu].dp_ce_size = rle->count;
- rle = resource_list_find(res, SYS_RES_MEMORY, 1);
- sc->sc_dp[cpu].dp_ci_pa = rle->start + sc->sc_dp_pa;
- sc->sc_dp[cpu].dp_ci_size = rle->count;
-
- /* Allocate interrupts */
- rle = resource_list_find(res, SYS_RES_IRQ, 0);
- sc->sc_dp[cpu].dp_irid = 0;
- sc->sc_dp[cpu].dp_ires = bus_alloc_resource(dev,
- SYS_RES_IRQ, &sc->sc_dp[cpu].dp_irid, rle->start, rle->end,
- rle->count, RF_ACTIVE);
- /* Save interrupt number for later use */
- sc->sc_dp[cpu].dp_intr_num = rle->start;
-
- if (sc->sc_dp[cpu].dp_ires == NULL) {
- device_printf(dev, "Could not allocate irq.\n");
+ /* Cache inhibited area */
+ sc->sc_mres[1] = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ 1, RF_ACTIVE);
+ if (sc->sc_mres[1] == NULL) {
+ device_printf(dev,
+ "Could not allocate cache inhibited memory.\n");
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mres[0]);
return (ENXIO);
}
- err = XX_PreallocAndBindIntr(dev, (uintptr_t)sc->sc_dp[cpu].dp_ires, cpu);
+ sc->sc_dev = dev;
+ sc->sc_ce_va = rman_get_bushandle(sc->sc_mres[0]);
+ sc->sc_ce_size = rman_get_size(sc->sc_mres[0]);
+ sc->sc_ce_pa = pmap_kextract(sc->sc_ce_va);
+ sc->sc_ci_va = rman_get_bushandle(sc->sc_mres[1]);
+ sc->sc_ci_size = rman_get_size(sc->sc_mres[1]);
+ sc->sc_ci_pa = pmap_kextract(sc->sc_ci_va);
+ tlb1_set_entry(sc->sc_ce_va, sc->sc_ce_pa, sc->sc_ce_size,
+ _TLB_ENTRY_MEM | _TLB_ENTRY_SHARED);
+ sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, 0, RF_ACTIVE);
- if (err != E_OK) {
- device_printf(dev, "Could not prealloc and bind interrupt\n");
- bus_release_resource(dev, SYS_RES_IRQ,
- sc->sc_dp[cpu].dp_irid, sc->sc_dp[cpu].dp_ires);
- sc->sc_dp[cpu].dp_ires = NULL;
+ /* Allocate interrupts */
+ if (sc->sc_ires == NULL) {
+ device_printf(dev, "Could not allocate irq.\n");
return (ENXIO);
}
-#if 0
- err = bus_generic_config_intr(dev, rle->start, di->di_intr_trig,
- di->di_intr_pol);
- if (err != 0) {
- device_printf(dev, "Could not configure interrupt\n");
- bus_release_resource(dev, SYS_RES_IRQ,
- sc->sc_dp[cpu].dp_irid, sc->sc_dp[cpu].dp_ires);
- sc->sc_dp[cpu].dp_ires = NULL;
- return (err);
- }
-#endif
-
return (0);
}
-
-void
-dpaa_portal_map_registers(struct dpaa_portals_softc *sc)
-{
- unsigned int cpu;
-
- sched_pin();
- cpu = PCPU_GET(cpuid);
- if (sc->sc_dp[cpu].dp_regs_mapped)
- goto out;
-
- tlb1_set_entry(rman_get_bushandle(sc->sc_rres[0]),
- sc->sc_dp[cpu].dp_ce_pa, sc->sc_dp[cpu].dp_ce_size,
- _TLB_ENTRY_MEM);
- tlb1_set_entry(rman_get_bushandle(sc->sc_rres[1]),
- sc->sc_dp[cpu].dp_ci_pa, sc->sc_dp[cpu].dp_ci_size,
- _TLB_ENTRY_IO);
-
- sc->sc_dp[cpu].dp_regs_mapped = 1;
-
-out:
- sched_unpin();
-}
diff --git a/sys/dev/dpaa/qman.c b/sys/dev/dpaa/qman.c
index fccaa853918b..9143ebde5cb4 100644
--- a/sys/dev/dpaa/qman.c
+++ b/sys/dev/dpaa/qman.c
@@ -1,3 +1,8 @@
+/*
+ * Copyright (c) 2026 Justin Hibbits
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
/*-
* Copyright (c) 2011-2012 Semihalf.
* All rights reserved.
@@ -29,6 +34,7 @@
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/lock.h>
+#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/proc.h>
@@ -41,139 +47,276 @@
#include <machine/resource.h>
#include <machine/tlb.h>
-#include "qman.h"
+#include "dpaa_common.h"
#include "portals.h"
+#include "qman.h"
+#include "qman_var.h"
+#include "qman_portal_if.h"
+
+/* Registers */
+#define QCSP_IO_CFG(n) (0x004 + (n) * 16)
+#define IO_CFG_SDEST_M 0x00ff0000
+#define IO_CFG_SDEST_S 16
+#define QMAN_DCP_CFG(n) (0x300 + (n) * 0x10)
+#define DCP_CFG_ED 0x00000100
+#define DCP_CFG_ED_3 0x00001000
+#define QMAN_PFDR_FP_LWIT 0x410
+#define QMAN_PFDR_CFG 0x414
+#define QMAN_SFDR_CFG 0x500
+#define QMAN_MCR 0xb00
+#define MCR_INIT_PFDR 0x01000000
+#define MCR_READ_PFDR 0x02000000
+#define MCR_READ_SFDR 0x03000000
+#define MCR_QUERY_FQD_FILL 0x10000000
+#define MCR_QUERY_FQD_TAGS 0x11000000
+#define MCR_QUERY_FQD_CACHE 0x12000000
+#define MCR_QUERY_WQ 0x20000000
+#define MCR_RSLT_OK 0xf0000000
+#define MCR_RSLT_OK_DATA 0xf1000000
+#define MCR_RSLT_ABRT_INV 0xf4000000
+#define MCR_RSLT_ABRT_DIS 0xf8000000
+#define MCR_RSLT_ABRT_IDX 0xff000000
+#define MCR_RSLT_ABRT_MASK 0xff000000
+#define QMAN_MCP0 0xb04
+#define QMAN_MCP1 0xb08
+#define QMAN_IP_REV_1 0xbf8
+#define IP_MJ_M 0x0000ff00
+#define IP_MJ_S 8
+#define IP_MN_M 0x000000ff
+#define QMAN_FQD_BARE 0xc00
+#define QMAN_FQD_BAR 0xc04
+#define QMAN_FQD_AR 0xc10
+#define AR_EN 0x80000000
+#define QMAN_PFDR_BARE 0xc20
+#define QMAN_PFDR_BAR 0xc24
+#define QMAN_PFDR_AR 0xc30
+#define QMAN_QCSP_BARE 0xc80
+#define QMAN_QCSP_BAR 0xc84
+#define QMAN_QCSP_AR 0xc90
+#define QMAN_CI_SCHED_CFG 0xd00
+#define CI_SCHED_CFG_SW 0x80000000
+#define CI_SCHED_CFG_SRCCIV 0x04000000 /* Recommended */
+#define CI_SCHED_CFG_SRQ_W_M 0x00000700
+#define CI_SCHED_CFG_SRQ_W_S 8
+#define CI_SCHED_CFG_RW_W_M 0x00000070
+#define CI_SCHED_CFG_RW_W_S 4
+#define CI_SCHED_CFG_BMAN_W_M 0x00000007
+#define QMAN_ERR_ISR 0xe00
+#define QMAN_ERR_IER 0xe04
+#define QCSP_IO_CFG_3(n) (0x1004 + (n) * 16)
+
+/* Software portals. Cache-inhibited registers */
+
+#define QCSP_DQRR_PDQCR 0x05c
+
+/* Software portals. Cache-enabled registers */
+
+#define QCSP_VERB_INIT_FQ_PARK 0x40
+#define QCSP_VERB_INIT_FQ_SCHED 0x41
+#define QCSP_VERB_QUERY_FQ 0x44
+#define QCSP_VERB_QUERY_FQ_NP 0x45
+#define QCSP_VERB_ALTER_FQ_SCHED 0x48
+#define QCSP_VERB_ALTER_FQ_FE 0x49
+#define QCSP_VERB_ALTER_FQ_RETIRE 0x4a
+#define QCSP_VERB_ALTER_FQ_TAKE_OUT 0x4b
+#define QCSP_VERB_ALTER_FQ_RETIRE_CTXB 0x4c
+#define QCSP_VERB_ALTER_FQ_XON 0x4d
+#define QCSP_VERB_ALTER_FQ_XOFF 0x4e
+
+/* Init FQ */
+#define QCSP_INIT_FQ_WE_OAC 0x0100
+#define QCSP_INIT_FQ_WE_ORPC 0x0080
+#define QCSP_INIT_FQ_WE_CGID 0x0040
+#define QCSP_INIT_FQ_WE_FQ_CTRL 0x0020
+#define QCSP_INIT_FQ_WE_DEST_WQ 0x0010
+#define QCSP_INIT_FQ_WE_ICS_CRED 0x0008
+#define QCSP_INIT_FQ_WE_TD_THRESH 0x0004
+#define QCSP_INIT_FQ_WE_CONTEXT_B 0x0002
+#define QCSP_INIT_FQ_WE_CONTEXT_A 0x0001
+
+#define QMAN_MC_RES_OK 0xf0
+
+#define QMAN_MC_AFQS_NE 0x01
+
+/* Init FQ options */
+#define QM_FQCTRL_CGE 0x0400
+#define QM_FQCTRL_TDE 0x0200
+#define QM_FQCTRL_ORP 0x0100
+#define QM_FQCTRL_CTXASTASH 0x0080
+#define QM_FQCTRL_CPCSTASH 0x0040
+#define QM_FQCTRL_FORCESFDR 0x0008
+#define QM_FQCTRL_AVOIDBLOCK 0x0004
+#define QM_FQCTRL_HOLDACTIVE 0x0002
+#define QM_FQCTRL_LIC 0x0001
+
+#define QMAN_CHANNEL_POOL1_REV1 0x21
+#define QMAN_CHANNEL_POOL1_REV3 0x401
+
+#define QMAN_PFDR_MAX 0xfffeff
+
+/* P1023 has only 3 pool channels, but we don't support that SoC. */
+#define QMAN_POOL_CHANNELS 15
+
+/* P1023 only supports 64 congestion groups... */
+#define QMAN_CGRS 256
-extern struct dpaa_portals_softc *qp_sc;
static struct qman_softc *qman_sc;
-extern t_Handle qman_portal_setup(struct qman_softc *qsc);
+static MALLOC_DEFINE(M_QMAN, "qman", "DPAA Queue Manager structures");
+
+int qman_channel_base;
+int qman_total_fqids;
+struct qman_fq **qman_fq_list;
+
+/* Entries sorted right-to-left in bit order of the ISR */
+static const char * const qman_errors[] = {
+ "Invalid enqueue queue",
+ "Invalid enqueue channel!",
+ "Invalid enqueue state",
+ "Invalid enqueue overflow",
+ "Invalid enqueue configuration",
+ NULL,
+ NULL,
+ NULL,
+ "Invalid dequeue queue",
+ "Invalid dequeue source",
+ "Invalid dequeue FQ",
+ "Invalid dequeue direct connect portal",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "Invalid command verb",
+ "Invalid FQ flow control state",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "Insufficient free PFDRs",
+ "Single-bit ECC error",
+ "Multi-bit ECC error",
+ "PFDR low watermark",
+ "Invalid target transaction",
+ "Initiator data error",
+ NULL,
+ NULL
+};
static void
-qman_exception(t_Handle app, e_QmExceptions exception)
+qman_isr(void *arg)
{
- struct qman_softc *sc;
- const char *message;
+ struct qman_softc *sc = arg;
+ uint32_t ier, isr, isr_bit;
+ int i;
- sc = app;
+ ier = bus_read_4(sc->sc_rres, QMAN_ERR_IER);
+ isr = bus_read_4(sc->sc_rres, QMAN_ERR_ISR);
- switch (exception) {
- case e_QM_EX_CORENET_INITIATOR_DATA:
- message = "Initiator Data Error";
- break;
- case e_QM_EX_CORENET_TARGET_DATA:
- message = "CoreNet Target Data Error";
- break;
- case e_QM_EX_CORENET_INVALID_TARGET_TRANSACTION:
- message = "Invalid Target Transaction";
- break;
- case e_QM_EX_PFDR_THRESHOLD:
- message = "PFDR Low Watermark Interrupt";
- break;
- case e_QM_EX_PFDR_ENQUEUE_BLOCKED:
- message = "PFDR Enqueues Blocked Interrupt";
- break;
- case e_QM_EX_SINGLE_ECC:
- message = "Single Bit ECC Error Interrupt";
- break;
- case e_QM_EX_MULTI_ECC:
- message = "Multi Bit ECC Error Interrupt";
- break;
- case e_QM_EX_INVALID_COMMAND:
- message = "Invalid Command Verb Interrupt";
- break;
- case e_QM_EX_DEQUEUE_DCP:
- message = "Invalid Dequeue Direct Connect Portal Interrupt";
- break;
- case e_QM_EX_DEQUEUE_FQ:
- message = "Invalid Dequeue FQ Interrupt";
- break;
- case e_QM_EX_DEQUEUE_SOURCE:
- message = "Invalid Dequeue Source Interrupt";
- break;
- case e_QM_EX_DEQUEUE_QUEUE:
- message = "Invalid Dequeue Queue Interrupt";
- break;
- case e_QM_EX_ENQUEUE_OVERFLOW:
- message = "Invalid Enqueue Overflow Interrupt";
- break;
- case e_QM_EX_ENQUEUE_STATE:
- message = "Invalid Enqueue State Interrupt";
- break;
- case e_QM_EX_ENQUEUE_CHANNEL:
- message = "Invalid Enqueue Channel Interrupt";
- break;
- case e_QM_EX_ENQUEUE_QUEUE:
- message = "Invalid Enqueue Queue Interrupt";
- break;
- case e_QM_EX_CG_STATE_CHANGE:
- message = "CG change state notification";
- break;
- default:
- message = "Unknown error";
+ if ((ier & isr) == 0)
+ return;
+
+ isr_bit = (isr & ier);
+ for (i = 0; isr_bit != 0; i++, isr_bit >>= 1) {
+ if (isr_bit & 1)
+ device_printf(sc->sc_dev, "%s", qman_errors[i]);
}
- device_printf(sc->sc_dev, "QMan Exception: %s.\n", message);
+ bus_write_4(sc->sc_rres, QMAN_ERR_ISR, isr);
}
-/**
- * General received frame callback.
- * This is called, when user did not register his own callback for a given
- * frame queue range (fqr).
- */
-e_RxStoreResponse
-qman_received_frame_callback(t_Handle app, t_Handle qm_fqr, t_Handle qm_portal,
- uint32_t fqid_offset, t_DpaaFD *frame)
+
+/* Set up reserved memory configuration for PFDR and FQD, per `off`. */
+static int
+qman_set_memory(struct qman_softc *sc, vm_paddr_t pa,
+ vm_size_t size, bus_size_t off)
{
- struct qman_softc *sc;
+ uint32_t bar, bare;
+ vm_paddr_t old_bar;
+
+ /*
+ * Register offsets:
+ * 0 - BARE
+ * 4 - BAR
+ * 0x10 - AR
+ */
+ bare = bus_read_4(sc->sc_rres, off);
+ bar = bus_read_4(sc->sc_rres, off + 4);
+ old_bar = (vm_paddr_t)bare << 32 | bar;
- sc = app;
+ if (old_bar != 0 && old_bar != pa) {
+ device_printf(sc->sc_dev, "QMan BAR already initialized!\n");
+ return (ENOMEM);
+ } else if (old_bar == pa)
+ return (EEXIST);
- device_printf(sc->sc_dev, "dummy callback for received frame.\n");
- return (e_RX_STORE_RESPONSE_CONTINUE);
+ /*
+ * Zero the memory and flush cache through DMAP. QMan accesses the
+ * memory as non-coherent.
+ */
+ memset((void *)PHYS_TO_DMAP(pa), 0, size);
+ cpu_flush_dcache((void *)PHYS_TO_DMAP(pa), size);
+
+ bus_write_4(sc->sc_rres, off, pa >> 32);
+ bus_write_4(sc->sc_rres, off + 4, (uint32_t)pa);
+ bus_write_4(sc->sc_rres, off + 0x10, AR_EN | (ilog2(size) - 1));
+
+ return (0);
}
-/**
- * General rejected frame callback.
- * This is called, when user did not register his own callback for a given
- * frame queue range (fqr).
+/*
+ * Set up PFDR structures. Some things to keep in mind:
+ * - npfdr is the total number of PFDRs in the private memory. PFDRs are 64
+ * bytes in size, so npfdr is (pfdr_sz/64).
+ * - PFDR 0-7 are reserved, so the base starts at 8, not 0, so we adjust
+ * internally.
+ * - The second parameter is the last PFDR, not the number of PFDRs, so needs to
+ * be adjusted down one more, so subtract 9.
*/
-e_RxStoreResponse
-qman_rejected_frame_callback(t_Handle app, t_Handle qm_fqr, t_Handle qm_portal,
- uint32_t fqid_offset, t_DpaaFD *frame,
- t_QmRejectedFrameInfo *qm_rejected_frame_info)
+static int
+qman_setup_pfdr(struct qman_softc *sc, int npfdr)
{
- struct qman_softc *sc;
+ uint32_t res;
+
+ npfdr = min(npfdr, QMAN_PFDR_MAX);
+ bus_write_4(sc->sc_rres, QMAN_MCP0, 8);
+ bus_write_4(sc->sc_rres, QMAN_MCP1, npfdr - 9);
+ bus_write_4(sc->sc_rres, QMAN_MCR, MCR_INIT_PFDR);
+
+ for (int timeout = 100000; timeout > 0; timeout--) {
+ DELAY(1);
+ res = bus_read_4(sc->sc_rres, QMAN_MCR);
+ if (res >= MCR_RSLT_OK)
+ break;
+ }
- sc = app;
+ if (res < MCR_RSLT_OK)
+ return (EBUSY);
+ if (res == MCR_RSLT_OK)
+ return (0);
- device_printf(sc->sc_dev, "dummy callback for rejected frame.\n");
- return (e_RX_STORE_RESPONSE_CONTINUE);
+ return (ENXIO);
}
int
qman_attach(device_t dev)
{
struct qman_softc *sc;
- t_QmParam qp;
- t_Error error;
- t_QmRevisionInfo rev;
+ int error;
+ vm_paddr_t fqd_pa, pfdr_pa;
+ vm_size_t fqd_sz, pfdr_sz;
+ int qman_channel_pool1 = QMAN_CHANNEL_POOL1_REV1;
+ uint32_t ver;
+ uint32_t nfqd;
+ bool qman3 = false;
sc = device_get_softc(dev);
sc->sc_dev = dev;
qman_sc = sc;
- if (XX_MallocSmartInit() != E_OK) {
- device_printf(dev, "could not initialize smart allocator.\n");
- return (ENXIO);
- }
-
- sched_pin();
-
/* Allocate resources */
sc->sc_rrid = 0;
- sc->sc_rres = bus_alloc_resource(dev, SYS_RES_MEMORY,
- &sc->sc_rrid, 0, ~0, QMAN_CCSR_SIZE, RF_ACTIVE);
+ sc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 0, RF_ACTIVE);
if (sc->sc_rres == NULL) {
device_printf(dev, "could not allocate memory.\n");
goto err;
@@ -186,57 +329,79 @@ qman_attach(device_t dev)
device_printf(dev, "could not allocate error interrupt.\n");
goto err;
}
+ error = dpaa_map_private_memory(dev, 0, "fsl,qman-fqd",
+ &fqd_pa, &fqd_sz);
+ error = dpaa_map_private_memory(dev, 1, "fsl,qman-pfdr",
+ &pfdr_pa, &pfdr_sz);
+
+ bzero((void *)PHYS_TO_DMAP(fqd_pa), fqd_sz);
+ cpu_flush_dcache((void *)PHYS_TO_DMAP(fqd_pa), fqd_sz);
+ /*
+ * FQDs are 64 bytes in size, with 24 bit pointers, so FQIDs are 24
+ * bits, fits fine in a uint32_t.
+ */
+ nfqd = fqd_sz / 64;
+ qman_total_fqids = nfqd;
+ qman_channel_base = qman_channel_pool1;
+ qman_fq_list = malloc(nfqd * sizeof(struct qman_fq *), M_QMAN,
+ M_WAITOK);
- if (qp_sc == NULL)
+ error = qman_set_memory(sc, fqd_pa, fqd_sz, QMAN_FQD_BARE);
+ if (error != 0 && error != EEXIST)
goto err;
+ error = qman_set_memory(sc, pfdr_pa, pfdr_sz, QMAN_PFDR_BARE);
+ if (error != 0 && error != EEXIST)
+ goto err;
+ if (error == 0) {
+ /* Initialize PFDRs if it hasn't been initialized before */
+ error = qman_setup_pfdr(sc, pfdr_sz / 64);
+ if (error != 0)
+ goto err;
+ /* Magic constant from documentation */
+ bus_write_4(sc->sc_rres, QMAN_PFDR_CFG, 64);
+ }
- dpaa_portal_map_registers(qp_sc);
+ bus_write_4(sc->sc_rres, QMAN_ERR_ISR, 0xffffffff);
+ bus_write_4(sc->sc_rres, QMAN_ERR_IER, 0xffffffff);
- /* Initialize QMan */
- qp.guestId = NCSW_MASTER_ID;
- qp.baseAddress = rman_get_bushandle(sc->sc_rres);
- qp.swPortalsBaseAddress = rman_get_bushandle(qp_sc->sc_rres[0]);
- qp.liodn = 0;
- qp.totalNumOfFqids = QMAN_MAX_FQIDS;
- qp.fqdMemPartitionId = NCSW_MASTER_ID;
- qp.pfdrMemPartitionId = NCSW_MASTER_ID;
- qp.f_Exception = qman_exception;
- qp.h_App = sc;
- qp.errIrq = (uintptr_t)sc->sc_ires;
- qp.partFqidBase = QMAN_FQID_BASE;
- qp.partNumOfFqids = QMAN_MAX_FQIDS;
- qp.partCgsBase = 0;
- qp.partNumOfCgs = 0;
+ ver = bus_read_4(sc->sc_rres, QMAN_IP_REV_1);
+ sc->sc_qman_major = ((ver & IP_MJ_M) >> IP_MJ_S);
+ if (sc->sc_qman_major >= 3)
+ qman3 = true;
- sc->sc_qh = QM_Config(&qp);
- if (sc->sc_qh == NULL) {
- device_printf(dev, "could not be configured\n");
- goto err;
- }
+ if (qman3)
+ qman_channel_pool1 = QMAN_CHANNEL_POOL1_REV3;
- error = QM_Init(sc->sc_qh);
- if (error != E_OK) {
- device_printf(dev, "could not be initialized\n");
+ sc->sc_qman_base_channel = qman_channel_pool1;
+
+ sc->sc_fqalloc =
+ vmem_create("qman-fqalloc", 1, nfqd - 1, 1, 0, M_WAITOK);
+ sc->sc_qpalloc =
+ vmem_create("qman-fqalloc", qman_channel_pool1,
+ QMAN_POOL_CHANNELS, 1, 0, M_WAITOK);
+ sc->sc_cgalloc = vmem_create("qman->cgalloc", 0, QMAN_CGRS,
+ 1, 0, M_WAITOK);
+
+ if (bus_setup_intr(dev, sc->sc_ires, INTR_TYPE_NET, NULL, qman_isr,
+ sc, &sc->sc_intr_cookie) != 0)
goto err;
- }
- error = QM_GetRevision(sc->sc_qh, &rev);
- if (error != E_OK) {
- device_printf(dev, "could not get QMan revision\n");
+ if (error != 0) {
+ device_printf(dev, "could not be initialized\n");
goto err;
}
+ bus_write_4(sc->sc_rres, QMAN_DCP_CFG(0),
+ qman3 ? DCP_CFG_ED_3 : DCP_CFG_ED);
+ bus_write_4(sc->sc_rres, QMAN_DCP_CFG(1),
+ qman3 ? DCP_CFG_ED_3 : DCP_CFG_ED);
- device_printf(dev, "Hardware version: %d.%d.\n",
- rev.majorRev, rev.minorRev);
+ bus_write_4(sc->sc_rres, 0xd00, 0x80000322);
- sched_unpin();
-
- qman_portal_setup(sc);
+ /* TODO: DO we need a taskqueue? Allocate here if so */
return (0);
err:
- sched_unpin();
qman_detach(dev);
return (ENXIO);
}
@@ -248,11 +413,15 @@ qman_detach(device_t dev)
sc = device_get_softc(dev);
- if (sc->sc_qh)
- QM_Free(sc->sc_qh);
+ if (sc->sc_fqalloc != NULL)
+ vmem_destroy(sc->sc_fqalloc);
+ if (sc->sc_qpalloc != NULL)
+ vmem_destroy(sc->sc_qpalloc);
+ if (sc->sc_cgalloc != NULL)
+ vmem_destroy(sc->sc_cgalloc);
- if (sc->sc_ires != NULL)
- XX_DeallocIntr((uintptr_t)sc->sc_ires);
+ if (sc->sc_intr_cookie != NULL)
+ bus_teardown_intr(dev, sc->sc_ires, sc->sc_intr_cookie);
if (sc->sc_ires != NULL)
bus_release_resource(dev, SYS_RES_IRQ,
@@ -262,6 +431,9 @@ qman_detach(device_t dev)
bus_release_resource(dev, SYS_RES_MEMORY,
sc->sc_rrid, sc->sc_rres);
+ free(qman_fq_list, M_QMAN);
+ qman_fq_list = NULL;
+
return (0);
}
@@ -286,261 +458,233 @@ qman_shutdown(device_t dev)
return (0);
}
+int
+qman_alloc_channel(void)
+{
+ struct qman_softc *sc = qman_sc;
+ vmem_addr_t channel;
+
+ vmem_alloc(sc->sc_qpalloc, 1, M_BESTFIT | M_WAITOK, &channel);
+
+ return (channel);
+}
+
+void
+qman_free_channel(int channel)
+{
+ struct qman_softc *sc = qman_sc;
+
+ vmem_free(sc->sc_qpalloc, channel, 1);
+}
/**
* @group QMan API functions implementation.
* @{
*/
-t_Handle
-qman_fqr_create(uint32_t fqids_num, e_QmFQChannel channel, uint8_t wq,
+struct qman_fq *
+qman_fq_from_index(uint32_t fqid)
+{
+ if (fqid > qman_total_fqids)
+ return (NULL);
+ return (qman_fq_list[fqid]);
+}
+
+/* Allocate and initialize an FQ Range */
+struct qman_fq *
+qman_fq_create(uint32_t fqids_num, int channel, uint8_t wq,
bool force_fqid, uint32_t fqid_or_align, bool init_parked,
bool hold_active, bool prefer_in_cache, bool congst_avoid_ena,
- t_Handle congst_group, int8_t overhead_accounting_len,
+ void *congst_group, int8_t overhead_accounting_len,
uint32_t tail_drop_threshold)
{
+ union qman_mc_command cmd;
struct qman_softc *sc;
- t_QmFqrParams fqr;
- t_Handle fqrh, portal;
+ union qman_mc_result *res;
+ struct qman_fq *fqh;
+ device_t portal;
+ vmem_addr_t fqid_base;
+ uint8_t rslt;
sc = qman_sc;
- sched_pin();
-
- /* Ensure we have got QMan port initialized */
- portal = qman_portal_setup(sc);
- if (portal == NULL) {
- device_printf(sc->sc_dev, "could not setup QMan portal\n");
- goto err;
+ if (fqids_num != 1) {
+ device_printf(sc->sc_dev,
+ "Only one fq allocation allowed currently\n");
+ return (NULL);
}
- fqr.h_Qm = sc->sc_qh;
- fqr.h_QmPortal = portal;
- fqr.initParked = init_parked;
- fqr.holdActive = hold_active;
- fqr.preferInCache = prefer_in_cache;
+ bzero(&cmd, sizeof(cmd));
+ vmem_alloc(sc->sc_fqalloc, fqids_num, M_BESTFIT | M_WAITOK, &fqid_base);
+ cmd.init_fq.fqid = fqid_base;
+ cmd.init_fq.count = fqids_num - 1;
+ cmd.init_fq.dest_chan = channel;
+ cmd.init_fq.dest_wq = wq;
+ cmd.init_fq.we_mask = QCSP_INIT_FQ_WE_DEST_WQ | QCSP_INIT_FQ_WE_FQ_CTRL;
+ if (init_parked)
+ cmd.init_fq.verb = QCSP_VERB_INIT_FQ_PARK;
+ else
+ cmd.init_fq.verb = QCSP_VERB_INIT_FQ_SCHED;
+ cmd.init_fq.fq_ctrl = (prefer_in_cache ? QM_FQCTRL_LIC : 0) |
+ (hold_active ? QM_FQCTRL_HOLDACTIVE : 0) |
+ (congst_avoid_ena ? QM_FQCTRL_AVOIDBLOCK : 0);
- /* We do not support stashing */
- fqr.useContextAForStash = FALSE;
- fqr.p_ContextA = 0;
- fqr.p_ContextB = 0;
+ critical_enter();
- fqr.channel = channel;
- fqr.wq = wq;
- fqr.shadowMode = FALSE;
- fqr.numOfFqids = fqids_num;
+ /* Ensure we have got QMan port initialized */
+ portal = DPCPU_GET(qman_affine_portal);
+ res = QMAN_PORTAL_MC_SEND_RAW(portal, &cmd);
- /* FQID */
- fqr.useForce = force_fqid;
- if (force_fqid) {
- fqr.qs.frcQ.fqid = fqid_or_align;
- } else {
- fqr.qs.nonFrcQs.align = fqid_or_align;
- }
+ rslt = 0;
+ if (res != NULL)
+ rslt = res->init_fq.rslt;
- /* Congestion Avoidance */
- fqr.congestionAvoidanceEnable = congst_avoid_ena;
- if (congst_avoid_ena) {
- fqr.congestionAvoidanceParams.h_QmCg = congst_group;
- fqr.congestionAvoidanceParams.overheadAccountingLength =
- overhead_accounting_len;
- fqr.congestionAvoidanceParams.fqTailDropThreshold =
- tail_drop_threshold;
- } else {
- fqr.congestionAvoidanceParams.h_QmCg = 0;
- fqr.congestionAvoidanceParams.overheadAccountingLength = 0;
- fqr.congestionAvoidanceParams.fqTailDropThreshold = 0;
- }
-
- fqrh = QM_FQR_Create(&fqr);
- if (fqrh == NULL) {
- device_printf(sc->sc_dev, "could not create Frame Queue Range"
- "\n");
+ critical_exit();
+ if (res == NULL || rslt != QMAN_MC_RES_OK) {
+ vmem_free(sc->sc_fqalloc, fqid_base, fqids_num);
goto err;
}
- sc->sc_fqr_cpu[QM_FQR_GetFqid(fqrh)] = PCPU_GET(cpuid);
+ fqh = malloc(sizeof(*fqh), M_QMAN, M_WAITOK | M_ZERO);
+ fqh->fqid = fqid_base;
- sched_unpin();
+ qman_fq_list[fqid_base] = fqh;
- return (fqrh);
+ return (fqh);
err:
- sched_unpin();
return (NULL);
}
-t_Error
-qman_fqr_free(t_Handle fqr)
+static int
+qman_fq_retire(device_t portal, struct qman_fq *fq)
{
- struct qman_softc *sc;
- t_Error error;
-
- sc = qman_sc;
- thread_lock(curthread);
- sched_bind(curthread, sc->sc_fqr_cpu[QM_FQR_GetFqid(fqr)]);
- thread_unlock(curthread);
+ union qman_mc_command cmd;
+ union qman_mc_result *rr;
- error = QM_FQR_Free(fqr);
+ bzero(&cmd, sizeof(cmd));
- thread_lock(curthread);
- sched_unbind(curthread);
- thread_unlock(curthread);
+ cmd.alter_fqs.verb = QCSP_VERB_ALTER_FQ_RETIRE;
+ cmd.alter_fqs.fqid = fq->fqid;
+ rr = QMAN_PORTAL_MC_SEND_RAW(portal, &cmd);
+ if (rr == NULL)
+ return (ETIMEDOUT);
- return (error);
-}
-
-t_Error
-qman_fqr_register_cb(t_Handle fqr, t_QmReceivedFrameCallback *callback,
- t_Handle app)
-{
- struct qman_softc *sc;
- t_Error error;
- t_Handle portal;
-
- sc = qman_sc;
- sched_pin();
-
- /* Ensure we have got QMan port initialized */
- portal = qman_portal_setup(sc);
- if (portal == NULL) {
- device_printf(sc->sc_dev, "could not setup QMan portal\n");
- sched_unpin();
- return (E_NOT_SUPPORTED);
+ if (rr->alter_fqs.rslt == QMAN_MC_RES_OK) {
+ if (rr->alter_fqs.fqs & QMAN_MC_AFQS_NE) {
+ /* TODO: Drain.... */
+ }
+ return (0);
}
- error = QM_FQR_RegisterCB(fqr, callback, app);
-
- sched_unpin();
-
- return (error);
+ return (0);
}
-t_Error
-qman_fqr_enqueue(t_Handle fqr, uint32_t fqid_off, t_DpaaFD *frame)
+int
+qman_fq_free(struct qman_fq *fq)
{
struct qman_softc *sc;
- t_Error error;
- t_Handle portal;
+ int error;
sc = qman_sc;
- sched_pin();
-
- /* Ensure we have got QMan port initialized */
- portal = qman_portal_setup(sc);
- if (portal == NULL) {
- device_printf(sc->sc_dev, "could not setup QMan portal\n");
- sched_unpin();
- return (E_NOT_SUPPORTED);
- }
-
- error = QM_FQR_Enqueue(fqr, portal, fqid_off, frame);
- sched_unpin();
+ critical_enter();
+ error = qman_fq_retire(DPCPU_GET(qman_affine_portal), fq);
+ /* TODO: Take FQ out of service. */
+ critical_exit();
+ if (error != 0)
+ return (error);
+ vmem_free(sc->sc_fqalloc, fq->fqid, 1);
+ qman_fq_list[fq->fqid] = NULL;
+ free(fq, M_QMAN);
- return (error);
+ return (0);
}
-uint32_t
-qman_fqr_get_counter(t_Handle fqr, uint32_t fqid_off,
- e_QmFqrCounters counter)
+int
+qman_fq_register_cb(struct qman_fq *fq, qman_cb_dqrr callback,
+ void *ctx)
{
- struct qman_softc *sc;
- uint32_t val;
- t_Handle portal;
-
- sc = qman_sc;
- sched_pin();
-
- /* Ensure we have got QMan port initialized */
- portal = qman_portal_setup(sc);
- if (portal == NULL) {
- device_printf(sc->sc_dev, "could not setup QMan portal\n");
- sched_unpin();
- return (0);
- }
+ fq->cb.dqrr = callback;
+ fq->cb.ctx = ctx;
- val = QM_FQR_GetCounter(fqr, portal, fqid_off, counter);
-
- sched_unpin();
-
- return (val);
+ return (0);
}
-t_Error
-qman_fqr_pull_frame(t_Handle fqr, uint32_t fqid_off, t_DpaaFD *frame)
+int
+qman_fq_enqueue(struct qman_fq *fq, struct dpaa_fd *frame)
{
struct qman_softc *sc;
- t_Error error;
- t_Handle portal;
+ int error;
+ void *portal;
sc = qman_sc;
- sched_pin();
+ critical_enter();
/* Ensure we have got QMan port initialized */
- portal = qman_portal_setup(sc);
+ portal = DPCPU_GET(qman_affine_portal);
if (portal == NULL) {
device_printf(sc->sc_dev, "could not setup QMan portal\n");
- sched_unpin();
- return (E_NOT_SUPPORTED);
+ critical_exit();
+ return (ENXIO);
}
- error = QM_FQR_PullFrame(fqr, portal, fqid_off, frame);
+ error = QMAN_PORTAL_ENQUEUE(portal, fq, frame);
- sched_unpin();
+ critical_exit();
return (error);
}
uint32_t
-qman_fqr_get_base_fqid(t_Handle fqr)
+qman_fq_get_fqid(struct qman_fq *fq)
{
- struct qman_softc *sc;
- uint32_t val;
- t_Handle portal;
+ return (fq->fqid);
+}
- sc = qman_sc;
- sched_pin();
- /* Ensure we have got QMan port initialized */
- portal = qman_portal_setup(sc);
- if (portal == NULL) {
- device_printf(sc->sc_dev, "could not setup QMan portal\n");
- sched_unpin();
- return (0);
- }
+uint32_t
+qman_fq_get_counter(struct qman_fq *fq, int counter)
+{
+ union qman_mc_result *cmd_res;
+ union qman_mc_command command;
+ device_t portal;
+ u_int ret = 0;
- val = QM_FQR_GetFqid(fqr);
+ bzero(&command, sizeof(command));
+ command.query_fq_np.verb = QCSP_VERB_QUERY_FQ_NP;
+ command.query_fq_np.fqid = fq->fqid;
+ critical_enter();
+ portal = DPCPU_GET(qman_affine_portal);
+ cmd_res = QMAN_PORTAL_MC_SEND_RAW(portal, &command);
+ if (counter == QMAN_COUNTER_FRAME)
+ ret = cmd_res->query_fq_np.frm_cnt;
+ else if (counter == QMAN_COUNTER_BYTES)
+ ret = cmd_res->query_fq_np.byte_cnt;
- sched_unpin();
+ critical_exit();
- return (val);
+ return (ret);
}
-t_Error
-qman_poll(e_QmPortalPollSource source)
+void
+qman_set_sdest(uint16_t channel, int cpu)
{
- struct qman_softc *sc;
- t_Error error;
- t_Handle portal;
-
- sc = qman_sc;
- sched_pin();
+ struct qman_softc *sc = qman_sc;
+ uint32_t reg;
- /* Ensure we have got QMan port initialized */
- portal = qman_portal_setup(sc);
- if (portal == NULL) {
- device_printf(sc->sc_dev, "could not setup QMan portal\n");
- sched_unpin();
- return (E_NOT_SUPPORTED);
+ if (sc->sc_qman_major >= 3) {
+ reg = bus_read_4(sc->sc_rres, QCSP_IO_CFG_3(channel));
+ reg &= IO_CFG_SDEST_M;
+ reg |= (cpu << IO_CFG_SDEST_S);
+ bus_write_4(sc->sc_rres, QCSP_IO_CFG_3(channel), reg);
+ } else {
+ reg = bus_read_4(sc->sc_rres, QCSP_IO_CFG(channel));
+ reg &= IO_CFG_SDEST_M;
+ reg |= (cpu << IO_CFG_SDEST_S);
+ bus_write_4(sc->sc_rres, QCSP_IO_CFG(channel), reg);
}
-
- error = QM_Poll(sc->sc_qh, source);
-
- sched_unpin();
-
- return (error);
}
/*
diff --git a/sys/dev/dpaa/qman.h b/sys/dev/dpaa/qman.h
index 815ef1f6d33a..0e841dbc6ae6 100644
--- a/sys/dev/dpaa/qman.h
+++ b/sys/dev/dpaa/qman.h
@@ -27,10 +27,13 @@
#ifndef _QMAN_H
#define _QMAN_H
+#include <sys/vmem.h>
#include <machine/vmparam.h>
-#include <contrib/ncsw/inc/Peripherals/qm_ext.h>
-
+struct qman_fq;
+struct qman_fq;
+struct dpaa_fd;
+struct qman_portal;
/**
* @group QMan private defines/declarations
@@ -44,13 +47,15 @@
/**
* Pool channel common to all software portals.
* @note Value of 0 reflects the e_QM_FQ_CHANNEL_POOL1 from e_QmFQChannel
- * type used in qman_fqr_create().
+ * type used in qman_fq_create().
*/
#define QMAN_COMMON_POOL_CHANNEL 0
#define QMAN_FQID_BASE 1
-#define QMAN_CCSR_SIZE 0x1000
+/* Counters */
+#define QMAN_COUNTER_FRAME 0
+#define QMAN_COUNTER_BYTES 1
/*
* Portal defines
@@ -69,18 +74,103 @@ struct qman_softc {
struct resource *sc_rres; /* register resource */
int sc_irid; /* interrupt rid */
struct resource *sc_ires; /* interrupt resource */
+ vmem_t *sc_fqalloc;
+ vmem_t *sc_qpalloc;
+ vmem_t *sc_cgalloc;
+ void *sc_intr_cookie;
+ int sc_qman_base_channel;
+ int sc_qman_major;
- bool sc_regs_mapped[MAXCPU];
-
- t_Handle sc_qh; /* QMAN handle */
- t_Handle sc_qph[MAXCPU]; /* QMAN portal handles */
vm_paddr_t sc_qp_pa; /* QMAN portal PA */
- int sc_fqr_cpu[QMAN_MAX_FQIDS];
+ int sc_fq_cpu[QMAN_MAX_FQIDS];
+};
+
+struct qman_fd {
+ uint64_t dd:2;
+ uint64_t liodn_off:6;
+ uint64_t bpid:8;
+ uint64_t eliodn_off:4;
+ uint64_t _rsvd0:4;
+ uint64_t addr:40;
+ union {
+ struct {
+ uint32_t format:3;
+ uint32_t offset:9;
+ uint32_t length:20;
+ };
+ struct {
+ uint32_t format2:3;
+ uint32_t wlength:29;
+ };
+ };
+ uint32_t cmd_stat;
+};
+
+_Static_assert(sizeof(struct qman_fd) == 16, "qman_fd size mismatch");
+
+struct qman_dqrr_entry {
+ uint8_t verb;
+ uint8_t stat;
+ uint16_t seqnum;
+ uint8_t tok;
+ uint8_t _rsvd0[3];
+ uint32_t fqid;
+ uint32_t ctxb;
+ struct qman_fd fd;
+ uint8_t _rsvd1[32];
+};
+
+/* Bits for qman_dqrr_entry fields */
+#define QMAN_DQRR_STAT_FQ_EMPTY 0x80
+#define QMAN_DQRR_STAT_FQ_HELD_ACTIVE 0x40
+#define QMAN_DQRR_STAT_FQ_FORCED 0x20
+#define QMAN_DQRR_STAT_HAS_FRAME 0x10
+#define QMAN_DQRR_STAT_VDQCR 0x02
+#define QMAN_DQRR_STAT_EXPIRED 0x01
+
+struct qman_mr_entry {
+ union {
+ struct {
+ uint8_t verb;
+ uint8_t data[63];
+ };
+ struct {
+ uint8_t verb;
+ uint8_t dca;
+ uint16_t seqnum;
+ uint32_t rc:8;
+ uint32_t orp:24;
+ uint32_t fqid;
+ uint32_t tag;
+ struct qman_fd fd;
+ uint8_t _rsvd[32];
+ } ern;
+ struct {
+ uint8_t verb;
+ uint8_t fqs;
+ uint8_t _rsvd0[6];
+ uint32_t fqid;
+ uint32_t ctxb;
+ uint8_t _rsvd1[48];
+ } fqscn;
+ };
};
+
+_Static_assert(sizeof(struct qman_mr_entry) == 64, "bad sizeof qman_mr");
/** @> */
+typedef int (*qman_cb_dqrr)(device_t, struct qman_fq *,
+ struct qman_fd *, void *);
+typedef void (*qman_cb_mr)(device_t, struct qman_fq *,
+ struct qman_mr_entry *);
+struct qman_cb {
+ qman_cb_dqrr dqrr;
+ qman_cb_mr ern;
+ qman_cb_mr fqscn;
+ void *ctx;
+};
/**
* @group QMan bus interface
* @{
@@ -91,6 +181,8 @@ int qman_suspend(device_t dev);
int qman_resume(device_t dev);
int qman_shutdown(device_t dev);
/** @> */
+int qman_create_affine_portal(device_t, vm_offset_t, vm_offset_t, int);
+void qman_set_sdest(uint16_t, int);
/**
@@ -149,69 +241,77 @@ int qman_shutdown(device_t dev);
*
* @return A handle to newly created FQR object.
*/
-t_Handle qman_fqr_create(uint32_t fqids_num, e_QmFQChannel channel, uint8_t wq,
- bool force_fqid, uint32_t fqid_or_align, bool init_parked,
+struct qman_fq *qman_fq_create(uint32_t fqids_num, int channel,
+ uint8_t wq, bool force_fqid, uint32_t fqid_or_align, bool init_parked,
bool hold_active, bool prefer_in_cache, bool congst_avoid_ena,
- t_Handle congst_group, int8_t overhead_accounting_len,
+ void *congst_group, int8_t overhead_accounting_len,
uint32_t tail_drop_threshold);
/**
* Free Frame Queue Range.
*
- * @param fqr A handle to FQR to be freed.
+ * @param fq A handle to FQR to be freed.
* @return E_OK on success; error code otherwise.
*/
-t_Error qman_fqr_free(t_Handle fqr);
+int qman_fq_free(struct qman_fq *fq);
/**
* Register the callback function.
* The callback function will be called when a frame comes from this FQR.
*
- * @param fqr A handle to FQR.
+ * @param fq A handle to FQR.
* @param callback A pointer to the callback function.
* @param app A pointer to the user's data.
* @return E_OK on success; error code otherwise.
*/
-t_Error qman_fqr_register_cb(t_Handle fqr, t_QmReceivedFrameCallback *callback,
- t_Handle app);
+int qman_fq_register_cb(struct qman_fq *fq, qman_cb_dqrr callback,
+ void *ctx);
/**
- * Enqueue a frame on a given FQR.
+ * Enqueue a frame on a given FQ.
*
- * @param fqr A handle to FQR.
- * @param fqid_off FQID offset wihin the FQR.
+ * @param fq A handle to FQ.
* @param frame A frame to be enqueued to the transmission.
* @return E_OK on success; error code otherwise.
*/
-t_Error qman_fqr_enqueue(t_Handle fqr, uint32_t fqid_off, t_DpaaFD *frame);
+int qman_fq_enqueue(struct qman_fq *fq, struct dpaa_fd *frame);
/**
- * Get one of the FQR counter's value.
+ * Get one of the FQ counter's value.
*
- * @param fqr A handle to FQR.
- * @param fqid_off FQID offset within the FQR.
+ * @param fq A handle to FQ.
* @param counter The requested counter.
* @return Counter's current value.
*/
-uint32_t qman_fqr_get_counter(t_Handle fqr, uint32_t fqid_off,
- e_QmFqrCounters counter);
+uint32_t qman_fq_get_counter(struct qman_fq *fq, int counter);
/**
- * Pull frame from FQR.
+ * Pull frame from FQ.
*
- * @param fqr A handle to FQR.
- * @param fqid_off FQID offset within the FQR.
+ * @param fq A handle to FQ.
* @param frame The received frame.
* @return E_OK on success; error code otherwise.
*/
-t_Error qman_fqr_pull_frame(t_Handle fqr, uint32_t fqid_off, t_DpaaFD *frame);
+int qman_fq_pull_frame(struct qman_fq *fq, struct dpaa_fd *frame);
/**
- * Get base FQID of the FQR.
- * @param fqr A handle to FQR.
- * @return Base FQID of the FQR.
+ * Get FQID of the FQ.
+ * @param fq A handle to FQ.
+ * @return FQID of the FQ.
+ */
+uint32_t qman_fq_get_fqid(struct qman_fq *fq);
+
+/*
+ * Allocate a QMan channel to be used with an FQ.
+ * @return Channel ID
+ */
+int qman_alloc_channel(void);
+
+/*
+ * Free a channel
+ * @param chan Channel ID returned from qman_alloc_channel().
*/
-uint32_t qman_fqr_get_base_fqid(t_Handle fqr);
+void qman_free_channel(int);
/**
* Poll frames from QMan.
@@ -220,24 +320,24 @@ uint32_t qman_fqr_get_base_fqid(t_Handle fqr);
* @param source Type of frames to be polled.
* @return E_OK on success; error otherwise.
*/
-t_Error qman_poll(e_QmPortalPollSource source);
+int qman_poll(int source);
/**
* General received frame callback.
* This is called, when user did not register his own callback for a given
- * frame queue range (fqr).
+ * frame queue range (fq).
*/
-e_RxStoreResponse qman_received_frame_callback(t_Handle app, t_Handle qm_fqr,
- t_Handle qm_portal, uint32_t fqid_offset, t_DpaaFD *frame);
+int qman_received_frame_callback(void *ctx, struct qman_fq *fq,
+ void *qm_portal, uint32_t fqid_offset, struct dpaa_fd *frame);
/**
* General rejected frame callback.
* This is called, when user did not register his own callback for a given
- * frame queue range (fqr).
+ * frame queue range (fq).
*/
-e_RxStoreResponse qman_rejected_frame_callback(t_Handle app, t_Handle qm_fqr,
- t_Handle qm_portal, uint32_t fqid_offset, t_DpaaFD *frame,
- t_QmRejectedFrameInfo *qm_rejected_frame_info);
+int qman_rejected_frame_callback(void *ctx, struct qman_fq *fq,
+ void *qm_portal, uint32_t fqid_offset, struct dpaa_fd *frame,
+ void *qm_rejected_frame_info);
/** @} */
diff --git a/sys/dev/dpaa/qman_fdt.c b/sys/dev/dpaa/qman_fdt.c
index 89bf802e0067..3536042abf9c 100644
--- a/sys/dev/dpaa/qman_fdt.c
+++ b/sys/dev/dpaa/qman_fdt.c
@@ -41,6 +41,8 @@
#include "qman.h"
#include "portals.h"
+#include "qman_var.h"
+#include "qman_portal_if.h"
#define FQMAN_DEVSTR "Freescale Queue Manager"
@@ -59,12 +61,7 @@ static device_method_t qman_methods[] = {
DEVMETHOD_END
};
-static driver_t qman_driver = {
- "qman",
- qman_methods,
- sizeof(struct qman_softc),
-};
-
+DEFINE_CLASS_0(qman, qman_driver, qman_methods, sizeof(struct qman_softc));
EARLY_DRIVER_MODULE(qman, simplebus, qman_driver, 0, 0, BUS_PASS_SUPPORTDEV);
static int
@@ -82,53 +79,38 @@ qman_fdt_probe(device_t dev)
/*
* QMAN Portals
*/
-#define QMAN_PORT_DEVSTR "Freescale Queue Manager - Portals"
+#define QMAN_PORT_DEVSTR "Freescale Queue Manager - Portal"
-static device_probe_t qman_portals_fdt_probe;
-static device_attach_t qman_portals_fdt_attach;
+static int portal_ncpus;
+static device_probe_t qman_portal_fdt_probe;
+static device_attach_t qman_portal_fdt_attach;
-static device_method_t qm_portals_methods[] = {
+static device_method_t qman_portal_methods[] = {
/* Device interface */
- DEVMETHOD(device_probe, qman_portals_fdt_probe),
- DEVMETHOD(device_attach, qman_portals_fdt_attach),
- DEVMETHOD(device_detach, qman_portals_detach),
+ DEVMETHOD(device_probe, qman_portal_fdt_probe),
+ DEVMETHOD(device_attach, qman_portal_fdt_attach),
+ DEVMETHOD(device_detach, qman_portal_detach),
- DEVMETHOD_END
-};
+ DEVMETHOD(qman_portal_enqueue, qman_portal_fq_enqueue),
+ DEVMETHOD(qman_portal_mc_send_raw, qman_portal_mc_send_raw),
+ DEVMETHOD(qman_portal_static_dequeue_channel,
+ qman_portal_static_dequeue_channel),
+ DEVMETHOD(qman_portal_static_dequeue_rm_channel,
+ qman_portal_static_dequeue_rm_channel),
-static driver_t qm_portals_driver = {
- "qman-portals",
- qm_portals_methods,
- sizeof(struct dpaa_portals_softc),
+ DEVMETHOD_END
};
-EARLY_DRIVER_MODULE(qman_portals, ofwbus, qm_portals_driver, 0, 0,
- BUS_PASS_BUS);
-
-static void
-get_addr_props(phandle_t node, uint32_t *addrp, uint32_t *sizep)
-{
-
- *addrp = 2;
- *sizep = 1;
- OF_getencprop(node, "#address-cells", addrp, sizeof(*addrp));
- OF_getencprop(node, "#size-cells", sizep, sizeof(*sizep));
-}
+DEFINE_CLASS_0(qman_portal, qman_portal_driver, qman_portal_methods,
+ sizeof(struct qman_softc));
+EARLY_DRIVER_MODULE(qman_portal, simplebus, qman_portal_driver, 0, 0,
+ BUS_PASS_SUPPORTDEV + BUS_PASS_ORDER_MIDDLE);
static int
-qman_portals_fdt_probe(device_t dev)
+qman_portal_fdt_probe(device_t dev)
{
- phandle_t node;
- if (ofw_bus_is_compatible(dev, "simple-bus")) {
- node = ofw_bus_get_node(dev);
- for (node = OF_child(node); node > 0; node = OF_peer(node)) {
- if (ofw_bus_node_is_compatible(node, "fsl,qman-portal"))
- break;
- }
- if (node <= 0)
- return (ENXIO);
- } else if (!ofw_bus_is_compatible(dev, "fsl,qman-portals"))
+ if (!ofw_bus_is_compatible(dev, "fsl,qman-portal"))
return (ENXIO);
device_set_desc(dev, QMAN_PORT_DEVSTR);
@@ -137,105 +119,15 @@ qman_portals_fdt_probe(device_t dev)
}
static int
-qman_portals_fdt_attach(device_t dev)
+qman_portal_fdt_attach(device_t dev)
{
- struct dpaa_portals_softc *sc;
- phandle_t node, child, cpu_node;
- vm_paddr_t portal_pa, portal_par_pa;
- vm_size_t portal_size;
- uint32_t addr, paddr, size;
- ihandle_t cpu;
- int cpu_num, cpus, intr_rid;
- struct dpaa_portals_devinfo di;
- struct ofw_bus_devinfo ofw_di = {};
- cell_t *range;
- int nrange;
- int i;
-
- cpus = 0;
- sc = device_get_softc(dev);
- sc->sc_dev = dev;
-
- node = ofw_bus_get_node(dev);
-
- /* Get this node's range */
- get_addr_props(ofw_bus_get_node(device_get_parent(dev)), &paddr, &size);
- get_addr_props(node, &addr, &size);
+ int portal_cpu = portal_ncpus;
- nrange = OF_getencprop_alloc_multi(node, "ranges",
- sizeof(*range), (void **)&range);
- if (nrange < addr + paddr + size)
+ /* Don't attach to more portals than we have CPUs */
+ if (mp_ncpus == portal_ncpus)
return (ENXIO);
- portal_pa = portal_par_pa = 0;
- portal_size = 0;
- for (i = 0; i < addr; i++) {
- portal_pa <<= 32;
- portal_pa |= range[i];
- }
- for (; i < paddr + addr; i++) {
- portal_par_pa <<= 32;
- portal_par_pa |= range[i];
- }
- portal_pa += portal_par_pa;
- for (; i < size + paddr + addr; i++) {
- portal_size = (uintmax_t)portal_size << 32;
- portal_size |= range[i];
- }
- OF_prop_free(range);
- sc->sc_dp_size = portal_size;
- sc->sc_dp_pa = portal_pa;
-
- /* Find portals tied to CPUs */
- for (child = OF_child(node); child != 0; child = OF_peer(child)) {
- if (cpus >= mp_ncpus)
- break;
- if (!ofw_bus_node_is_compatible(child, "fsl,qman-portal")) {
- continue;
- }
- /* Checkout related cpu */
- if (OF_getprop(child, "cpu-handle", (void *)&cpu,
- sizeof(cpu)) > 0) {
- cpu_node = OF_instance_to_package(cpu);
- /* Acquire cpu number */
- if (OF_getencprop(cpu_node, "reg", &cpu_num, sizeof(cpu_num)) <= 0) {
- device_printf(dev, "Could not retrieve CPU number.\n");
- return (ENXIO);
- }
- } else
- cpu_num = cpus;
- cpus++;
-
- if (ofw_bus_gen_setup_devinfo(&ofw_di, child) != 0) {
- device_printf(dev, "could not set up devinfo\n");
- continue;
- }
-
- resource_list_init(&di.di_res);
- if (ofw_bus_reg_to_rl(dev, child, addr, size, &di.di_res)) {
- device_printf(dev, "%s: could not process 'reg' "
- "property\n", ofw_di.obd_name);
- ofw_bus_gen_destroy_devinfo(&ofw_di);
- continue;
- }
- if (ofw_bus_intr_to_rl(dev, child, &di.di_res, &intr_rid)) {
- device_printf(dev, "%s: could not process "
- "'interrupts' property\n", ofw_di.obd_name);
- resource_list_free(&di.di_res);
- ofw_bus_gen_destroy_devinfo(&ofw_di);
- continue;
- }
- di.di_intr_rid = intr_rid;
-
- if (dpaa_portal_alloc_res(dev, &di, cpu_num))
- goto err;
- }
- ofw_bus_gen_destroy_devinfo(&ofw_di);
+ portal_ncpus++;
- return (qman_portals_attach(dev));
-err:
- resource_list_free(&di.di_res);
- ofw_bus_gen_destroy_devinfo(&ofw_di);
- qman_portals_detach(dev);
- return (ENXIO);
+ return (qman_portal_attach(dev, portal_cpu));
}
diff --git a/sys/dev/dpaa/qman_portal_if.m b/sys/dev/dpaa/qman_portal_if.m
new file mode 100644
index 000000000000..2efe31dd6980
--- /dev/null
+++ b/sys/dev/dpaa/qman_portal_if.m
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2026 Justin Hibbits
+#
+# SPDX-License-Identifier: BSD-2-Clause
+
+#include <sys/pcpu.h>
+#include <machine/bus.h>
+#include <dev/dpaa/portals.h>
+#include <dev/dpaa/qman.h>
+#include <dev/dpaa/qman_var.h>
+
+/**
+ * @brief DPAA QMan portal interface
+ *
+ */
+INTERFACE qman_portal;
+
+METHOD int enqueue {
+ device_t dev;
+ struct qman_fq *fq;
+ struct dpaa_fd *fd;
+};
+
+METHOD union qman_mc_result * mc_send_raw {
+ device_t dev;
+ union qman_mc_command *cmd;
+};
+
+METHOD void static_dequeue_channel {
+ device_t dev;
+ int channel;
+}
+
+METHOD void static_dequeue_rm_channel {
+ device_t dev;
+ int channel;
+}
diff --git a/sys/dev/dpaa/qman_portals.c b/sys/dev/dpaa/qman_portals.c
index 0f00a9f1a173..3b64aca71cb7 100644
--- a/sys/dev/dpaa/qman_portals.c
+++ b/sys/dev/dpaa/qman_portals.c
@@ -1,27 +1,7 @@
-/*-
- * Copyright (c) 2012 Semihalf.
- * All rights reserved.
+/*
+ * Copyright (c) 2026 Justin Hibbits
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON 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 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * SPDX-License-Identifier: BSD-2-Clause
*/
#include "opt_platform.h"
@@ -36,6 +16,7 @@
#include <sys/proc.h>
#include <sys/pcpu.h>
#include <sys/sched.h>
+#include <ddb/ddb.h>
#include <machine/bus.h>
#include <machine/tlb.h>
@@ -47,143 +28,412 @@
#include "qman.h"
#include "portals.h"
+#include "qman_var.h"
+
+
+/* Cache-enabled registers */
+#define QCSP_EQCR_N(n) (0x0000 + (n * 64))
+#define QMAN_EQCR_COUNT 8
+#define QCSP_DQRR_N(n) (0x1000 + (n * 64))
+#define QMAN_DQRR_COUNT 16
+#define QCSP_MR_N(n) (0x2000 + (n * 64))
+#define QMAN_MR_COUNT 8
+#define QCSP_CR 0x3800
+#define QCSP_RR(n) (0x3900 + 0x40 * (n))
+
+#define QCSP_EQCR_PI_CENA 0x0000
+#define EQCR_PI_VP 0x00000008
+#define EQCR_PI_PI_M 0x00000007
+#define QCSP_EQCR_CI_CENA 0x0004
+#define EQCR_CI_C 0x00000008
+#define EQCR_CI_CI_M 0x00000007
+#define QCSP_DQRR_PI_CENA 0x0000
+#define DQRR_PI_VP 0x00000010
+#define DQRR_PI_PI_M 0x0000000f
+#define QCSP_DQRR_CI_CENA 0x0004
+#define DQRR_CI_C 0x00000010
+#define DQRR_CI_CI_M 0x0000000f
+
+#define QMAN_MC_VERB_VBIT 0x80
+
+
+/* Cache-inhibited registers */
+#define QCSP_EQCR_PI_CINH 0x0000
+#define QCSP_EQCR_CI_CINH 0x0004
+#define QCSP_DQRR_PI_CINH 0x0040
+#define QCSP_DQRR_CI_CINH 0x0044
+#define QCSP_EQCR_ITR 0x0008
+#define QCSP_DQRR_ITR 0x0048
+#define QCSP_DQRR_SDQCR 0x0054
+#define SDQCR_SS 0x40000000
+#define SDQCR_FC 0x20000000
+#define SDQCR_DP 0x10000000
+#define SDQCR_DCT_NUL 0x00000000
+#define SDQCR_DCT_PRI_PREC 0x01000000
+#define SDQCR_DCT_ACTIVE_WQ 0x02000000
+#define SDQCR_DCT_ACTIVE_FQ_O 0x03000000
+#define SDQCR_DCT_M 0x03000000
+#define SDQCR_TOKEN_M 0x00ff0000
+#define SDQCR_TOKEN_S 16
+#define DQRR_DQ_SRC_M 0x0000ffff
+#define DQRR_DQ_SRC_DCP 0x00008000
+#define SDQCR_DQ_SRC_CHAN(n) (0x8000 >> (n + 1))
+#define QCSP_DQRR_VDQCR 0x0058
+#define QCSP_DQRR_PDQCR 0x005c
+#define QCSP_MR_ITR 0x0088
+#define QCSP_CFG 0x0100
+#define CFG_EST_M 0x70000000
+#define CFG_EST_S 28
+#define CFG_EP 0x04000000
+#define CFG_EPM_M 0x03000000
+#define CFG_EPM_PI_CI 0x00000000
+#define CFG_EPM_PI_CE 0x01000000
+#define CFG_EPM_VB1 0x02000000
+#define CFG_EPM_VB2 0x03000000
+#define CFG_DQRR_MF_M 0x00f00000
+#define CFG_DQRR_MF_S 20
+#define CFG_DP 0x00040000
+#define CFG_DCM_C_M 0x00030000
+#define CFG_DCM_CI_CI 0x00000000
+#define CFG_DCM_CI_CE 0x00010000
+#define CFG_DCM_DCA1 0x00020000
+#define CFG_DCM_DCA2 0x00030000
+#define CFG_SD 0x00000200
+#define CFG_MM 0x00000100
+#define CFG_RE 0x00000080
+#define CFG_RP 0x00000040
+#define CFG_SE 0x00000020
+#define CFG_SP 0x00000010
+#define CFG_SDEST_M 0x00000007
+#define QCSP_ISR 0x0e00
+#define QM_PIRQ_CSCI 0x00100000
+#define QM_PIRQ_EQCI 0x00080000
+#define QM_PIRQ_EQRI 0x00040000
+#define QM_PIRQ_DQRI 0x00020000
+#define QM_PIRQ_MRI 0x00010000
+#define QM_PIRQ_DQ_AVAIL_M 0x0000ffff
+#define QCSP_IER 0x0e04
+#define QCSP_ISDR 0x0e08
+#define QCSP_IIR 0xe0c
+
+#define QM_EQCR_VERB_CMD_ENQUEUE 0x01
+#define QM_EQCR_VERB_BIT_INT 0x04
+
+#define DEF_SDQCR_TOKEN 0xab
-extern e_RxStoreResponse qman_received_frame_callback(t_Handle, t_Handle,
- t_Handle, uint32_t, t_DpaaFD *);
-extern e_RxStoreResponse qman_rejected_frame_callback(t_Handle, t_Handle,
- t_Handle, uint32_t, t_DpaaFD *, t_QmRejectedFrameInfo *);
+static void qman_portal_loop_rings(struct qman_portal_softc *sc);
+static void qman_portal_isr(void *);
-t_Handle qman_portal_setup(struct qman_softc *);
+DPCPU_DEFINE(device_t, qman_affine_portal);
+DPAA_RING(qman_eqcr, QMAN_EQCR_COUNT, QCSP_EQCR_PI_CENA, QCSP_EQCR_CI_CENA,
+ QCSP_EQCR_PI_CINH, QCSP_EQCR_CI_CINH);
+DPAA_RING(qman_dqrr, QMAN_DQRR_COUNT, QCSP_DQRR_PI_CENA, QCSP_DQRR_CI_CENA,
+ QCSP_DQRR_PI_CINH, QCSP_DQRR_CI_CINH);
-struct dpaa_portals_softc *qp_sc;
+/*
+ * pmode: one of the CFG_EPM constants.
+ * stash_prio: 0 or CFG_EP
+ * stash_thresh: 0-7
+ */
+static int
+qman_eqcr_init(struct qman_portal_softc *sc, int pmode, u_int stash_thresh,
+ u_int stash_prio)
+{
+ struct resource *regs = sc->sc_base.sc_mres[1];
+ uint32_t reg;
+
+ sc->sc_eqcr.ring =
+ (struct qman_eqcr_entry *)(sc->sc_base.sc_ce_va + QCSP_EQCR_N(0));
+ qman_eqcr_ring_init(&sc->sc_eqcr, &sc->sc_base);
+ reg = bus_read_4(regs, QCSP_CFG);
+ reg &= 0x00ffffff;
+ reg |= pmode;
+ reg |= ((stash_thresh << CFG_EST_S) & CFG_EST_M);
+ reg |= stash_prio;
+
+ bus_write_4(regs, QCSP_CFG, reg);
+ return (0);
+}
+
+static int
+qman_dqrr_init(struct qman_portal_softc *sc)
+{
+ struct resource *regs = sc->sc_base.sc_mres[1];
+ uint32_t reg;
+
+ /* Dequeue from the direct-connect channel and pool 0, up to 3 frames */
+ bus_write_4(regs, QCSP_DQRR_SDQCR,
+ SDQCR_FC | SDQCR_DP | SDQCR_DCT_PRI_PREC |
+ (DEF_SDQCR_TOKEN << SDQCR_TOKEN_S) |
+ DQRR_DQ_SRC_DCP | SDQCR_DQ_SRC_CHAN(0));
+ bus_write_4(regs, QCSP_DQRR_VDQCR, 0);
+ bus_write_4(regs, QCSP_DQRR_PDQCR, 0);
+
+ sc->sc_dqrr.ring =
+ (struct qman_dqrr_entry *)(sc->sc_base.sc_ce_va + QCSP_DQRR_N(0));
+ qman_dqrr_ring_init(&sc->sc_dqrr, &sc->sc_base);
+
+ /* Set DQRR max fill to 15 */
+ reg = bus_read_4(regs, QCSP_CFG);
+ reg |= (0xf << CFG_DQRR_MF_S);
+ bus_write_4(regs, QCSP_CFG, reg);
+
+ for (int i = 0; i < QMAN_DQRR_COUNT; i++)
+ __asm __volatile ("dcbi 0,%0" :: "r"(&sc->sc_dqrr.ring[i]) : "memory");
+
+ return (0);
+}
int
-qman_portals_attach(device_t dev)
+qman_portal_attach(device_t dev, int cpu)
{
- struct dpaa_portals_softc *sc;
+ struct qman_portal_softc *sc = device_get_softc(dev);
+ union qman_mc_command *cr;
+ pcell_t cell;
+ phandle_t node;
+
+ sc->sc_base.sc_cpu = cpu;
+ dpaa_portal_alloc_res(dev, cpu);
- sc = qp_sc = device_get_softc(dev);
-
- /* Map bman portal to physical address space */
- if (law_enable(OCP85XX_TGTIF_QMAN, sc->sc_dp_pa, sc->sc_dp_size)) {
- qman_portals_detach(dev);
+ qman_eqcr_init(sc, CFG_EPM_VB1, 0, 0);
+ qman_dqrr_init(sc);
+ bus_setup_intr(dev, sc->sc_base.sc_ires, INTR_TYPE_NET | INTR_MPSAFE,
+ NULL, qman_portal_isr, sc, &sc->sc_base.sc_intr_cookie);
+ bus_bind_intr(dev, sc->sc_base.sc_ires, cpu);
+
+ node = ofw_bus_get_node(dev);
+ if (OF_getencprop(node, "cell-index", &cell, sizeof(cell)) <= 0) {
+ device_printf(dev, "missing 'cell-index' property\n");
return (ENXIO);
}
- /* Set portal properties for XX_VirtToPhys() */
- XX_PortalSetInfo(dev);
+ sc->sc_affine_channel = cell;
+ DPCPU_ID_SET(cpu, qman_affine_portal, dev);
+ bus_write_4(sc->sc_base.sc_mres[1], QCSP_IER,
+ QM_PIRQ_EQCI | QM_PIRQ_EQRI | QM_PIRQ_MRI | QM_PIRQ_CSCI |
+ QM_PIRQ_DQRI);
+ bus_write_4(sc->sc_base.sc_mres[1], QCSP_ISDR, 0);
+
+ /* Initialize the MC polarity bit, it may not be 0. */
+ cr = (union qman_mc_command *)(sc->sc_base.sc_ce_va + QCSP_CR);
+ sc->sc_mc.polarity =
+ (cr->common.verb & QMAN_MC_VERB_VBIT) ^ QMAN_MC_VERB_VBIT;
+ /* TODO: LIODN. Fake it for now */
+
+ qman_set_sdest(sc->sc_affine_channel, cpu);
- bus_attach_children(dev);
return (0);
}
+
int
-qman_portals_detach(device_t dev)
+qman_portal_detach(device_t dev)
{
- struct dpaa_portals_softc *sc;
+ struct qman_portal_softc *sc;
int i;
- qp_sc = NULL;
sc = device_get_softc(dev);
- for (i = 0; i < ARRAY_SIZE(sc->sc_dp); i++) {
- if (sc->sc_dp[i].dp_ph != NULL) {
- thread_lock(curthread);
- sched_bind(curthread, i);
- thread_unlock(curthread);
+ /* TODO: Unmap TLB regions */
+ thread_lock(curthread);
+ sched_bind(curthread, sc->sc_base.sc_cpu);
+ thread_unlock(curthread);
- QM_PORTAL_Free(sc->sc_dp[i].dp_ph);
+ if (sc->sc_base.sc_ires != NULL)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_base.sc_ires);
- thread_lock(curthread);
- sched_unbind(curthread);
- thread_unlock(curthread);
- }
-
- if (sc->sc_dp[i].dp_ires != NULL) {
- XX_DeallocIntr((uintptr_t)sc->sc_dp[i].dp_ires);
- bus_release_resource(dev, SYS_RES_IRQ,
- sc->sc_dp[i].dp_irid, sc->sc_dp[i].dp_ires);
- }
- }
- for (i = 0; i < ARRAY_SIZE(sc->sc_rres); i++) {
- if (sc->sc_rres[i] != NULL)
+ for (i = 0; i < nitems(sc->sc_base.sc_mres); i++) {
+ if (sc->sc_base.sc_mres[i] != NULL)
bus_release_resource(dev, SYS_RES_MEMORY,
- sc->sc_rrid[i],
- sc->sc_rres[i]);
+ i, sc->sc_base.sc_mres[i]);
}
+ thread_lock(curthread);
+ sched_unbind(curthread);
+ thread_unlock(curthread);
+
return (0);
}
-t_Handle
-qman_portal_setup(struct qman_softc *qsc)
+static void
+qman_portal_isr(void *arg)
{
- struct dpaa_portals_softc *sc;
- t_QmPortalParam qpp;
- unsigned int cpu;
- uintptr_t p;
- t_Handle portal;
+ struct qman_portal_softc *sc = arg;
- /* Return NULL if we're not ready or while detach */
- if (qp_sc == NULL)
- return (NULL);
+ qman_portal_loop_rings(sc);
+}
+
+int
+qman_portal_fq_enqueue(device_t dev, struct qman_fq *fq, struct dpaa_fd *frame)
+{
+ struct qman_portal_softc *sc = device_get_softc(dev);
+ struct qman_eqcr_entry *eqcr;
+
+ /* Get available... */
+ eqcr = qman_eqcr_start(&sc->sc_eqcr, &sc->sc_base);
+ if (eqcr == NULL)
+ return (EBUSY);
+ eqcr->fd = *frame;
+ eqcr->fqid = fq->fqid;
+ qman_eqcr_commit(&sc->sc_eqcr, QM_EQCR_VERB_CMD_ENQUEUE);
+
+ return (0);
+}
+
+static int
+qman_portal_loop_dqrr(struct qman_portal_softc *sc)
+{
+ struct qman_dqrr_entry *dqrr;
+ struct qman_dqrr_entry *base;
+ struct qman_fq *fq;
+ int ci = bus_read_4(sc->sc_base.sc_mres[1], QCSP_DQRR_CI_CINH) &
+ DQRR_CI_CI_M;
+ int pi = bus_read_4(sc->sc_base.sc_mres[1], QCSP_DQRR_PI_CINH) &
+ DQRR_PI_PI_M;
+
+ base = sc->sc_dqrr.ring;
+ do {
+ dqrr = &base[ci];
+ dpaa_flush_line(dqrr);
+ dpaa_touch_line(dqrr);
+ if ((dqrr->stat & QMAN_DQRR_STAT_HAS_FRAME)) {
+ fq = qman_fq_from_index(dqrr->fqid);
+ if (fq != NULL && fq->cb.dqrr != NULL) {
+ fq->cb.dqrr(sc->sc_base.sc_dev, fq,
+ &dqrr->fd, fq->cb.ctx);
+ }
+ } else
+ break;
+ ci = (ci + 1) & DQRR_CI_CI_M;
+ bus_write_4(sc->sc_base.sc_mres[1], QCSP_DQRR_CI_CINH, ci);
+ } while (ci != pi);
+
+ return (0);
+}
+
+static void
+qman_portal_loop_rings(struct qman_portal_softc *sc)
+{
+ uint32_t isr;
- sc = qp_sc;
+ isr = bus_read_4(sc->sc_base.sc_mres[1], QCSP_ISR);
- sched_pin();
- portal = NULL;
- cpu = PCPU_GET(cpuid);
+ /* Handle DQRR first. */
+ if ((isr & QM_PIRQ_DQRI)) {
+ qman_portal_loop_dqrr(sc);
+ }
+ if ((isr & QM_PIRQ_CSCI)) {
+ }
+ if ((isr & QM_PIRQ_EQRI)) {
+ qman_eqcr_update(&sc->sc_eqcr, &sc->sc_base);
+ }
+ bus_write_4(sc->sc_base.sc_mres[1], QCSP_ISR, isr);
+}
- /* Check if portal is ready */
- while (atomic_cmpset_acq_ptr((uintptr_t *)&sc->sc_dp[cpu].dp_ph,
- 0, -1) == 0) {
- p = atomic_load_acq_ptr((uintptr_t *)&sc->sc_dp[cpu].dp_ph);
+/* MC commands */
+
+/* Assumes pinned */
+union qman_mc_result *
+qman_portal_mc_send_raw(device_t dev, union qman_mc_command *c)
+{
+ struct qman_portal_softc *sc;
+ int res_idx;
+ union qman_mc_result *rr;
+ union qman_mc_command *cr;
+ int timeout = 10000;
+ uint8_t verb;
+
+ sc = device_get_softc(dev);
- /* Return if portal is already initialized */
- if (p != 0 && p != -1) {
- sched_unpin();
- return ((t_Handle)p);
- }
+ verb = c->common.verb;
+ c->common.verb = 0;
+ cr = (union qman_mc_command *)(sc->sc_base.sc_ce_va + QCSP_CR);
+ dpaa_zero_line(cr);
+ *cr = *c;
+ dpaa_lw_barrier();
+ cr->common.verb = verb | sc->sc_mc.polarity;
+ res_idx = (sc->sc_mc.polarity ? 1 : 0);
+ sc->sc_mc.polarity ^= QMAN_MC_VERB_VBIT;
+ dpaa_flush_line(cr);
+ dpaa_touch_line(cr);
- /* Not inititialized and "owned" by another thread */
- sched_relinquish(curthread);
+ rr = (union qman_mc_result *)(sc->sc_base.sc_ce_va + QCSP_RR(res_idx));
+ for (; timeout > 0; --timeout) {
+ dpaa_flush_line(rr);
+ if (rr->common.verb != 0)
+ break;
}
+ if (timeout == 0)
+ return (NULL);
+ return (rr);
+}
- /* Map portal registers */
- dpaa_portal_map_registers(sc);
+void
+qman_portal_static_dequeue_channel(device_t dev, int channel)
+{
+ struct qman_portal_softc *sc = device_get_softc(dev);
+ uint32_t reg;
- /* Configure and initialize portal */
- qpp.ceBaseAddress = rman_get_bushandle(sc->sc_rres[0]);
- qpp.ciBaseAddress = rman_get_bushandle(sc->sc_rres[1]);
- qpp.h_Qm = qsc->sc_qh;
- qpp.swPortalId = cpu;
- qpp.irq = (uintptr_t)sc->sc_dp[cpu].dp_ires;
- qpp.fdLiodnOffset = 0;
- qpp.f_DfltFrame = qman_received_frame_callback;
- qpp.f_RejectedFrame = qman_rejected_frame_callback;
- qpp.h_App = qsc;
+ reg = bus_read_4(sc->sc_base.sc_mres[1], QCSP_DQRR_SDQCR);
+ reg |= (1 << (15 - (channel - qman_channel_base)));
+ bus_write_4(sc->sc_base.sc_mres[1], QCSP_DQRR_SDQCR, reg);
+}
- portal = QM_PORTAL_Config(&qpp);
- if (portal == NULL)
- goto err;
+void
+qman_portal_static_dequeue_rm_channel(device_t dev, int channel)
+{
+ struct qman_portal_softc *sc = device_get_softc(dev);
+ uint32_t reg;
- if (QM_PORTAL_Init(portal) != E_OK)
- goto err;
+ reg = bus_read_4(sc->sc_base.sc_mres[1], QCSP_DQRR_SDQCR);
+ reg &= ~(1 << (15 - (channel - qman_channel_base)));
+ bus_write_4(sc->sc_base.sc_mres[1], QCSP_DQRR_SDQCR, reg);
+}
- if (QM_PORTAL_AddPoolChannel(portal, QMAN_COMMON_POOL_CHANNEL) != E_OK)
- goto err;
+DB_SHOW_COMMAND(fqid, qman_show_fqid)
+{
+ union qman_mc_command cmd;
+ union qman_mc_result *res;
+ union qman_mc_result save_res;
+ device_t portal;
- atomic_store_rel_ptr((uintptr_t *)&sc->sc_dp[cpu].dp_ph,
- (uintptr_t)portal);
- sched_unpin();
+ if (!have_addr)
+ return;
- return (portal);
+ bzero(&cmd, sizeof(cmd));
+ cmd.query_fq_np.fqid = addr;
-err:
- if (portal != NULL)
- QM_PORTAL_Free(portal);
+ /* Ensure we have got QMan port initialized */
+ portal = DPCPU_GET(qman_affine_portal);
+ res = qman_portal_mc_send_raw(portal, &cmd);
- atomic_store_rel_32((uint32_t *)&sc->sc_dp[cpu].dp_ph, 0);
- sched_unpin();
+ if (res != NULL)
+ save_res = *res;
- return (NULL);
+ /* Dump all NP fields */
+ if (res != NULL && save_res.query_fq_np.rslt == 0xf0) {
+ db_printf("FQID: %d\n", (int)addr);
+ db_printf(" State: %x\n", save_res.query_fq_np.state);
+ db_printf(" Link: %x\n", save_res.query_fq_np.fqd_link);
+ db_printf(" ODP_SEQ: %x\n", save_res.query_fq_np.odp_seq);
+ db_printf(" ORP_NESN: %x\n", save_res.query_fq_np.orp_nesn);
+ db_printf(" ORP_EA_HSEQ: %x\n",
+ save_res.query_fq_np.orp_ea_hseq);
+ db_printf(" ORP_EA_TSEQ: %x\n",
+ save_res.query_fq_np.orp_ea_tseq);
+ db_printf(" ORP_EA_HPTR: %x\n",
+ save_res.query_fq_np.orp_ea_hptr);
+ db_printf(" ORP_EA_TPTR: %x\n",
+ save_res.query_fq_np.orp_ea_tptr);
+ db_printf(" pfdr_hptr: %x\n", save_res.query_fq_np.pfdr_hptr);
+ db_printf(" pfdr_tptr: %x\n", save_res.query_fq_np.pfdr_tptr);
+ db_printf(" IS: %x\n", save_res.query_fq_np.is);
+ db_printf(" ICS_SURP: %x\n", save_res.query_fq_np.ics_surp);
+ db_printf(" byte_cnt: %x\n", save_res.query_fq_np.byte_cnt);
+ db_printf(" frm_cnt: %x\n", save_res.query_fq_np.frm_cnt);
+ db_printf(" ra1_sfdr: %x\n", save_res.query_fq_np.ra1_sfdr);
+ db_printf(" ra2_sfdr: %x\n", save_res.query_fq_np.ra2_sfdr);
+ db_printf(" od1_sfdr: %x\n", save_res.query_fq_np.od1_sfdr);
+ db_printf(" od2_sfdr: %x\n", save_res.query_fq_np.od2_sfdr);
+ db_printf(" od3_sfdr: %x\n", save_res.query_fq_np.od3_sfdr);
+ }
}
diff --git a/sys/dev/dpaa/qman_var.h b/sys/dev/dpaa/qman_var.h
new file mode 100644
index 000000000000..8ed36bbb6a35
--- /dev/null
+++ b/sys/dev/dpaa/qman_var.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2026 Justin Hibbits
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef QMAN_VAR_H
+#define QMAN_VAR_H
+
+#include "dpaa_common.h"
+#include "portals.h"
+
+struct qman_eqcr_entry {
+ uint8_t verb;
+ uint8_t dca;
+ uint16_t seqnum;
+ uint32_t orp;
+ uint32_t fqid;
+ uint32_t tag;
+ struct dpaa_fd fd;
+ uint8_t _rsvd[32];
+};
+_Static_assert(sizeof(struct qman_eqcr_entry) == 64, "EQCR entry mis-sized");
+DPAA_RING_DECLARE(qman_eqcr);
+DPAA_RING_DECLARE(qman_dqrr);
+DPAA_RING_DECLARE(qman_mr);
+
+union qman_mc_command {
+ struct {
+ uint8_t verb;
+ uint8_t data[63];
+ } common;
+ struct {
+ uint8_t verb;
+ uint8_t _rsvd0;
+ uint16_t we_mask;
+ uint32_t fqid; /* Only bottom 24 bits allowed */
+ uint16_t count;
+ uint8_t orpc;
+ uint8_t cgid;
+ uint16_t fq_ctrl;
+ uint16_t dest_chan:13;
+ uint16_t dest_wq:3;
+ uint16_t ics_cred;
+ uint16_t td_thresh_oac;
+ uint32_t context_b;
+ uint32_t context_a;
+ uint8_t _rsvd1[32];
+ } init_fq;
+ struct {
+ uint8_t verb;
+ uint8_t _rsvd0[3];
+ uint32_t fqid; /* Only bottom 24 bits used */
+ uint8_t _rsvd1[56];
+ } query_fq;
+ struct {
+ uint8_t verb;
+ uint8_t _rsvd0[3];
+ uint32_t fqid;
+ uint8_t _rsvd1[56];
+ } query_fq_np;
+ struct {
+ uint8_t verb;
+ uint8_t _rsvd0[3];
+ uint32_t fqid;
+ uint8_t _rsvd1;
+ uint8_t count;
+ uint8_t _rsvd2[10];
+ uint32_t context_b;
+ uint8_t _rsvd3[40];
+ } alter_fqs;
+};
+
+union qman_mc_result {
+ struct {
+ uint8_t verb;
+ uint8_t data[63];
+ } common;
+ struct {
+ uint8_t verb;
+ uint8_t rslt;
+ uint8_t _rsvd[62];
+ } init_fq;
+ struct {
+ uint8_t verb;
+ uint8_t rslt;
+ uint8_t _rsvd0[8];
+ uint8_t orpc;
+ uint8_t cgid;
+ uint16_t fq_ctrl;
+ uint16_t dest_wq;
+ uint16_t ics_cred;
+ uint16_t td_thresh;
+ uint32_t context_b;
+ uint32_t context_a;
+ uint16_t oac;
+ uint8_t _rsvd1[30];
+ } query_fq;
+ struct {
+ uint8_t verb;
+ uint8_t rslt;
+ uint8_t _rsvd0;
+ uint8_t state;
+ uint32_t fqd_link;
+ uint16_t odp_seq;
+ uint16_t orp_nesn;
+ uint16_t orp_ea_hseq;
+ uint16_t orp_ea_tseq;
+ uint32_t orp_ea_hptr;
+ uint32_t orp_ea_tptr;
+ uint32_t pfdr_hptr;
+ uint32_t pfdr_tptr;
+ uint8_t _rsvd1[5];
+ uint8_t is;
+ uint16_t ics_surp;
+ uint32_t byte_cnt;
+ uint32_t frm_cnt;
+ uint32_t _rsvd2;
+ uint16_t ra1_sfdr;
+ uint16_t ra2_sfdr;
+ uint16_t _rsvd3;
+ uint16_t od1_sfdr;
+ uint16_t od2_sfdr;
+ uint16_t od3_sfdr;
+ } query_fq_np;
+ struct {
+ uint8_t verb;
+ uint8_t rslt;
+ uint8_t fqs;
+ uint8_t _rsvd[61];
+ } alter_fqs;
+};
+
+struct qman_mc {
+ uint8_t polarity;
+ bool busy;
+};
+
+struct qman_fq {
+ uint32_t fqid;
+ struct qman_cb cb;
+};
+
+struct qman_portal_softc {
+ struct dpaa_portal_softc sc_base;
+
+ /* Rings (Enqueue, Dequeue, Message */
+ struct qman_eqcr_ring sc_eqcr;
+ struct qman_dqrr_ring sc_dqrr;
+ struct qman_mr_ring sc_mr;
+ struct qman_mc sc_mc;
+
+ int sc_affine_channel;
+};
+
+struct qman_fq *qman_fq_from_index(uint32_t fqid);
+
+union qman_mc_result *
+qman_portal_mc_send_raw(device_t, union qman_mc_command *);
+int qman_portal_fq_enqueue(device_t, struct qman_fq *, struct dpaa_fd *);
+void qman_portal_static_dequeue_channel(device_t, int);
+void qman_portal_static_dequeue_rm_channel(device_t dev, int channel);
+
+extern int qman_channel_base;
+DPCPU_DECLARE(device_t, qman_affine_portal);
+
+#endif /* QMAN_VAR_H */
diff --git a/sys/dev/hwpmc/hwpmc_amd.c b/sys/dev/hwpmc/hwpmc_amd.c
index 51505bfcff37..299021494716 100644
--- a/sys/dev/hwpmc/hwpmc_amd.c
+++ b/sys/dev/hwpmc/hwpmc_amd.c
@@ -40,6 +40,7 @@
#include <sys/pmc.h>
#include <sys/pmckern.h>
#include <sys/smp.h>
+#include <sys/sysctl.h>
#include <sys/systm.h>
#include <machine/cpu.h>
@@ -178,6 +179,63 @@ struct amd_cpu {
};
static struct amd_cpu **amd_pcpu;
+/* Populated by amd_init_policy(); PRECISERETIRE is OR-ed in per-allocation. */
+static uint64_t amd_core_allowed_mask;
+static uint64_t amd_l3_allowed_mask;
+static uint64_t amd_df_allowed_mask;
+
+static uint64_t amd_core_extra_mask;
+static uint64_t amd_l3_extra_mask;
+static uint64_t amd_df_extra_mask;
+
+SYSCTL_DECL(_kern_hwpmc);
+
+SYSCTL_U64(_kern_hwpmc, OID_AUTO, amd_core_extra_mask, CTLFLAG_RDTUN,
+ &amd_core_extra_mask, 0,
+ "Extra allowed bits in AMD core PMU PERFEVTSEL (override; default 0)");
+
+SYSCTL_U64(_kern_hwpmc, OID_AUTO, amd_l3_extra_mask, CTLFLAG_RDTUN,
+ &amd_l3_extra_mask, 0,
+ "Extra allowed bits in AMD L3 PMU control (override; default 0)");
+
+SYSCTL_U64(_kern_hwpmc, OID_AUTO, amd_df_extra_mask, CTLFLAG_RDTUN,
+ &amd_df_extra_mask, 0,
+ "Extra allowed bits in AMD DF PMU control (override; default 0)");
+
+static void
+amd_init_policy(void)
+{
+ int family;
+
+ family = CPUID_TO_FAMILY(cpu_id);
+
+ amd_core_allowed_mask = AMD_VALID_BITS;
+
+ amd_l3_allowed_mask = (family <= 0x17) ?
+ AMD_PMC_L3_FAMILY17_MASK : AMD_PMC_L3_FAMILY19_MASK;
+
+ amd_df_allowed_mask = (family <= 0x19) ?
+ AMD_PMC_DF_FAMILY17_MASK : AMD_PMC_DF_FAMILY1A_MASK;
+}
+
+static uint64_t
+amd_config_mask(enum sub_class subclass, uint64_t caps)
+{
+
+ switch (subclass) {
+ case PMC_AMD_SUB_CLASS_CORE:
+ return (amd_core_allowed_mask | amd_core_extra_mask |
+ (((caps & PMC_CAP_PRECISE) != 0) ?
+ AMD_PMC_PRECISERETIRE : 0));
+ case PMC_AMD_SUB_CLASS_L3_CACHE:
+ return (amd_l3_allowed_mask | amd_l3_extra_mask);
+ case PMC_AMD_SUB_CLASS_DATA_FABRIC:
+ return (amd_df_allowed_mask | amd_df_extra_mask);
+ default:
+ return (0);
+ }
+}
+
/*
* Read a PMC value from the MSR.
*/
@@ -358,9 +416,13 @@ amd_allocate_pmc(int cpu __unused, int ri, struct pmc *pm,
return (EINVAL);
if (strlen(pmc_cpuid) != 0) {
- pm->pm_md.pm_amd.pm_amd_evsel = a->pm_md.pm_amd.pm_amd_config;
- PMCDBG2(MDP, ALL, 2,"amd-allocate ri=%d -> config=0x%x", ri,
- a->pm_md.pm_amd.pm_amd_config);
+ config = a->pm_md.pm_amd.pm_amd_config;
+ if ((config & ~amd_config_mask(amd_pmcdesc[ri].pm_subclass,
+ caps)) != 0)
+ return (EINVAL);
+ pm->pm_md.pm_amd.pm_amd_evsel = config;
+ PMCDBG2(MDP, ALL, 2, "amd-allocate ri=%d -> config=0x%jx",
+ ri, (uintmax_t)config);
return (0);
}
@@ -981,6 +1043,8 @@ pmc_amd_initialize(void)
pmc_mdep->pmd_npmc += amd_npmcs;
+ amd_init_policy();
+
PMCDBG0(MDP, INI, 0, "amd-initialize");
if (nclasses >= 3) {
diff --git a/sys/dev/hwpmc/hwpmc_amd.h b/sys/dev/hwpmc/hwpmc_amd.h
index 6d8ab8203942..616d115ecc25 100644
--- a/sys/dev/hwpmc/hwpmc_amd.h
+++ b/sys/dev/hwpmc/hwpmc_amd.h
@@ -122,6 +122,18 @@
#define AMD_PMC_L3_TO_UNITMASK(x) (((x) << 8) & AMD_PMC_UNITMASK)
#define AMD_PMC_L3_TO_EVENTMASK(x) ((x) & 0xFF)
+#define AMD_PMC_L3_FAMILY17_MASK \
+ (AMD_PMC_ENABLE | AMD_PMC_L3_TO_EVENTMASK(0xff) | \
+ AMD_PMC_L3_TO_UNITMASK(0xff) | \
+ AMD_PMC_L31_SLICEMASK | AMD_PMC_L31_COREMASK)
+
+#define AMD_PMC_L3_FAMILY19_MASK \
+ (AMD_PMC_ENABLE | AMD_PMC_L3_TO_EVENTMASK(0xff) | \
+ AMD_PMC_L3_TO_UNITMASK(0xff) | \
+ AMD_PMC_L32_THREADMASK | AMD_PMC_L32_SOURCEMASK | \
+ AMD_PMC_L32_ALLCORES | AMD_PMC_L32_ALLSOURCES | \
+ AMD_PMC_L32_COREMASK)
+
#define AMD_PMC_L3_CAPS (PMC_CAP_READ | PMC_CAP_WRITE | \
PMC_CAP_QUALIFIER | PMC_CAP_DOMWIDE)
@@ -148,6 +160,16 @@
#define AMD_PMC_DF2_TO_UNITMASK(x) ((((x) & 0xFF) << 8) | \
(((uint64_t)(x) & 0x0F00) << 16))
+#define AMD_PMC_DF_FAMILY17_MASK \
+ (AMD_PMC_ENABLE | \
+ AMD_PMC_DF1_TO_EVENTMASK(0x3fff) | \
+ AMD_PMC_DF1_TO_UNITMASK(0xff))
+
+#define AMD_PMC_DF_FAMILY1A_MASK \
+ (AMD_PMC_ENABLE | \
+ AMD_PMC_DF2_TO_EVENTMASK(0x7fff) | \
+ AMD_PMC_DF2_TO_UNITMASK(0xfff))
+
#define AMD_NPMCS_K8 4
#define AMD_NPMCS_MAX (AMD_PMC_CORE_MAX + AMD_PMC_L3_MAX + \
AMD_PMC_DF_MAX)
diff --git a/sys/dev/hwpmc/hwpmc_ibs.c b/sys/dev/hwpmc/hwpmc_ibs.c
index 56903699ac51..8cfe7b2df145 100644
--- a/sys/dev/hwpmc/hwpmc_ibs.c
+++ b/sys/dev/hwpmc/hwpmc_ibs.c
@@ -36,8 +36,12 @@
#include <sys/pmckern.h>
#include <sys/pmclog.h>
#include <sys/smp.h>
+#include <sys/sysctl.h>
#include <sys/systm.h>
+#define EXTERR_CATEGORY EXTERR_CAT_HWPMC_IBS
+#include <sys/exterrvar.h>
+
#include <machine/cpu.h>
#include <machine/cpufunc.h>
#include <machine/md_var.h>
@@ -54,6 +58,21 @@ struct ibs_descr {
* Globals
*/
static uint64_t ibs_features;
+static uint64_t ibs_fetch_allowed_mask;
+static uint64_t ibs_op_allowed_mask;
+
+static uint64_t ibs_fetch_extra_mask;
+static uint64_t ibs_op_extra_mask;
+
+SYSCTL_DECL(_kern_hwpmc);
+
+SYSCTL_U64(_kern_hwpmc, OID_AUTO, ibs_fetch_extra_mask, CTLFLAG_RDTUN,
+ &ibs_fetch_extra_mask, 0,
+ "Extra allowed bits in the IBS fetch control MSR (override; default 0)");
+
+SYSCTL_U64(_kern_hwpmc, OID_AUTO, ibs_op_extra_mask, CTLFLAG_RDTUN,
+ &ibs_op_extra_mask, 0,
+ "Extra allowed bits in the IBS op control MSR (override; default 0)");
/*
* Per-processor information
@@ -68,6 +87,75 @@ struct ibs_cpu {
};
static struct ibs_cpu **ibs_pcpu;
+static void
+ibs_init_policy(void)
+{
+
+ ibs_fetch_allowed_mask = IBS_FETCH_ALLOWED_MASK_BASE;
+
+ ibs_op_allowed_mask = IBS_OP_CTL_MAXCNTBASEMASK;
+
+ if ((ibs_features & CPUID_IBSID_ZEN4IBSEXTENSIONS) != 0)
+ ibs_fetch_allowed_mask |= IBS_FETCH_CTL_L3MISSONLY;
+
+ if ((ibs_features & CPUID_IBSID_OPCNT) != 0)
+ ibs_op_allowed_mask |= IBS_OP_CTL_COUNTERCONTROL;
+
+ if ((ibs_features & CPUID_IBSID_OPCNTEXT) != 0)
+ ibs_op_allowed_mask |= IBS_OP_CTL_MAXCNTEXTMASK;
+
+ if ((ibs_features & CPUID_IBSID_ZEN4IBSEXTENSIONS) != 0)
+ ibs_op_allowed_mask |= IBS_OP_CTL_L3MISSONLY;
+}
+
+static int
+ibs_validate_fetch_config(uint64_t config)
+{
+
+ if ((config & ~(ibs_fetch_allowed_mask | ibs_fetch_extra_mask)) != 0)
+ return (EINVAL);
+
+ return (0);
+}
+
+static int
+ibs_validate_op_config(uint64_t config)
+{
+ uint64_t allowed_mask;
+
+ allowed_mask = ibs_op_allowed_mask;
+
+ if ((config & IBS_OP_CTL_LATFLTEN) != 0) {
+ if ((ibs_features & CPUID_IBSID_IBSLOADLATENCYFILT) == 0)
+ return (EINVAL);
+ if ((config & IBS_OP_CTL_L3MISSONLY) == 0)
+ return (EINVAL);
+
+ allowed_mask |= IBS_OP_CTL_LDLATMASK | IBS_OP_CTL_L3MISSONLY;
+ }
+
+ allowed_mask |= ibs_op_extra_mask;
+
+ if ((config & ~allowed_mask) != 0)
+ return (EINVAL);
+
+ return (0);
+}
+
+static int
+ibs_validate_pmc_config(int ri, uint64_t config)
+{
+
+ switch (ri) {
+ case IBS_PMC_FETCH:
+ return (ibs_validate_fetch_config(config));
+ case IBS_PMC_OP:
+ return (ibs_validate_op_config(config));
+ default:
+ return (EINVAL);
+ }
+}
+
/*
* Read a PMC value from the MSR.
*/
@@ -179,30 +267,37 @@ ibs_allocate_pmc(int cpu __unused, int ri, struct pmc *pm,
const struct pmc_op_pmcallocate *a)
{
uint64_t caps, config;
+ int error;
KASSERT(ri >= 0 && ri < IBS_NPMCS,
("[ibs,%d] illegal row index %d", __LINE__, ri));
/* check class match */
if (a->pm_class != PMC_CLASS_IBS)
- return (EINVAL);
+ return (EXTERROR(EINVAL, "PMC class is not IBS"));
if (a->pm_md.pm_ibs.ibs_type != ri)
- return (EINVAL);
+ return (EXTERROR(EINVAL,
+ "IBS type %ju does not match PMC index %ju",
+ (uint64_t)a->pm_md.pm_ibs.ibs_type, (uint64_t)ri));
caps = pm->pm_caps;
PMCDBG2(MDP, ALL, 1, "ibs-allocate ri=%d caps=0x%x", ri, caps);
if ((caps & PMC_CAP_SYSTEM) == 0)
- return (EINVAL);
+ return (EXTERROR(EINVAL, "IBS requires SYSTEM capability"));
if (!PMC_IS_SAMPLING_MODE(a->pm_mode))
return (EINVAL);
config = a->pm_md.pm_ibs.ibs_ctl;
+ error = ibs_validate_pmc_config(ri, config);
+ if (error != 0)
+ return (error);
pm->pm_md.pm_ibs.ibs_ctl = config;
- PMCDBG2(MDP, ALL, 2, "ibs-allocate ri=%d -> config=0x%x", ri, config);
+ PMCDBG2(MDP, ALL, 2, "ibs-allocate ri=%d -> config=0x%jx", ri,
+ config);
return (0);
}
@@ -356,7 +451,6 @@ pmc_ibs_process_fetch(struct pmc *pm, struct trapframe *tf, uint64_t config)
if ((ibs_features & CPUID_IBSID_IBSFETCHCTLEXTD) != 0) {
mpd.pl_mpdata[PMC_MPIDX_FETCH_EXTCTL] = rdmsr(IBS_FETCH_EXTCTL);
}
- mpd.pl_mpdata[PMC_MPIDX_FETCH_CTL] = config;
mpd.pl_mpdata[PMC_MPIDX_FETCH_LINADDR] = rdmsr(IBS_FETCH_LINADDR);
if ((config & IBS_FETCH_CTL_PHYSADDRVALID) != 0) {
mpd.pl_mpdata[PMC_MPIDX_FETCH_PHYSADDR] =
@@ -617,10 +711,14 @@ pmc_ibs_initialize(struct pmc_mdep *pmc_mdep, int ncpus)
if (cpu_exthigh >= CPUID_IBSID) {
do_cpuid(CPUID_IBSID, regs);
ibs_features = regs[0];
+ if ((ibs_features & CPUID_IBSID_IBSFFV) == 0)
+ ibs_features = 0;
} else {
ibs_features = 0;
}
+ ibs_init_policy();
+
PMCDBG0(MDP, INI, 0, "ibs-initialize");
return (0);
diff --git a/sys/dev/hwpmc/hwpmc_ibs.h b/sys/dev/hwpmc/hwpmc_ibs.h
index 2b4e111ba171..433397954d4f 100644
--- a/sys/dev/hwpmc/hwpmc_ibs.h
+++ b/sys/dev/hwpmc/hwpmc_ibs.h
@@ -100,6 +100,8 @@
#define IBS_FETCH_CTL_TO_LAT(_c) (((_c) >> 32) & 0x0000FFFF)
#define IBS_FETCH_COUNT_TO_CTL(_c) (((_c) << 12) & IBS_FETCH_CTL_CURCNTMASK)
#define IBS_FETCH_CTL_TO_COUNT(_c) (((_c) & IBS_FETCH_CTL_CURCNTMASK) >> 12)
+#define IBS_FETCH_ALLOWED_MASK_BASE (IBS_FETCH_CTL_MAXCNTMASK | \
+ IBS_FETCH_CTL_RANDOMIZE)
#define IBS_FETCH_LINADDR 0xC0011031 /* Fetch Linear Address */
#define IBS_FETCH_PHYSADDR 0xC0011032 /* Fetch Physical Address */
@@ -118,12 +120,22 @@
#define IBS_OP_CTL_VALID (1ULL << 18) /* Valid */
#define IBS_OP_CTL_ENABLE (1ULL << 17) /* Enable */
#define IBS_OP_CTL_L3MISSONLY (1ULL << 16) /* L3 Miss Filtering */
-#define IBS_OP_CTL_MAXCNTMASK 0x07F0FFFFULL
+#define IBS_OP_CTL_MAXCNTMASK 0x07F0FFFFULL /* Max Count */
+#define IBS_OP_CTL_MAXCNTEXTMASK 0x07F00000ULL /* Max Count Extended */
+#define IBS_OP_CTL_MAXCNTBASEMASK (IBS_OP_CTL_MAXCNTMASK & \
+ ~IBS_OP_CTL_MAXCNTEXTMASK) /* Max Count Base */
#define IBS_OP_CTL_CURCNTMASK 0x07FFFFFF00000000ULL
+#define IBS_OP_CTL_LDLATTRSHMASK (0xFULL << 59) /* Load Lat Threshold */
+#define IBS_OP_CTL_LDLATMASK (IBS_OP_CTL_LATFLTEN | \
+ IBS_OP_CTL_LDLATTRSHMASK) /* Load Lat Combined */
-#define IBS_OP_CTL_LDLAT_TO_CTL(_c) ((((ldlat) >> 7) - 1) << 59)
-#define IBS_OP_INTERVAL_TO_CTL(_c) ((((_c) >> 4) & 0x0000FFFFULL) | ((_c) & 0x07F00000))
-#define IBS_OP_CTL_TO_INTERVAL(_c) ((((_c) & 0x0000FFFFULL) << 4) | ((_c) & 0x07F00000))
+#define IBS_OP_CTL_LDLAT_TO_CTL(_c) (((((_c) >> 7) - 1) & 0xFULL) << 59)
+#define IBS_OP_INTERVAL_TO_CTL(_c) \
+ ((((_c) >> 4) & IBS_OP_CTL_MAXCNTBASEMASK) | \
+ ((_c) & IBS_OP_CTL_MAXCNTEXTMASK))
+#define IBS_OP_CTL_TO_INTERVAL(_c) \
+ ((((_c) & IBS_OP_CTL_MAXCNTBASEMASK) << 4) | \
+ ((_c) & IBS_OP_CTL_MAXCNTEXTMASK))
#define IBS_OP_COUNT_TO_CTL(_c) (((_c) << 32) & IBS_OP_CTL_CURCNTMASK)
#define IBS_OP_CTL_TO_COUNT(_c) (((_c) & IBS_OP_CTL_CURCNTMASK) >> 32)
diff --git a/sys/dev/ichsmb/ichsmb.c b/sys/dev/ichsmb/ichsmb.c
index e40a8a8a3886..0df757d9cc0e 100644
--- a/sys/dev/ichsmb/ichsmb.c
+++ b/sys/dev/ichsmb/ichsmb.c
@@ -395,6 +395,15 @@ ichsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
sc->block_write = true;
mtx_lock(&sc->mutex);
+ /*
+ * We don't expect the block buffer to be enabled. However, BIOS code
+ * might enable it and doesn't restore it at any time, so we should
+ * ensure it's disabled before sending an SMBus command.
+ */
+ if (sc->features & ICHSMB_FEATURE_BLOCK_BUFFER) {
+ bus_write_1(sc->io_res, ICH_AUX_CNT,
+ bus_read_1(sc->io_res, ICH_AUX_CNT) & ~ICH_AUX_CNT_E32B);
+ }
sc->ich_cmd = ICH_HST_CNT_SMB_CMD_BLOCK;
bus_write_1(sc->io_res, ICH_XMIT_SLVA,
slave | ICH_XMIT_SLVA_WRITE);
@@ -424,6 +433,15 @@ ichsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf)
sc->block_write = false;
mtx_lock(&sc->mutex);
+ /*
+ * We don't expect the block buffer to be enabled. However, BIOS code
+ * might enable it and doesn't restore it at any time, so we should
+ * ensure it's disabled before sending an SMBus command.
+ */
+ if (sc->features & ICHSMB_FEATURE_BLOCK_BUFFER) {
+ bus_write_1(sc->io_res, ICH_AUX_CNT,
+ bus_read_1(sc->io_res, ICH_AUX_CNT) & ~ICH_AUX_CNT_E32B);
+ }
sc->ich_cmd = ICH_HST_CNT_SMB_CMD_BLOCK;
bus_write_1(sc->io_res, ICH_XMIT_SLVA,
slave | ICH_XMIT_SLVA_READ);
diff --git a/sys/dev/ichsmb/ichsmb_pci.c b/sys/dev/ichsmb/ichsmb_pci.c
index 7d6d94dbb4a4..7f9409e4452c 100644
--- a/sys/dev/ichsmb/ichsmb_pci.c
+++ b/sys/dev/ichsmb/ichsmb_pci.c
@@ -110,7 +110,8 @@
#define ID_ELKHARTLAKE 0x4b23
#define ID_GEMINILAKE 0x31d4
#define ID_CEDARFORK 0x18df
-#define ID_ICELAKE 0x34a3
+#define ID_ICELAKELP 0x34a3
+#define ID_ICELAKEN 0x38a3
#define ID_ALDERLAKE 0x7aa3
#define ID_ALDERLAKE2 0x51a3
#define ID_ALDERLAKE3 0x54a3
@@ -129,106 +130,155 @@ static const struct pci_device_table ichsmb_devices[] = {
{ PCI_DEV(PCI_VENDOR_INTEL, ID_82801CA),
PCI_DESCR("Intel 82801CA (ICH3) SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_82801DC),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel 82801DC (ICH4) SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_82801EB),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel 82801EB (ICH5) SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_82801FB),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel 82801FB (ICH6) SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_82801GB),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel 82801GB (ICH7) SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_82801H),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel 82801H (ICH8) SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_82801I),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel 82801I (ICH9) SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_82801GB),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel 82801GB (ICH7) SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_82801H),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel 82801H (ICH8) SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_82801I),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel 82801I (ICH9) SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_EP80579),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel EP80579 SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_82801JI),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel 82801JI (ICH10) SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_82801JD),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel 82801JD (ICH10) SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_PCH),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel PCH SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_6300ESB),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel 6300ESB (ICH) SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_631xESB),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel 631xESB/6321ESB (ESB2) SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_DH89XXCC),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel DH89xxCC SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_PATSBURG),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel Patsburg SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_CPT),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel Cougar Point SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_PPT),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel Panther Point SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_AVOTON),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel Avoton SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_LPT),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel Lynx Point SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_LPTLP),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel Lynx Point-LP SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_WCPT),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel Wildcat Point SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_WCPTLP),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel Wildcat Point-LP SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_BAYTRAIL),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel Baytrail SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_BRASWELL),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel Braswell SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_COLETOCRK),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel Coleto Creek SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_WELLSBURG),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel Wellsburg SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_SRPT),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel Sunrise Point-H SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_SRPTLP),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel Sunrise Point-LP SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_DENVERTON),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel Denverton SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_BROXTON),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel Broxton SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_LEWISBURG),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel Lewisburg SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_LEWISBURG2),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel Lewisburg SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_KABYLAKE),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel Kaby Lake SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_CANNONLAKE),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel Cannon Lake SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_COMETLAKE),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel Comet Lake SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_COMETLAKE2),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel Comet Lake SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_TIGERLAKE),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel Tiger Lake SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_TIGERLAKE2),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel Tiger Lake SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_ELKHARTLAKE),
PCI_DESCR("Intel Elkhart Lake SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_GEMINILAKE),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel Gemini Lake SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_CEDARFORK),
PCI_DESCR("Intel Cedar Fork SMBus controller") },
- { PCI_DEV(PCI_VENDOR_INTEL, ID_ICELAKE),
- PCI_DESCR("Intel Ice Lake SMBus controller") },
+ { PCI_DEV(PCI_VENDOR_INTEL, ID_ICELAKELP),
+ PCI_DESCR("Intel Ice Lake-LP SMBus controller") },
+ { PCI_DEV(PCI_VENDOR_INTEL, ID_ICELAKEN),
+ PCI_DESCR("Intel Ice Lake-N SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_ALDERLAKE),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel Alder Lake SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_ALDERLAKE2),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel Alder Lake SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_ALDERLAKE3),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel Alder Lake SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_RAPTORLAKE),
PCI_DESCR("Intel Raptor Lake SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_METEORLAKE),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel Meteor Lake SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_METEORLAKE2),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel Meteor Lake SMBus controller") },
{ PCI_DEV(PCI_VENDOR_INTEL, ID_METEORLAKE3),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel Meteor Lake SMBus controller") },
};
@@ -288,6 +338,7 @@ ichsmb_pci_probe(device_t dev)
static int
ichsmb_pci_attach(device_t dev)
{
+ const struct pci_device_table *tbl;
const sc_p sc = device_get_softc(dev);
int error;
@@ -296,6 +347,12 @@ ichsmb_pci_attach(device_t dev)
sc->ich_cmd = -1;
sc->dev = dev;
+ tbl = PCI_MATCH(dev, ichsmb_devices);
+ if (tbl == NULL)
+ return (ENXIO);
+
+ sc->features = (uint32_t)tbl->driver_data;
+
/* Allocate an I/O range */
sc->io_rid = ICH_SMB_BASE;
sc->io_res = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT,
diff --git a/sys/dev/ichsmb/ichsmb_reg.h b/sys/dev/ichsmb/ichsmb_reg.h
index 78e398a556ef..be3b9e4a899d 100644
--- a/sys/dev/ichsmb/ichsmb_reg.h
+++ b/sys/dev/ichsmb/ichsmb_reg.h
@@ -84,6 +84,9 @@
#define ICH_D0 0x05 /* host data 0 */
#define ICH_D1 0x06 /* host data 1 */
#define ICH_BLOCK_DB 0x07 /* block data byte */
+#define ICH_AUX_CNT 0x0d /* auxiliary control */
+#define ICH_AUX_CNT_E32B 0x02 /* enable 32 byte buffer */
+#define ICH_AUX_CNT_AAC 0x01 /* automatically append crc */
#endif /* _DEV_ICHSMB_ICHSMB_REG_H_ */
diff --git a/sys/dev/ichsmb/ichsmb_var.h b/sys/dev/ichsmb/ichsmb_var.h
index 8aeaf403781b..f16a40be9777 100644
--- a/sys/dev/ichsmb/ichsmb_var.h
+++ b/sys/dev/ichsmb/ichsmb_var.h
@@ -41,6 +41,8 @@
#include "smbus_if.h"
+#define ICHSMB_FEATURE_BLOCK_BUFFER 0x01 /* supports 32 byte block buffer */
+
/* Per-device private info */
struct ichsmb_softc {
@@ -52,6 +54,7 @@ struct ichsmb_softc {
struct resource *irq_res; /* interrupt resource */
int irq_rid; /* interrupt bus id */
void *irq_handle; /* handle for interrupt code */
+ uint32_t features; /* supported device features */
/* Device state */
int ich_cmd; /* ich command, or -1 */
diff --git a/sys/dev/iicbus/mux/iicmux.c b/sys/dev/iicbus/mux/iicmux.c
index 96164719577c..32b7405ebe19 100644
--- a/sys/dev/iicbus/mux/iicmux.c
+++ b/sys/dev/iicbus/mux/iicmux.c
@@ -62,7 +62,7 @@ iicmux_callback(device_t dev, int index, caddr_t data)
/* If it's not one of the operations we know about, bail early. */
if (index != IIC_REQUEST_BUS && index != IIC_RELEASE_BUS)
- return (iic2errno(EOPNOTSUPP));
+ return (errno2iic(EOPNOTSUPP));
/*
* Ensure that the data passed to us includes the device_t of the child
@@ -72,12 +72,12 @@ iicmux_callback(device_t dev, int index, caddr_t data)
*/
rd = (struct iic_reqbus_data *)data;
if (!(rd->flags & IIC_REQBUS_DEV))
- return (iic2errno(EINVAL));
+ return (errno2iic(EINVAL));
for (i = 0; i <= sc->maxbus && sc->childdevs[i] != rd->bus; ++i)
continue;
if (i > sc->maxbus)
- return (iic2errno(ENOENT));
+ return (errno2iic(ENOENT));
/*
* If the operation is a release it "cannot fail". Idle the downstream
diff --git a/sys/dev/iicbus/rtc/rs5c372a.c b/sys/dev/iicbus/rtc/rs5c372a.c
new file mode 100644
index 000000000000..1511025801f5
--- /dev/null
+++ b/sys/dev/iicbus/rtc/rs5c372a.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2026 Justin Hibbits
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/clock.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/iicbus/iiconf.h>
+#include <dev/iicbus/iicbus.h>
+
+#include "clock_if.h"
+#include "iicbus_if.h"
+
+/*
+ * Driver for the Richo rs5c372a RTC. The chip itself includes 2 alarm clocks
+ * in addition to the clock component, but this driver offers only the RTC
+ * component.
+ *
+ * Like many other RTCs, this reports the date and time in BCD.
+ *
+ * The `Hour' register uses bit 5 in a dual role: In 24-hour time, it's a part
+ * of the first digit (0, 1, 2). In 12-hour time it denotes PM, so 12PM is
+ * reported as 0x32, 1PM is 0x21, etc.
+ */
+#define RS5C372_REG_SEC 0x0
+#define RS5C372_REG_MIN 0x1
+#define RS5C372_REG_HOUR 0x2
+#define HOUR_HR_M 0x1f
+#define HOUR_PM 0x20
+#define RS5C372_REG_DOW 0x3
+#define RS5C372_REG_DAY 0x4
+#define RS5C372_REG_MON 0x5
+#define RS5C372_REG_YEAR 0x6
+#define RS5C372_REG_CTRL1 0xe
+#define RS5C372_REG_CTRL2 0xf
+#define CTRL_PM 0x20
+
+static struct ofw_compat_data compat_data[] = {
+ { "ricoh,rs5c372a", 1 },
+ { NULL, 0 }
+};
+
+static int
+rs5c372a_gettime(device_t dev, struct timespec *ts)
+{
+ struct bcd_clocktime ct = {};
+ uint8_t clock_regs[7];
+ int err;
+ uint8_t ctrl2;
+ bool is_12hr = true;
+
+ err = iicdev_readfrom(dev, RS5C372_REG_CTRL2, &ctrl2,
+ sizeof(ctrl2), IIC_WAIT);
+ if (err != 0)
+ return (err);
+ err = iicdev_readfrom(dev, RS5C372_REG_SEC, clock_regs,
+ sizeof(clock_regs), IIC_WAIT);
+ if (err != 0)
+ return (err);
+
+ if (ctrl2 & CTRL_PM)
+ is_12hr = false;
+ ct.sec = clock_regs[RS5C372_REG_SEC];
+ ct.min = clock_regs[RS5C372_REG_MIN];
+ ct.hour = clock_regs[RS5C372_REG_HOUR];
+ ct.dow = clock_regs[RS5C372_REG_DOW];
+ ct.day = clock_regs[RS5C372_REG_DAY];
+ ct.mon = clock_regs[RS5C372_REG_MON];
+ ct.year = clock_regs[RS5C372_REG_YEAR];
+
+ if (is_12hr) {
+ ct.ispm = ct.hour & HOUR_PM;
+ ct.hour &= HOUR_HR_M;
+ }
+ clock_bcd_to_ts(&ct, ts, ct.ispm);
+
+ return (0);
+}
+
+static int
+rs5c372a_settime(device_t dev, struct timespec *ts)
+{
+ struct bcd_clocktime ct;
+ uint8_t clock_regs[7];
+ uint8_t ctrl2;
+ int err;
+ bool is_12hr = true;
+
+ err = iicdev_readfrom(dev, RS5C372_REG_CTRL2, &ctrl2,
+ sizeof(ctrl2), IIC_WAIT);
+ if (err != 0)
+ return (err);
+ if (ctrl2 & CTRL_PM)
+ is_12hr = false;
+ clock_ts_to_bcd(ts, &ct, is_12hr);
+ clock_regs[RS5C372_REG_SEC] = ct.sec;
+ clock_regs[RS5C372_REG_MIN] = ct.min;
+ clock_regs[RS5C372_REG_HOUR] = ct.hour;
+ clock_regs[RS5C372_REG_DAY] = ct.day;
+ clock_regs[RS5C372_REG_DOW] = ct.dow;
+ clock_regs[RS5C372_REG_MON] = ct.mon;
+ clock_regs[RS5C372_REG_YEAR] = ct.year & 0xff;
+
+ if (is_12hr) {
+ if (ct.ispm)
+ clock_regs[RS5C372_REG_HOUR] |= HOUR_PM;
+ }
+
+ err = iicdev_writeto(dev, RS5C372_REG_SEC, clock_regs,
+ sizeof(clock_regs), IIC_WAIT);
+
+ return (err);
+}
+
+static int
+rs5c372a_probe(device_t dev)
+{
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "Richo RS5C372A RTC");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+rs5c372a_attach(device_t dev)
+{
+
+ /* Register with 1s resolution */
+ clock_register(dev, 1000000);
+ clock_schedule(dev, 1);
+ return (0);
+}
+
+static device_method_t rs5c372a_methods[] = {
+ /* Device methods */
+ DEVMETHOD(device_probe, rs5c372a_probe),
+ DEVMETHOD(device_attach, rs5c372a_attach),
+
+ /* Clock methods */
+ DEVMETHOD(clock_gettime, rs5c372a_gettime),
+ DEVMETHOD(clock_settime, rs5c372a_settime),
+ DEVMETHOD_END
+};
+
+
+DEFINE_CLASS_0(rs5c372a, rs5c372a_driver, rs5c372a_methods, 0);
+DRIVER_MODULE(rs5c372a, iicbus, rs5c372a_driver, NULL, NULL);
+MODULE_VERSION(rs5c372a, 1);
+MODULE_DEPEND(rs5c372a, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER);
+IICBUS_FDT_PNP_INFO(compat_data);
diff --git a/sys/dev/mfi/mfi.c b/sys/dev/mfi/mfi.c
index 6f94e4203f1a..767d5ba0902c 100644
--- a/sys/dev/mfi/mfi.c
+++ b/sys/dev/mfi/mfi.c
@@ -371,9 +371,6 @@ mfi_attach(struct mfi_softc *sc)
if (sc == NULL)
return EINVAL;
- device_printf(sc->mfi_dev, "LSI MegaRAID SAS driver version: %s\n",
- MEGASAS_VERSION);
-
mtx_init(&sc->mfi_io_lock, "MFI I/O lock", NULL, MTX_DEF);
sx_init(&sc->mfi_config_lock, "MFI config");
TAILQ_INIT(&sc->mfi_ld_tqh);
@@ -764,6 +761,10 @@ mfi_attach(struct mfi_softc *sc)
sc->mfi_cdev, "%s", "megaraid_sas_ioctl_node");
if (sc->mfi_cdev != NULL)
sc->mfi_cdev->si_drv1 = sc;
+ SYSCTL_ADD_STRING(device_get_sysctl_ctx(sc->mfi_dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(sc->mfi_dev)),
+ OID_AUTO, "driver_version", CTLFLAG_RD, MEGASAS_VERSION,
+ strlen(MEGASAS_VERSION), "driver version");
SYSCTL_ADD_INT(device_get_sysctl_ctx(sc->mfi_dev),
SYSCTL_CHILDREN(device_get_sysctl_tree(sc->mfi_dev)),
OID_AUTO, "delete_busy_volumes", CTLFLAG_RW,
diff --git a/sys/dev/mii/miidevs b/sys/dev/mii/miidevs
index ca7e78a1cdd5..89d8e54a1843 100644
--- a/sys/dev/mii/miidevs
+++ b/sys/dev/mii/miidevs
@@ -72,7 +72,7 @@ oui RDC 0x00d02d RDC Semiconductor
oui REALTEK 0x00e04c Realtek Semicondctor
oui SEEQ 0x00a07d Seeq Technology
oui SIS 0x00e006 Silicon Integrated Systems
-oui SMC 0x00800f SMC
+oui SMSC 0x00800f Microchip (formerly SMSC)
oui TI 0x080028 Texas Instruments
oui TSC 0x00c039 TDK Semiconductor
oui VITESSE 0x0001c1 Vitesse Semiconductor
@@ -361,6 +361,6 @@ model xxVITESSE VSC8514 0x0027 Vitesse VSC8514 10/100/1000TX PHY
/* XaQti Corp. PHYs */
model xxXAQTI XMACII 0x0000 XaQti Corp. XMAC II gigabit interface
-/* SMC */
-model SMC LAN8710A 0x000F SMC LAN8710A 10/100 interface
-model SMC LAN8700 0x000C SMC LAN8700 10/100 interface
+/* Microchip (formerly SMSC) */
+model SMSC LAN8710A 0x000F Microchip LAN8710A 10/100 interface
+model SMSC LAN8700 0x000C Microchip LAN8700 10/100 interface
diff --git a/sys/dev/mii/smscphy.c b/sys/dev/mii/smscphy.c
index 4e0d3cd3e18e..d578242f5a61 100644
--- a/sys/dev/mii/smscphy.c
+++ b/sys/dev/mii/smscphy.c
@@ -74,8 +74,8 @@ static driver_t smscphy_driver = {
DRIVER_MODULE(smscphy, miibus, smscphy_driver, 0, 0);
static const struct mii_phydesc smscphys[] = {
- MII_PHY_DESC(SMC, LAN8710A),
- MII_PHY_DESC(SMC, LAN8700),
+ MII_PHY_DESC(SMSC, LAN8710A),
+ MII_PHY_DESC(SMSC, LAN8700),
MII_PHY_END
};
diff --git a/sys/dev/mlx5/mlx5_en/mlx5_en_hw_tls_rx.c b/sys/dev/mlx5/mlx5_en/mlx5_en_hw_tls_rx.c
index 89d2010656c5..b6a9a0c01d09 100644
--- a/sys/dev/mlx5/mlx5_en/mlx5_en_hw_tls_rx.c
+++ b/sys/dev/mlx5/mlx5_en/mlx5_en_hw_tls_rx.c
@@ -596,14 +596,21 @@ mlx5e_tls_rx_work(struct work_struct *work)
if (ptag->flow_rule != NULL)
mlx5e_accel_fs_del_inpcb(ptag->flow_rule);
+ /*
+ * Destroy TIR before DEK. DESTROY_TIR for a TLS-
+ * enabled TIR issues a TRA RX fence that drains all
+ * in-flight packets from the crypto pipeline. If the
+ * DEK were destroyed first, packets still in flight
+ * would hit a TPT encryption error (vendor syndrome
+ * 0x55) because the key they reference is already gone.
+ */
+ if (ptag->tirn != 0)
+ mlx5_tls_close_tir(priv->mdev, ptag->tirn);
+
/* try to destroy DEK context by ID */
if (ptag->dek_index_ok)
mlx5_encryption_key_destroy(priv->mdev, ptag->dek_index);
- /* try to destroy TIR context by ID */
- if (ptag->tirn != 0)
- mlx5_tls_close_tir(priv->mdev, ptag->tirn);
-
/* free tag */
mlx5e_tls_rx_tag_zfree(ptag);
break;
diff --git a/sys/dev/mrsas/mrsas.c b/sys/dev/mrsas/mrsas.c
index 379fcbcb19ca..e8f43ad52ed8 100644
--- a/sys/dev/mrsas/mrsas.c
+++ b/sys/dev/mrsas/mrsas.c
@@ -824,9 +824,6 @@ mrsas_attach(device_t dev)
struct mrsas_softc *sc = device_get_softc(dev);
uint32_t cmd, error;
- device_printf(dev, "AVAGO MegaRAID SAS driver version: %s\n",
- MRSAS_VERSION);
-
memset(sc, 0, sizeof(struct mrsas_softc));
/* Look up our softc and initialize its fields. */
diff --git a/sys/dev/netmap/netmap.c b/sys/dev/netmap/netmap.c
index f531151fb656..6f79c2c45b39 100644
--- a/sys/dev/netmap/netmap.c
+++ b/sys/dev/netmap/netmap.c
@@ -3503,6 +3503,7 @@ nmreq_copyin(struct nmreq_header *hdr, int nr_body_is_user)
/* check optsz and nro_size to avoid for possible integer overflows of rqsz */
if ((optsz > NETMAP_REQ_MAXSIZE) || (opt->nro_size > NETMAP_REQ_MAXSIZE)
|| (rqsz + optsz > NETMAP_REQ_MAXSIZE)
+ || (p - ker + optsz > bufsz)
|| (optsz > 0 && rqsz + optsz <= rqsz)) {
error = EMSGSIZE;
goto out_restore;
diff --git a/sys/dev/rtsx/rtsx.c b/sys/dev/rtsx/rtsx.c
index aed0bd6c8b8c..958eb08311c4 100644
--- a/sys/dev/rtsx/rtsx.c
+++ b/sys/dev/rtsx/rtsx.c
@@ -139,7 +139,7 @@ struct rtsx_softc {
uint64_t rtsx_write_count; /* count of write operations */
bool rtsx_discovery_mode; /* are we in discovery mode? */
bool rtsx_tuning_mode; /* are we tuning */
- bool rtsx_double_clk; /* double clock freqency */
+ bool rtsx_double_clk; /* double clock frequency */
bool rtsx_vpclk; /* voltage at Pulse-width Modulation(PWM) clock? */
uint8_t rtsx_ssc_depth; /* Spread spectrum clocking depth */
uint8_t rtsx_card_drive_sel; /* value for RTSX_CARD_DRIVE_SEL */
@@ -2837,7 +2837,7 @@ rtsx_xfer_start(struct rtsx_softc *sc)
} else {
dma_dir = RTSX_DMA_DIR_TO_CARD;
/*
- * Use transfer mode AUTO_WRITE3, wich assumes we've already
+ * Use transfer mode AUTO_WRITE3, which assumes we've already
* sent the write command and gotten the response, and will
* send CMD 12 manually after writing.
*/
diff --git a/sys/dev/smartpqi/smartpqi_cam.c b/sys/dev/smartpqi/smartpqi_cam.c
index 690b38c9f855..6ded8aa97e39 100644
--- a/sys/dev/smartpqi/smartpqi_cam.c
+++ b/sys/dev/smartpqi/smartpqi_cam.c
@@ -1,5 +1,5 @@
/*-
- * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries.
+ * Copyright 2016-2026 Microchip Technology, Inc. and/or its subsidiaries.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -1300,7 +1300,7 @@ register_sim(struct pqisrc_softstate *softs, int card_index)
csa.callback_arg = softs;
xpt_action((union ccb *)&csa);
if (csa.ccb_h.status != CAM_REQ_CMP) {
- DBG_ERR("Unable to register smartpqi_aysnc handler: %d!\n",
+ DBG_ERR("Unable to register smartpqi_async handler: %d!\n",
csa.ccb_h.status);
}
diff --git a/sys/dev/smartpqi/smartpqi_defines.h b/sys/dev/smartpqi/smartpqi_defines.h
index 0277abd3e318..c4084f069588 100644
--- a/sys/dev/smartpqi/smartpqi_defines.h
+++ b/sys/dev/smartpqi/smartpqi_defines.h
@@ -1,5 +1,5 @@
/*-
- * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries.
+ * Copyright 2016-2026 Microchip Technology, Inc. and/or its subsidiaries.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -944,12 +944,12 @@ typedef uint8_t *passthru_buf_type_t;
#define PQISRC_DRIVER_MAJOR __FreeBSD__
#if __FreeBSD__ <= 14
-#define PQISRC_DRIVER_MINOR 4690
+#define PQISRC_DRIVER_MINOR 4691
#else
#define PQISRC_DRIVER_MINOR 2
#endif
-#define PQISRC_DRIVER_RELEASE 0
-#define PQISRC_DRIVER_REVISION 2008
+#define PQISRC_DRIVER_RELEASE 1
+#define PQISRC_DRIVER_REVISION 2000
#define STR(s) # s
#define PQISRC_VERSION(a, b, c, d) STR(a.b.c-d)
diff --git a/sys/dev/smartpqi/smartpqi_discovery.c b/sys/dev/smartpqi/smartpqi_discovery.c
index a7de5a149810..8682e6cabd7e 100644
--- a/sys/dev/smartpqi/smartpqi_discovery.c
+++ b/sys/dev/smartpqi/smartpqi_discovery.c
@@ -1,5 +1,5 @@
/*-
- * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries.
+ * Copyright 2016-2026 Microchip Technology, Inc. and/or its subsidiaries.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -155,7 +155,7 @@ pqisrc_remove_target_bit(pqisrc_softstate_t *softs, int target)
softs->bit_map.bit_vector[target] = SLOT_AVAILABLE;
}
-/* Use bit map to find availible targets */
+/* Use bit map to find available targets */
int
pqisrc_find_avail_target(pqisrc_softstate_t *softs)
{
@@ -1423,7 +1423,11 @@ pqisrc_add_device(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device)
if(device->expose_device) {
pqisrc_init_device_active_io(softs, device);
- /* TBD: Call OS upper layer function to add the device entry */
+ device_printf(softs->os_specific.pqi_dev,
+ "device added: vendor=%s model=%s B%d:T%d:L%d type=%s\n",
+ device->vendor, device->model,
+ device->bus, device->target, device->lun,
+ device->is_physical_device ? "physical" : "logical");
os_add_device(softs,device);
}
DBG_FUNC("OUT\n");
@@ -1451,6 +1455,11 @@ pqisrc_remove_device(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device)
}
/* Wait for device outstanding Io's */
pqisrc_wait_for_device_commands_to_complete(softs, device);
+ device_printf(softs->os_specific.pqi_dev,
+ "device removed: vendor=%s model=%s B%d:T%d:L%d type=%s\n",
+ device->vendor, device->model,
+ device->bus, device->target, device->lun,
+ device->is_physical_device ? "physical" : "logical");
/* Call OS upper layer function to remove the exposed device entry */
os_remove_device(softs,device);
DBG_FUNC("OUT\n");
@@ -1674,10 +1683,14 @@ pqisrc_update_device_list(pqisrc_softstate_t *softs,
case DEVICE_NOT_FOUND:
/* Device not found in existing list */
device->new_device = true;
+ DBG_DISC("new device found B%d:T%d:L%d\n",
+ device->bus, device->target, device->lun);
break;
case DEVICE_CHANGED:
/* Actual device gone need to add device to list*/
device->new_device = true;
+ DBG_DISC("device changed B%d:T%d:L%d\n",
+ device->bus, device->target, device->lun);
break;
case DEVICE_IN_REMOVE:
/*Older device with same target/lun is in removal stage*/
@@ -1686,6 +1699,8 @@ pqisrc_update_device_list(pqisrc_softstate_t *softs,
* free call*/
device->new_device = false;
same_device->schedule_rescan = true;
+ DBG_DISC("device in removal B%d:T%d:L%d, scheduling rescan\n",
+ device->bus, device->target, device->lun);
break;
default:
break;
diff --git a/sys/dev/smartpqi/smartpqi_event.c b/sys/dev/smartpqi/smartpqi_event.c
index 77a70f9fb031..c3c27c9e1c0b 100644
--- a/sys/dev/smartpqi/smartpqi_event.c
+++ b/sys/dev/smartpqi/smartpqi_event.c
@@ -1,5 +1,5 @@
/*-
- * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries.
+ * Copyright 2016-2026 Microchip Technology, Inc. and/or its subsidiaries.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -204,6 +204,17 @@ pqisrc_process_event_intr_src(pqisrc_softstate_t *softs,int obq_id)
}
if (event_index >= 0) {
+ static const char *event_names[] = {
+ [PQI_EVENT_HOTPLUG] = "hotplug",
+ [PQI_EVENT_HARDWARE] = "hardware",
+ [PQI_EVENT_PHYSICAL_DEVICE] = "physical device",
+ [PQI_EVENT_LOGICAL_DEVICE] = "logical device",
+ [PQI_EVENT_AIO_STATE_CHANGE] = "AIO state change",
+ [PQI_EVENT_AIO_CONFIG_CHANGE] = "AIO config change",
+ };
+ device_printf(softs->os_specific.pqi_dev,
+ "event: %s (type=0x%x)\n",
+ event_names[event_index], response.event_type);
if(response.request_acknowledge) {
pending_event = &softs->pending_events[event_index];
pending_event->pending = true;
@@ -385,7 +396,7 @@ pqisrc_report_event_config(pqisrc_softstate_t *softs)
pqi_event_config_request_t request;
pqi_event_config_t *event_config_p ;
dma_mem_t buf_report_event ;
- /*bytes to be allocaed for report event config data-in buffer */
+ /*bytes to be allocated for report event config data-in buffer */
uint32_t alloc_size = sizeof(pqi_event_config_t) ;
memset(&request, 0 , sizeof(request));
@@ -446,7 +457,7 @@ pqisrc_set_event_config(pqisrc_softstate_t *softs)
pqi_event_config_request_t request;
pqi_event_config_t *event_config_p;
dma_mem_t buf_set_event;
- /*bytes to be allocaed for set event config data-out buffer */
+ /*bytes to be allocated for set event config data-out buffer */
uint32_t alloc_size = sizeof(pqi_event_config_t);
memset(&request, 0 , sizeof(request));
diff --git a/sys/dev/smartpqi/smartpqi_main.c b/sys/dev/smartpqi/smartpqi_main.c
index 1f006939bf7c..fbfbcc962f35 100644
--- a/sys/dev/smartpqi/smartpqi_main.c
+++ b/sys/dev/smartpqi/smartpqi_main.c
@@ -1,5 +1,5 @@
/*-
- * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries.
+ * Copyright 2016-2026 Microchip Technology, Inc. and/or its subsidiaries.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -427,6 +427,16 @@ smartpqi_attach(device_t dev)
goto out;
}
+ /* Register sysctl for runtime debug_level changes */
+ {
+ struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev);
+ struct sysctl_oid *tree = device_get_sysctl_tree(dev);
+
+ SYSCTL_ADD_ULONG(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+ "debug_level", CTLFLAG_RW, &logging_level,
+ "Debug logging bitmask");
+ }
+
goto out;
dma_out:
diff --git a/sys/dev/smartpqi/smartpqi_misc.c b/sys/dev/smartpqi/smartpqi_misc.c
index 6db0d80ed993..fd0b907aa252 100644
--- a/sys/dev/smartpqi/smartpqi_misc.c
+++ b/sys/dev/smartpqi/smartpqi_misc.c
@@ -1,5 +1,5 @@
/*-
- * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries.
+ * Copyright 2016-2026 Microchip Technology, Inc. and/or its subsidiaries.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -252,7 +252,7 @@ bsd_set_hint_scatter_gather_config(struct pqisrc_softstate *softs)
DBG_FUNC("IN\n");
- /* At least > 16 sg's required to wotk hint correctly.
+ /* At least > 16 sg's required to work hint correctly.
* Default the sg count set by driver/controller. */
if ((!softs->hint.sg_segments) || (softs->hint.sg_segments >
diff --git a/sys/dev/smartpqi/smartpqi_queue.c b/sys/dev/smartpqi/smartpqi_queue.c
index e8a467531aa4..679d956f6f36 100644
--- a/sys/dev/smartpqi/smartpqi_queue.c
+++ b/sys/dev/smartpqi/smartpqi_queue.c
@@ -1,5 +1,5 @@
/*-
- * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries.
+ * Copyright 2016-2026 Microchip Technology, Inc. and/or its subsidiaries.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -729,7 +729,7 @@ pqisrc_create_op_ibq(pqisrc_softstate_t *softs,
op_ib_q->pi_register_offset);
} else {
int i = 0;
- DBG_WARN("Error Status Decsriptors\n");
+ DBG_WARN("Error Status Descriptors\n");
for (i = 0; i < 4; i++)
DBG_WARN(" %x\n",admin_resp.resp_type.create_op_iq.status_desc[i]);
}
diff --git a/sys/dev/smartpqi/smartpqi_request.c b/sys/dev/smartpqi/smartpqi_request.c
index c5f8ac3c41ba..655660615797 100644
--- a/sys/dev/smartpqi/smartpqi_request.c
+++ b/sys/dev/smartpqi/smartpqi_request.c
@@ -1,5 +1,5 @@
/*-
- * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries.
+ * Copyright 2016-2026 Microchip Technology, Inc. and/or its subsidiaries.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -1998,7 +1998,7 @@ pqisrc_send_raid_tmf(pqisrc_softstate_t *softs, pqi_scsi_dev_t const *devp,
if (softs->timeout_in_tmf &&
tmf_type == SOP_TASK_MANAGEMENT_LUN_RESET) {
- /* OS_TMF_TIMEOUT_SEC - 1 to accomodate driver processing */
+ /* OS_TMF_TIMEOUT_SEC - 1 to accommodate driver processing */
tmf_req.timeout_in_sec = OS_TMF_TIMEOUT_SEC - 1;
}
diff --git a/sys/dev/smartpqi/smartpqi_response.c b/sys/dev/smartpqi/smartpqi_response.c
index 38695860e520..1ae74a5b95ff 100644
--- a/sys/dev/smartpqi/smartpqi_response.c
+++ b/sys/dev/smartpqi/smartpqi_response.c
@@ -1,5 +1,5 @@
/*-
- * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries.
+ * Copyright 2016-2026 Microchip Technology, Inc. and/or its subsidiaries.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -275,7 +275,7 @@ pqisrc_is_innocuous_error(pqisrc_softstate_t *softs, rcb_t *rcb, void *err_info)
if (raid_err->data_out_result == PQI_RAID_DATA_IN_OUT_UNDERFLOW)
return true;
- /* We get these a alot: leave a tiny breadcrumb about the error,
+ /* We get these a lot: leave a tiny breadcrumb about the error,
but don't do full spew about it */
if (raid_err->status == PQI_AIO_STATUS_CHECK_CONDITION)
{
diff --git a/sys/dev/smartpqi/smartpqi_sis.c b/sys/dev/smartpqi/smartpqi_sis.c
index 82eb999ca4b8..99aa952eb149 100644
--- a/sys/dev/smartpqi/smartpqi_sis.c
+++ b/sys/dev/smartpqi/smartpqi_sis.c
@@ -1,5 +1,5 @@
/*-
- * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries.
+ * Copyright 2016-2026 Microchip Technology, Inc. and/or its subsidiaries.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,7 +26,7 @@
#include "smartpqi_includes.h"
-/* Function for disabling msix interrupots */
+/* Function for disabling msix interrupts */
void
sis_disable_msix(pqisrc_softstate_t *softs)
{
@@ -96,7 +96,7 @@ sis_disable_interrupt(pqisrc_softstate_t *softs)
sis_disable_msix(softs);
break;
default:
- DBG_ERR("Inerrupt mode none!\n");
+ DBG_ERR("Interrupt mode none!\n");
break;
}
diff --git a/sys/dev/smartpqi/smartpqi_structures.h b/sys/dev/smartpqi/smartpqi_structures.h
index 0c9ad375823d..ada6676ada8f 100644
--- a/sys/dev/smartpqi/smartpqi_structures.h
+++ b/sys/dev/smartpqi/smartpqi_structures.h
@@ -1,5 +1,5 @@
/*-
- * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries.
+ * Copyright 2016-2026 Microchip Technology, Inc. and/or its subsidiaries.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -1168,7 +1168,7 @@ typedef struct bmic_sense_feature_page_header {
uint8_t page;
uint8_t sub_page;
uint16_t total_length; /** Total length of the page.
- * The length is the same wheteher the request buffer is too short or not.
+ * The length is the same whether the request buffer is too short or not.
* When printing out the page, only print the buffer length. */
} OS_ATTRIBUTE_PACKED bmic_sense_feature_page_header_t;
diff --git a/sys/dev/sound/pcm/sound.c b/sys/dev/sound/pcm/sound.c
index 305d663cd6ad..9eb2dffeb908 100644
--- a/sys/dev/sound/pcm/sound.c
+++ b/sys/dev/sound/pcm/sound.c
@@ -242,7 +242,6 @@ pcm_getdevinfo(device_t dev)
unsigned int
pcm_getbuffersize(device_t dev, unsigned int minbufsz, unsigned int deflt, unsigned int maxbufsz)
{
- struct snddev_info *d = device_get_softc(dev);
int sz, x;
sz = 0;
@@ -264,8 +263,6 @@ pcm_getbuffersize(device_t dev, unsigned int minbufsz, unsigned int deflt, unsig
sz = deflt;
}
- d->bufsz = sz;
-
return sz;
}
@@ -406,12 +403,6 @@ pcm_register(device_t dev, char *str)
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "rec",
CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "recording channels node");
- /* XXX: a user should be able to set this with a control tool, the
- sysadmin then needs min+max sysctls for this */
- SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
- SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
- OID_AUTO, "buffersize", CTLFLAG_RD, &d->bufsz, 0,
- "allocated buffer size");
SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
"bitperfect", CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, d,
diff --git a/sys/dev/sound/pcm/sound.h b/sys/dev/sound/pcm/sound.h
index de9af6bd5324..4795eb7585c5 100644
--- a/sys/dev/sound/pcm/sound.h
+++ b/sys/dev/sound/pcm/sound.h
@@ -204,7 +204,6 @@ struct snddev_info {
} channels;
unsigned playcount, reccount, pvchancount, rvchancount;
unsigned flags;
- unsigned int bufsz;
void *devinfo;
device_t dev;
char status[SND_STATUSLEN];
diff --git a/sys/dev/sound/usb/uaudio.c b/sys/dev/sound/usb/uaudio.c
index 65976ced8a75..f477eb768fde 100644
--- a/sys/dev/sound/usb/uaudio.c
+++ b/sys/dev/sound/usb/uaudio.c
@@ -713,6 +713,10 @@ static driver_t uaudio_driver = {
.size = sizeof(struct uaudio_softc),
};
+static const STRUCT_USB_HOST_ID uaudio_vendor_audio[] = {
+ { USB_VPI(USB_VENDOR_ROLAND, 0x0132, 0) }, /* UA-33 */
+};
+
/* The following table is derived from Linux's quirks-table.h */
static const STRUCT_USB_HOST_ID uaudio_vendor_midi[] = {
{ USB_VPI(USB_VENDOR_YAMAHA, 0x1000, 0) }, /* UX256 */
@@ -868,6 +872,11 @@ uaudio_probe(device_t dev)
/* lookup non-standard device(s) */
+ if (usbd_lookup_id_by_uaa(uaudio_vendor_audio,
+ sizeof(uaudio_vendor_audio), uaa) == 0) {
+ return (BUS_PROBE_SPECIFIC);
+ }
+
if (usbd_lookup_id_by_uaa(uaudio_vendor_midi,
sizeof(uaudio_vendor_midi), uaa) == 0) {
return (BUS_PROBE_SPECIFIC);
@@ -6258,4 +6267,5 @@ MODULE_DEPEND(snd_uaudio, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
MODULE_DEPEND(snd_uaudio, hid, 1, 1, 1);
MODULE_VERSION(snd_uaudio, 1);
USB_PNP_HOST_INFO(uaudio_devs);
+USB_PNP_HOST_INFO(uaudio_vendor_audio);
USB_PNP_HOST_INFO(uaudio_vendor_midi);
diff --git a/sys/dev/usb/net/if_smsc.c b/sys/dev/usb/net/if_smsc.c
index 8e16b8609144..c3c21fd22472 100644
--- a/sys/dev/usb/net/if_smsc.c
+++ b/sys/dev/usb/net/if_smsc.c
@@ -1296,7 +1296,7 @@ smsc_phy_init(struct smsc_softc *sc)
} while ((bmcr & BMCR_RESET) && ((ticks - start_ticks) < max_ticks));
if (((usb_ticks_t)(ticks - start_ticks)) >= max_ticks) {
- smsc_err_printf(sc, "PHY reset timed-out");
+ smsc_err_printf(sc, "PHY reset timed-out\n");
return (EIO);
}
diff --git a/sys/dev/usb/quirk/usb_quirk.c b/sys/dev/usb/quirk/usb_quirk.c
index 303f76f37fb0..c1976a59acbe 100644
--- a/sys/dev/usb/quirk/usb_quirk.c
+++ b/sys/dev/usb/quirk/usb_quirk.c
@@ -565,6 +565,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK(CMEDIA, CM6206, UQ_AU_SET_SPDIF_CM6206),
USB_QUIRK(PLOYTEC, SPL_CRIMSON_1, UQ_CFG_INDEX_1),
USB_QUIRK(ROLAND, UA25EX_AD, UQ_AU_VENDOR_CLASS),
+ USB_QUIRK(ROLAND, UA33, UQ_AU_VENDOR_CLASS),
/* DYMO LabelManager Pnp */
USB_QUIRK(DYMO, LABELMANAGERPNP, UQ_MSC_DYMO_EJECT),
diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs
index e1394e903cb3..594afafbb07f 100644
--- a/sys/dev/usb/usbdevs
+++ b/sys/dev/usb/usbdevs
@@ -4208,6 +4208,7 @@ product ROLAND UA700 0x002b UA-700 Audio I/F
product ROLAND PCR300 0x0033 EDIROL PCR-300 MIDI I/F
product ROLAND UA25EX_AD 0x00e6 EDIROL UA-25EX (Advanced Driver)
product ROLAND UA25EX_CC 0x00e7 EDIROL UA-25EX (Class Compliant)
+product ROLAND UA33 0x0132 UA-33 Audio I/F
/* Rockfire products */
product ROCKFIRE GAMEPAD 0x2033 gamepad 203USB
diff --git a/sys/dev/virtio/network/if_vtnet.c b/sys/dev/virtio/network/if_vtnet.c
index 40792482672c..ef01833b9e03 100644
--- a/sys/dev/virtio/network/if_vtnet.c
+++ b/sys/dev/virtio/network/if_vtnet.c
@@ -96,17 +96,6 @@
#define VTNET_ETHER_ALIGN ETHER_ALIGN
#endif
-/*
- * Worst case offset to ensure header doesn't share any cache lines with
- * payload.
- */
-#define VTNET_RX_BUFFER_HEADER_OFFSET 128
-
-struct vtnet_rx_buffer_header {
- bus_addr_t addr;
- bus_dmamap_t dmap;
-};
-
static int vtnet_modevent(module_t, int, void *);
static int vtnet_probe(device_t);
@@ -219,7 +208,7 @@ static void vtnet_init_locked(struct vtnet_softc *, int);
static void vtnet_init(void *);
static void vtnet_free_ctrl_vq(struct vtnet_softc *);
-static int vtnet_exec_ctrl_cmd(struct vtnet_softc *, uint8_t *,
+static void vtnet_exec_ctrl_cmd(struct vtnet_softc *, void *,
struct sglist *, int, int);
static int vtnet_ctrl_mac_cmd(struct vtnet_softc *, uint8_t *);
static int vtnet_ctrl_guest_offloads(struct vtnet_softc *, uint64_t);
@@ -395,17 +384,6 @@ MODULE_DEPEND(vtnet, netmap, 1, 1, 1);
VIRTIO_SIMPLE_PNPINFO(vtnet, VIRTIO_ID_NETWORK, "VirtIO Networking Adapter");
-static struct vtnet_rx_buffer_header *
-vtnet_mbuf_to_rx_buffer_header(struct vtnet_softc *sc, struct mbuf *m)
-{
- if (VTNET_ETHER_ALIGN != 0 && sc->vtnet_hdr_size % 4 == 0)
- return (struct vtnet_rx_buffer_header *)((uintptr_t)m->m_data -
- VTNET_RX_BUFFER_HEADER_OFFSET - VTNET_ETHER_ALIGN);
- else
- return (struct vtnet_rx_buffer_header *)((uintptr_t)m->m_data -
- VTNET_RX_BUFFER_HEADER_OFFSET);
-}
-
static int
vtnet_modevent(module_t mod __unused, int type, void *unused __unused)
{
@@ -479,106 +457,6 @@ vtnet_attach(device_t dev)
goto fail;
}
- mtx_init(&sc->vtnet_rx_mtx, device_get_nameunit(dev),
- "VirtIO Net RX lock", MTX_DEF);
-
- error = bus_dma_tag_create(
- bus_get_dma_tag(dev), /* parent */
- sizeof(uint16_t), /* alignment */
- 0, /* boundary */
- BUS_SPACE_MAXADDR, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, NULL, /* filter, filterarg */
- MJUM9BYTES, /* max request size */
- 1, /* max # segments */
- MJUM9BYTES, /* maxsegsize - worst case */
- BUS_DMA_COHERENT, /* flags */
- busdma_lock_mutex, /* lockfunc */
- &sc->vtnet_rx_mtx, /* lockarg */
- &sc->vtnet_rx_dmat);
- if (error) {
- device_printf(dev, "cannot create bus_dma_tag\n");
- goto fail;
- }
-
- mtx_init(&sc->vtnet_tx_mtx, device_get_nameunit(dev),
- "VirtIO Net TX lock", MTX_DEF);
-
- error = bus_dma_tag_create(
- bus_get_dma_tag(dev), /* parent */
- sizeof(uint16_t), /* alignment */
- 0, /* boundary */
- BUS_SPACE_MAXADDR, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, NULL, /* filter, filterarg */
- sc->vtnet_tx_nsegs * MJUM9BYTES, /* max request size */
- sc->vtnet_tx_nsegs, /* max # segments */
- MJUM9BYTES, /* maxsegsize */
- BUS_DMA_COHERENT, /* flags */
- busdma_lock_mutex, /* lockfunc */
- &sc->vtnet_tx_mtx, /* lockarg */
- &sc->vtnet_tx_dmat);
- if (error) {
- device_printf(dev, "cannot create bus_dma_tag\n");
- goto fail;
- }
-
- mtx_init(&sc->vtnet_hdr_mtx, device_get_nameunit(dev),
- "VirtIO Net header lock", MTX_DEF);
-
- error = bus_dma_tag_create(
- bus_get_dma_tag(dev), /* parent */
- sizeof(uint16_t), /* alignment */
- 0, /* boundary */
- BUS_SPACE_MAXADDR, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, NULL, /* filter, filterarg */
- PAGE_SIZE, /* max request size */
- 1, /* max # segments */
- PAGE_SIZE, /* maxsegsize */
- BUS_DMA_COHERENT, /* flags */
- busdma_lock_mutex, /* lockfunc */
- &sc->vtnet_hdr_mtx, /* lockarg */
- &sc->vtnet_hdr_dmat);
- if (error) {
- device_printf(dev, "cannot create bus_dma_tag\n");
- goto fail;
- }
-
- mtx_init(&sc->vtnet_ack_mtx, device_get_nameunit(dev),
- "VirtIO Net ACK lock", MTX_DEF);
-
- error = bus_dma_tag_create(
- bus_get_dma_tag(dev), /* parent */
- sizeof(uint8_t), /* alignment */
- 0, /* boundary */
- BUS_SPACE_MAXADDR, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, NULL, /* filter, filterarg */
- sizeof(uint8_t), /* max request size */
- 1, /* max # segments */
- sizeof(uint8_t), /* maxsegsize */
- BUS_DMA_COHERENT, /* flags */
- busdma_lock_mutex, /* lockfunc */
- &sc->vtnet_ack_mtx, /* lockarg */
- &sc->vtnet_ack_dmat);
- if (error) {
- device_printf(dev, "cannot create bus_dma_tag\n");
- goto fail;
- }
-
-#ifdef __powerpc__
- /*
- * Virtio uses physical addresses rather than bus addresses, so we
- * need to ask busdma to skip the iommu physical->bus mapping. At
- * present, this is only a thing on the powerpc architectures.
- */
- bus_dma_tag_set_iommu(sc->vtnet_rx_dmat, NULL, NULL);
- bus_dma_tag_set_iommu(sc->vtnet_tx_dmat, NULL, NULL);
- bus_dma_tag_set_iommu(sc->vtnet_hdr_dmat, NULL, NULL);
- bus_dma_tag_set_iommu(sc->vtnet_ack_dmat, NULL, NULL);
-#endif
-
error = vtnet_alloc_rx_filters(sc);
if (error) {
device_printf(dev, "cannot allocate Rx filters\n");
@@ -1667,11 +1545,6 @@ static struct mbuf *
vtnet_rx_alloc_buf(struct vtnet_softc *sc, int nbufs, struct mbuf **m_tailp)
{
struct mbuf *m_head, *m_tail, *m;
- struct vtnet_rx_buffer_header *vthdr;
- bus_dma_segment_t segs[1];
- bus_dmamap_t dmap;
- int nsegs;
- int err;
int i, size;
m_head = NULL;
@@ -1689,43 +1562,13 @@ vtnet_rx_alloc_buf(struct vtnet_softc *sc, int nbufs, struct mbuf **m_tailp)
}
m->m_len = size;
- vthdr = (struct vtnet_rx_buffer_header *)m->m_data;
-
- /* Reserve space for header */
- m_adj(m, VTNET_RX_BUFFER_HEADER_OFFSET);
-
/*
* Need to offset the mbuf if the header we're going to add
* will misalign.
*/
- if (VTNET_ETHER_ALIGN != 0 && sc->vtnet_hdr_size % 4 == 0)
+ if (VTNET_ETHER_ALIGN != 0 && sc->vtnet_hdr_size % 4 == 0) {
m_adj(m, VTNET_ETHER_ALIGN);
-
- err = bus_dmamap_create(sc->vtnet_rx_dmat, 0, &dmap);
- if (err) {
- printf("Failed to create dmamap, err :%d\n",
- err);
- m_freem(m);
- return (NULL);
- }
-
- nsegs = 0;
- err = bus_dmamap_load_mbuf_sg(sc->vtnet_rx_dmat, dmap, m, segs,
- &nsegs, BUS_DMA_NOWAIT);
- if (err != 0) {
- printf("Failed to map mbuf into DMA visible memory, err: %d\n",
- err);
- m_freem(m);
- bus_dmamap_destroy(sc->vtnet_rx_dmat, dmap);
- return (NULL);
}
- KASSERT(nsegs == 1,
- ("%s: unexpected number of DMA segments for rx buffer: %d",
- __func__, nsegs));
-
- vthdr->addr = segs[0].ds_addr;
- vthdr->dmap = dmap;
-
if (m_head != NULL) {
m_tail->m_next = m;
m_tail = m;
@@ -1751,7 +1594,7 @@ vtnet_rxq_replace_lro_nomrg_buf(struct vtnet_rxq *rxq, struct mbuf *m0,
int len, clustersz, nreplace, error;
sc = rxq->vtnrx_sc;
- clustersz = sc->vtnet_rx_clustersz - VTNET_RX_BUFFER_HEADER_OFFSET;
+ clustersz = sc->vtnet_rx_clustersz;
/*
* Need to offset the mbuf if the header we're going to add will
* misalign, account for that here.
@@ -1866,12 +1709,9 @@ vtnet_rxq_replace_buf(struct vtnet_rxq *rxq, struct mbuf *m, int len)
static int
vtnet_rxq_enqueue_buf(struct vtnet_rxq *rxq, struct mbuf *m)
{
- struct vtnet_rx_buffer_header *hdr;
struct vtnet_softc *sc;
struct sglist *sg;
int header_inlined, error;
- bus_addr_t paddr;
- struct mbuf *mp;
sc = rxq->vtnrx_sc;
sg = rxq->vtnrx_sg;
@@ -1884,38 +1724,28 @@ vtnet_rxq_enqueue_buf(struct vtnet_rxq *rxq, struct mbuf *m)
header_inlined = vtnet_modern(sc) ||
(sc->vtnet_flags & VTNET_FLAG_MRG_RXBUFS) != 0; /* TODO: ANY_LAYOUT */
- hdr = vtnet_mbuf_to_rx_buffer_header(sc, m);
- paddr = hdr->addr;
-
/*
* Note: The mbuf has been already adjusted when we allocate it if we
* have to do strict alignment.
*/
- if (header_inlined) {
- error = sglist_append_phys(sg, paddr, m->m_len);
- } else {
+ if (header_inlined)
+ error = sglist_append_mbuf(sg, m);
+ else {
+ struct vtnet_rx_header *rxhdr =
+ mtod(m, struct vtnet_rx_header *);
MPASS(sc->vtnet_hdr_size == sizeof(struct virtio_net_hdr));
/* Append the header and remaining mbuf data. */
- error = sglist_append_phys(sg, paddr, sc->vtnet_hdr_size);
+ error = sglist_append(sg, &rxhdr->vrh_hdr, sc->vtnet_hdr_size);
if (error)
return (error);
- error = sglist_append_phys(sg,
- paddr + sizeof(struct vtnet_rx_header),
+ error = sglist_append(sg, &rxhdr[1],
m->m_len - sizeof(struct vtnet_rx_header));
if (error)
return (error);
- mp = m->m_next;
- while (mp) {
- hdr = vtnet_mbuf_to_rx_buffer_header(sc, mp);
- paddr = hdr->addr;
- error = sglist_append_phys(sg, paddr, mp->m_len);
- if (error)
- return (error);
-
- mp = mp->m_next;
- }
+ if (m->m_next != NULL)
+ error = sglist_append_mbuf(sg, m->m_next);
}
if (error)
@@ -2101,7 +1931,6 @@ vtnet_rxq_merged_eof(struct vtnet_rxq *rxq, struct mbuf *m_head, int nbufs)
m_tail = m_head;
while (--nbufs > 0) {
- struct vtnet_rx_buffer_header *vthdr;
struct mbuf *m;
uint32_t len;
@@ -2111,10 +1940,6 @@ vtnet_rxq_merged_eof(struct vtnet_rxq *rxq, struct mbuf *m_head, int nbufs)
goto fail;
}
- vthdr = vtnet_mbuf_to_rx_buffer_header(sc, m);
- bus_dmamap_sync(sc->vtnet_rx_dmat, vthdr->dmap,
- BUS_DMASYNC_POSTREAD);
-
if (vtnet_rxq_new_buf(rxq) != 0) {
rxq->vtnrx_stats.vrxs_iqdrops++;
vtnet_rxq_discard_buf(rxq, m);
@@ -2235,7 +2060,6 @@ static int
vtnet_rxq_eof(struct vtnet_rxq *rxq)
{
struct virtio_net_hdr lhdr, *hdr;
- struct vtnet_rx_buffer_header *vthdr;
struct vtnet_softc *sc;
if_t ifp;
struct virtqueue *vq;
@@ -2251,31 +2075,14 @@ vtnet_rxq_eof(struct vtnet_rxq *rxq)
CURVNET_SET(if_getvnet(ifp));
while (count-- > 0) {
- struct mbuf *m, *mp;
+ struct mbuf *m;
uint32_t len, nbufs, adjsz;
- uint32_t synced;
m = virtqueue_dequeue(vq, &len);
if (m == NULL)
break;
deq++;
- mp = m;
-
- /*
- * Sync all mbufs in this packet. There will only be a single
- * mbuf unless LRO is in use.
- */
- synced = 0;
- while (mp && synced < len) {
- vthdr = vtnet_mbuf_to_rx_buffer_header(sc, mp);
- bus_dmamap_sync(sc->vtnet_rx_dmat, vthdr->dmap,
- BUS_DMASYNC_POSTREAD);
-
- synced += mp->m_len;
- mp = mp->m_next;
- }
-
if (len < sc->vtnet_hdr_size + ETHER_HDR_LEN) {
rxq->vtnrx_stats.vrxs_ierrors++;
vtnet_rxq_discard_buf(rxq, m);
@@ -2535,14 +2342,6 @@ vtnet_txq_free_mbufs(struct vtnet_txq *txq)
while ((txhdr = virtqueue_drain(vq, &last)) != NULL) {
if (kring == NULL) {
- bus_dmamap_unload(txq->vtntx_sc->vtnet_tx_dmat,
- txhdr->dmap);
- bus_dmamap_destroy(txq->vtntx_sc->vtnet_tx_dmat,
- txhdr->dmap);
- bus_dmamap_unload(txq->vtntx_sc->vtnet_tx_dmat,
- txhdr->hdr_dmap);
- bus_dmamap_destroy(txq->vtntx_sc->vtnet_tx_dmat,
- txhdr->hdr_dmap);
m_freem(txhdr->vth_mbuf);
uma_zfree(vtnet_tx_header_zone, txhdr);
}
@@ -2712,36 +2511,15 @@ drop:
return (NULL);
}
-static void
-vtnet_txq_enqueue_callback(void *arg, bus_dma_segment_t *segs,
- int nsegs, int error)
-{
- vm_paddr_t *hdr_paddr;
-
- if (error != 0)
- return;
-
- KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs));
-
- hdr_paddr = (vm_paddr_t *)arg;
- *hdr_paddr = segs[0].ds_addr;
-}
-
static int
vtnet_txq_enqueue_buf(struct vtnet_txq *txq, struct mbuf **m_head,
struct vtnet_tx_header *txhdr)
{
- bus_dma_segment_t segs[VTNET_TX_SEGS_MAX];
- int nsegs;
struct vtnet_softc *sc;
struct virtqueue *vq;
struct sglist *sg;
struct mbuf *m;
int error;
- vm_paddr_t hdr_paddr;
- bus_dmamap_t hdr_dmap;
- bus_dmamap_t dmap;
- int i;
sc = txq->vtntx_sc;
vq = txq->vtntx_vq;
@@ -2749,55 +2527,15 @@ vtnet_txq_enqueue_buf(struct vtnet_txq *txq, struct mbuf **m_head,
m = *m_head;
sglist_reset(sg);
-
- error = bus_dmamap_create(sc->vtnet_tx_dmat, 0, &hdr_dmap);
- if (error)
- goto fail;
-
- error = bus_dmamap_load(sc->vtnet_tx_dmat, hdr_dmap, &txhdr->vth_uhdr,
- sc->vtnet_hdr_size, vtnet_txq_enqueue_callback, &hdr_paddr,
- BUS_DMA_NOWAIT);
- if (error)
- goto fail_hdr_dmamap_destroy;
-
- error = sglist_append_phys(sg, hdr_paddr, sc->vtnet_hdr_size);
+ error = sglist_append(sg, &txhdr->vth_uhdr, sc->vtnet_hdr_size);
if (error != 0 || sg->sg_nseg != 1) {
KASSERT(0, ("%s: cannot add header to sglist error %d nseg %d",
__func__, error, sg->sg_nseg));
- goto fail_hdr_dmamap_unload;
+ goto fail;
}
- bus_dmamap_sync(sc->vtnet_tx_dmat, hdr_dmap, BUS_DMASYNC_PREWRITE);
-
- error = bus_dmamap_create(sc->vtnet_tx_dmat, 0, &dmap);
- if (error)
- goto fail_hdr_dmamap_unload;
-
- nsegs = 0;
- error = bus_dmamap_load_mbuf_sg(sc->vtnet_tx_dmat, dmap, m, segs,
- &nsegs, BUS_DMA_NOWAIT);
- if (error != 0)
- goto fail_dmamap_destroy;
- KASSERT(nsegs <= sc->vtnet_tx_nsegs,
- ("%s: unexpected number of DMA segments for tx buffer: %d (max %d)",
- __func__, nsegs, sc->vtnet_tx_nsegs));
-
- bus_dmamap_sync(sc->vtnet_tx_dmat, dmap, BUS_DMASYNC_PREWRITE);
-
- for (i = 0; i < nsegs && !error; i++)
- error = sglist_append_phys(sg, segs[i].ds_addr, segs[i].ds_len);
-
+ error = sglist_append_mbuf(sg, m);
if (error) {
- sglist_reset(sg);
- bus_dmamap_unload(sc->vtnet_tx_dmat, dmap);
-
- error = sglist_append_phys(sg, hdr_paddr, sc->vtnet_hdr_size);
- if (error != 0 || sg->sg_nseg != 1) {
- KASSERT(0, ("%s: cannot add header to sglist error %d nseg %d",
- __func__, error, sg->sg_nseg));
- goto fail_dmamap_destroy;
- }
-
m = m_defrag(m, M_NOWAIT);
if (m == NULL) {
sc->vtnet_stats.tx_defrag_failed++;
@@ -2807,41 +2545,16 @@ vtnet_txq_enqueue_buf(struct vtnet_txq *txq, struct mbuf **m_head,
*m_head = m;
sc->vtnet_stats.tx_defragged++;
- nsegs = 0;
- error = bus_dmamap_load_mbuf_sg(sc->vtnet_tx_dmat, dmap, m,
- segs, &nsegs, BUS_DMA_NOWAIT);
- if (error != 0)
- goto fail_dmamap_destroy;
- KASSERT(nsegs <= sc->vtnet_tx_nsegs,
- ("%s: unexpected number of DMA segments for tx buffer: %d (max %d)",
- __func__, nsegs, sc->vtnet_tx_nsegs));
-
- bus_dmamap_sync(sc->vtnet_tx_dmat, dmap, BUS_DMASYNC_PREWRITE);
-
- for (i = 0; i < nsegs && !error; i++)
- error = sglist_append_phys(sg, segs[i].ds_addr,
- segs[i].ds_len);
-
+ error = sglist_append_mbuf(sg, m);
if (error)
- goto fail_dmamap_unload;
+ goto fail;
}
txhdr->vth_mbuf = m;
- txhdr->dmap = dmap;
- txhdr->hdr_dmap = hdr_dmap;
-
error = virtqueue_enqueue(vq, txhdr, sg, sg->sg_nseg, 0);
return (error);
-fail_dmamap_unload:
- bus_dmamap_unload(sc->vtnet_tx_dmat, dmap);
-fail_dmamap_destroy:
- bus_dmamap_destroy(sc->vtnet_tx_dmat, dmap);
-fail_hdr_dmamap_unload:
- bus_dmamap_unload(sc->vtnet_tx_dmat, hdr_dmap);
-fail_hdr_dmamap_destroy:
- bus_dmamap_destroy(sc->vtnet_tx_dmat, hdr_dmap);
fail:
m_freem(*m_head);
*m_head = NULL;
@@ -3797,43 +3510,10 @@ vtnet_free_ctrl_vq(struct vtnet_softc *sc)
}
static void
-vtnet_load_callback(void *arg, bus_dma_segment_t *segs, int nsegs,
- int error)
-{
- bus_addr_t *paddr;
-
- if (error != 0)
- return;
-
- KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs));
-
- paddr = (bus_addr_t *)arg;
- *paddr = segs[0].ds_addr;
-}
-
-static int
-vtnet_exec_ctrl_cmd(struct vtnet_softc *sc, uint8_t *ack, struct sglist *sg,
- int readable, int writable)
+vtnet_exec_ctrl_cmd(struct vtnet_softc *sc, void *cookie,
+ struct sglist *sg, int readable, int writable)
{
- bus_dmamap_t ack_dmap;
- bus_addr_t ack_paddr;
struct virtqueue *vq;
- int error;
-
- error = bus_dmamap_create(sc->vtnet_ack_dmat, 0, &ack_dmap);
- if (error)
- goto error_out;
-
- error = bus_dmamap_load(sc->vtnet_ack_dmat, ack_dmap, ack,
- sizeof(uint8_t), vtnet_load_callback, &ack_paddr, BUS_DMA_NOWAIT);
- if (error)
- goto error_destroy;
-
- bus_dmamap_sync(sc->vtnet_ack_dmat, ack_dmap, BUS_DMASYNC_PREWRITE);
-
- error = sglist_append_phys(sg, ack_paddr, sizeof(uint8_t));
- if (error)
- goto error_unload;
vq = sc->vtnet_ctrl_vq;
@@ -3841,237 +3521,152 @@ vtnet_exec_ctrl_cmd(struct vtnet_softc *sc, uint8_t *ack, struct sglist *sg,
VTNET_CORE_LOCK_ASSERT(sc);
if (!virtqueue_empty(vq))
- goto error_unload;
+ return;
/*
* Poll for the response, but the command is likely completed before
* returning from the notify.
*/
- if (virtqueue_enqueue(vq, (void *)ack, sg, readable, writable) == 0) {
+ if (virtqueue_enqueue(vq, cookie, sg, readable, writable) == 0) {
virtqueue_notify(vq);
virtqueue_poll(vq, NULL);
}
-
- bus_dmamap_sync(sc->vtnet_ack_dmat, ack_dmap, BUS_DMASYNC_POSTREAD);
-
-error_unload:
- bus_dmamap_unload(sc->vtnet_ack_dmat, ack_dmap);
-error_destroy:
- bus_dmamap_destroy(sc->vtnet_ack_dmat, ack_dmap);
-error_out:
- return (error);
}
static int
vtnet_ctrl_mac_cmd(struct vtnet_softc *sc, uint8_t *hwaddr)
{
struct sglist_seg segs[3];
- bus_dmamap_t hdr_dmap;
- bus_addr_t hdr_paddr;
struct sglist sg;
struct {
struct virtio_net_ctrl_hdr hdr __aligned(2);
uint8_t pad1;
uint8_t addr[ETHER_ADDR_LEN] __aligned(8);
uint8_t pad2;
+ uint8_t ack;
} s;
- uint8_t ack;
int error;
- error = bus_dmamap_create(sc->vtnet_hdr_dmat, 0, &hdr_dmap);
- if (error)
- goto error_out;
-
- error = bus_dmamap_load(sc->vtnet_hdr_dmat, hdr_dmap, &s,
- sizeof(s), vtnet_load_callback, &hdr_paddr, BUS_DMA_NOWAIT);
- if (error)
- goto error_destroy_hdr;
-
+ error = 0;
MPASS(sc->vtnet_flags & VTNET_FLAG_CTRL_MAC);
s.hdr.class = VIRTIO_NET_CTRL_MAC;
s.hdr.cmd = VIRTIO_NET_CTRL_MAC_ADDR_SET;
bcopy(hwaddr, &s.addr[0], ETHER_ADDR_LEN);
- ack = VIRTIO_NET_ERR;
- bus_dmamap_sync(sc->vtnet_hdr_dmat, hdr_dmap, BUS_DMASYNC_PREWRITE);
+ s.ack = VIRTIO_NET_ERR;
sglist_init(&sg, nitems(segs), segs);
- error |= sglist_append_phys(&sg, hdr_paddr,
- sizeof(struct virtio_net_ctrl_hdr));
- error |= sglist_append_phys(&sg,
- hdr_paddr + ((uintptr_t)&s.addr - (uintptr_t)&s),
- ETHER_ADDR_LEN);
- MPASS(error == 0 && sg.sg_nseg == nitems(segs) - 1);
+ error |= sglist_append(&sg, &s.hdr, sizeof(struct virtio_net_ctrl_hdr));
+ error |= sglist_append(&sg, &s.addr[0], ETHER_ADDR_LEN);
+ error |= sglist_append(&sg, &s.ack, sizeof(uint8_t));
+ MPASS(error == 0 && sg.sg_nseg == nitems(segs));
if (error == 0)
- error = vtnet_exec_ctrl_cmd(sc, &ack, &sg, sg.sg_nseg, 1);
- if (error == 0)
- error = (ack == VIRTIO_NET_OK ? 0 : EIO);
+ vtnet_exec_ctrl_cmd(sc, &s.ack, &sg, sg.sg_nseg - 1, 1);
- bus_dmamap_unload(sc->vtnet_hdr_dmat, hdr_dmap);
-error_destroy_hdr:
- bus_dmamap_destroy(sc->vtnet_hdr_dmat, hdr_dmap);
-error_out:
- return (error);
+ return (s.ack == VIRTIO_NET_OK ? 0 : EIO);
}
static int
vtnet_ctrl_guest_offloads(struct vtnet_softc *sc, uint64_t offloads)
{
struct sglist_seg segs[3];
- bus_dmamap_t hdr_dmap;
- bus_addr_t hdr_paddr;
struct sglist sg;
struct {
struct virtio_net_ctrl_hdr hdr __aligned(2);
uint8_t pad1;
uint64_t offloads __aligned(8);
uint8_t pad2;
+ uint8_t ack;
} s;
- uint8_t ack;
int error;
- error = bus_dmamap_create(sc->vtnet_hdr_dmat, 0, &hdr_dmap);
- if (error)
- goto error_out;
-
- error = bus_dmamap_load(sc->vtnet_hdr_dmat, hdr_dmap, &s,
- sizeof(s), vtnet_load_callback, &hdr_paddr, BUS_DMA_NOWAIT);
- if (error)
- goto error_destroy_hdr;
-
+ error = 0;
MPASS(sc->vtnet_features & VIRTIO_NET_F_CTRL_GUEST_OFFLOADS);
s.hdr.class = VIRTIO_NET_CTRL_GUEST_OFFLOADS;
s.hdr.cmd = VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET;
s.offloads = vtnet_gtoh64(sc, offloads);
- ack = VIRTIO_NET_ERR;
- bus_dmamap_sync(sc->vtnet_hdr_dmat, hdr_dmap, BUS_DMASYNC_PREWRITE);
+ s.ack = VIRTIO_NET_ERR;
sglist_init(&sg, nitems(segs), segs);
- error |= sglist_append_phys(&sg, hdr_paddr,
- sizeof(struct virtio_net_ctrl_hdr));
- error |= sglist_append_phys(&sg,
- hdr_paddr + ((uintptr_t)&s.offloads - (uintptr_t)&s),
- sizeof(uint64_t));
- MPASS(error == 0 && sg.sg_nseg == nitems(segs) - 1);
+ error |= sglist_append(&sg, &s.hdr, sizeof(struct virtio_net_ctrl_hdr));
+ error |= sglist_append(&sg, &s.offloads, sizeof(uint64_t));
+ error |= sglist_append(&sg, &s.ack, sizeof(uint8_t));
+ MPASS(error == 0 && sg.sg_nseg == nitems(segs));
if (error == 0)
- error = vtnet_exec_ctrl_cmd(sc, &ack, &sg, sg.sg_nseg, 1);
- if (error == 0)
- error = (ack == VIRTIO_NET_OK ? 0 : EIO);
+ vtnet_exec_ctrl_cmd(sc, &s.ack, &sg, sg.sg_nseg - 1, 1);
- bus_dmamap_unload(sc->vtnet_hdr_dmat, hdr_dmap);
-error_destroy_hdr:
- bus_dmamap_destroy(sc->vtnet_hdr_dmat, hdr_dmap);
-error_out:
- return (error);
+ return (s.ack == VIRTIO_NET_OK ? 0 : EIO);
}
static int
vtnet_ctrl_mq_cmd(struct vtnet_softc *sc, uint16_t npairs)
{
struct sglist_seg segs[3];
- bus_dmamap_t hdr_dmap;
- bus_addr_t hdr_paddr;
struct sglist sg;
struct {
struct virtio_net_ctrl_hdr hdr __aligned(2);
uint8_t pad1;
struct virtio_net_ctrl_mq mq __aligned(2);
uint8_t pad2;
+ uint8_t ack;
} s;
- uint8_t ack;
int error;
- error = bus_dmamap_create(sc->vtnet_hdr_dmat, 0, &hdr_dmap);
- if (error)
- goto error_out;
-
- error = bus_dmamap_load(sc->vtnet_hdr_dmat, hdr_dmap, &s,
- sizeof(s), vtnet_load_callback, &hdr_paddr, BUS_DMA_NOWAIT);
- if (error)
- goto error_destroy_hdr;
-
+ error = 0;
MPASS(sc->vtnet_flags & VTNET_FLAG_MQ);
s.hdr.class = VIRTIO_NET_CTRL_MQ;
s.hdr.cmd = VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET;
s.mq.virtqueue_pairs = vtnet_gtoh16(sc, npairs);
- ack = VIRTIO_NET_ERR;
- bus_dmamap_sync(sc->vtnet_hdr_dmat, hdr_dmap, BUS_DMASYNC_PREWRITE);
+ s.ack = VIRTIO_NET_ERR;
sglist_init(&sg, nitems(segs), segs);
- error |= sglist_append_phys(&sg, hdr_paddr,
- sizeof(struct virtio_net_ctrl_hdr));
- error |= sglist_append_phys(&sg,
- hdr_paddr + ((uintptr_t)&s.mq - (uintptr_t)&s),
- sizeof(struct virtio_net_ctrl_mq));
- MPASS(error == 0 && sg.sg_nseg == nitems(segs) - 1);
+ error |= sglist_append(&sg, &s.hdr, sizeof(struct virtio_net_ctrl_hdr));
+ error |= sglist_append(&sg, &s.mq, sizeof(struct virtio_net_ctrl_mq));
+ error |= sglist_append(&sg, &s.ack, sizeof(uint8_t));
+ MPASS(error == 0 && sg.sg_nseg == nitems(segs));
if (error == 0)
- error = vtnet_exec_ctrl_cmd(sc, &ack, &sg, sg.sg_nseg, 1);
- if (error == 0)
- error = (ack == VIRTIO_NET_OK ? 0 : EIO);
+ vtnet_exec_ctrl_cmd(sc, &s.ack, &sg, sg.sg_nseg - 1, 1);
- bus_dmamap_unload(sc->vtnet_hdr_dmat, hdr_dmap);
-error_destroy_hdr:
- bus_dmamap_destroy(sc->vtnet_hdr_dmat, hdr_dmap);
-error_out:
- return (error);
+ return (s.ack == VIRTIO_NET_OK ? 0 : EIO);
}
static int
vtnet_ctrl_rx_cmd(struct vtnet_softc *sc, uint8_t cmd, bool on)
{
struct sglist_seg segs[3];
- bus_dmamap_t hdr_dmap;
- bus_addr_t hdr_paddr;
struct sglist sg;
struct {
struct virtio_net_ctrl_hdr hdr __aligned(2);
uint8_t pad1;
uint8_t onoff;
uint8_t pad2;
+ uint8_t ack;
} s;
- uint8_t ack;
int error;
- error = bus_dmamap_create(sc->vtnet_hdr_dmat, 0, &hdr_dmap);
- if (error)
- goto error_out;
-
- error = bus_dmamap_load(sc->vtnet_hdr_dmat, hdr_dmap, &s,
- sizeof(s), vtnet_load_callback, &hdr_paddr, BUS_DMA_NOWAIT);
- if (error)
- goto error_destroy_hdr;
-
+ error = 0;
MPASS(sc->vtnet_flags & VTNET_FLAG_CTRL_RX);
s.hdr.class = VIRTIO_NET_CTRL_RX;
s.hdr.cmd = cmd;
s.onoff = on;
- ack = VIRTIO_NET_ERR;
- bus_dmamap_sync(sc->vtnet_hdr_dmat, hdr_dmap, BUS_DMASYNC_PREWRITE);
+ s.ack = VIRTIO_NET_ERR;
sglist_init(&sg, nitems(segs), segs);
- error |= sglist_append_phys(&sg, hdr_paddr,
- sizeof(struct virtio_net_ctrl_hdr));
- error |= sglist_append_phys(&sg,
- hdr_paddr + ((uintptr_t)&s.onoff - (uintptr_t)&s),
- sizeof(uint8_t));
- MPASS(error == 0 && sg.sg_nseg == nitems(segs) - 1);
+ error |= sglist_append(&sg, &s.hdr, sizeof(struct virtio_net_ctrl_hdr));
+ error |= sglist_append(&sg, &s.onoff, sizeof(uint8_t));
+ error |= sglist_append(&sg, &s.ack, sizeof(uint8_t));
+ MPASS(error == 0 && sg.sg_nseg == nitems(segs));
if (error == 0)
- error = vtnet_exec_ctrl_cmd(sc, &ack, &sg, sg.sg_nseg, 1);
- if (error == 0)
- error = (ack == VIRTIO_NET_OK ? 0 : EIO);
+ vtnet_exec_ctrl_cmd(sc, &s.ack, &sg, sg.sg_nseg - 1, 1);
- bus_dmamap_unload(sc->vtnet_hdr_dmat, hdr_dmap);
-error_destroy_hdr:
- bus_dmamap_destroy(sc->vtnet_hdr_dmat, hdr_dmap);
-error_out:
- return (error);
+ return (s.ack == VIRTIO_NET_OK ? 0 : EIO);
}
static int
@@ -4142,10 +3737,6 @@ vtnet_rx_filter_mac(struct vtnet_softc *sc)
struct virtio_net_ctrl_hdr hdr __aligned(2);
struct vtnet_mac_filter *filter;
struct sglist_seg segs[4];
- bus_dmamap_t filter_dmap;
- bus_addr_t filter_paddr;
- bus_dmamap_t hdr_dmap;
- bus_addr_t hdr_paddr;
struct sglist sg;
if_t ifp;
bool promisc, allmulti;
@@ -4185,25 +3776,6 @@ vtnet_rx_filter_mac(struct vtnet_softc *sc)
if (promisc && allmulti)
goto out;
- error = bus_dmamap_create(sc->vtnet_hdr_dmat, 0, &hdr_dmap);
- if (error)
- goto out_error;
-
- error = bus_dmamap_load(sc->vtnet_hdr_dmat, hdr_dmap, &hdr,
- sizeof(hdr), vtnet_load_callback, &hdr_paddr, BUS_DMA_NOWAIT);
- if (error)
- goto out_destroy_hdr;
-
- error = bus_dmamap_create(sc->vtnet_hdr_dmat, 0, &filter_dmap);
- if (error)
- goto out_unload_hdr;
-
- error = bus_dmamap_load(sc->vtnet_hdr_dmat, hdr_dmap, filter,
- sizeof(*filter), vtnet_load_callback, &filter_paddr,
- BUS_DMA_NOWAIT);
- if (error)
- goto out_destroy_filter;
-
filter->vmf_unicast.nentries = vtnet_gtoh32(sc, ucnt);
filter->vmf_multicast.nentries = vtnet_gtoh32(sc, mcnt);
@@ -4212,33 +3784,19 @@ vtnet_rx_filter_mac(struct vtnet_softc *sc)
ack = VIRTIO_NET_ERR;
sglist_init(&sg, nitems(segs), segs);
- error |= sglist_append_phys(&sg, hdr_paddr,
- sizeof(struct virtio_net_ctrl_hdr));
- error |= sglist_append_phys(&sg,
- filter_paddr + ((uintptr_t)&filter->vmf_unicast -
- (uintptr_t)filter),
+ error |= sglist_append(&sg, &hdr, sizeof(struct virtio_net_ctrl_hdr));
+ error |= sglist_append(&sg, &filter->vmf_unicast,
sizeof(uint32_t) + ucnt * ETHER_ADDR_LEN);
- error |= sglist_append_phys(&sg,
- filter_paddr + ((uintptr_t)&filter->vmf_multicast -
- (uintptr_t)filter),
+ error |= sglist_append(&sg, &filter->vmf_multicast,
sizeof(uint32_t) + mcnt * ETHER_ADDR_LEN);
- MPASS(error == 0 && sg.sg_nseg == nitems(segs) - 1);
+ error |= sglist_append(&sg, &ack, sizeof(uint8_t));
+ MPASS(error == 0 && sg.sg_nseg == nitems(segs));
if (error == 0)
- error = vtnet_exec_ctrl_cmd(sc, &ack, &sg, sg.sg_nseg, 1);
- if (error == 0)
- error = (ack == VIRTIO_NET_OK ? 0 : EIO);
-
- bus_dmamap_unload(sc->vtnet_hdr_dmat, filter_dmap);
-out_destroy_filter:
- bus_dmamap_destroy(sc->vtnet_hdr_dmat, filter_dmap);
-out_unload_hdr:
- bus_dmamap_unload(sc->vtnet_hdr_dmat, hdr_dmap);
-out_destroy_hdr:
- bus_dmamap_destroy(sc->vtnet_hdr_dmat, hdr_dmap);
-out_error:
- if (error != 0)
+ vtnet_exec_ctrl_cmd(sc, &ack, &sg, sg.sg_nseg - 1, 1);
+ if (ack != VIRTIO_NET_OK)
if_printf(ifp, "error setting host MAC filter table\n");
+
out:
if (promisc && vtnet_set_promisc(sc, true) != 0)
if_printf(ifp, "cannot enable promiscuous mode\n");
@@ -4250,53 +3808,34 @@ static int
vtnet_exec_vlan_filter(struct vtnet_softc *sc, int add, uint16_t tag)
{
struct sglist_seg segs[3];
- bus_dmamap_t hdr_dmap;
- bus_addr_t hdr_paddr;
struct sglist sg;
struct {
struct virtio_net_ctrl_hdr hdr __aligned(2);
uint8_t pad1;
uint16_t tag __aligned(2);
uint8_t pad2;
+ uint8_t ack;
} s;
- uint8_t ack;
int error;
- error = bus_dmamap_create(sc->vtnet_hdr_dmat, 0, &hdr_dmap);
- if (error)
- goto error_out;
-
- error = bus_dmamap_load(sc->vtnet_hdr_dmat, hdr_dmap, &s,
- sizeof(s), vtnet_load_callback, &hdr_paddr, BUS_DMA_NOWAIT);
- if (error)
- goto error_destroy_hdr;
-
+ error = 0;
MPASS(sc->vtnet_flags & VTNET_FLAG_VLAN_FILTER);
s.hdr.class = VIRTIO_NET_CTRL_VLAN;
s.hdr.cmd = add ? VIRTIO_NET_CTRL_VLAN_ADD : VIRTIO_NET_CTRL_VLAN_DEL;
s.tag = vtnet_gtoh16(sc, tag);
- ack = VIRTIO_NET_ERR;
- bus_dmamap_sync(sc->vtnet_hdr_dmat, hdr_dmap, BUS_DMASYNC_PREWRITE);
+ s.ack = VIRTIO_NET_ERR;
sglist_init(&sg, nitems(segs), segs);
- error |= sglist_append_phys(&sg, hdr_paddr,
- sizeof(struct virtio_net_ctrl_hdr));
- error |= sglist_append_phys(&sg,
- hdr_paddr + ((uintptr_t)&s.tag - (uintptr_t)&s),
- sizeof(uint16_t));
- MPASS(error == 0 && sg.sg_nseg == nitems(segs) - 1);
+ error |= sglist_append(&sg, &s.hdr, sizeof(struct virtio_net_ctrl_hdr));
+ error |= sglist_append(&sg, &s.tag, sizeof(uint16_t));
+ error |= sglist_append(&sg, &s.ack, sizeof(uint8_t));
+ MPASS(error == 0 && sg.sg_nseg == nitems(segs));
if (error == 0)
- error = vtnet_exec_ctrl_cmd(sc, &ack, &sg, sg.sg_nseg, 1);
- if (error == 0)
- error = (ack == VIRTIO_NET_OK ? 0 : EIO);
+ vtnet_exec_ctrl_cmd(sc, &s.ack, &sg, sg.sg_nseg - 1, 1);
- bus_dmamap_unload(sc->vtnet_hdr_dmat, hdr_dmap);
-error_destroy_hdr:
- bus_dmamap_destroy(sc->vtnet_hdr_dmat, hdr_dmap);
-error_out:
- return (error);
+ return (s.ack == VIRTIO_NET_OK ? 0 : EIO);
}
static void
diff --git a/sys/dev/virtio/network/if_vtnetvar.h b/sys/dev/virtio/network/if_vtnetvar.h
index e445bdf6d6cb..eb5e6784b07f 100644
--- a/sys/dev/virtio/network/if_vtnetvar.h
+++ b/sys/dev/virtio/network/if_vtnetvar.h
@@ -190,18 +190,6 @@ struct vtnet_softc {
struct mtx vtnet_mtx;
char vtnet_mtx_name[16];
uint8_t vtnet_hwaddr[ETHER_ADDR_LEN];
-
- bus_dma_tag_t vtnet_rx_dmat;
- struct mtx vtnet_rx_mtx;
-
- bus_dma_tag_t vtnet_tx_dmat;
- struct mtx vtnet_tx_mtx;
-
- bus_dma_tag_t vtnet_hdr_dmat;
- struct mtx vtnet_hdr_mtx;
-
- bus_dma_tag_t vtnet_ack_dmat;
- struct mtx vtnet_ack_mtx;
};
/* vtnet flag descriptions for use with printf(9) %b identifier. */
#define VTNET_FLAGS_BITS \
@@ -285,10 +273,6 @@ struct vtnet_tx_header {
} vth_uhdr;
struct mbuf *vth_mbuf;
-
- bus_dmamap_t dmap;
-
- bus_dmamap_t hdr_dmap;
};
/*
diff --git a/sys/dev/virtio/p9fs/virtio_p9fs.c b/sys/dev/virtio/p9fs/virtio_p9fs.c
index 2b276a60aa9a..19a32fea458e 100644
--- a/sys/dev/virtio/p9fs/virtio_p9fs.c
+++ b/sys/dev/virtio/p9fs/virtio_p9fs.c
@@ -464,16 +464,20 @@ static int
vt9p_modevent(module_t mod, int type, void *unused)
{
int error;
+ static int loaded = 0;
error = 0;
switch (type) {
case MOD_LOAD:
- p9_init_zones();
- p9_register_trans(&vt9p_trans);
+ if (loaded++ == 0) {
+ p9_register_trans(&vt9p_trans);
+ }
break;
case MOD_UNLOAD:
- p9_destroy_zones();
+ if (--loaded == 0) {
+ p9_unregister_trans(&vt9p_trans);
+ }
break;
case MOD_SHUTDOWN:
break;
@@ -481,6 +485,7 @@ vt9p_modevent(module_t mod, int type, void *unused)
error = EOPNOTSUPP;
break;
}
+
return (error);
}
diff --git a/sys/dev/vt/vt_core.c b/sys/dev/vt/vt_core.c
index 68a9a71c3d72..f7cffcea5b92 100644
--- a/sys/dev/vt/vt_core.c
+++ b/sys/dev/vt/vt_core.c
@@ -1684,6 +1684,9 @@ vtterm_splash(struct vt_device *vd)
uintptr_t image;
vt_axis_t top, left;
+ if (KERNEL_PANICKED())
+ return;
+
if ((vd->vd_flags & VDF_TEXTMODE) != 0 || (boothowto & RB_MUTE) == 0)
return;