Page MenuHomeFreeBSD

D7195.id18355.diff
No OneTemporary

D7195.id18355.diff

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

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)

Event Timeline