Page MenuHomeFreeBSD

D7622.id19615.diff
No OneTemporary

D7622.id19615.diff

Index: sys/dev/hyperv/include/vmbus.h
===================================================================
--- sys/dev/hyperv/include/vmbus.h
+++ sys/dev/hyperv/include/vmbus.h
@@ -134,6 +134,8 @@
struct vmbus_channel *
vmbus_chan_cpu2chan(struct vmbus_channel *chan, int cpu);
void vmbus_chan_set_readbatch(struct vmbus_channel *chan, bool on);
+int vmbus_chan_array(struct vmbus_channel *pri_chan,
+ struct vmbus_channel **chan_array, int array_max_len);
struct vmbus_channel **
vmbus_subchan_get(struct vmbus_channel *pri_chan,
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
@@ -75,11 +75,10 @@
#include <dev/hyperv/include/hyperv.h>
#include <dev/hyperv/include/vmbus.h>
-
+#include <dev/hyperv/vmbus/vmbus_reg.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 +120,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,
@@ -132,11 +129,28 @@
SYSCTL_NODE(_hw, OID_AUTO, storvsc, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL,
"Hyper-V storage interface");
+static u_int hv_storvsc_use_win8ext_flags = 1;
+SYSCTL_INT(_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");
+static u_int hv_storvsc_ringbuffer_size = (64 * PAGE_SIZE);
+SYSCTL_INT(_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_INT(_hw_storvsc, OID_AUTO, max_io, CTLFLAG_RDTUN,
+ &hv_storvsc_max_io, 0, "Hyper-V storage max io limit");
+
+#define STORVSC_MAX_IO \
+ (hv_storvsc_ringbuffer_size - PAGE_SIZE) / \
+ MAX_SIZE_BUFRING_ITEM(STORVSC_DATA_SEGCNT_MAX, \
+ VSTOR_PKT_SIZE)
struct hv_storvsc_sysctl {
u_long data_bio_cnt;
u_long data_vaddr_cnt;
@@ -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_lun2chan[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.
@@ -687,6 +701,7 @@
struct vstor_packet *vstor_packet = &request->vstor_packet;
struct vmbus_channel* outgoing_channel = NULL;
int ret = 0;
+ int 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;
+ outgoing_channel = sc->hs_lun2chan[ch_sel % sc->hs_nchan];
mtx_unlock(&request->softc->hs_lock);
if (request->prp_list.gpa_range.gpa_len) {
@@ -906,17 +922,10 @@
}
static void
-storvsc_create_cpu2chan(struct storvsc_softc *sc)
+storvsc_create_lun2chan(struct storvsc_softc *sc)
{
- int cpu;
-
- 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]));
- }
- }
+ int nchan = vmbus_chan_array(sc->hs_chan, sc->hs_lun2chan, MAXCPU);
+ sc->hs_nchan = nchan;
}
static int
@@ -1029,7 +1038,15 @@
/* 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 =
+ STORVSC_MAX_IO > hv_storvsc_max_io ?
+ hv_storvsc_max_io : 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 +1068,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 +1099,7 @@
}
/* Construct cpu to channel mapping */
- storvsc_create_cpu2chan(sc);
+ storvsc_create_lun2chan(sc);
/*
* Create the device queue.
@@ -1839,18 +1856,39 @@
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_DATA_IN;
+ }
break;
default:
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_DATA_IN;
+ }
break;
}
Index: sys/dev/hyperv/storvsc/hv_vstorage.h
===================================================================
--- sys/dev/hyperv/storvsc/hv_vstorage.h
+++ 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
*/
Index: sys/dev/hyperv/vmbus/vmbus_chan.c
===================================================================
--- sys/dev/hyperv/vmbus/vmbus_chan.c
+++ sys/dev/hyperv/vmbus/vmbus_chan.c
@@ -173,6 +173,9 @@
SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(chid_tree), OID_AUTO,
"cpu", CTLFLAG_RD, &chan->ch_cpuid, 0, "owner CPU id");
+ SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(chid_tree), OID_AUTO,
+ "send", CTLFLAG_RD, &chan->ch_stat_send_nreq, 0,
+ "requests sent from this channel");
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(chid_tree), OID_AUTO,
"mnf", CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
chan, 0, vmbus_chan_sysctl_mnf, "I",
@@ -629,6 +632,10 @@
error = vmbus_txbr_write(&chan->ch_txbr, iov, 3, &send_evt);
if (!error && send_evt)
vmbus_chan_signal_tx(chan);
+ // statistc for this channel
+ if (!error) {
+ chan->ch_stat_send_nreq++;
+ }
return error;
}
@@ -668,6 +675,10 @@
error = vmbus_txbr_write(&chan->ch_txbr, iov, 4, &send_evt);
if (!error && send_evt)
vmbus_chan_signal_tx(chan);
+ // statistc for this channel
+ if (!error) {
+ chan->ch_stat_send_nreq++;
+ }
return error;
}
@@ -709,6 +720,10 @@
error = vmbus_txbr_write(&chan->ch_txbr, iov, 4, &send_evt);
if (!error && send_evt)
vmbus_chan_signal_tx(chan);
+ // statistc for this channel
+ if (!error) {
+ chan->ch_stat_send_nreq++;
+ }
return error;
}
@@ -1314,6 +1329,30 @@
return sel;
}
+int
+vmbus_chan_array(struct vmbus_channel *pri_chan,
+ struct vmbus_channel **chan_array, int array_max_len)
+{
+ struct vmbus_channel *chan;
+ int nchan = 0;
+ chan_array[nchan++] = pri_chan;
+
+ if (TAILQ_EMPTY(&pri_chan->ch_subchans)) {
+ return nchan;
+ }
+ mtx_lock(&pri_chan->ch_subchan_lock);
+ TAILQ_FOREACH(chan, &pri_chan->ch_subchans, ch_sublink) {
+ KASSERT(chan->ch_stflags & VMBUS_CHAN_ST_OPENED,
+ ("chan%u is not opened", chan->ch_id));
+ KASSERT(nchan + 1 < array_max_len,
+ ("channel array's capacity %d is reached\n",
+ array_max_len));
+ chan_array[nchan++] = chan;
+ }
+ mtx_unlock(&pri_chan->ch_subchan_lock);
+ return nchan;
+}
+
struct vmbus_channel **
vmbus_subchan_get(struct vmbus_channel *pri_chan, int subchan_cnt)
{
Index: sys/dev/hyperv/vmbus/vmbus_chanvar.h
===================================================================
--- sys/dev/hyperv/vmbus/vmbus_chanvar.h
+++ sys/dev/hyperv/vmbus/vmbus_chanvar.h
@@ -89,7 +89,7 @@
volatile u_long *ch_evtflag; /* event flag loc. */
/*
- * Rarely used fields.
+ * Rarepy used fields.
*/
struct hyperv_mon_param *ch_monprm;
@@ -133,6 +133,7 @@
struct hyperv_guid ch_guid_inst;
struct sysctl_ctx_list ch_sysctl_ctx;
+ u_int ch_stat_send_nreq;
} __aligned(CACHE_LINE_SIZE);
#define VMBUS_CHAN_ISPRIMARY(chan) ((chan)->ch_subidx == 0)
Index: sys/dev/hyperv/vmbus/vmbus_reg.h
===================================================================
--- sys/dev/hyperv/vmbus/vmbus_reg.h
+++ sys/dev/hyperv/vmbus/vmbus_reg.h
@@ -171,6 +171,10 @@
struct vmbus_gpa_range cp_range[];
} __packed;
+#define MAX_SIZE_BUFRING_ITEM(GPA_PAGE_CNT, SRB_SIZE) \
+ (roundup2(__offsetof(struct vmbus_chanpkt_prplist, \
+ cp_range[0].gpa_page[GPA_PAGE_CNT]) + SRB_SIZE, \
+ VMBUS_CHANPKT_SIZE_ALIGN) + sizeof(uint64_t))
/*
* Channel messages
* - Embedded in vmbus_message.msg_data, e.g. response and notification.

File Metadata

Mime Type
text/plain
Expires
Tue, May 19, 6:24 PM (1 h, 13 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33324911
Default Alt Text
D7622.id19615.diff (11 KB)

Event Timeline