Page MenuHomeFreeBSD

D7622.diff
No OneTemporary

D7622.diff

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

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)

Event Timeline