Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/hyperv/netvsc/hv_rndis_filter.c
Show All 28 Lines | |||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/mbuf.h> | #include <sys/mbuf.h> | ||||
#include <sys/socket.h> | #include <sys/socket.h> | ||||
#include <sys/lock.h> | #include <sys/lock.h> | ||||
#include <sys/mutex.h> | #include <sys/mutex.h> | ||||
#include <net/if.h> | |||||
#include <net/if_arp.h> | #include <net/if_arp.h> | ||||
#include <net/if_var.h> | |||||
#include <net/ethernet.h> | #include <net/ethernet.h> | ||||
#include <sys/types.h> | #include <sys/types.h> | ||||
#include <machine/atomic.h> | #include <machine/atomic.h> | ||||
#include <sys/sema.h> | #include <sys/sema.h> | ||||
#include <vm/vm.h> | #include <vm/vm.h> | ||||
#include <vm/vm_param.h> | #include <vm/vm_param.h> | ||||
#include <vm/pmap.h> | #include <vm/pmap.h> | ||||
Show All 23 Lines | |||||
/* | /* | ||||
* Forward declarations | * Forward declarations | ||||
*/ | */ | ||||
static int hv_rf_send_request(rndis_device *device, rndis_request *request, | static int hv_rf_send_request(rndis_device *device, rndis_request *request, | ||||
uint32_t message_type); | uint32_t message_type); | ||||
static void hv_rf_receive_response(rndis_device *device, rndis_msg *response); | static void hv_rf_receive_response(rndis_device *device, rndis_msg *response); | ||||
static void hv_rf_receive_indicate_status(rndis_device *device, | static void hv_rf_receive_indicate_status(rndis_device *device, | ||||
rndis_msg *response); | rndis_msg *response); | ||||
static void hv_rf_receive_data(rndis_device *device, rndis_msg *message, | static void hv_rf_receive_data(struct hn_rx_ring *rxr, rndis_msg *message, | ||||
struct hv_vmbus_channel *chan, | |||||
netvsc_packet *pkt); | netvsc_packet *pkt); | ||||
static int hv_rf_query_device(rndis_device *device, uint32_t oid, | static int hv_rf_query_device(rndis_device *device, uint32_t oid, | ||||
void *result, uint32_t *result_size); | void *result, uint32_t *result_size); | ||||
static inline int hv_rf_query_device_mac(rndis_device *device); | static inline int hv_rf_query_device_mac(rndis_device *device); | ||||
static inline int hv_rf_query_device_link_status(rndis_device *device); | static inline int hv_rf_query_device_link_status(rndis_device *device); | ||||
static int hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter); | static int hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter); | ||||
static int hv_rf_init_device(rndis_device *device); | static int hv_rf_init_device(rndis_device *device); | ||||
static int hv_rf_open_device(rndis_device *device); | static int hv_rf_open_device(rndis_device *device); | ||||
▲ Show 20 Lines • Show All 435 Lines • ▼ Show 20 Lines | skip: | ||||
} | } | ||||
return 0; | return 0; | ||||
} | } | ||||
/* | /* | ||||
* RNDIS filter receive data | * RNDIS filter receive data | ||||
*/ | */ | ||||
static void | static void | ||||
hv_rf_receive_data(rndis_device *device, rndis_msg *message, | hv_rf_receive_data(struct hn_rx_ring *rxr, rndis_msg *message, | ||||
struct hv_vmbus_channel *chan, netvsc_packet *pkt) | netvsc_packet *pkt) | ||||
{ | { | ||||
rndis_packet *rndis_pkt; | rndis_packet *rndis_pkt; | ||||
uint32_t data_offset; | uint32_t data_offset; | ||||
device_t dev = device->net_dev->sc->hn_dev; | |||||
struct hv_rf_recvinfo info; | struct hv_rf_recvinfo info; | ||||
rndis_pkt = &message->msg.packet; | rndis_pkt = &message->msg.packet; | ||||
/* | /* | ||||
* Fixme: Handle multiple rndis pkt msgs that may be enclosed in this | * Fixme: Handle multiple rndis pkt msgs that may be enclosed in this | ||||
* netvsc packet (ie tot_data_buf_len != message_length) | * netvsc packet (ie tot_data_buf_len != message_length) | ||||
*/ | */ | ||||
/* Remove rndis header, then pass data packet up the stack */ | /* Remove rndis header, then pass data packet up the stack */ | ||||
data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset; | data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset; | ||||
pkt->tot_data_buf_len -= data_offset; | pkt->tot_data_buf_len -= data_offset; | ||||
if (pkt->tot_data_buf_len < rndis_pkt->data_length) { | if (pkt->tot_data_buf_len < rndis_pkt->data_length) { | ||||
pkt->status = nvsp_status_failure; | pkt->status = nvsp_status_failure; | ||||
device_printf(dev, | if_printf(rxr->hn_ifp, | ||||
"total length %u is less than data length %u\n", | "total length %u is less than data length %u\n", | ||||
pkt->tot_data_buf_len, rndis_pkt->data_length); | pkt->tot_data_buf_len, rndis_pkt->data_length); | ||||
return; | return; | ||||
} | } | ||||
pkt->tot_data_buf_len = rndis_pkt->data_length; | pkt->tot_data_buf_len = rndis_pkt->data_length; | ||||
pkt->data = (void *)((unsigned long)pkt->data + data_offset); | pkt->data = (void *)((unsigned long)pkt->data + data_offset); | ||||
if (hv_rf_find_recvinfo(rndis_pkt, &info)) { | if (hv_rf_find_recvinfo(rndis_pkt, &info)) { | ||||
pkt->status = nvsp_status_failure; | pkt->status = nvsp_status_failure; | ||||
device_printf(dev, "recvinfo parsing failed\n"); | if_printf(rxr->hn_ifp, "recvinfo parsing failed\n"); | ||||
return; | return; | ||||
} | } | ||||
if (info.vlan_info != NULL) | if (info.vlan_info != NULL) | ||||
pkt->vlan_tci = info.vlan_info->u1.s1.vlan_id; | pkt->vlan_tci = info.vlan_info->u1.s1.vlan_id; | ||||
else | else | ||||
pkt->vlan_tci = 0; | pkt->vlan_tci = 0; | ||||
netvsc_recv(chan, pkt, info.csum_info, info.hash_info, info.hash_value); | netvsc_recv(rxr, pkt, info.csum_info, info.hash_info, info.hash_value); | ||||
} | } | ||||
/* | /* | ||||
* RNDIS filter on receive | * RNDIS filter on receive | ||||
*/ | */ | ||||
int | int | ||||
hv_rf_on_receive(netvsc_dev *net_dev, | hv_rf_on_receive(netvsc_dev *net_dev, | ||||
struct hv_vmbus_channel *chan, netvsc_packet *pkt) | struct hn_rx_ring *rxr, netvsc_packet *pkt) | ||||
{ | { | ||||
rndis_device *rndis_dev; | rndis_device *rndis_dev; | ||||
rndis_msg *rndis_hdr; | rndis_msg *rndis_hdr; | ||||
/* Make sure the rndis device state is initialized */ | /* Make sure the rndis device state is initialized */ | ||||
if (net_dev->extension == NULL) { | if (net_dev->extension == NULL) { | ||||
pkt->status = nvsp_status_failure; | pkt->status = nvsp_status_failure; | ||||
return (ENODEV); | return (ENODEV); | ||||
} | } | ||||
rndis_dev = (rndis_device *)net_dev->extension; | rndis_dev = (rndis_device *)net_dev->extension; | ||||
if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) { | if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) { | ||||
pkt->status = nvsp_status_failure; | pkt->status = nvsp_status_failure; | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
rndis_hdr = pkt->data; | rndis_hdr = pkt->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: | ||||
hv_rf_receive_data(rndis_dev, rndis_hdr, chan, pkt); | hv_rf_receive_data(rxr, rndis_hdr, pkt); | ||||
break; | break; | ||||
/* completion messages */ | /* completion messages */ | ||||
case REMOTE_NDIS_INITIALIZE_CMPLT: | case REMOTE_NDIS_INITIALIZE_CMPLT: | ||||
case REMOTE_NDIS_QUERY_CMPLT: | case REMOTE_NDIS_QUERY_CMPLT: | ||||
case REMOTE_NDIS_SET_CMPLT: | case REMOTE_NDIS_SET_CMPLT: | ||||
case REMOTE_NDIS_RESET_CMPLT: | case REMOTE_NDIS_RESET_CMPLT: | ||||
case REMOTE_NDIS_KEEPALIVE_CMPLT: | case REMOTE_NDIS_KEEPALIVE_CMPLT: | ||||
hv_rf_receive_response(rndis_dev, rndis_hdr); | hv_rf_receive_response(rndis_dev, rndis_hdr); | ||||
▲ Show 20 Lines • Show All 442 Lines • ▼ Show 20 Lines | hv_rf_close_device(rndis_device *device) | ||||
return (ret); | return (ret); | ||||
} | } | ||||
/* | /* | ||||
* 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 nchan) | int nchan, struct hn_rx_ring *rxr) | ||||
{ | { | ||||
int ret; | int ret; | ||||
netvsc_dev *net_dev; | netvsc_dev *net_dev; | ||||
rndis_device *rndis_dev; | rndis_device *rndis_dev; | ||||
nvsp_msg *init_pkt; | nvsp_msg *init_pkt; | ||||
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; | ||||
rndis_dev = hv_get_rndis_device(); | rndis_dev = hv_get_rndis_device(); | ||||
if (rndis_dev == NULL) { | if (rndis_dev == NULL) { | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
/* | /* | ||||
* 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); | net_dev = hv_nv_on_device_add(sc, additl_info, rxr); | ||||
if (!net_dev) { | if (!net_dev) { | ||||
hv_put_rndis_device(rndis_dev); | hv_put_rndis_device(rndis_dev); | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
/* | /* | ||||
* Initialize the rndis device | * Initialize the rndis device | ||||
▲ Show 20 Lines • Show All 168 Lines • ▼ Show 20 Lines | hv_rf_on_send_request_halt_completion(struct hv_vmbus_channel *chan __unused, | ||||
* Notify hv_rf_halt_device() about halt completion. | * Notify hv_rf_halt_device() about halt completion. | ||||
* The halt code must wait for completion before freeing | * The halt code must wait for completion before freeing | ||||
* the transaction resources. | * the transaction resources. | ||||
*/ | */ | ||||
request->halt_complete_flag = 1; | request->halt_complete_flag = 1; | ||||
} | } | ||||
void | void | ||||
hv_rf_channel_rollup(struct hv_vmbus_channel *chan) | hv_rf_channel_rollup(struct hn_rx_ring *rxr, struct hn_tx_ring *txr) | ||||
{ | { | ||||
netvsc_channel_rollup(chan); | netvsc_channel_rollup(rxr, txr); | ||||
} | } |