Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/hyperv/netvsc/hv_rndis_filter.c
Show First 20 Lines • Show All 234 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* | * | ||||
*/ | */ | ||||
static int | static int | ||||
hv_rf_send_request(rndis_device *device, rndis_request *request, | hv_rf_send_request(rndis_device *device, rndis_request *request, | ||||
uint32_t message_type) | uint32_t message_type) | ||||
{ | { | ||||
struct hn_softc *sc = device->net_dev->sc; | struct hn_softc *sc = device->sc; | ||||
uint32_t send_buf_section_idx, tot_data_buf_len; | uint32_t send_buf_section_idx, tot_data_buf_len; | ||||
struct vmbus_gpa gpa[2]; | struct vmbus_gpa gpa[2]; | ||||
int gpa_cnt, send_buf_section_size; | int gpa_cnt, send_buf_section_size; | ||||
hn_sent_callback_t cb; | hn_sent_callback_t cb; | ||||
/* Set up the packet to send it */ | /* Set up the packet to send it */ | ||||
tot_data_buf_len = request->request_msg.msg_len; | tot_data_buf_len = request->request_msg.msg_len; | ||||
▲ Show 20 Lines • Show All 89 Lines • ▼ Show 20 Lines | |||||
int | int | ||||
hv_rf_send_offload_request(struct hn_softc *sc, | hv_rf_send_offload_request(struct hn_softc *sc, | ||||
rndis_offload_params *offloads) | rndis_offload_params *offloads) | ||||
{ | { | ||||
rndis_request *request; | rndis_request *request; | ||||
rndis_set_request *set; | rndis_set_request *set; | ||||
rndis_offload_params *offload_req; | rndis_offload_params *offload_req; | ||||
rndis_set_complete *set_complete; | rndis_set_complete *set_complete; | ||||
rndis_device *rndis_dev; | rndis_device *rndis_dev = sc->rndis_dev; | ||||
device_t dev = sc->hn_dev; | device_t dev = sc->hn_dev; | ||||
netvsc_dev *net_dev = sc->net_dev; | |||||
uint32_t extlen = sizeof(rndis_offload_params); | uint32_t extlen = sizeof(rndis_offload_params); | ||||
int ret; | int ret; | ||||
if (sc->hn_nvs_ver <= NVSP_PROTOCOL_VERSION_4) { | if (sc->hn_nvs_ver <= NVSP_PROTOCOL_VERSION_4) { | ||||
extlen = VERSION_4_OFFLOAD_SIZE; | extlen = VERSION_4_OFFLOAD_SIZE; | ||||
/* On NVSP_PROTOCOL_VERSION_4 and below, we do not support | /* On NVSP_PROTOCOL_VERSION_4 and below, we do not support | ||||
* UDP checksum offload. | * UDP checksum offload. | ||||
*/ | */ | ||||
offloads->udp_ipv4_csum = 0; | offloads->udp_ipv4_csum = 0; | ||||
offloads->udp_ipv6_csum = 0; | offloads->udp_ipv6_csum = 0; | ||||
} | } | ||||
rndis_dev = net_dev->extension; | |||||
request = hv_rndis_request(rndis_dev, REMOTE_NDIS_SET_MSG, | request = hv_rndis_request(rndis_dev, REMOTE_NDIS_SET_MSG, | ||||
RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen); | RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen); | ||||
if (!request) | if (!request) | ||||
return (ENOMEM); | return (ENOMEM); | ||||
set = &request->request_msg.msg.set_request; | set = &request->request_msg.msg.set_request; | ||||
set->oid = RNDIS_OID_TCP_OFFLOAD_PARAMETERS; | set->oid = RNDIS_OID_TCP_OFFLOAD_PARAMETERS; | ||||
set->info_buffer_length = extlen; | set->info_buffer_length = extlen; | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
static void | static void | ||||
hv_rf_receive_indicate_status(rndis_device *device, const rndis_msg *response) | hv_rf_receive_indicate_status(rndis_device *device, const rndis_msg *response) | ||||
{ | { | ||||
const rndis_indicate_status *indicate = &response->msg.indicate_status; | const rndis_indicate_status *indicate = &response->msg.indicate_status; | ||||
switch(indicate->status) { | switch(indicate->status) { | ||||
case RNDIS_STATUS_MEDIA_CONNECT: | case RNDIS_STATUS_MEDIA_CONNECT: | ||||
netvsc_linkstatus_callback(device->net_dev->sc, 1); | netvsc_linkstatus_callback(device->sc, 1); | ||||
break; | break; | ||||
case RNDIS_STATUS_MEDIA_DISCONNECT: | case RNDIS_STATUS_MEDIA_DISCONNECT: | ||||
netvsc_linkstatus_callback(device->net_dev->sc, 0); | netvsc_linkstatus_callback(device->sc, 0); | ||||
break; | break; | ||||
default: | default: | ||||
/* TODO: */ | /* TODO: */ | ||||
device_printf(device->net_dev->sc->hn_dev, | device_printf(device->sc->hn_dev, | ||||
"unknown status %d received\n", indicate->status); | "unknown status %d received\n", indicate->status); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
static int | static int | ||||
hv_rf_find_recvinfo(const rndis_packet *rpkt, struct hn_recvinfo *info) | hv_rf_find_recvinfo(const rndis_packet *rpkt, struct hn_recvinfo *info) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 110 Lines • ▼ Show 20 Lines | hv_rf_receive_data(struct hn_rx_ring *rxr, const void *data, int dlen) | ||||
} | } | ||||
netvsc_recv(rxr, data, dlen, &info); | netvsc_recv(rxr, data, dlen, &info); | ||||
} | } | ||||
/* | /* | ||||
* RNDIS filter on receive | * RNDIS filter on receive | ||||
*/ | */ | ||||
int | int | ||||
hv_rf_on_receive(netvsc_dev *net_dev, | hv_rf_on_receive(struct hn_softc *sc, struct hn_rx_ring *rxr, | ||||
struct hn_rx_ring *rxr, const void *data, int dlen) | const void *data, int dlen) | ||||
{ | { | ||||
rndis_device *rndis_dev; | rndis_device *rndis_dev; | ||||
const rndis_msg *rndis_hdr; | const rndis_msg *rndis_hdr; | ||||
/* Make sure the rndis device state is initialized */ | rndis_dev = sc->rndis_dev; | ||||
if (net_dev->extension == NULL) | |||||
return (ENODEV); | |||||
rndis_dev = (rndis_device *)net_dev->extension; | |||||
if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) | if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) | ||||
return (EINVAL); | return (EINVAL); | ||||
rndis_hdr = data; | rndis_hdr = data; | ||||
switch (rndis_hdr->ndis_msg_type) { | switch (rndis_hdr->ndis_msg_type) { | ||||
/* data message */ | /* data message */ | ||||
case REMOTE_NDIS_PACKET_MSG: | case REMOTE_NDIS_PACKET_MSG: | ||||
▲ Show 20 Lines • Show All 455 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) | ||||
{ | { | ||||
struct hn_send_ctx sndc; | struct hn_send_ctx sndc; | ||||
int ret; | int ret; | ||||
netvsc_dev *net_dev; | |||||
rndis_device *rndis_dev; | rndis_device *rndis_dev; | ||||
rndis_offload_params offloads; | 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; | struct vmbus_xact *xact; | ||||
uint32_t status, nsubch; | uint32_t status, nsubch; | ||||
int nchan = *nchan0; | int nchan = *nchan0; | ||||
rndis_dev = hv_get_rndis_device(); | rndis_dev = hv_get_rndis_device(); | ||||
if (rndis_dev == NULL) { | if (rndis_dev == NULL) { | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
sc->rndis_dev = rndis_dev; | |||||
rndis_dev->sc = sc; | |||||
/* | /* | ||||
* Let the inner driver handle this first to create the netvsc channel | * Let the inner driver handle this first to create the netvsc channel | ||||
* NOTE! Once the channel is created, we may get a receive callback | * NOTE! Once the channel is created, we may get a receive callback | ||||
* (hv_rf_on_receive()) before this call is completed. | * (hv_rf_on_receive()) before this call is completed. | ||||
* Note: Earlier code used a function pointer here. | * Note: Earlier code used a function pointer here. | ||||
*/ | */ | ||||
net_dev = hv_nv_on_device_add(sc, additl_info, rxr); | ret = hv_nv_on_device_add(sc, rxr); | ||||
if (!net_dev) { | if (ret != 0) { | ||||
hv_put_rndis_device(rndis_dev); | hv_put_rndis_device(rndis_dev); | ||||
return (ret); | |||||
return (ENOMEM); | |||||
} | } | ||||
/* | /* | ||||
* Initialize the rndis device | * Initialize the rndis device | ||||
*/ | */ | ||||
net_dev->extension = rndis_dev; | |||||
rndis_dev->net_dev = net_dev; | |||||
/* Send the rndis initialization message */ | /* Send the rndis initialization message */ | ||||
ret = hv_rf_init_device(rndis_dev); | ret = hv_rf_init_device(rndis_dev); | ||||
if (ret != 0) { | if (ret != 0) { | ||||
/* | /* | ||||
* TODO: If rndis init failed, we will need to shut down | * TODO: If rndis init failed, we will need to shut down | ||||
* the channel | * the channel | ||||
*/ | */ | ||||
} | } | ||||
▲ Show 20 Lines • Show All 114 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
/* | /* | ||||
* RNDIS filter on device remove | * RNDIS filter on device remove | ||||
*/ | */ | ||||
int | int | ||||
hv_rf_on_device_remove(struct hn_softc *sc, boolean_t destroy_channel) | hv_rf_on_device_remove(struct hn_softc *sc, boolean_t destroy_channel) | ||||
{ | { | ||||
netvsc_dev *net_dev = sc->net_dev; | rndis_device *rndis_dev = sc->rndis_dev; | ||||
rndis_device *rndis_dev = (rndis_device *)net_dev->extension; | |||||
int ret; | int ret; | ||||
/* Halt and release the rndis device */ | /* Halt and release the rndis device */ | ||||
ret = hv_rf_halt_device(rndis_dev); | ret = hv_rf_halt_device(rndis_dev); | ||||
sc->rndis_dev = NULL; | |||||
hv_put_rndis_device(rndis_dev); | hv_put_rndis_device(rndis_dev); | ||||
net_dev->extension = NULL; | |||||
/* Pass control to inner driver to remove the device */ | /* Pass control to inner driver to remove the device */ | ||||
ret |= hv_nv_on_device_remove(sc, destroy_channel); | ret |= hv_nv_on_device_remove(sc, destroy_channel); | ||||
return (ret); | return (ret); | ||||
} | } | ||||
/* | /* | ||||
* RNDIS filter on open | * RNDIS filter on open | ||||
*/ | */ | ||||
int | int | ||||
hv_rf_on_open(struct hn_softc *sc) | hv_rf_on_open(struct hn_softc *sc) | ||||
{ | { | ||||
netvsc_dev *net_dev = sc->net_dev; | |||||
return (hv_rf_open_device((rndis_device *)net_dev->extension)); | return (hv_rf_open_device(sc->rndis_dev)); | ||||
} | } | ||||
/* | /* | ||||
* RNDIS filter on close | * RNDIS filter on close | ||||
*/ | */ | ||||
int | int | ||||
hv_rf_on_close(struct hn_softc *sc) | hv_rf_on_close(struct hn_softc *sc) | ||||
{ | { | ||||
netvsc_dev *net_dev = sc->net_dev; | |||||
return (hv_rf_close_device((rndis_device *)net_dev->extension)); | return (hv_rf_close_device(sc->rndis_dev)); | ||||
} | } | ||||
static void | static void | ||||
hn_rndis_sent_cb(struct hn_send_ctx *sndc, struct hn_softc *sc, | hn_rndis_sent_cb(struct hn_send_ctx *sndc, struct hn_softc *sc, | ||||
struct vmbus_channel *chan __unused, const void *data __unused, | struct vmbus_channel *chan __unused, const void *data __unused, | ||||
int dlen __unused) | int dlen __unused) | ||||
{ | { | ||||
if (sndc->hn_chim_idx != HN_NVS_CHIM_IDX_INVALID) | if (sndc->hn_chim_idx != HN_NVS_CHIM_IDX_INVALID) | ||||
Show All 27 Lines |