diff options
Diffstat (limited to 'usr/src/uts/common/io/vioblk/vioblk.c')
| -rw-r--r-- | usr/src/uts/common/io/vioblk/vioblk.c | 118 |
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. |
