svn commit: r302701 - head/sys/dev/hyperv/storvsc
Sepherosa Ziehau
sephe at FreeBSD.org
Wed Jul 13 05:28:09 UTC 2016
Author: sephe
Date: Wed Jul 13 05:28:07 2016
New Revision: 302701
URL: https://svnweb.freebsd.org/changeset/base/302701
Log:
hyperv/stor: Avoid the hv_device and nuke the broken get_stor_device
This paves way to nuke the hv_device, which is actually an unncessary
indirection.
MFC after: 1 week
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D7027
Modified:
head/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
Modified: head/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
==============================================================================
--- head/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c Wed Jul 13 05:19:45 2016 (r302700)
+++ head/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c Wed Jul 13 05:28:07 2016 (r302701)
@@ -125,7 +125,7 @@ struct hv_storvsc_request {
};
struct storvsc_softc {
- struct hv_device *hs_dev;
+ struct hv_vmbus_channel *hs_chan;
LIST_HEAD(, hv_storvsc_request) hs_free_list;
struct mtx hs_lock;
struct storvsc_driver_props *hs_drv_props;
@@ -139,6 +139,7 @@ struct storvsc_softc {
struct sema hs_drain_sema;
struct hv_storvsc_request hs_init_req;
struct hv_storvsc_request hs_reset_req;
+ device_t hs_dev;
};
@@ -264,11 +265,11 @@ static int create_storvsc_request(union
static void storvsc_free_request(struct storvsc_softc *sc, struct hv_storvsc_request *reqp);
static enum hv_storage_type storvsc_get_storage_type(device_t dev);
static void hv_storvsc_rescan_target(struct storvsc_softc *sc);
-static void hv_storvsc_on_channel_callback(void *context);
+static void hv_storvsc_on_channel_callback(void *xchan);
static void hv_storvsc_on_iocompletion( struct storvsc_softc *sc,
struct vstor_packet *vstor_packet,
struct hv_storvsc_request *request);
-static int hv_storvsc_connect_vsp(struct hv_device *device);
+static int hv_storvsc_connect_vsp(struct storvsc_softc *);
static void storvsc_io_done(struct hv_storvsc_request *reqp);
static void storvsc_copy_sgl_to_bounce_buf(struct sglist *bounce_sgl,
bus_dma_segment_t *orig_sgl,
@@ -297,72 +298,16 @@ DRIVER_MODULE(storvsc, vmbus, storvsc_dr
MODULE_VERSION(storvsc, 1);
MODULE_DEPEND(storvsc, vmbus, 1, 1, 1);
-
-/**
- * The host is capable of sending messages to us that are
- * completely unsolicited. So, we need to address the race
- * condition where we may be in the process of unloading the
- * driver when the host may send us an unsolicited message.
- * We address this issue by implementing a sequentially
- * consistent protocol:
- *
- * 1. Channel callback is invoked while holding the channel lock
- * and an unloading driver will reset the channel callback under
- * the protection of this channel lock.
- *
- * 2. To ensure bounded wait time for unloading a driver, we don't
- * permit outgoing traffic once the device is marked as being
- * destroyed.
- *
- * 3. Once the device is marked as being destroyed, we only
- * permit incoming traffic to properly account for
- * packets already sent out.
- */
-static inline struct storvsc_softc *
-get_stor_device(struct hv_device *device,
- boolean_t outbound)
-{
- struct storvsc_softc *sc;
-
- sc = device_get_softc(device->device);
-
- if (outbound) {
- /*
- * Here we permit outgoing I/O only
- * if the device is not being destroyed.
- */
-
- if (sc->hs_destroy) {
- sc = NULL;
- }
- } else {
- /*
- * inbound case; if being destroyed
- * only permit to account for
- * messages already sent out.
- */
- if (sc->hs_destroy && (sc->hs_num_out_reqs == 0)) {
- sc = NULL;
- }
- }
- return sc;
-}
-
static void
-storvsc_subchan_attach(struct hv_vmbus_channel *new_channel)
+storvsc_subchan_attach(struct storvsc_softc *sc,
+ struct hv_vmbus_channel *new_channel)
{
- struct hv_device *device;
- struct storvsc_softc *sc;
struct vmstor_chan_props props;
int ret = 0;
- device = new_channel->device;
- sc = get_stor_device(device, TRUE);
- if (sc == NULL)
- return;
-
memset(&props, 0, sizeof(props));
+ new_channel->hv_chan_priv1 = sc;
vmbus_channel_cpu_rr(new_channel);
ret = hv_vmbus_channel_open(new_channel,
sc->hs_drv_props->drv_ringbuffer_size,
@@ -371,8 +316,6 @@ storvsc_subchan_attach(struct hv_vmbus_c
sizeof(struct vmstor_chan_props),
hv_storvsc_on_channel_callback,
new_channel);
-
- return;
}
/**
@@ -382,10 +325,9 @@ storvsc_subchan_attach(struct hv_vmbus_c
* @param max_chans the max channels supported by vmbus
*/
static void
-storvsc_send_multichannel_request(struct hv_device *dev, int max_chans)
+storvsc_send_multichannel_request(struct storvsc_softc *sc, int max_chans)
{
struct hv_vmbus_channel **subchan;
- struct storvsc_softc *sc;
struct hv_storvsc_request *request;
struct vstor_packet *vstor_packet;
int request_channels_cnt = 0;
@@ -394,13 +336,6 @@ storvsc_send_multichannel_request(struct
/* get multichannels count that need to create */
request_channels_cnt = MIN(max_chans, mp_ncpus);
- sc = get_stor_device(dev, TRUE);
- if (sc == NULL) {
- printf("Storvsc_error: get sc failed while send mutilchannel "
- "request\n");
- return;
- }
-
request = &sc->hs_init_req;
/* request the host to create multi-channel */
@@ -415,7 +350,7 @@ storvsc_send_multichannel_request(struct
vstor_packet->u.multi_channels_cnt = request_channels_cnt;
ret = hv_vmbus_channel_send_packet(
- dev->channel,
+ sc->hs_chan,
vstor_packet,
VSTOR_PKT_SIZE,
(uint64_t)(uintptr_t)request,
@@ -439,11 +374,11 @@ storvsc_send_multichannel_request(struct
}
/* Wait for sub-channels setup to complete. */
- subchan = vmbus_get_subchan(dev->channel, request_channels_cnt);
+ subchan = vmbus_get_subchan(sc->hs_chan, request_channels_cnt);
/* Attach the sub-channels. */
for (i = 0; i < request_channels_cnt; ++i)
- storvsc_subchan_attach(subchan[i]);
+ storvsc_subchan_attach(sc, subchan[i]);
/* Release the sub-channels. */
vmbus_rel_subchan(subchan, request_channels_cnt);
@@ -459,12 +394,11 @@ storvsc_send_multichannel_request(struct
* @returns 0 on success, non-zero error on failure
*/
static int
-hv_storvsc_channel_init(struct hv_device *dev)
+hv_storvsc_channel_init(struct storvsc_softc *sc)
{
int ret = 0, i;
struct hv_storvsc_request *request;
struct vstor_packet *vstor_packet;
- struct storvsc_softc *sc;
uint16_t max_chans = 0;
boolean_t support_multichannel = FALSE;
uint32_t version;
@@ -472,10 +406,6 @@ hv_storvsc_channel_init(struct hv_device
max_chans = 0;
support_multichannel = FALSE;
- sc = get_stor_device(dev, TRUE);
- if (sc == NULL)
- return (ENODEV);
-
request = &sc->hs_init_req;
memset(request, 0, sizeof(struct hv_storvsc_request));
vstor_packet = &request->vstor_packet;
@@ -491,7 +421,7 @@ hv_storvsc_channel_init(struct hv_device
ret = hv_vmbus_channel_send_packet(
- dev->channel,
+ sc->hs_chan,
vstor_packet,
VSTOR_PKT_SIZE,
(uint64_t)(uintptr_t)request,
@@ -525,7 +455,7 @@ hv_storvsc_channel_init(struct hv_device
vstor_packet->u.version.revision = 0;
ret = hv_vmbus_channel_send_packet(
- dev->channel,
+ sc->hs_chan,
vstor_packet,
VSTOR_PKT_SIZE,
(uint64_t)(uintptr_t)request,
@@ -568,7 +498,7 @@ hv_storvsc_channel_init(struct hv_device
vstor_packet->flags = REQUEST_COMPLETION_FLAG;
ret = hv_vmbus_channel_send_packet(
- dev->channel,
+ sc->hs_chan,
vstor_packet,
VSTOR_PKT_SIZE,
(uint64_t)(uintptr_t)request,
@@ -592,8 +522,7 @@ hv_storvsc_channel_init(struct hv_device
/* multi-channels feature is supported by WIN8 and above version */
max_chans = vstor_packet->u.chan_props.max_channel_cnt;
- version = VMBUS_GET_VERSION(device_get_parent(dev->device),
- dev->device);
+ version = VMBUS_GET_VERSION(device_get_parent(sc->hs_dev), sc->hs_dev);
if (version != VMBUS_VERSION_WIN7 && version != VMBUS_VERSION_WS2008 &&
(vstor_packet->u.chan_props.flags &
HV_STORAGE_SUPPORTS_MULTI_CHANNEL)) {
@@ -605,7 +534,7 @@ hv_storvsc_channel_init(struct hv_device
vstor_packet->flags = REQUEST_COMPLETION_FLAG;
ret = hv_vmbus_channel_send_packet(
- dev->channel,
+ sc->hs_chan,
vstor_packet,
VSTOR_PKT_SIZE,
(uint64_t)(uintptr_t)request,
@@ -631,7 +560,7 @@ hv_storvsc_channel_init(struct hv_device
* request to host.
*/
if (support_multichannel)
- storvsc_send_multichannel_request(dev, max_chans);
+ storvsc_send_multichannel_request(sc, max_chans);
cleanup:
sema_destroy(&request->synch_sema);
@@ -647,53 +576,45 @@ cleanup:
* @returns 0 on success, non-zero error on failure
*/
static int
-hv_storvsc_connect_vsp(struct hv_device *dev)
+hv_storvsc_connect_vsp(struct storvsc_softc *sc)
{
int ret = 0;
struct vmstor_chan_props props;
- struct storvsc_softc *sc;
- sc = device_get_softc(dev->device);
-
memset(&props, 0, sizeof(struct vmstor_chan_props));
/*
* Open the channel
*/
- vmbus_channel_cpu_rr(dev->channel);
+ KASSERT(sc->hs_chan->hv_chan_priv1 == sc, ("invalid chan priv1"));
+ vmbus_channel_cpu_rr(sc->hs_chan);
ret = hv_vmbus_channel_open(
- dev->channel,
+ sc->hs_chan,
sc->hs_drv_props->drv_ringbuffer_size,
sc->hs_drv_props->drv_ringbuffer_size,
(void *)&props,
sizeof(struct vmstor_chan_props),
hv_storvsc_on_channel_callback,
- dev->channel);
+ sc->hs_chan);
if (ret != 0) {
return ret;
}
- ret = hv_storvsc_channel_init(dev);
+ ret = hv_storvsc_channel_init(sc);
return (ret);
}
#if HVS_HOST_RESET
static int
-hv_storvsc_host_reset(struct hv_device *dev)
+hv_storvsc_host_reset(struct storvsc_softc *sc)
{
int ret = 0;
- struct storvsc_softc *sc;
struct hv_storvsc_request *request;
struct vstor_packet *vstor_packet;
- sc = get_stor_device(dev, TRUE);
- if (sc == NULL) {
- return ENODEV;
- }
-
request = &sc->hs_reset_req;
request->softc = sc;
vstor_packet = &request->vstor_packet;
@@ -740,20 +661,13 @@ cleanup:
* @returns 0 on success, non-zero error on failure
*/
static int
-hv_storvsc_io_request(struct hv_device *device,
+hv_storvsc_io_request(struct storvsc_softc *sc,
struct hv_storvsc_request *request)
{
- struct storvsc_softc *sc;
struct vstor_packet *vstor_packet = &request->vstor_packet;
struct hv_vmbus_channel* outgoing_channel = NULL;
int ret = 0;
- sc = get_stor_device(device, TRUE);
-
- if (sc == NULL) {
- return ENODEV;
- }
-
vstor_packet->flags |= REQUEST_COMPLETION_FLAG;
vstor_packet->u.vm_srb.length = VSTOR_PKT_SIZE;
@@ -764,7 +678,7 @@ hv_storvsc_io_request(struct hv_device *
vstor_packet->operation = VSTOR_OPERATION_EXECUTESRB;
- outgoing_channel = vmbus_select_outgoing_channel(device->channel);
+ outgoing_channel = vmbus_select_outgoing_channel(sc->hs_chan);
mtx_unlock(&request->softc->hs_lock);
if (request->data_buf.length) {
@@ -875,27 +789,17 @@ hv_storvsc_rescan_target(struct storvsc_
}
static void
-hv_storvsc_on_channel_callback(void *context)
+hv_storvsc_on_channel_callback(void *xchan)
{
int ret = 0;
- hv_vmbus_channel *channel = (hv_vmbus_channel *)context;
- struct hv_device *device = NULL;
- struct storvsc_softc *sc;
+ hv_vmbus_channel *channel = xchan;
+ struct storvsc_softc *sc = channel->hv_chan_priv1;
uint32_t bytes_recvd;
uint64_t request_id;
uint8_t packet[roundup2(sizeof(struct vstor_packet), 8)];
struct hv_storvsc_request *request;
struct vstor_packet *vstor_packet;
- device = channel->device;
- KASSERT(device, ("device is NULL"));
-
- sc = get_stor_device(device, FALSE);
- if (sc == NULL) {
- printf("Storvsc_error: get stor device failed.\n");
- return;
- }
-
ret = hv_vmbus_channel_recv_packet(
channel,
packet,
@@ -999,7 +903,6 @@ storvsc_probe(device_t dev)
static int
storvsc_attach(device_t dev)
{
- struct hv_device *hv_dev = vmbus_get_devctx(dev);
enum hv_storage_type stor_type;
struct storvsc_softc *sc;
struct cam_devq *devq;
@@ -1015,6 +918,8 @@ storvsc_attach(device_t dev)
root_mount_token = root_mount_hold("storvsc");
sc = device_get_softc(dev);
+ sc->hs_chan = vmbus_get_channel(dev);
+ sc->hs_chan->hv_chan_priv1 = sc;
stor_type = storvsc_get_storage_type(dev);
@@ -1028,7 +933,7 @@ storvsc_attach(device_t dev)
/* fill in device specific properties */
sc->hs_unit = device_get_unit(dev);
- sc->hs_dev = hv_dev;
+ sc->hs_dev = dev;
LIST_INIT(&sc->hs_free_list);
mtx_init(&sc->hs_lock, "hvslck", NULL, MTX_DEF);
@@ -1077,7 +982,7 @@ storvsc_attach(device_t dev)
sc->hs_drain_notify = FALSE;
sema_init(&sc->hs_drain_sema, 0, "Store Drain Sema");
- ret = hv_storvsc_connect_vsp(hv_dev);
+ ret = hv_storvsc_connect_vsp(sc);
if (ret != 0) {
goto cleanup;
}
@@ -1175,7 +1080,6 @@ storvsc_detach(device_t dev)
{
struct storvsc_softc *sc = device_get_softc(dev);
struct hv_storvsc_request *reqp = NULL;
- struct hv_device *hv_device = vmbus_get_devctx(dev);
struct hv_sgl_node *sgl_node = NULL;
int j = 0;
@@ -1197,7 +1101,7 @@ storvsc_detach(device_t dev)
* under the protection of the incoming channel lock.
*/
- hv_vmbus_channel_close(hv_device->channel);
+ hv_vmbus_channel_close(sc->hs_chan);
mtx_lock(&sc->hs_lock);
while (!LIST_EMPTY(&sc->hs_free_list)) {
@@ -1251,7 +1155,7 @@ storvsc_timeout_test(struct hv_storvsc_r
if (wait) {
mtx_lock(&reqp->event.mtx);
}
- ret = hv_storvsc_io_request(sc->hs_dev, reqp);
+ ret = hv_storvsc_io_request(sc, reqp);
if (ret != 0) {
if (wait) {
mtx_unlock(&reqp->event.mtx);
@@ -1362,7 +1266,7 @@ storvsc_poll(struct cam_sim *sim)
mtx_assert(&sc->hs_lock, MA_OWNED);
mtx_unlock(&sc->hs_lock);
- hv_storvsc_on_channel_callback(sc->hs_dev->channel);
+ hv_storvsc_on_channel_callback(sc->hs_chan);
mtx_lock(&sc->hs_lock);
}
@@ -1447,7 +1351,7 @@ storvsc_action(struct cam_sim *sim, unio
case XPT_RESET_BUS:
case XPT_RESET_DEV:{
#if HVS_HOST_RESET
- if ((res = hv_storvsc_host_reset(sc->hs_dev)) != 0) {
+ if ((res = hv_storvsc_host_reset(sc)) != 0) {
xpt_print(ccb->ccb_h.path,
"hv_storvsc_host_reset failed with %d\n", res);
ccb->ccb_h.status = CAM_PROVIDE_FAIL;
@@ -1520,7 +1424,7 @@ storvsc_action(struct cam_sim *sim, unio
}
#endif
- if ((res = hv_storvsc_io_request(sc->hs_dev, reqp)) != 0) {
+ if ((res = hv_storvsc_io_request(sc, reqp)) != 0) {
xpt_print(ccb->ccb_h.path,
"hv_storvsc_io_request failed with %d\n", res);
ccb->ccb_h.status = CAM_PROVIDE_FAIL;
More information about the svn-src-head
mailing list