Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
Show First 20 Lines • Show All 160 Lines • ▼ Show 20 Lines | |||||
struct hn_txdesc { | struct hn_txdesc { | ||||
#ifndef HN_USE_TXDESC_BUFRING | #ifndef HN_USE_TXDESC_BUFRING | ||||
SLIST_ENTRY(hn_txdesc) link; | SLIST_ENTRY(hn_txdesc) link; | ||||
#endif | #endif | ||||
struct mbuf *m; | struct mbuf *m; | ||||
struct hn_tx_ring *txr; | struct hn_tx_ring *txr; | ||||
int refs; | int refs; | ||||
uint32_t flags; /* HN_TXD_FLAG_ */ | uint32_t flags; /* HN_TXD_FLAG_ */ | ||||
netvsc_packet netvsc_pkt; /* XXX to be removed */ | struct hn_send_ctx send_ctx; | ||||
bus_dmamap_t data_dmap; | bus_dmamap_t data_dmap; | ||||
bus_addr_t rndis_msg_paddr; | bus_addr_t rndis_msg_paddr; | ||||
rndis_msg *rndis_msg; | rndis_msg *rndis_msg; | ||||
bus_dmamap_t rndis_msg_dmap; | bus_dmamap_t rndis_msg_dmap; | ||||
}; | }; | ||||
▲ Show 20 Lines • Show All 598 Lines • ▼ Show 20 Lines | |||||
static __inline void | static __inline void | ||||
hn_txeof(struct hn_tx_ring *txr) | hn_txeof(struct hn_tx_ring *txr) | ||||
{ | { | ||||
txr->hn_has_txeof = 0; | txr->hn_has_txeof = 0; | ||||
txr->hn_txeof(txr); | txr->hn_txeof(txr); | ||||
} | } | ||||
static void | static void | ||||
hn_tx_done(struct vmbus_channel *chan, void *xpkt) | hn_tx_done(struct hn_send_ctx *sndc, struct netvsc_dev_ *net_dev, | ||||
struct vmbus_channel *chan, const struct nvsp_msg_ *msg __unused) | |||||
{ | { | ||||
netvsc_packet *packet = xpkt; | struct hn_txdesc *txd = sndc->hn_cbarg; | ||||
struct hn_txdesc *txd; | |||||
struct hn_tx_ring *txr; | struct hn_tx_ring *txr; | ||||
txd = (struct hn_txdesc *)(uintptr_t) | if (sndc->hn_chim_idx != NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) | ||||
packet->compl.send.send_completion_tid; | hn_chim_free(net_dev, sndc->hn_chim_idx); | ||||
txr = txd->txr; | txr = txd->txr; | ||||
KASSERT(txr->hn_chan == chan, | KASSERT(txr->hn_chan == chan, | ||||
("channel mismatch, on chan%u, should be chan%u", | ("channel mismatch, on chan%u, should be chan%u", | ||||
vmbus_chan_subidx(chan), vmbus_chan_subidx(txr->hn_chan))); | vmbus_chan_subidx(chan), vmbus_chan_subidx(txr->hn_chan))); | ||||
txr->hn_has_txeof = 1; | txr->hn_has_txeof = 1; | ||||
hn_txdesc_put(txr, txd); | hn_txdesc_put(txr, txd); | ||||
Show All 30 Lines | |||||
* If this function fails, then both txd and m_head0 will be freed. | * If this function fails, then both txd and m_head0 will be freed. | ||||
*/ | */ | ||||
static int | static int | ||||
hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) | hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) | ||||
{ | { | ||||
bus_dma_segment_t segs[HN_TX_DATA_SEGCNT_MAX]; | bus_dma_segment_t segs[HN_TX_DATA_SEGCNT_MAX]; | ||||
int error, nsegs, i; | int error, nsegs, i; | ||||
struct mbuf *m_head = *m_head0; | struct mbuf *m_head = *m_head0; | ||||
netvsc_packet *packet; | |||||
rndis_msg *rndis_mesg; | rndis_msg *rndis_mesg; | ||||
rndis_packet *rndis_pkt; | rndis_packet *rndis_pkt; | ||||
rndis_per_packet_info *rppi; | rndis_per_packet_info *rppi; | ||||
struct rndis_hash_value *hash_value; | struct rndis_hash_value *hash_value; | ||||
uint32_t rndis_msg_size; | uint32_t rndis_msg_size, tot_data_buf_len, send_buf_section_idx; | ||||
int send_buf_section_size; | |||||
packet = &txd->netvsc_pkt; | tot_data_buf_len = m_head->m_pkthdr.len; | ||||
packet->is_data_pkt = TRUE; | |||||
packet->tot_data_buf_len = m_head->m_pkthdr.len; | |||||
/* | /* | ||||
* extension points to the area reserved for the | * extension points to the area reserved for the | ||||
* rndis_filter_packet, which is placed just after | * rndis_filter_packet, which is placed just after | ||||
* the netvsc_packet (and rppi struct, if present; | * the netvsc_packet (and rppi struct, if present; | ||||
* length is updated later). | * length is updated later). | ||||
*/ | */ | ||||
rndis_mesg = txd->rndis_msg; | rndis_mesg = txd->rndis_msg; | ||||
/* XXX not necessary */ | /* XXX not necessary */ | ||||
memset(rndis_mesg, 0, HN_RNDIS_MSG_LEN); | memset(rndis_mesg, 0, HN_RNDIS_MSG_LEN); | ||||
rndis_mesg->ndis_msg_type = REMOTE_NDIS_PACKET_MSG; | rndis_mesg->ndis_msg_type = REMOTE_NDIS_PACKET_MSG; | ||||
rndis_pkt = &rndis_mesg->msg.packet; | rndis_pkt = &rndis_mesg->msg.packet; | ||||
rndis_pkt->data_offset = sizeof(rndis_packet); | rndis_pkt->data_offset = sizeof(rndis_packet); | ||||
rndis_pkt->data_length = packet->tot_data_buf_len; | rndis_pkt->data_length = tot_data_buf_len; | ||||
rndis_pkt->per_pkt_info_offset = sizeof(rndis_packet); | rndis_pkt->per_pkt_info_offset = sizeof(rndis_packet); | ||||
rndis_msg_size = RNDIS_MESSAGE_SIZE(rndis_packet); | rndis_msg_size = RNDIS_MESSAGE_SIZE(rndis_packet); | ||||
/* | /* | ||||
* Set the hash value for this packet, so that the host could | * Set the hash value for this packet, so that the host could | ||||
* dispatch the TX done event for this packet back to this TX | * dispatch the TX done event for this packet back to this TX | ||||
* ring's channel. | * ring's channel. | ||||
▲ Show 20 Lines • Show All 91 Lines • ▼ Show 20 Lines | #endif | ||||
if (m_head->m_pkthdr.csum_flags & CSUM_TCP) { | if (m_head->m_pkthdr.csum_flags & CSUM_TCP) { | ||||
csum_info->xmit.tcp_csum = 1; | csum_info->xmit.tcp_csum = 1; | ||||
csum_info->xmit.tcp_header_offset = 0; | csum_info->xmit.tcp_header_offset = 0; | ||||
} else if (m_head->m_pkthdr.csum_flags & CSUM_UDP) { | } else if (m_head->m_pkthdr.csum_flags & CSUM_UDP) { | ||||
csum_info->xmit.udp_csum = 1; | csum_info->xmit.udp_csum = 1; | ||||
} | } | ||||
} | } | ||||
rndis_mesg->msg_len = packet->tot_data_buf_len + rndis_msg_size; | rndis_mesg->msg_len = tot_data_buf_len + rndis_msg_size; | ||||
packet->tot_data_buf_len = rndis_mesg->msg_len; | tot_data_buf_len = rndis_mesg->msg_len; | ||||
/* | /* | ||||
* Chimney send, if the packet could fit into one chimney buffer. | * Chimney send, if the packet could fit into one chimney buffer. | ||||
*/ | */ | ||||
if (packet->tot_data_buf_len < txr->hn_tx_chimney_size) { | if (tot_data_buf_len < txr->hn_tx_chimney_size) { | ||||
netvsc_dev *net_dev = txr->hn_sc->net_dev; | netvsc_dev *net_dev = txr->hn_sc->net_dev; | ||||
uint32_t send_buf_section_idx; | |||||
txr->hn_tx_chimney_tried++; | txr->hn_tx_chimney_tried++; | ||||
send_buf_section_idx = | send_buf_section_idx = | ||||
hv_nv_get_next_send_section(net_dev); | 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) { | ||||
uint8_t *dest = ((uint8_t *)net_dev->send_buf + | uint8_t *dest = ((uint8_t *)net_dev->send_buf + | ||||
(send_buf_section_idx * | (send_buf_section_idx * | ||||
net_dev->send_section_size)); | net_dev->send_section_size)); | ||||
memcpy(dest, rndis_mesg, rndis_msg_size); | memcpy(dest, rndis_mesg, rndis_msg_size); | ||||
dest += rndis_msg_size; | dest += rndis_msg_size; | ||||
m_copydata(m_head, 0, m_head->m_pkthdr.len, dest); | m_copydata(m_head, 0, m_head->m_pkthdr.len, dest); | ||||
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; | |||||
txr->hn_gpa_cnt = 0; | txr->hn_gpa_cnt = 0; | ||||
txr->hn_tx_chimney++; | txr->hn_tx_chimney++; | ||||
goto done; | goto done; | ||||
} | } | ||||
} | } | ||||
error = hn_txdesc_dmamap_load(txr, txd, &m_head, segs, &nsegs); | error = hn_txdesc_dmamap_load(txr, txd, &m_head, segs, &nsegs); | ||||
if (error) { | if (error) { | ||||
Show All 30 Lines | for (i = 0; i < nsegs; ++i) { | ||||
struct vmbus_gpa *gpa = &txr->hn_gpa[ | struct vmbus_gpa *gpa = &txr->hn_gpa[ | ||||
i + HV_RF_NUM_TX_RESERVED_PAGE_BUFS]; | i + HV_RF_NUM_TX_RESERVED_PAGE_BUFS]; | ||||
gpa->gpa_page = atop(segs[i].ds_addr); | gpa->gpa_page = atop(segs[i].ds_addr); | ||||
gpa->gpa_ofs = segs[i].ds_addr & PAGE_MASK; | gpa->gpa_ofs = segs[i].ds_addr & PAGE_MASK; | ||||
gpa->gpa_len = segs[i].ds_len; | gpa->gpa_len = segs[i].ds_len; | ||||
} | } | ||||
packet->send_buf_section_idx = | send_buf_section_idx = NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX; | ||||
NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX; | send_buf_section_size = 0; | ||||
packet->send_buf_section_size = 0; | |||||
done: | done: | ||||
txd->m = m_head; | txd->m = m_head; | ||||
/* Set the completion routine */ | /* Set the completion routine */ | ||||
packet->compl.send.on_send_completion = hn_tx_done; | hn_send_ctx_init(&txd->send_ctx, hn_tx_done, txd, | ||||
packet->compl.send.send_completion_context = packet; | send_buf_section_idx, send_buf_section_size); | ||||
packet->compl.send.send_completion_tid = (uint64_t)(uintptr_t)txd; | |||||
return 0; | return 0; | ||||
} | } | ||||
/* | /* | ||||
* NOTE: | * NOTE: | ||||
* If this function fails, then txd will be freed, but the mbuf | * If this function fails, then txd will be freed, but the mbuf | ||||
* associated w/ the txd will _not_ be freed. | * associated w/ the txd will _not_ be freed. | ||||
*/ | */ | ||||
static int | static int | ||||
hn_send_pkt(struct ifnet *ifp, struct hn_tx_ring *txr, struct hn_txdesc *txd) | hn_send_pkt(struct ifnet *ifp, struct hn_tx_ring *txr, struct hn_txdesc *txd) | ||||
{ | { | ||||
int error, send_failed = 0; | int error, send_failed = 0; | ||||
again: | again: | ||||
/* | /* | ||||
* Make sure that txd is not freed before ETHER_BPF_MTAP. | * Make sure that txd is not freed before ETHER_BPF_MTAP. | ||||
*/ | */ | ||||
hn_txdesc_hold(txd); | hn_txdesc_hold(txd); | ||||
error = hv_nv_on_send(txr->hn_chan, &txd->netvsc_pkt, | error = hv_nv_on_send(txr->hn_chan, true, &txd->send_ctx, | ||||
txr->hn_gpa, txr->hn_gpa_cnt); | txr->hn_gpa, txr->hn_gpa_cnt); | ||||
if (!error) { | if (!error) { | ||||
ETHER_BPF_MTAP(ifp, txd->m); | ETHER_BPF_MTAP(ifp, txd->m); | ||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); | if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); | ||||
if (!hn_use_if_start) { | if (!hn_use_if_start) { | ||||
if_inc_counter(ifp, IFCOUNTER_OBYTES, | if_inc_counter(ifp, IFCOUNTER_OBYTES, | ||||
txd->m->m_pkthdr.len); | txd->m->m_pkthdr.len); | ||||
if (txd->m->m_flags & M_MCAST) | if (txd->m->m_flags & M_MCAST) | ||||
▲ Show 20 Lines • Show All 1,962 Lines • Show Last 20 Lines |