Module Name:    src
Committed By:   mlelstv
Date:           Sat Feb 22 09:57:09 UTC 2025

Modified Files:
        src/sys/dev/pci: ld_virtio.c

Log Message:
Query device for id string.


To generate a diff of this commit:
cvs rdiff -u -r1.38 -r1.39 src/sys/dev/pci/ld_virtio.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/pci/ld_virtio.c
diff -u src/sys/dev/pci/ld_virtio.c:1.38 src/sys/dev/pci/ld_virtio.c:1.39
--- src/sys/dev/pci/ld_virtio.c:1.38	Sat Feb 22 09:55:31 2025
+++ src/sys/dev/pci/ld_virtio.c	Sat Feb 22 09:57:09 2025
@@ -1,4 +1,4 @@
-/*	$NetBSD: ld_virtio.c,v 1.38 2025/02/22 09:55:31 mlelstv Exp $	*/
+/*	$NetBSD: ld_virtio.c,v 1.39 2025/02/22 09:57:09 mlelstv Exp $	*/
 
 /*
  * Copyright (c) 2010 Minoura Makoto.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ld_virtio.c,v 1.38 2025/02/22 09:55:31 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ld_virtio.c,v 1.39 2025/02/22 09:57:09 mlelstv Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -178,6 +178,7 @@ struct ld_virtio_softc {
 	kcondvar_t		sc_sync_wait;
 	kmutex_t		sc_sync_wait_lock;
 	uint8_t			sc_sync_status;
+	uint8_t			*sc_typename;
 
 	uint32_t		sc_max_discard_sectors;
 	uint32_t		sc_max_discard_seg;
@@ -208,6 +209,7 @@ static int ld_virtio_vq_done(struct virt
 static int ld_virtio_dump(struct ld_softc *, void *, int, int);
 static int ld_virtio_start(struct ld_softc *, struct buf *);
 static int ld_virtio_ioctl(struct ld_softc *, u_long, void *, int32_t, bool);
+static int ld_virtio_info(struct ld_softc *);
 static int ld_virtio_discard(struct ld_softc *, struct buf *);
 
 static int
@@ -427,6 +429,11 @@ ld_virtio_attach(device_t parent, device
 	ld->sc_start = ld_virtio_start;
 	ld->sc_ioctl = ld_virtio_ioctl;
 
+	if (ld_virtio_info(ld) == 0)
+		ld->sc_typename = sc->sc_typename;
+	else
+		ld->sc_typename = __UNCONST("Virtio Block Device");
+
 	if (features & VIRTIO_BLK_F_DISCARD) {
 		ld->sc_discard = ld_virtio_discard;
 		sc->sc_max_discard_sectors = virtio_read_device_config_4(vsc,
@@ -451,6 +458,98 @@ err:
 }
 
 static int
+ld_virtio_info(struct ld_softc *ld)
+{
+	struct ld_virtio_softc *sc = device_private(ld->sc_dv);
+	struct virtio_softc *vsc = sc->sc_virtio;
+	struct virtqueue *vq = &sc->sc_vq;
+	struct virtio_blk_req *vr;
+	int r;
+	int slot;
+	uint8_t id_data[20]; /* virtio v1.2 5.2.6 */
+
+	if (sc->sc_typename != NULL) {
+		kmem_strfree(sc->sc_typename);
+		sc->sc_typename = NULL;
+	}
+
+	r = virtio_enqueue_prep(vsc, vq, &slot);
+	if (r != 0)
+		return r;
+
+	vr = &sc->sc_reqs[slot];
+	KASSERT(vr->vr_bp == NULL);
+
+	r = bus_dmamap_load(virtio_dmat(vsc), vr->vr_payload,
+			    id_data, sizeof(id_data), NULL,
+			    BUS_DMA_READ|BUS_DMA_NOWAIT);
+	if (r != 0) {
+		aprint_error_dev(sc->sc_dev,
+		    "payload dmamap failed, error code %d\n", r);
+		virtio_enqueue_abort(vsc, vq, slot);
+		return r;
+	}
+
+	KASSERT(vr->vr_payload->dm_nsegs <= sc->sc_seg_max);
+	r = virtio_enqueue_reserve(vsc, vq, slot, vr->vr_payload->dm_nsegs +
+	    VIRTIO_BLK_CTRL_SEGMENTS);
+	if (r != 0) {
+		bus_dmamap_unload(virtio_dmat(vsc), vr->vr_payload);
+		return r;
+	}
+
+	vr->vr_bp = DUMMY_VR_BP;
+	vr->vr_hdr.type   = virtio_rw32(vsc, VIRTIO_BLK_T_GET_ID);
+	vr->vr_hdr.ioprio = virtio_rw32(vsc, 0);
+	vr->vr_hdr.sector = virtio_rw64(vsc, 0);
+
+	bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts,
+			0, sizeof(struct virtio_blk_req_hdr),
+			BUS_DMASYNC_PREWRITE);
+	bus_dmamap_sync(virtio_dmat(vsc), vr->vr_payload,
+			0, sizeof(id_data),
+			BUS_DMASYNC_PREREAD);
+	bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts,
+			offsetof(struct virtio_blk_req, vr_status),
+			sizeof(uint8_t),
+			BUS_DMASYNC_PREREAD);
+
+	virtio_enqueue_p(vsc, vq, slot, vr->vr_cmdsts,
+			 0, sizeof(struct virtio_blk_req_hdr),
+			 true);
+	virtio_enqueue(vsc, vq, slot, vr->vr_payload, false);
+	virtio_enqueue_p(vsc, vq, slot, vr->vr_cmdsts,
+			 offsetof(struct virtio_blk_req, vr_status),
+			 sizeof(uint8_t),
+	                 false);
+	virtio_enqueue_commit(vsc, vq, slot, true);
+
+	mutex_enter(&sc->sc_sync_wait_lock);
+	while (sc->sc_sync_use != SYNC_DONE)
+		cv_wait(&sc->sc_sync_wait, &sc->sc_sync_wait_lock);
+
+	if (sc->sc_sync_status == VIRTIO_BLK_S_OK)
+		r = 0;
+	else
+		r = EIO;
+
+	sc->sc_sync_use = SYNC_FREE;
+	cv_broadcast(&sc->sc_sync_wait);
+	mutex_exit(&sc->sc_sync_wait_lock);
+
+	bus_dmamap_sync(virtio_dmat(vsc), vr->vr_payload,
+			0, sizeof(id_data), BUS_DMASYNC_POSTREAD);
+	bus_dmamap_unload(virtio_dmat(vsc), vr->vr_payload);
+
+	if (r != 0)
+		return r;
+
+	sc->sc_typename = kmem_strndup(id_data, sizeof(id_data), KM_NOSLEEP);
+
+	return 0;
+}
+
+static int
 ld_virtio_start(struct ld_softc *ld, struct buf *bp)
 {
 	/* splbio */
@@ -734,6 +833,9 @@ ld_virtio_detach(device_t self, int flag
 
 	ldenddetach(ld);
 
+	if (sc->sc_typename != NULL)
+		kmem_strfree(sc->sc_typename);
+
 	cv_destroy(&sc->sc_sync_wait);
 	mutex_destroy(&sc->sc_sync_wait_lock);
 

Reply via email to