diff options
author | sephe <sephe@FreeBSD.org> | 2016-10-17 05:28:06 +0000 |
---|---|---|
committer | sephe <sephe@FreeBSD.org> | 2016-10-17 05:28:06 +0000 |
commit | 2db1a26248edbbf17b26fe3421c491dfe9d7a25c (patch) | |
tree | 611b5de6161e23aa958d63cea6095988291fe507 /sys | |
parent | 6e71a2ac17c192f1e242d06eddb8959724a09f79 (diff) | |
download | FreeBSD-src-2db1a26248edbbf17b26fe3421c491dfe9d7a25c.zip FreeBSD-src-2db1a26248edbbf17b26fe3421c491dfe9d7a25c.tar.gz |
MFC 303603-303605,303764
303603
hyperv/vmbus: Remove the artificial entry limit of SG and PRP list.
Just make sure that the total channel packet size does not exceed 1/2
data size of the TX bufring.
Sponsored by: Microsoft
Differential Revision: https://reviews.freebsd.org/D7359
303604
hyperv/storvsc: Set maxio to 128KB.
Sponsored by: Microsoft
Differential Revision: https://reviews.freebsd.org/D7360
303605
hyperv/storvsc: Stringent PRP list assertions
Sponsored by: Microsoft
Differential Revision: https://reviews.freebsd.org/D7361
303764
hyperv/vmbus: Only make sure the TX bufring will not be closed.
KVP can write data, whose size is > 1/2 TX bufring size.
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D7414
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/hyperv/include/vmbus.h | 3 | ||||
-rw-r--r-- | sys/dev/hyperv/netvsc/hv_net_vsc.h | 3 | ||||
-rw-r--r-- | sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c | 2 | ||||
-rw-r--r-- | sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c | 43 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/vmbus_brvar.h | 11 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/vmbus_chan.c | 12 |
6 files changed, 57 insertions, 17 deletions
diff --git a/sys/dev/hyperv/include/vmbus.h b/sys/dev/hyperv/include/vmbus.h index cb50643..8fde588 100644 --- a/sys/dev/hyperv/include/vmbus.h +++ b/sys/dev/hyperv/include/vmbus.h @@ -102,9 +102,6 @@ struct vmbus_chanpkt_rxbuf { struct vmbus_rxbuf_desc cp_rxbuf[]; } __packed; -#define VMBUS_CHAN_SGLIST_MAX 32 -#define VMBUS_CHAN_PRPLIST_MAX 32 - struct vmbus_channel; struct hyperv_guid; diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.h b/sys/dev/hyperv/netvsc/hv_net_vsc.h index 44b04c4..55a2a13 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.h +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.h @@ -1088,6 +1088,7 @@ struct vmbus_channel; typedef void (*pfn_on_send_rx_completion)(struct vmbus_channel *, void *); #define NETVSC_DEVICE_RING_BUFFER_SIZE (128 * PAGE_SIZE) +#define NETVSC_PACKET_MAXPAGE 32 #define NETVSC_VLAN_PRIO_MASK 0xe000 #define NETVSC_VLAN_PRIO_SHIFT 13 @@ -1137,7 +1138,7 @@ typedef struct netvsc_packet_ { uint32_t tot_data_buf_len; void *data; uint32_t gpa_cnt; - struct vmbus_gpa gpa[VMBUS_CHAN_SGLIST_MAX]; + struct vmbus_gpa gpa[NETVSC_PACKET_MAXPAGE]; } netvsc_packet; typedef struct { diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c index ea4d7db..5f0608b 100644 --- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c +++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c @@ -152,7 +152,7 @@ __FBSDID("$FreeBSD$"); #define HN_TX_DATA_MAXSIZE IP_MAXPACKET #define HN_TX_DATA_SEGSIZE PAGE_SIZE #define HN_TX_DATA_SEGCNT_MAX \ - (VMBUS_CHAN_SGLIST_MAX - HV_RF_NUM_TX_RESERVED_PAGE_BUFS) + (NETVSC_PACKET_MAXPAGE - HV_RF_NUM_TX_RESERVED_PAGE_BUFS) #define HN_DIRECT_TX_SIZE_DEF 128 diff --git a/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c b/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c index 946307f..7ec4a3f 100644 --- a/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c +++ b/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c @@ -88,10 +88,25 @@ __FBSDID("$FreeBSD$"); #define VSTOR_PKT_SIZE (sizeof(struct vstor_packet) - vmscsi_size_delta) -#define STORVSC_DATA_SEGCNT_MAX VMBUS_CHAN_PRPLIST_MAX +/* + * 33 segments are needed to allow 128KB maxio, in case the data + * in the first page is _not_ PAGE_SIZE aligned, e.g. + * + * |<----------- 128KB ----------->| + * | | + * 0 2K 4K 8K 16K 124K 128K 130K + * | | | | | | | | + * +--+--+-----+-----+.......+-----+--+--+ + * | | | | | | | | | DATA + * | | | | | | | | | + * +--+--+-----+-----+.......------+--+--+ + * | | | | + * | 1| 31 | 1| ...... # of segments + */ +#define STORVSC_DATA_SEGCNT_MAX 33 #define STORVSC_DATA_SEGSZ_MAX PAGE_SIZE #define STORVSC_DATA_SIZE_MAX \ - (STORVSC_DATA_SEGCNT_MAX * STORVSC_DATA_SEGSZ_MAX) + ((STORVSC_DATA_SEGCNT_MAX - 1) * STORVSC_DATA_SEGSZ_MAX) struct storvsc_softc; @@ -1388,6 +1403,7 @@ storvsc_action(struct cam_sim *sim, union ccb *ccb) cpi->hba_misc = PIM_NOBUSRESET; if (hv_storvsc_use_pim_unmapped) cpi->hba_misc |= PIM_UNMAPPED; + cpi->maxio = STORVSC_DATA_SIZE_MAX; cpi->hba_eng_cnt = 0; cpi->max_target = STORVSC_MAX_TARGETS; cpi->max_lun = sc->hs_drv_props->drv_max_luns_per_target; @@ -1761,13 +1777,28 @@ storvsc_xferbuf_prepare(void *arg, bus_dma_segment_t *segs, int nsegs, int error prplist->gpa_range.gpa_ofs = segs[0].ds_addr & PAGE_MASK; for (i = 0; i < nsegs; i++) { - prplist->gpa_page[i] = atop(segs[i].ds_addr); #ifdef INVARIANTS - if (i != 0 && i != nsegs - 1) { - KASSERT((segs[i].ds_addr & PAGE_MASK) == 0 && - segs[i].ds_len == PAGE_SIZE, ("not a full page")); + if (nsegs > 1) { + if (i == 0) { + KASSERT((segs[i].ds_addr & PAGE_MASK) + + segs[i].ds_len == PAGE_SIZE, + ("invalid 1st page, ofs 0x%jx, len %zu", + (uintmax_t)segs[i].ds_addr, + segs[i].ds_len)); + } else if (i == nsegs - 1) { + KASSERT((segs[i].ds_addr & PAGE_MASK) == 0, + ("invalid last page, ofs 0x%jx", + (uintmax_t)segs[i].ds_addr)); + } else { + KASSERT((segs[i].ds_addr & PAGE_MASK) == 0 && + segs[i].ds_len == PAGE_SIZE, + ("not a full page, ofs 0x%jx, len %zu", + (uintmax_t)segs[i].ds_addr, + segs[i].ds_len)); + } } #endif + prplist->gpa_page[i] = atop(segs[i].ds_addr); } reqp->prp_cnt = nsegs; } diff --git a/sys/dev/hyperv/vmbus/vmbus_brvar.h b/sys/dev/hyperv/vmbus/vmbus_brvar.h index 892845b..da0ca9d 100644 --- a/sys/dev/hyperv/vmbus/vmbus_brvar.h +++ b/sys/dev/hyperv/vmbus/vmbus_brvar.h @@ -71,6 +71,17 @@ struct vmbus_txbr { struct sysctl_ctx_list; struct sysctl_oid; +static __inline int +vmbus_txbr_maxpktsz(const struct vmbus_txbr *tbr) +{ + /* + * - 64 bits for the trailing start index (- sizeof(uint64_t)). + * - The rindex and windex can't be same (- 1). See + * the comment near vmbus_bufring.br_{r,w}index. + */ + return (tbr->txbr_dsize - sizeof(uint64_t) - 1); +} + void vmbus_br_sysctl_create(struct sysctl_ctx_list *ctx, struct sysctl_oid *br_tree, struct vmbus_br *br, const char *name); diff --git a/sys/dev/hyperv/vmbus/vmbus_chan.c b/sys/dev/hyperv/vmbus/vmbus_chan.c index a763547..bb88c0c 100644 --- a/sys/dev/hyperv/vmbus/vmbus_chan.c +++ b/sys/dev/hyperv/vmbus/vmbus_chan.c @@ -610,6 +610,8 @@ vmbus_chan_send(struct vmbus_channel *chan, uint16_t type, uint16_t flags, hlen = sizeof(pkt); pktlen = hlen + dlen; pad_pktlen = VMBUS_CHANPKT_TOTLEN(pktlen); + KASSERT(pad_pktlen <= vmbus_txbr_maxpktsz(&chan->ch_txbr), + ("invalid packet size %d", pad_pktlen)); pkt.cp_hdr.cph_type = type; pkt.cp_hdr.cph_flags = flags; @@ -640,12 +642,11 @@ vmbus_chan_send_sglist(struct vmbus_channel *chan, boolean_t send_evt; uint64_t pad = 0; - KASSERT(sglen < VMBUS_CHAN_SGLIST_MAX, - ("invalid sglist len %d", sglen)); - hlen = __offsetof(struct vmbus_chanpkt_sglist, cp_gpa[sglen]); pktlen = hlen + dlen; pad_pktlen = VMBUS_CHANPKT_TOTLEN(pktlen); + KASSERT(pad_pktlen <= vmbus_txbr_maxpktsz(&chan->ch_txbr), + ("invalid packet size %d", pad_pktlen)); pkt.cp_hdr.cph_type = VMBUS_CHANPKT_TYPE_GPA; pkt.cp_hdr.cph_flags = VMBUS_CHANPKT_FLAG_RC; @@ -681,13 +682,12 @@ vmbus_chan_send_prplist(struct vmbus_channel *chan, boolean_t send_evt; uint64_t pad = 0; - KASSERT(prp_cnt < VMBUS_CHAN_PRPLIST_MAX, - ("invalid prplist entry count %d", prp_cnt)); - hlen = __offsetof(struct vmbus_chanpkt_prplist, cp_range[0].gpa_page[prp_cnt]); pktlen = hlen + dlen; pad_pktlen = VMBUS_CHANPKT_TOTLEN(pktlen); + KASSERT(pad_pktlen <= vmbus_txbr_maxpktsz(&chan->ch_txbr), + ("invalid packet size %d", pad_pktlen)); pkt.cp_hdr.cph_type = VMBUS_CHANPKT_TYPE_GPA; pkt.cp_hdr.cph_flags = VMBUS_CHANPKT_FLAG_RC; |