hyperv/hn: Recover half of the chimney sending space

We lost half of the chimney sending space, because we mis-used
ffs() on a 64 bits mask, where ffsl() should be used.

While I'm here:
- Use system atomic operation instead.
- Stringent chimney sending index assertion.

Reviewed by:	adrian
Approved by:	adrian (mentor)
MFC after:	1 week
Sponsored by:	Microsoft OSTC
Differential Revision:	https://reviews.freebsd.org/D5159
This commit is contained in:
Sepherosa Ziehau 2016-02-05 05:31:31 +00:00
parent b256e94549
commit 1e4bb37d22

View File

@ -136,15 +136,15 @@ hv_nv_get_next_send_section(netvsc_dev *net_dev)
int i;
for (i = 0; i < bitsmap_words; i++) {
idx = ffs(~bitsmap[i]);
idx = ffsl(~bitsmap[i]);
if (0 == idx)
continue;
idx--;
if (i * BITS_PER_LONG + idx >= net_dev->send_section_count)
return (ret);
KASSERT(i * BITS_PER_LONG + idx < net_dev->send_section_count,
("invalid i %d and idx %lu", i, idx));
if (synch_test_and_set_bit(idx, &bitsmap[i]))
if (atomic_testandset_long(&bitsmap[i], idx))
continue;
ret = i * BITS_PER_LONG + idx;
@ -789,8 +789,27 @@ hv_nv_on_send_completion(netvsc_dev *net_dev,
if (NULL != net_vsc_pkt) {
if (net_vsc_pkt->send_buf_section_idx !=
NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) {
synch_change_bit(net_vsc_pkt->send_buf_section_idx,
net_dev->send_section_bitsmap);
u_long mask;
int idx;
idx = net_vsc_pkt->send_buf_section_idx /
BITS_PER_LONG;
KASSERT(idx < net_dev->bitsmap_words,
("invalid section index %u",
net_vsc_pkt->send_buf_section_idx));
mask = 1UL <<
(net_vsc_pkt->send_buf_section_idx %
BITS_PER_LONG);
KASSERT(net_dev->send_section_bitsmap[idx] &
mask,
("index bitmap 0x%lx, section index %u, "
"bitmap idx %d, bitmask 0x%lx",
net_dev->send_section_bitsmap[idx],
net_vsc_pkt->send_buf_section_idx,
idx, mask));
atomic_clear_long(
&net_dev->send_section_bitsmap[idx], mask);
}
/* Notify the layer above us */