Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/hyperv/netvsc/hv_rndis_filter.c
Show First 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | |||||
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); | ||||
static int hv_rf_close_device(rndis_device *device); | static int hv_rf_close_device(rndis_device *device); | ||||
static void hv_rf_on_send_request_completion(struct vmbus_channel *, void *context); | |||||
static void hv_rf_on_send_request_halt_completion(struct vmbus_channel *, void *context); | |||||
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); | ||||
static void hn_rndis_sent_halt(struct hn_send_ctx *sndc, | |||||
struct netvsc_dev_ *net_dev, struct vmbus_channel *chan, | |||||
const struct nvsp_msg_ *msg); | |||||
static void hn_rndis_sent_cb(struct hn_send_ctx *sndc, | |||||
struct netvsc_dev_ *net_dev, struct vmbus_channel *chan, | |||||
const struct nvsp_msg_ *msg); | |||||
/* | /* | ||||
* Set the Per-Packet-Info with the specified type | * Set the Per-Packet-Info with the specified type | ||||
*/ | */ | ||||
void * | void * | ||||
hv_set_rppi_data(rndis_msg *rndis_mesg, uint32_t rppi_size, | hv_set_rppi_data(rndis_msg *rndis_mesg, uint32_t rppi_size, | ||||
int pkt_type) | int pkt_type) | ||||
{ | { | ||||
rndis_packet *rndis_pkt; | rndis_packet *rndis_pkt; | ||||
▲ Show 20 Lines • Show All 132 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) | ||||
{ | { | ||||
netvsc_packet *packet; | |||||
netvsc_dev *net_dev = device->net_dev; | netvsc_dev *net_dev = device->net_dev; | ||||
int send_buf_section_idx; | uint32_t send_buf_section_idx, tot_data_buf_len; | ||||
struct vmbus_gpa gpa[2]; | struct vmbus_gpa gpa[2]; | ||||
int gpa_cnt; | int gpa_cnt, send_buf_section_size; | ||||
hn_sent_callback_t cb; | |||||
/* Set up the packet to send it */ | /* Set up the packet to send it */ | ||||
packet = &request->pkt; | tot_data_buf_len = request->request_msg.msg_len; | ||||
packet->is_data_pkt = FALSE; | |||||
packet->tot_data_buf_len = request->request_msg.msg_len; | |||||
gpa_cnt = 1; | gpa_cnt = 1; | ||||
gpa[0].gpa_page = hv_get_phys_addr(&request->request_msg) >> PAGE_SHIFT; | gpa[0].gpa_page = hv_get_phys_addr(&request->request_msg) >> PAGE_SHIFT; | ||||
gpa[0].gpa_len = request->request_msg.msg_len; | gpa[0].gpa_len = request->request_msg.msg_len; | ||||
gpa[0].gpa_ofs = (unsigned long)&request->request_msg & (PAGE_SIZE - 1); | gpa[0].gpa_ofs = (unsigned long)&request->request_msg & (PAGE_SIZE - 1); | ||||
if (gpa[0].gpa_ofs + gpa[0].gpa_len > PAGE_SIZE) { | if (gpa[0].gpa_ofs + gpa[0].gpa_len > PAGE_SIZE) { | ||||
gpa_cnt = 2; | gpa_cnt = 2; | ||||
gpa[0].gpa_len = PAGE_SIZE - gpa[0].gpa_ofs; | gpa[0].gpa_len = PAGE_SIZE - gpa[0].gpa_ofs; | ||||
gpa[1].gpa_page = | gpa[1].gpa_page = | ||||
hv_get_phys_addr((char*)&request->request_msg + | hv_get_phys_addr((char*)&request->request_msg + | ||||
gpa[0].gpa_len) >> PAGE_SHIFT; | gpa[0].gpa_len) >> PAGE_SHIFT; | ||||
gpa[1].gpa_ofs = 0; | gpa[1].gpa_ofs = 0; | ||||
gpa[1].gpa_len = request->request_msg.msg_len - gpa[0].gpa_len; | gpa[1].gpa_len = request->request_msg.msg_len - gpa[0].gpa_len; | ||||
} | } | ||||
packet->compl.send.send_completion_context = request; /* packet */ | if (message_type != REMOTE_NDIS_HALT_MSG) | ||||
if (message_type != REMOTE_NDIS_HALT_MSG) { | cb = hn_rndis_sent_cb; | ||||
packet->compl.send.on_send_completion = | else | ||||
hv_rf_on_send_request_completion; | cb = hn_rndis_sent_halt; | ||||
} else { | |||||
packet->compl.send.on_send_completion = | if (tot_data_buf_len < net_dev->send_section_size) { | ||||
hv_rf_on_send_request_halt_completion; | |||||
} | |||||
packet->compl.send.send_completion_tid = (unsigned long)device; | |||||
if (packet->tot_data_buf_len < net_dev->send_section_size) { | |||||
send_buf_section_idx = hv_nv_get_next_send_section(net_dev); | send_buf_section_idx = hv_nv_get_next_send_section(net_dev); | ||||
if (send_buf_section_idx != | if (send_buf_section_idx != | ||||
NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) { | NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) { | ||||
char *dest = ((char *)net_dev->send_buf + | char *dest = ((char *)net_dev->send_buf + | ||||
send_buf_section_idx * net_dev->send_section_size); | send_buf_section_idx * net_dev->send_section_size); | ||||
memcpy(dest, &request->request_msg, request->request_msg.msg_len); | memcpy(dest, &request->request_msg, request->request_msg.msg_len); | ||||
packet->send_buf_section_idx = send_buf_section_idx; | send_buf_section_size = tot_data_buf_len; | ||||
packet->send_buf_section_size = packet->tot_data_buf_len; | |||||
gpa_cnt = 0; | gpa_cnt = 0; | ||||
goto sendit; | goto sendit; | ||||
} | } | ||||
/* Failed to allocate chimney send buffer; move on */ | /* Failed to allocate chimney send buffer; move on */ | ||||
} | } | ||||
packet->send_buf_section_idx = NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX; | send_buf_section_idx = NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX; | ||||
packet->send_buf_section_size = 0; | send_buf_section_size = 0; | ||||
sendit: | sendit: | ||||
return hv_nv_on_send(device->net_dev->sc->hn_prichan, packet, | hn_send_ctx_init(&request->send_ctx, cb, request, | ||||
gpa, gpa_cnt); | send_buf_section_idx, send_buf_section_size); | ||||
return hv_nv_on_send(device->net_dev->sc->hn_prichan, false, | |||||
&request->send_ctx, gpa, gpa_cnt); | |||||
} | } | ||||
/* | /* | ||||
* RNDIS filter receive response | * RNDIS filter receive response | ||||
*/ | */ | ||||
static void | static void | ||||
hv_rf_receive_response(rndis_device *device, rndis_msg *response) | hv_rf_receive_response(rndis_device *device, rndis_msg *response) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 745 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 nchan, struct hn_rx_ring *rxr) | int nchan, struct hn_rx_ring *rxr) | ||||
{ | { | ||||
struct hn_send_ctx sndc; | |||||
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; | ||||
▲ Show 20 Lines • Show All 90 Lines • ▼ Show 20 Lines | hv_rf_on_device_add(struct hn_softc *sc, void *additl_info, | ||||
memset(init_pkt, 0, sizeof(nvsp_msg)); | memset(init_pkt, 0, sizeof(nvsp_msg)); | ||||
init_pkt->hdr.msg_type = nvsp_msg5_type_subchannel; | init_pkt->hdr.msg_type = nvsp_msg5_type_subchannel; | ||||
init_pkt->msgs.vers_5_msgs.subchannel_request.op = | init_pkt->msgs.vers_5_msgs.subchannel_request.op = | ||||
NVSP_SUBCHANNE_ALLOCATE; | NVSP_SUBCHANNE_ALLOCATE; | ||||
init_pkt->msgs.vers_5_msgs.subchannel_request.num_subchannels = | init_pkt->msgs.vers_5_msgs.subchannel_request.num_subchannels = | ||||
net_dev->num_channel - 1; | net_dev->num_channel - 1; | ||||
hn_send_ctx_init_simple(&sndc, hn_nvs_sent_wakeup, NULL); | |||||
ret = vmbus_chan_send(sc->hn_prichan, | ret = vmbus_chan_send(sc->hn_prichan, | ||||
VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC, | VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC, | ||||
init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt); | init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)&sndc); | ||||
if (ret != 0) { | if (ret != 0) { | ||||
device_printf(dev, "Fail to allocate subchannel\n"); | device_printf(dev, "Fail to allocate subchannel\n"); | ||||
goto out; | goto out; | ||||
} | } | ||||
sema_wait(&net_dev->channel_init_sema); | sema_wait(&net_dev->channel_init_sema); | ||||
if (init_pkt->msgs.vers_5_msgs.subchn_complete.status != | if (init_pkt->msgs.vers_5_msgs.subchn_complete.status != | ||||
▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | |||||
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; | netvsc_dev *net_dev = sc->net_dev; | ||||
return (hv_rf_close_device((rndis_device *)net_dev->extension)); | return (hv_rf_close_device((rndis_device *)net_dev->extension)); | ||||
} | } | ||||
/* | |||||
* RNDIS filter on send request completion callback | |||||
*/ | |||||
static void | static void | ||||
hv_rf_on_send_request_completion(struct vmbus_channel *chan __unused, | hn_rndis_sent_cb(struct hn_send_ctx *sndc, struct netvsc_dev_ *net_dev, | ||||
void *context __unused) | struct vmbus_channel *chan __unused, const struct nvsp_msg_ *msg __unused) | ||||
{ | { | ||||
if (sndc->hn_chim_idx != NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) | |||||
hn_chim_free(net_dev, sndc->hn_chim_idx); | |||||
} | } | ||||
/* | |||||
* RNDIS filter on send request (halt only) completion callback | |||||
*/ | |||||
static void | static void | ||||
hv_rf_on_send_request_halt_completion(struct vmbus_channel *chan __unused, | hn_rndis_sent_halt(struct hn_send_ctx *sndc, struct netvsc_dev_ *net_dev, | ||||
void *context) | struct vmbus_channel *chan __unused, const struct nvsp_msg_ *msg __unused) | ||||
{ | { | ||||
rndis_request *request = context; | rndis_request *request = sndc->hn_cbarg; | ||||
if (sndc->hn_chim_idx != NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) | |||||
hn_chim_free(net_dev, sndc->hn_chim_idx); | |||||
/* | /* | ||||
* 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 hn_rx_ring *rxr, struct hn_tx_ring *txr) | hv_rf_channel_rollup(struct hn_rx_ring *rxr, struct hn_tx_ring *txr) | ||||
{ | { | ||||
netvsc_channel_rollup(rxr, txr); | netvsc_channel_rollup(rxr, txr); | ||||
} | } |