Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F81969300
D7622.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
D7622.diff
View Options
Index: head/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
===================================================================
--- head/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
+++ head/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
@@ -75,11 +75,9 @@
#include <dev/hyperv/include/hyperv.h>
#include <dev/hyperv/include/vmbus.h>
-
#include "hv_vstorage.h"
#include "vmbus_if.h"
-#define STORVSC_RINGBUFFER_SIZE (20*PAGE_SIZE)
#define STORVSC_MAX_LUNS_PER_TARGET (64)
#define STORVSC_MAX_IO_REQUESTS (STORVSC_MAX_LUNS_PER_TARGET * 2)
#define BLKVSC_MAX_IDE_DISKS_PER_TARGET (1)
@@ -121,8 +119,6 @@
boolean_t is_init;
} g_hv_sgl_page_pool;
-#define STORVSC_MAX_SG_PAGE_CNT STORVSC_MAX_IO_REQUESTS * STORVSC_DATA_SEGCNT_MAX
-
enum storvsc_request_type {
WRITE_TYPE,
READ_TYPE,
@@ -130,17 +126,35 @@
};
SYSCTL_NODE(_hw, OID_AUTO, storvsc, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL,
- "Hyper-V storage interface");
+ "Hyper-V storage interface");
+
+static u_int hv_storvsc_use_win8ext_flags = 1;
+SYSCTL_UINT(_hw_storvsc, OID_AUTO, use_win8ext_flags, CTLFLAG_RW,
+ &hv_storvsc_use_win8ext_flags, 0,
+ "Use win8 extension flags or not");
static u_int hv_storvsc_use_pim_unmapped = 1;
-SYSCTL_INT(_hw_storvsc, OID_AUTO, use_pim_unmapped, CTLFLAG_RDTUN,
- &hv_storvsc_use_pim_unmapped, 0,
- "Optimize storvsc by using unmapped I/O");
+SYSCTL_UINT(_hw_storvsc, OID_AUTO, use_pim_unmapped, CTLFLAG_RDTUN,
+ &hv_storvsc_use_pim_unmapped, 0,
+ "Optimize storvsc by using unmapped I/O");
+
+static u_int hv_storvsc_ringbuffer_size = (64 * PAGE_SIZE);
+SYSCTL_UINT(_hw_storvsc, OID_AUTO, ringbuffer_size, CTLFLAG_RDTUN,
+ &hv_storvsc_ringbuffer_size, 0, "Hyper-V storage ringbuffer size");
+
+static u_int hv_storvsc_max_io = 512;
+SYSCTL_UINT(_hw_storvsc, OID_AUTO, max_io, CTLFLAG_RDTUN,
+ &hv_storvsc_max_io, 0, "Hyper-V storage max io limit");
+
+#define STORVSC_MAX_IO \
+ vmbus_chan_prplist_nelem(hv_storvsc_ringbuffer_size, \
+ STORVSC_DATA_SEGCNT_MAX, VSTOR_PKT_SIZE)
struct hv_storvsc_sysctl {
u_long data_bio_cnt;
u_long data_vaddr_cnt;
u_long data_sg_cnt;
+ u_long chan_send_cnt[MAXCPU];
};
struct storvsc_gpa_range {
@@ -184,10 +198,18 @@
device_t hs_dev;
bus_dma_tag_t storvsc_req_dtag;
struct hv_storvsc_sysctl sysctl_data;
-
- struct vmbus_channel *hs_cpu2chan[MAXCPU];
+ uint32_t hs_nchan;
+ struct vmbus_channel *hs_sel_chan[MAXCPU];
};
+/*
+ * The size of the vmscsi_request has changed in win8. The
+ * additional size is for the newly added elements in the
+ * structure. These elements are valid only when we are talking
+ * to a win8 host.
+ * Track the correct size we need to apply.
+ */
+static int vmscsi_size_delta = sizeof(struct vmscsi_win8_extension);
/**
* HyperV storvsc timeout testing cases:
@@ -211,7 +233,7 @@
char *drv_name;
char *drv_desc;
uint8_t drv_max_luns_per_target;
- uint8_t drv_max_ios_per_target;
+ uint32_t drv_max_ios_per_target;
uint32_t drv_ringbuffer_size;
};
@@ -240,10 +262,10 @@
static struct storvsc_driver_props g_drv_props_table[] = {
{"blkvsc", "Hyper-V IDE Storage Interface",
BLKVSC_MAX_IDE_DISKS_PER_TARGET, BLKVSC_MAX_IO_REQUESTS,
- STORVSC_RINGBUFFER_SIZE},
+ 20*PAGE_SIZE},
{"storvsc", "Hyper-V SCSI Storage Interface",
STORVSC_MAX_LUNS_PER_TARGET, STORVSC_MAX_IO_REQUESTS,
- STORVSC_RINGBUFFER_SIZE}
+ 20*PAGE_SIZE}
};
/*
@@ -253,14 +275,6 @@
static int sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE;
/*
- * The size of the vmscsi_request has changed in win8. The
- * additional size is for the newly added elements in the
- * structure. These elements are valid only when we are talking
- * to a win8 host.
- * Track the correct size we need to apply.
- */
-static int vmscsi_size_delta;
-/*
* The storage protocol version is determined during the
* initial exchange with the host. It will indicate which
* storage functionality is available in the host.
@@ -413,6 +427,9 @@
return;
}
+ /* Update channel count */
+ sc->hs_nchan = request_channels_cnt + 1;
+
/* Wait for sub-channels setup to complete. */
subchan = vmbus_subchan_get(sc->hs_chan, request_channels_cnt);
@@ -585,7 +602,6 @@
*/
if (support_multichannel)
storvsc_send_multichannel_request(sc, max_chans);
-
cleanup:
sema_destroy(&request->synch_sema);
return (ret);
@@ -624,7 +640,6 @@
}
ret = hv_storvsc_channel_init(sc);
-
return (ret);
}
@@ -686,7 +701,7 @@
{
struct vstor_packet *vstor_packet = &request->vstor_packet;
struct vmbus_channel* outgoing_channel = NULL;
- int ret = 0;
+ int ret = 0, ch_sel;
vstor_packet->flags |= REQUEST_COMPLETION_FLAG;
@@ -699,7 +714,8 @@
vstor_packet->operation = VSTOR_OPERATION_EXECUTESRB;
- outgoing_channel = sc->hs_cpu2chan[curcpu];
+ ch_sel = (vstor_packet->u.vm_srb.lun + curcpu) % sc->hs_nchan;
+ outgoing_channel = sc->hs_sel_chan[ch_sel];
mtx_unlock(&request->softc->hs_lock);
if (request->prp_list.gpa_range.gpa_len) {
@@ -711,6 +727,10 @@
VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC,
vstor_packet, VSTOR_PKT_SIZE, (uint64_t)(uintptr_t)request);
}
+ /* statistic for successful request sending on each channel */
+ if (!ret) {
+ sc->sysctl_data.chan_send_cnt[ch_sel]++;
+ }
mtx_lock(&request->softc->hs_lock);
if (ret != 0) {
@@ -906,17 +926,20 @@
}
static void
-storvsc_create_cpu2chan(struct storvsc_softc *sc)
+storvsc_create_chan_sel(struct storvsc_softc *sc)
{
- int cpu;
+ struct vmbus_channel **subch;
+ int i, nsubch;
- CPU_FOREACH(cpu) {
- sc->hs_cpu2chan[cpu] = vmbus_chan_cpu2chan(sc->hs_chan, cpu);
- if (bootverbose) {
- device_printf(sc->hs_dev, "cpu%d -> chan%u\n",
- cpu, vmbus_chan_id(sc->hs_cpu2chan[cpu]));
- }
- }
+ sc->hs_sel_chan[0] = sc->hs_chan;
+ nsubch = sc->hs_nchan - 1;
+ if (nsubch == 0)
+ return;
+
+ subch = vmbus_subchan_get(sc->hs_chan, nsubch);
+ for (i = 0; i < nsubch; i++)
+ sc->hs_sel_chan[i + 1] = subch[i];
+ vmbus_subchan_rel(subch, nsubch);
}
static int
@@ -976,7 +999,10 @@
{
struct sysctl_oid_list *child;
struct sysctl_ctx_list *ctx;
+ struct sysctl_oid *ch_tree, *chid_tree;
struct storvsc_softc *sc;
+ char name[16];
+ int i;
sc = device_get_softc(dev);
ctx = device_get_sysctl_ctx(dev);
@@ -988,6 +1014,28 @@
&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");
+
+ /* dev.storvsc.UNIT.channel */
+ ch_tree = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "channel",
+ CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "");
+ if (ch_tree == NULL)
+ return;
+
+ for (i = 0; i < sc->hs_nchan; i++) {
+ uint32_t ch_id;
+
+ ch_id = vmbus_chan_id(sc->hs_sel_chan[i]);
+ snprintf(name, sizeof(name), "%d", ch_id);
+ /* dev.storvsc.UNIT.channel.CHID */
+ chid_tree = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(ch_tree),
+ OID_AUTO, name, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "");
+ if (chid_tree == NULL)
+ return;
+ /* dev.storvsc.UNIT.channel.CHID.send_req */
+ SYSCTL_ADD_ULONG(ctx, SYSCTL_CHILDREN(chid_tree), OID_AUTO,
+ "send_req", CTLFLAG_RD, &sc->sysctl_data.chan_send_cnt[i],
+ "# of request sending from this channel");
+ }
}
/**
@@ -1018,6 +1066,7 @@
root_mount_token = root_mount_hold("storvsc");
sc = device_get_softc(dev);
+ sc->hs_nchan = 1;
sc->hs_chan = vmbus_get_channel(dev);
stor_type = storvsc_get_storage_type(dev);
@@ -1029,7 +1078,14 @@
/* fill in driver specific properties */
sc->hs_drv_props = &g_drv_props_table[stor_type];
-
+ sc->hs_drv_props->drv_ringbuffer_size = hv_storvsc_ringbuffer_size;
+ sc->hs_drv_props->drv_max_ios_per_target =
+ MIN(STORVSC_MAX_IO, hv_storvsc_max_io);
+ if (bootverbose) {
+ printf("storvsc ringbuffer size: %d, max_io: %d\n",
+ sc->hs_drv_props->drv_ringbuffer_size,
+ sc->hs_drv_props->drv_max_ios_per_target);
+ }
/* fill in device specific properties */
sc->hs_unit = device_get_unit(dev);
sc->hs_dev = dev;
@@ -1051,7 +1107,7 @@
* STORVSC_DATA_SEGCNT_MAX segments, each
* segment has one page buffer
*/
- for (i = 0; i < STORVSC_MAX_IO_REQUESTS; i++) {
+ for (i = 0; i < sc->hs_drv_props->drv_max_ios_per_target; i++) {
sgl_node = malloc(sizeof(struct hv_sgl_node),
M_DEVBUF, M_WAITOK|M_ZERO);
@@ -1082,7 +1138,7 @@
}
/* Construct cpu to channel mapping */
- storvsc_create_cpu2chan(sc);
+ storvsc_create_chan_sel(sc);
/*
* Create the device queue.
@@ -1839,19 +1895,37 @@
csio->cdb_len);
}
+ if (hv_storvsc_use_win8ext_flags) {
+ reqp->vstor_packet.u.vm_srb.win8_extension.time_out_value = 60;
+ reqp->vstor_packet.u.vm_srb.win8_extension.srb_flags |=
+ SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
+ }
switch (ccb->ccb_h.flags & CAM_DIR_MASK) {
case CAM_DIR_OUT:
- reqp->vstor_packet.u.vm_srb.data_in = WRITE_TYPE;
+ reqp->vstor_packet.u.vm_srb.data_in = WRITE_TYPE;
+ if (hv_storvsc_use_win8ext_flags) {
+ reqp->vstor_packet.u.vm_srb.win8_extension.srb_flags |=
+ SRB_FLAGS_DATA_OUT;
+ }
break;
case CAM_DIR_IN:
reqp->vstor_packet.u.vm_srb.data_in = READ_TYPE;
+ if (hv_storvsc_use_win8ext_flags) {
+ reqp->vstor_packet.u.vm_srb.win8_extension.srb_flags |=
+ SRB_FLAGS_DATA_IN;
+ }
break;
case CAM_DIR_NONE:
reqp->vstor_packet.u.vm_srb.data_in = UNKNOWN_TYPE;
+ if (hv_storvsc_use_win8ext_flags) {
+ reqp->vstor_packet.u.vm_srb.win8_extension.srb_flags |=
+ SRB_FLAGS_NO_DATA_TRANSFER;
+ }
break;
default:
- reqp->vstor_packet.u.vm_srb.data_in = UNKNOWN_TYPE;
- break;
+ printf("Error: unexpected data direction: 0x%x\n",
+ ccb->ccb_h.flags & CAM_DIR_MASK);
+ return (EINVAL);
}
reqp->sense_data = &csio->sense_data;
Index: head/sys/dev/hyperv/storvsc/hv_vstorage.h
===================================================================
--- head/sys/dev/hyperv/storvsc/hv_vstorage.h
+++ head/sys/dev/hyperv/storvsc/hv_vstorage.h
@@ -253,6 +253,22 @@
#define SRB_STATUS_AUTOSENSE_VALID 0x80
#define SRB_STATUS_INVALID_LUN 0X20
+/*
+ * SRB Flag Bits
+ */
+
+#define SRB_FLAGS_QUEUE_ACTION_ENABLE 0x00000002
+#define SRB_FLAGS_DISABLE_DISCONNECT 0x00000004
+#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER 0x00000008
+#define SRB_FLAGS_BYPASS_FROZEN_QUEUE 0x00000010
+#define SRB_FLAGS_DISABLE_AUTOSENSE 0x00000020
+#define SRB_FLAGS_DATA_IN 0x00000040
+#define SRB_FLAGS_DATA_OUT 0x00000080
+#define SRB_FLAGS_NO_DATA_TRANSFER 0x00000000
+#define SRB_FLAGS_UNSPECIFIED_DIRECTION (SRB_FLAGS_DATA_IN | SRB_FLAGS_DATA_OUT)
+#define SRB_FLAGS_NO_QUEUE_FREEZE 0x00000100
+#define SRB_FLAGS_ADAPTER_CACHE_ENABLE 0x00000200
+#define SRB_FLAGS_FREE_SENSE_BUFFER 0x00000400
/**
* Packet flags
*/
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Dec 15, 4:50 AM (21 h, 14 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
9091421
Default Alt Text
D7622.diff (10 KB)
Attached To
Mode
D7622: hyperv/storvsc: tune storage performance by changing io max and channel selection
Attached
Detach File
Event Timeline
Log In to Comment