hyperv/hn: Fix detach error handling.
MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D8613
This commit is contained in:
parent
7379c46064
commit
9c0617e0cd
@ -62,8 +62,8 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
static int hn_nvs_conn_chim(struct hn_softc *);
|
||||
static int hn_nvs_conn_rxbuf(struct hn_softc *);
|
||||
static int hn_nvs_disconn_chim(struct hn_softc *);
|
||||
static int hn_nvs_disconn_rxbuf(struct hn_softc *);
|
||||
static void hn_nvs_disconn_chim(struct hn_softc *);
|
||||
static void hn_nvs_disconn_rxbuf(struct hn_softc *);
|
||||
static int hn_nvs_conf_ndis(struct hn_softc *, int);
|
||||
static int hn_nvs_init_ndis(struct hn_softc *);
|
||||
static int hn_nvs_doinit(struct hn_softc *, uint32_t);
|
||||
@ -308,7 +308,7 @@ cleanup:
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
hn_nvs_disconn_rxbuf(struct hn_softc *sc)
|
||||
{
|
||||
int error;
|
||||
@ -328,7 +328,12 @@ hn_nvs_disconn_rxbuf(struct hn_softc *sc)
|
||||
if (error) {
|
||||
if_printf(sc->hn_ifp,
|
||||
"send nvs rxbuf disconn failed: %d\n", error);
|
||||
return (error);
|
||||
/*
|
||||
* Fine for a revoked channel, since the hypervisor
|
||||
* does not drain TX bufring for a revoked channel.
|
||||
*/
|
||||
if (!vmbus_chan_is_revoked(sc->hn_prichan))
|
||||
sc->hn_flags |= HN_FLAG_RXBUF_REF;
|
||||
}
|
||||
sc->hn_flags &= ~HN_FLAG_RXBUF_CONNECTED;
|
||||
|
||||
@ -357,14 +362,13 @@ hn_nvs_disconn_rxbuf(struct hn_softc *sc)
|
||||
if (error) {
|
||||
if_printf(sc->hn_ifp,
|
||||
"rxbuf gpadl disconn failed: %d\n", error);
|
||||
return (error);
|
||||
sc->hn_flags |= HN_FLAG_RXBUF_REF;
|
||||
}
|
||||
sc->hn_rxbuf_gpadl = 0;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
hn_nvs_disconn_chim(struct hn_softc *sc)
|
||||
{
|
||||
int error;
|
||||
@ -384,7 +388,12 @@ hn_nvs_disconn_chim(struct hn_softc *sc)
|
||||
if (error) {
|
||||
if_printf(sc->hn_ifp,
|
||||
"send nvs chim disconn failed: %d\n", error);
|
||||
return (error);
|
||||
/*
|
||||
* Fine for a revoked channel, since the hypervisor
|
||||
* does not drain TX bufring for a revoked channel.
|
||||
*/
|
||||
if (!vmbus_chan_is_revoked(sc->hn_prichan))
|
||||
sc->hn_flags |= HN_FLAG_CHIM_REF;
|
||||
}
|
||||
sc->hn_flags &= ~HN_FLAG_CHIM_CONNECTED;
|
||||
|
||||
@ -414,7 +423,7 @@ hn_nvs_disconn_chim(struct hn_softc *sc)
|
||||
if (error) {
|
||||
if_printf(sc->hn_ifp,
|
||||
"chim gpadl disconn failed: %d\n", error);
|
||||
return (error);
|
||||
sc->hn_flags |= HN_FLAG_CHIM_REF;
|
||||
}
|
||||
sc->hn_chim_gpadl = 0;
|
||||
}
|
||||
@ -423,7 +432,6 @@ hn_nvs_disconn_chim(struct hn_softc *sc)
|
||||
free(sc->hn_chim_bmap, M_DEVBUF);
|
||||
sc->hn_chim_bmap = NULL;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -296,6 +296,7 @@ static int hn_synth_attach(struct hn_softc *, int);
|
||||
static void hn_synth_detach(struct hn_softc *);
|
||||
static int hn_synth_alloc_subchans(struct hn_softc *,
|
||||
int *);
|
||||
static bool hn_synth_attachable(const struct hn_softc *);
|
||||
static void hn_suspend(struct hn_softc *);
|
||||
static void hn_suspend_data(struct hn_softc *);
|
||||
static void hn_suspend_mgmt(struct hn_softc *);
|
||||
@ -3249,7 +3250,10 @@ hn_destroy_rx_data(struct hn_softc *sc)
|
||||
int i;
|
||||
|
||||
if (sc->hn_rxbuf != NULL) {
|
||||
hyperv_dmamem_free(&sc->hn_rxbuf_dma, sc->hn_rxbuf);
|
||||
if ((sc->hn_flags & HN_FLAG_RXBUF_REF) == 0)
|
||||
hyperv_dmamem_free(&sc->hn_rxbuf_dma, sc->hn_rxbuf);
|
||||
else
|
||||
device_printf(sc->hn_dev, "RXBUF is referenced\n");
|
||||
sc->hn_rxbuf = NULL;
|
||||
}
|
||||
|
||||
@ -3261,7 +3265,12 @@ hn_destroy_rx_data(struct hn_softc *sc)
|
||||
|
||||
if (rxr->hn_br == NULL)
|
||||
continue;
|
||||
hyperv_dmamem_free(&rxr->hn_br_dma, rxr->hn_br);
|
||||
if ((rxr->hn_rx_flags & HN_RX_FLAG_BR_REF) == 0) {
|
||||
hyperv_dmamem_free(&rxr->hn_br_dma, rxr->hn_br);
|
||||
} else {
|
||||
device_printf(sc->hn_dev,
|
||||
"%dth channel bufring is referenced", i);
|
||||
}
|
||||
rxr->hn_br = NULL;
|
||||
|
||||
#if defined(INET) || defined(INET6)
|
||||
@ -3730,7 +3739,12 @@ hn_destroy_tx_data(struct hn_softc *sc)
|
||||
int i;
|
||||
|
||||
if (sc->hn_chim != NULL) {
|
||||
hyperv_dmamem_free(&sc->hn_chim_dma, sc->hn_chim);
|
||||
if ((sc->hn_flags & HN_FLAG_CHIM_REF) == 0) {
|
||||
hyperv_dmamem_free(&sc->hn_chim_dma, sc->hn_chim);
|
||||
} else {
|
||||
device_printf(sc->hn_dev,
|
||||
"chimney sending buffer is referenced");
|
||||
}
|
||||
sc->hn_chim = NULL;
|
||||
}
|
||||
|
||||
@ -4214,7 +4228,7 @@ static void
|
||||
hn_chan_detach(struct hn_softc *sc, struct vmbus_channel *chan)
|
||||
{
|
||||
struct hn_rx_ring *rxr;
|
||||
int idx;
|
||||
int idx, error;
|
||||
|
||||
idx = vmbus_chan_subidx(chan);
|
||||
|
||||
@ -4243,7 +4257,16 @@ hn_chan_detach(struct hn_softc *sc, struct vmbus_channel *chan)
|
||||
* NOTE:
|
||||
* Channel closing does _not_ destroy the target channel.
|
||||
*/
|
||||
vmbus_chan_close(chan);
|
||||
error = vmbus_chan_close_direct(chan);
|
||||
if (error == EISCONN) {
|
||||
if_printf(sc->hn_ifp, "chan%u subidx%u "
|
||||
"bufring is connected after being closed\n",
|
||||
vmbus_chan_id(chan), vmbus_chan_subidx(chan));
|
||||
rxr->hn_rx_flags |= HN_RX_FLAG_BR_REF;
|
||||
} else if (error) {
|
||||
if_printf(sc->hn_ifp, "chan%u subidx%u close failed: %d\n",
|
||||
vmbus_chan_id(chan), vmbus_chan_subidx(chan), error);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
@ -4373,6 +4396,23 @@ hn_synth_alloc_subchans(struct hn_softc *sc, int *nsubch)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static bool
|
||||
hn_synth_attachable(const struct hn_softc *sc)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (sc->hn_flags & HN_FLAG_ERRORS)
|
||||
return (false);
|
||||
|
||||
for (i = 0; i < sc->hn_rx_ring_cnt; ++i) {
|
||||
const struct hn_rx_ring *rxr = &sc->hn_rx_ring[i];
|
||||
|
||||
if (rxr->hn_rx_flags & HN_RX_FLAG_BR_REF)
|
||||
return (false);
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
|
||||
static int
|
||||
hn_synth_attach(struct hn_softc *sc, int mtu)
|
||||
{
|
||||
@ -4383,6 +4423,9 @@ hn_synth_attach(struct hn_softc *sc, int mtu)
|
||||
KASSERT((sc->hn_flags & HN_FLAG_SYNTH_ATTACHED) == 0,
|
||||
("synthetic parts were attached"));
|
||||
|
||||
if (!hn_synth_attachable(sc))
|
||||
return (ENXIO);
|
||||
|
||||
/* Save capabilities for later verification. */
|
||||
old_caps = sc->hn_caps;
|
||||
sc->hn_caps = 0;
|
||||
|
@ -91,7 +91,8 @@ struct hn_rx_ring {
|
||||
#define HN_TRUST_HCSUM_TCP 0x0002
|
||||
#define HN_TRUST_HCSUM_UDP 0x0004
|
||||
|
||||
#define HN_RX_FLAG_ATTACHED 0x1
|
||||
#define HN_RX_FLAG_ATTACHED 0x0001
|
||||
#define HN_RX_FLAG_BR_REF 0x0002
|
||||
|
||||
struct hn_tx_ring {
|
||||
#ifndef HN_USE_TXDESC_BUFRING
|
||||
@ -162,8 +163,8 @@ struct hn_tx_ring {
|
||||
struct sysctl_oid *hn_tx_sysctl_tree;
|
||||
} __aligned(CACHE_LINE_SIZE);
|
||||
|
||||
#define HN_TX_FLAG_ATTACHED 0x1
|
||||
#define HN_TX_FLAG_HASHVAL 0x2 /* support HASHVAL pktinfo */
|
||||
#define HN_TX_FLAG_ATTACHED 0x0001
|
||||
#define HN_TX_FLAG_HASHVAL 0x0002 /* support HASHVAL pktinfo */
|
||||
|
||||
/*
|
||||
* Device-specific softc structure
|
||||
@ -237,6 +238,10 @@ struct hn_softc {
|
||||
#define HN_FLAG_HAS_RSSIND 0x0008
|
||||
#define HN_FLAG_SYNTH_ATTACHED 0x0010
|
||||
#define HN_FLAG_NO_SLEEPING 0x0020
|
||||
#define HN_FLAG_RXBUF_REF 0x0040
|
||||
#define HN_FLAG_CHIM_REF 0x0080
|
||||
|
||||
#define HN_FLAG_ERRORS (HN_FLAG_RXBUF_REF | HN_FLAG_CHIM_REF)
|
||||
|
||||
#define HN_NO_SLEEPING(sc) \
|
||||
do { \
|
||||
|
Loading…
x
Reference in New Issue
Block a user