Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/hyperv/netvsc/hv_rndis_filter.c
Show First 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | |||||
#include <vm/pmap.h> | #include <vm/pmap.h> | ||||
#include <dev/hyperv/include/hyperv.h> | #include <dev/hyperv/include/hyperv.h> | ||||
#include <dev/hyperv/include/vmbus_xact.h> | #include <dev/hyperv/include/vmbus_xact.h> | ||||
#include <dev/hyperv/netvsc/hv_net_vsc.h> | #include <dev/hyperv/netvsc/hv_net_vsc.h> | ||||
#include <dev/hyperv/netvsc/hv_rndis.h> | #include <dev/hyperv/netvsc/hv_rndis.h> | ||||
#include <dev/hyperv/netvsc/hv_rndis_filter.h> | #include <dev/hyperv/netvsc/hv_rndis_filter.h> | ||||
#include <dev/hyperv/netvsc/if_hnreg.h> | #include <dev/hyperv/netvsc/if_hnreg.h> | ||||
#include <dev/hyperv/netvsc/ndis.h> | |||||
#define HV_RF_RECVINFO_VLAN 0x1 | #define HV_RF_RECVINFO_VLAN 0x1 | ||||
#define HV_RF_RECVINFO_CSUM 0x2 | #define HV_RF_RECVINFO_CSUM 0x2 | ||||
#define HV_RF_RECVINFO_HASHINF 0x4 | #define HV_RF_RECVINFO_HASHINF 0x4 | ||||
#define HV_RF_RECVINFO_HASHVAL 0x8 | #define HV_RF_RECVINFO_HASHVAL 0x8 | ||||
#define HV_RF_RECVINFO_ALL \ | #define HV_RF_RECVINFO_ALL \ | ||||
(HV_RF_RECVINFO_VLAN | \ | (HV_RF_RECVINFO_VLAN | \ | ||||
HV_RF_RECVINFO_CSUM | \ | HV_RF_RECVINFO_CSUM | \ | ||||
Show All 31 Lines | |||||
static void hn_rndis_sent_halt(struct hn_send_ctx *sndc, | static void hn_rndis_sent_halt(struct hn_send_ctx *sndc, | ||||
struct hn_softc *sc, struct vmbus_channel *chan, | struct hn_softc *sc, struct vmbus_channel *chan, | ||||
const void *data, int dlen); | const void *data, int dlen); | ||||
static void hn_rndis_sent_cb(struct hn_send_ctx *sndc, | static void hn_rndis_sent_cb(struct hn_send_ctx *sndc, | ||||
struct hn_softc *sc, struct vmbus_channel *chan, | struct hn_softc *sc, struct vmbus_channel *chan, | ||||
const void *data, int dlen); | const void *data, int dlen); | ||||
static int hn_rndis_query(struct hn_softc *sc, uint32_t oid, | static int hn_rndis_query(struct hn_softc *sc, uint32_t oid, | ||||
const void *idata, size_t idlen, void *odata, size_t *odlen0); | const void *idata, size_t idlen, void *odata, size_t *odlen0); | ||||
static int hn_rndis_set(struct hn_softc *sc, uint32_t oid, const void *data, | |||||
size_t dlen); | |||||
static int hn_rndis_conf_offload(struct hn_softc *sc); | |||||
static __inline uint32_t | static __inline uint32_t | ||||
hn_rndis_rid(struct hn_softc *sc) | hn_rndis_rid(struct hn_softc *sc) | ||||
{ | { | ||||
uint32_t rid; | uint32_t rid; | ||||
again: | again: | ||||
rid = atomic_fetchadd_int(&sc->hn_rndis_rid, 1); | rid = atomic_fetchadd_int(&sc->hn_rndis_rid, 1); | ||||
▲ Show 20 Lines • Show All 888 Lines • ▼ Show 20 Lines | hn_rndis_query(struct hn_softc *sc, uint32_t oid, | ||||
struct vmbus_xact *xact; | struct vmbus_xact *xact; | ||||
size_t reqlen, odlen = *odlen0, comp_len; | size_t reqlen, odlen = *odlen0, comp_len; | ||||
int error, ofs; | int error, ofs; | ||||
uint32_t rid; | uint32_t rid; | ||||
reqlen = sizeof(*req) + idlen; | reqlen = sizeof(*req) + idlen; | ||||
xact = vmbus_xact_get(sc->hn_xact, reqlen); | xact = vmbus_xact_get(sc->hn_xact, reqlen); | ||||
if (xact == NULL) { | if (xact == NULL) { | ||||
if_printf(sc->hn_ifp, "no xact for RNDIS query\n"); | if_printf(sc->hn_ifp, "no xact for RNDIS query 0x%08x\n", oid); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
rid = hn_rndis_rid(sc); | rid = hn_rndis_rid(sc); | ||||
req = vmbus_xact_req_data(xact); | req = vmbus_xact_req_data(xact); | ||||
req->rm_type = REMOTE_NDIS_QUERY_MSG; | req->rm_type = REMOTE_NDIS_QUERY_MSG; | ||||
req->rm_len = reqlen; | req->rm_len = reqlen; | ||||
req->rm_rid = rid; | req->rm_rid = rid; | ||||
req->rm_oid = oid; | req->rm_oid = oid; | ||||
▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | hn_rndis_query(struct hn_softc *sc, uint32_t oid, | ||||
*odlen0 = odlen; | *odlen0 = odlen; | ||||
error = 0; | error = 0; | ||||
done: | done: | ||||
vmbus_xact_put(xact); | vmbus_xact_put(xact); | ||||
return (error); | return (error); | ||||
} | } | ||||
static int | |||||
hn_rndis_set(struct hn_softc *sc, uint32_t oid, const void *data, size_t dlen) | |||||
{ | |||||
struct rndis_set_req *req; | |||||
const struct rndis_set_comp *comp; | |||||
struct vmbus_xact *xact; | |||||
size_t reqlen, comp_len; | |||||
uint32_t rid; | |||||
int error; | |||||
KASSERT(dlen > 0, ("invalid dlen %zu", dlen)); | |||||
reqlen = sizeof(*req) + dlen; | |||||
xact = vmbus_xact_get(sc->hn_xact, reqlen); | |||||
if (xact == NULL) { | |||||
if_printf(sc->hn_ifp, "no xact for RNDIS set 0x%08x\n", oid); | |||||
return (ENXIO); | |||||
} | |||||
rid = hn_rndis_rid(sc); | |||||
req = vmbus_xact_req_data(xact); | |||||
req->rm_type = REMOTE_NDIS_SET_MSG; | |||||
req->rm_len = reqlen; | |||||
req->rm_rid = rid; | |||||
req->rm_oid = oid; | |||||
req->rm_infobuflen = dlen; | |||||
req->rm_infobufoffset = RNDIS_SET_REQ_INFOBUFOFFSET; | |||||
/* Data immediately follows RNDIS set. */ | |||||
memcpy(req + 1, data, dlen); | |||||
comp_len = sizeof(*comp); | |||||
comp = hn_rndis_xact_execute(sc, xact, rid, reqlen, &comp_len, | |||||
REMOTE_NDIS_SET_CMPLT); | |||||
if (comp == NULL) { | |||||
if_printf(sc->hn_ifp, "exec RNDIS set 0x%08x failed\n", oid); | |||||
error = EIO; | |||||
goto done; | |||||
} | |||||
if (comp->rm_status != RNDIS_STATUS_SUCCESS) { | |||||
if_printf(sc->hn_ifp, "RNDIS set 0x%08x failed: " | |||||
"status 0x%08x\n", oid, comp->rm_status); | |||||
error = EIO; | |||||
goto done; | |||||
} | |||||
error = 0; | |||||
done: | |||||
vmbus_xact_put(xact); | |||||
return (error); | |||||
} | |||||
static int | |||||
hn_rndis_conf_offload(struct hn_softc *sc) | |||||
{ | |||||
struct ndis_offload_params params; | |||||
size_t paramsz; | |||||
int error; | |||||
/* NOTE: 0 means "no change" */ | |||||
memset(¶ms, 0, sizeof(params)); | |||||
params.ndis_hdr.ndis_type = NDIS_OBJTYPE_DEFAULT; | |||||
if (sc->hn_ndis_ver < NDIS_VERSION_6_30) { | |||||
params.ndis_hdr.ndis_rev = NDIS_OFFLOAD_PARAMS_REV_2; | |||||
paramsz = NDIS_OFFLOAD_PARAMS_SIZE_6_1; | |||||
} else { | |||||
params.ndis_hdr.ndis_rev = NDIS_OFFLOAD_PARAMS_REV_3; | |||||
paramsz = NDIS_OFFLOAD_PARAMS_SIZE; | |||||
} | |||||
params.ndis_hdr.ndis_size = paramsz; | |||||
params.ndis_ip4csum = NDIS_OFFLOAD_PARAM_TXRX; | |||||
params.ndis_tcp4csum = NDIS_OFFLOAD_PARAM_TXRX; | |||||
params.ndis_tcp6csum = NDIS_OFFLOAD_PARAM_TXRX; | |||||
if (sc->hn_ndis_ver >= NDIS_VERSION_6_30) { | |||||
params.ndis_udp4csum = NDIS_OFFLOAD_PARAM_TXRX; | |||||
params.ndis_udp6csum = NDIS_OFFLOAD_PARAM_TXRX; | |||||
} | |||||
params.ndis_lsov2_ip4 = NDIS_OFFLOAD_LSOV2_ON; | |||||
/* XXX ndis_lsov2_ip6 = NDIS_OFFLOAD_LSOV2_ON */ | |||||
error = hn_rndis_set(sc, OID_TCP_OFFLOAD_PARAMETERS, ¶ms, paramsz); | |||||
if (error) { | |||||
if_printf(sc->hn_ifp, "offload config failed: %d\n", error); | |||||
} else { | |||||
if (bootverbose) | |||||
if_printf(sc->hn_ifp, "offload config done\n"); | |||||
} | |||||
return (error); | |||||
} | |||||
/* | /* | ||||
* RNDIS filter init device | * RNDIS filter init device | ||||
*/ | */ | ||||
static int | static int | ||||
hv_rf_init_device(rndis_device *device) | hv_rf_init_device(rndis_device *device) | ||||
{ | { | ||||
struct hn_softc *sc = device->sc; | struct hn_softc *sc = device->sc; | ||||
struct rndis_init_req *req; | struct rndis_init_req *req; | ||||
▲ Show 20 Lines • Show All 149 Lines • ▼ Show 20 Lines | |||||
* RNDIS filter on device add | * RNDIS filter on device add | ||||
*/ | */ | ||||
int | int | ||||
hv_rf_on_device_add(struct hn_softc *sc, void *additl_info, | hv_rf_on_device_add(struct hn_softc *sc, void *additl_info, | ||||
int *nchan0, struct hn_rx_ring *rxr) | int *nchan0, struct hn_rx_ring *rxr) | ||||
{ | { | ||||
int ret; | int ret; | ||||
rndis_device *rndis_dev; | rndis_device *rndis_dev; | ||||
rndis_offload_params offloads; | |||||
struct rndis_recv_scale_cap rsscaps; | struct rndis_recv_scale_cap rsscaps; | ||||
uint32_t rsscaps_size = sizeof(struct rndis_recv_scale_cap); | uint32_t rsscaps_size = sizeof(struct rndis_recv_scale_cap); | ||||
netvsc_device_info *dev_info = (netvsc_device_info *)additl_info; | netvsc_device_info *dev_info = (netvsc_device_info *)additl_info; | ||||
device_t dev = sc->hn_dev; | device_t dev = sc->hn_dev; | ||||
struct hn_nvs_subch_req *req; | struct hn_nvs_subch_req *req; | ||||
const struct hn_nvs_subch_resp *resp; | const struct hn_nvs_subch_resp *resp; | ||||
size_t resp_len; | size_t resp_len; | ||||
struct vmbus_xact *xact = NULL; | struct vmbus_xact *xact = NULL; | ||||
Show All 33 Lines | hv_rf_on_device_add(struct hn_softc *sc, void *additl_info, | ||||
} | } | ||||
/* Get the mac address */ | /* Get the mac address */ | ||||
ret = hv_rf_query_device_mac(rndis_dev); | ret = hv_rf_query_device_mac(rndis_dev); | ||||
if (ret != 0) { | if (ret != 0) { | ||||
/* TODO: shut down rndis device and the channel */ | /* TODO: shut down rndis device and the channel */ | ||||
} | } | ||||
/* config csum offload and send request to host */ | /* Configure NDIS offload settings */ | ||||
memset(&offloads, 0, sizeof(offloads)); | hn_rndis_conf_offload(sc); | ||||
offloads.ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED; | |||||
offloads.tcp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED; | |||||
offloads.udp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED; | |||||
offloads.tcp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED; | |||||
offloads.udp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED; | |||||
offloads.lso_v2_ipv4 = RNDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED; | |||||
ret = hv_rf_send_offload_request(sc, &offloads); | |||||
if (ret != 0) { | |||||
/* TODO: shut down rndis device and the channel */ | |||||
device_printf(dev, | |||||
"hv_rf_send_offload_request failed, ret=%d\n", ret); | |||||
} | |||||
memcpy(dev_info->mac_addr, rndis_dev->hw_mac_addr, ETHER_ADDR_LEN); | memcpy(dev_info->mac_addr, rndis_dev->hw_mac_addr, ETHER_ADDR_LEN); | ||||
hv_rf_query_device_link_status(rndis_dev); | hv_rf_query_device_link_status(rndis_dev); | ||||
dev_info->link_state = rndis_dev->link_status; | dev_info->link_state = rndis_dev->link_status; | ||||
if (sc->hn_nvs_ver < NVSP_PROTOCOL_VERSION_5 || nchan == 1) | if (sc->hn_nvs_ver < NVSP_PROTOCOL_VERSION_5 || nchan == 1) | ||||
▲ Show 20 Lines • Show All 153 Lines • Show Last 20 Lines |