summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/io/vioblk/vioblk.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/io/vioblk/vioblk.c')
-rw-r--r--usr/src/uts/common/io/vioblk/vioblk.c118
1 files changed, 80 insertions, 38 deletions
diff --git a/usr/src/uts/common/io/vioblk/vioblk.c b/usr/src/uts/common/io/vioblk/vioblk.c
index 0cccb84bce..f6649bdd12 100644
--- a/usr/src/uts/common/io/vioblk/vioblk.c
+++ b/usr/src/uts/common/io/vioblk/vioblk.c
@@ -25,6 +25,7 @@
* Copyright 2020 Joyent Inc.
* Copyright 2019 Western Digital Corporation.
* Copyright 2020 Oxide Computer Company
+ * Copyright 2022 OmniOS Community Edition (OmniOSce) Association.
*/
/*
@@ -94,9 +95,10 @@
#include "vioblk.h"
static void vioblk_get_id(vioblk_t *);
-uint_t vioblk_int_handler(caddr_t, caddr_t);
+static uint_t vioblk_int_handler(caddr_t, caddr_t);
static uint_t vioblk_poll(vioblk_t *);
static int vioblk_quiesce(dev_info_t *);
+static int vioblk_read_capacity(vioblk_t *);
static int vioblk_attach(dev_info_t *, ddi_attach_cmd_t);
static int vioblk_detach(dev_info_t *, ddi_detach_cmd_t);
@@ -737,8 +739,8 @@ vioblk_poll(vioblk_t *vib)
return (count);
}
-uint_t
-vioblk_int_handler(caddr_t arg0, caddr_t arg1)
+static uint_t
+vioblk_int_handler(caddr_t arg0, caddr_t arg1 __unused)
{
vioblk_t *vib = (vioblk_t *)arg0;
uint_t count;
@@ -755,6 +757,33 @@ vioblk_int_handler(caddr_t arg0, caddr_t arg1)
return (DDI_INTR_CLAIMED);
}
+static uint_t
+vioblk_cfgchange(caddr_t arg0, caddr_t arg1 __unused)
+{
+ vioblk_t *vib = (vioblk_t *)arg0;
+
+ dev_err(vib->vib_dip, CE_NOTE, "!Configuration changed");
+
+ mutex_enter(&vib->vib_mutex);
+
+ /*
+ * The configuration space of the device has changed in some way.
+ * At present, we only re-read the device capacity and trigger
+ * blkdev to check the device state.
+ */
+
+ if (vioblk_read_capacity(vib) == DDI_FAILURE) {
+ mutex_exit(&vib->vib_mutex);
+ return (DDI_INTR_CLAIMED);
+ }
+
+ mutex_exit(&vib->vib_mutex);
+
+ bd_state_change(vib->vib_bd_h);
+
+ return (DDI_INTR_CLAIMED);
+}
+
static void
vioblk_free_reqs(vioblk_t *vib)
{
@@ -823,6 +852,50 @@ fail:
}
static int
+vioblk_read_capacity(vioblk_t *vib)
+{
+ virtio_t *vio = vib->vib_virtio;
+
+ /* The capacity is always available */
+ if ((vib->vib_nblks = virtio_dev_get64(vio,
+ VIRTIO_BLK_CONFIG_CAPACITY)) == UINT64_MAX) {
+ dev_err(vib->vib_dip, CE_WARN, "invalid capacity");
+ return (DDI_FAILURE);
+ }
+
+ /*
+ * Determine the optimal logical block size recommended by the device.
+ * This size is advisory; the protocol always deals in 512 byte blocks.
+ */
+ vib->vib_blk_size = DEV_BSIZE;
+ if (virtio_feature_present(vio, VIRTIO_BLK_F_BLK_SIZE)) {
+ uint32_t v = virtio_dev_get32(vio, VIRTIO_BLK_CONFIG_BLK_SIZE);
+
+ if (v != 0 && v != PCI_EINVAL32)
+ vib->vib_blk_size = v;
+ }
+
+ /*
+ * Device capacity is always in 512-byte units, convert to
+ * native blocks.
+ */
+ vib->vib_nblks = (vib->vib_nblks * DEV_BSIZE) / vib->vib_blk_size;
+
+ /*
+ * The device may also provide an advisory physical block size.
+ */
+ vib->vib_pblk_size = vib->vib_blk_size;
+ if (virtio_feature_present(vio, VIRTIO_BLK_F_TOPOLOGY)) {
+ uint8_t v = virtio_dev_get8(vio, VIRTIO_BLK_CONFIG_TOPO_PBEXP);
+
+ if (v != PCI_EINVAL8)
+ vib->vib_pblk_size <<= v;
+ }
+
+ return (DDI_SUCCESS);
+}
+
+static int
vioblk_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
int instance = ddi_get_instance(dip);
@@ -906,6 +979,8 @@ vioblk_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
goto fail;
}
+ virtio_register_cfgchange_handler(vio, vioblk_cfgchange, vib);
+
if (virtio_init_complete(vio, 0) != DDI_SUCCESS) {
dev_err(dip, CE_WARN, "failed to complete Virtio init");
goto fail;
@@ -944,42 +1019,9 @@ vioblk_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
kstat_install(vib->vib_kstat);
vib->vib_readonly = virtio_feature_present(vio, VIRTIO_BLK_F_RO);
- if ((vib->vib_nblks = virtio_dev_get64(vio,
- VIRTIO_BLK_CONFIG_CAPACITY)) == UINT64_MAX) {
- dev_err(dip, CE_WARN, "invalid capacity");
- goto fail;
- }
-
- /*
- * Determine the optimal logical block size recommended by the device.
- * This size is advisory; the protocol always deals in 512 byte blocks.
- */
- vib->vib_blk_size = DEV_BSIZE;
- if (virtio_feature_present(vio, VIRTIO_BLK_F_BLK_SIZE)) {
- uint32_t v = virtio_dev_get32(vio, VIRTIO_BLK_CONFIG_BLK_SIZE);
-
- if (v != 0 && v != PCI_EINVAL32) {
- vib->vib_blk_size = v;
- }
- }
-
- /*
- * Device capacity is always in 512-byte units, convert to
- * native blocks.
- */
- vib->vib_nblks = (vib->vib_nblks * DEV_BSIZE) / vib->vib_blk_size;
- /*
- * The device may also provide an advisory physical block size.
- */
- vib->vib_pblk_size = vib->vib_blk_size;
- if (virtio_feature_present(vio, VIRTIO_BLK_F_TOPOLOGY)) {
- uint8_t v = virtio_dev_get8(vio, VIRTIO_BLK_CONFIG_TOPO_PBEXP);
-
- if (v != PCI_EINVAL8) {
- vib->vib_pblk_size <<= v;
- }
- }
+ if (vioblk_read_capacity(vib) == DDI_FAILURE)
+ goto fail;
/*
* The maximum size for a cookie in a request.