Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F82887952
D7195.id18355.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D7195.id18355.diff
View Options
Index: sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
===================================================================
--- sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
+++ sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
@@ -40,6 +40,7 @@
#include <sys/condvar.h>
#include <sys/time.h>
#include <sys/systm.h>
+#include <sys/sysctl.h>
#include <sys/sockio.h>
#include <sys/mbuf.h>
#include <sys/malloc.h>
@@ -108,37 +109,55 @@
UNKNOWN_TYPE
};
+#define STORVSC_DATA_SEGCNT_MAX (32)
+SYSCTL_NODE(_hw, OID_AUTO, storvsc, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL,
+ "Hyper-V storage interface");
+
+static u_int hv_storvsc_use_pim_unmapped = 1;
+TUNABLE_INT("hw.storvsc.use_pim_unmapped", &hv_storvsc_use_pim_unmapped);
+SYSCTL_INT(_hw_storvsc, OID_AUTO, use_pim_unmapped, CTLFLAG_RDTUN,
+ &hv_storvsc_use_pim_unmapped, 0, "Optimize storvsc by using unmapped memory");
+
+struct hv_storvsc_sysctl {
+ u_long data_bio_cnt;
+ u_long data_vaddr_cnt;
+ u_long data_sg_cnt;
+};
+
struct hv_storvsc_request {
- LIST_ENTRY(hv_storvsc_request) link;
- struct vstor_packet vstor_packet;
- hv_vmbus_multipage_buffer data_buf;
- void *sense_data;
- uint8_t sense_info_len;
- uint8_t retries;
- union ccb *ccb;
- struct storvsc_softc *softc;
- struct callout callout;
- struct sema synch_sema; /*Synchronize the request/response if needed */
- struct sglist *bounce_sgl;
- unsigned int bounce_sgl_count;
- uint64_t not_aligned_seg_bits;
+ LIST_ENTRY(hv_storvsc_request) link;
+ struct vstor_packet vstor_packet;
+ hv_vmbus_multipage_buffer data_buf;
+ void *sense_data;
+ uint8_t sense_info_len;
+ uint8_t retries;
+ union ccb *ccb;
+ struct storvsc_softc *softc;
+ struct callout callout;
+ struct sema synch_sema; /*Synchronize the request/response if needed */
+ struct sglist *bounce_sgl;
+ unsigned int bounce_sgl_count;
+ uint64_t not_aligned_seg_bits;
+ bus_dmamap_t data_dmap;
};
struct storvsc_softc {
- struct hv_device *hs_dev;
- LIST_HEAD(, hv_storvsc_request) hs_free_list;
- struct mtx hs_lock;
- struct storvsc_driver_props *hs_drv_props;
- int hs_unit;
- uint32_t hs_frozen;
- struct cam_sim *hs_sim;
- struct cam_path *hs_path;
- uint32_t hs_num_out_reqs;
- boolean_t hs_destroy;
- boolean_t hs_drain_notify;
- struct sema hs_drain_sema;
- struct hv_storvsc_request hs_init_req;
- struct hv_storvsc_request hs_reset_req;
+ struct hv_device *hs_dev;
+ LIST_HEAD(, hv_storvsc_request) hs_free_list;
+ struct mtx hs_lock;
+ struct storvsc_driver_props *hs_drv_props;
+ int hs_unit;
+ uint32_t hs_frozen;
+ struct cam_sim *hs_sim;
+ struct cam_path *hs_path;
+ uint32_t hs_num_out_reqs;
+ boolean_t hs_destroy;
+ boolean_t hs_drain_notify;
+ struct sema hs_drain_sema;
+ struct hv_storvsc_request hs_init_req;
+ struct hv_storvsc_request hs_reset_req;
+ bus_dma_tag_t storvsc_req_dtag;
+ struct hv_storvsc_sysctl sysctl_data;
};
@@ -986,6 +1005,76 @@
return (ret);
}
+static int storvsc_init_requests(device_t dev)
+{
+ struct storvsc_softc *sc;
+ struct hv_storvsc_request *reqp;
+ int error, i;
+
+ sc = device_get_softc(dev);
+ LIST_INIT(&sc->hs_free_list);
+ error = bus_dma_tag_create(
+ bus_get_dma_tag(dev), /* parent */
+ 1, /* alignment */
+ PAGE_SIZE, /* boundary */
+ BUS_SPACE_MAXADDR, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ STORVSC_DATA_SEGCNT_MAX*PAGE_SIZE, /* maxsize */
+ STORVSC_DATA_SEGCNT_MAX, /* nsegments */
+ PAGE_SIZE, /* maxsegsize */
+ 0, /* flags */
+ NULL, /* lockfunc */
+ NULL, /* lockfuncarg */
+ &sc->storvsc_req_dtag);
+ if (error) {
+ device_printf(sc->hs_dev->device, "failed to create storvsc dma tag\n");
+ return (error);
+ }
+
+ for (i = 0; i < sc->hs_drv_props->drv_max_ios_per_target; ++i) {
+ reqp = malloc(sizeof(struct hv_storvsc_request),
+ M_DEVBUF, M_WAITOK|M_ZERO);
+ reqp->softc = sc;
+ error = bus_dmamap_create(sc->storvsc_req_dtag, 0,
+ &reqp->data_dmap);
+ if (error) {
+ device_printf(sc->hs_dev->device, "failed to allocate storvsc data dmamap\n");
+ goto cleanup;
+ }
+ LIST_INSERT_HEAD(&sc->hs_free_list, reqp, link);
+ }
+ return (0);
+
+cleanup:
+ while (!LIST_EMPTY(&sc->hs_free_list)) {
+ reqp = LIST_FIRST(&sc->hs_free_list);
+ LIST_REMOVE(reqp, link);
+ bus_dmamap_destroy(sc->storvsc_req_dtag, reqp->data_dmap);
+ free(reqp, M_DEVBUF);
+ }
+ return (0);
+}
+
+static void
+storvsc_sysctl(device_t dev)
+{
+ struct sysctl_oid_list *child;
+ struct sysctl_ctx_list *ctx;
+ struct storvsc_softc *sc;
+
+ sc = device_get_softc(dev);
+ ctx = device_get_sysctl_ctx(dev);
+ child = SYSCTL_CHILDREN(device_get_sysctl_tree(dev));
+
+ SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "data_bio_cnt", CTLFLAG_RW,
+ &sc->sysctl_data.data_bio_cnt, "# of bio data block");
+ SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "data_vaddr_cnt", CTLFLAG_RW,
+ &sc->sysctl_data.data_vaddr_cnt, "# of vaddr data block");
+ SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "data_sg_cnt", CTLFLAG_RW,
+ &sc->sysctl_data.data_sg_cnt, "# of sg data block");
+}
+
/**
* @brief StorVSC attach function
*
@@ -1030,15 +1119,11 @@
sc->hs_unit = device_get_unit(dev);
sc->hs_dev = hv_dev;
- LIST_INIT(&sc->hs_free_list);
mtx_init(&sc->hs_lock, "hvslck", NULL, MTX_DEF);
- for (i = 0; i < sc->hs_drv_props->drv_max_ios_per_target; ++i) {
- reqp = malloc(sizeof(struct hv_storvsc_request),
- M_DEVBUF, M_WAITOK|M_ZERO);
- reqp->softc = sc;
-
- LIST_INSERT_HEAD(&sc->hs_free_list, reqp, link);
+ if (storvsc_init_requests(dev)) {
+ ret = ENODEV;
+ goto cleanup;
}
/* create sg-list page pool */
@@ -1130,6 +1215,8 @@
goto cleanup;
}
+ storvsc_sysctl(dev);
+
mtx_unlock(&sc->hs_lock);
root_mount_rel(root_mount_token);
@@ -1396,6 +1483,9 @@
cpi->hba_inquiry = PI_TAG_ABLE|PI_SDTR_ABLE;
cpi->target_sprt = 0;
cpi->hba_misc = PIM_NOBUSRESET;
+ if (hv_storvsc_use_pim_unmapped) {
+ cpi->hba_misc |= PIM_UNMAPPED;
+ }
cpi->hba_eng_cnt = 0;
cpi->max_target = STORVSC_MAX_TARGETS;
cpi->max_lun = sc->hs_drv_props->drv_max_luns_per_target;
@@ -1744,6 +1834,31 @@
}
/**
+ * Copy bus_dma segments to multiple page buffer, which requires
+ * the pages are compact composed except for the 1st and last pages.
+ */
+static void
+storvsc_xferbuf_prepare(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+ struct hv_storvsc_request *reqp = arg;
+ union ccb *ccb = reqp->ccb;
+ struct ccb_scsiio *csio = &ccb->csio;
+ int i;
+
+ reqp->data_buf.offset = segs[0].ds_addr & PAGE_MASK;
+ reqp->data_buf.length = csio->dxfer_len;
+
+ for (i = 0; i < nsegs; i++) {
+ reqp->data_buf.pfn_array[i] = atop(segs[i].ds_addr);
+ if (i != 0 && i != nsegs - 1) {
+ KASSERT((segs[i].ds_addr & PAGE_MASK) == 0 &&
+ segs[i].ds_len == PAGE_SIZE,
+ ("bus_dma page segment is not a full page"));
+ }
+ }
+}
+
+/**
* @brief Fill in a request structure based on a CAM control block
*
* Fills in a request structure based on the contents of a CAM control
@@ -1758,11 +1873,9 @@
{
struct ccb_scsiio *csio = &ccb->csio;
uint64_t phys_addr;
- uint32_t bytes_to_copy = 0;
- uint32_t pfn_num = 0;
uint32_t pfn;
uint64_t not_aligned_seg_bits = 0;
-
+ int error;
/* refer to struct vmscsi_req for meanings of these two fields */
reqp->vstor_packet.u.vm_srb.port =
cam_sim_unit(xpt_path_sim(ccb->ccb_h.path));
@@ -1808,29 +1921,23 @@
reqp->data_buf.length = csio->dxfer_len;
switch (ccb->ccb_h.flags & CAM_DATA_MASK) {
+ case CAM_DATA_BIO:
case CAM_DATA_VADDR:
{
- bytes_to_copy = csio->dxfer_len;
- phys_addr = vtophys(csio->data_ptr);
- reqp->data_buf.offset = phys_addr & PAGE_MASK;
-
- while (bytes_to_copy != 0) {
- int bytes, page_offset;
- phys_addr =
- vtophys(&csio->data_ptr[reqp->data_buf.length -
- bytes_to_copy]);
- pfn = phys_addr >> PAGE_SHIFT;
- reqp->data_buf.pfn_array[pfn_num] = pfn;
- page_offset = phys_addr & PAGE_MASK;
-
- bytes = min(PAGE_SIZE - page_offset, bytes_to_copy);
-
- bytes_to_copy -= bytes;
- pfn_num++;
+ error = bus_dmamap_load_ccb(reqp->softc->storvsc_req_dtag,
+ reqp->data_dmap, ccb, storvsc_xferbuf_prepare,
+ reqp, BUS_DMA_NOWAIT);
+ if (error) {
+ printf("Storvsc: failed in bus_dmamap_load_ccb: %d\n", error);
+ return (error);
+ }
+ if ((ccb->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_BIO) {
+ reqp->softc->sysctl_data.data_bio_cnt++;
+ } else {
+ reqp->softc->sysctl_data.data_vaddr_cnt++;
}
break;
}
-
case CAM_DATA_SG:
{
int i = 0;
@@ -1940,6 +2047,7 @@
reqp->bounce_sgl_count = 0;
}
+ reqp->softc->sysctl_data.data_sg_cnt++;
break;
}
default:
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Jan 8, 1:14 PM (42 m, 30 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
9293227
Default Alt Text
D7195.id18355.diff (9 KB)
Attached To
Mode
D7195: hyperv/stor: Refactor storvsc by applying BUS_DMA for CAM_DATA_BIO
Attached
Detach File
Event Timeline
Log In to Comment