From 845773a994638565570c3c346dfdcfed50716171 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Oct 20 2017 11:22:03 +0000 Subject: Merge remote-tracking branch 'origin/users/ohering/SLE15/for-next' into SLE15 --- diff --git a/patches.suse/msft-hv-1376-tools-hv-ignore-a-NIC-if-it-has-been-configured.patch b/patches.suse/msft-hv-1376-tools-hv-ignore-a-NIC-if-it-has-been-configured.patch new file mode 100644 index 0000000..0945a42 --- /dev/null +++ b/patches.suse/msft-hv-1376-tools-hv-ignore-a-NIC-if-it-has-been-configured.patch @@ -0,0 +1,67 @@ +From: "sixiao@microsoft.com" +Date: Fri, 14 Jul 2017 10:47:20 -0700 +Patch-mainline: v4.14-rc1 +Subject: tools: hv: ignore a NIC if it has been configured +Git-commit: 1c3a044c6013b7fcf4738129a1141c9c1994bb86 +References: fate#323887 + +Let bondvf.sh ignore this NIC if it has been configured, to prevent +user configuration from being overwritten unexpectly. + +Signed-off-by: Simon Xiao +Signed-off-by: David S. Miller +Acked-by: Olaf Hering +--- + tools/hv/bondvf.sh | 27 +++++++++++++++++++++++++-- + 1 file changed, 25 insertions(+), 2 deletions(-) + +diff --git a/tools/hv/bondvf.sh b/tools/hv/bondvf.sh +--- a/tools/hv/bondvf.sh ++++ b/tools/hv/bondvf.sh +@@ -211,6 +211,30 @@ function create_bond { + + echo $'\nBond name:' $bondname + ++ if [ $distro == ubuntu ] ++ then ++ local mainfn=$cfgdir/interfaces ++ local s="^[ \t]*(auto|iface|mapping|allow-.*)[ \t]+${bondname}" ++ ++ grep -E "$s" $mainfn ++ if [ $? -eq 0 ] ++ then ++ echo "WARNING: ${bondname} has been configured already" ++ return ++ fi ++ elif [ $distro == redhat ] || [ $distro == suse ] ++ then ++ local fn=$cfgdir/ifcfg-$bondname ++ if [ -f $fn ] ++ then ++ echo "WARNING: ${bondname} has been configured already" ++ return ++ fi ++ else ++ echo "Unsupported Distro: ${distro}" ++ return ++ fi ++ + echo configuring $primary + create_eth_cfg_pri_$distro $primary $bondname + +@@ -219,8 +243,6 @@ function create_bond { + + echo creating: $bondname with primary slave: $primary + create_bond_cfg_$distro $bondname $primary $secondary +- +- let bondcnt=bondcnt+1 + } + + for (( i=0; i < $eth_cnt-1; i++ )) +@@ -228,5 +250,6 @@ do + if [ -n "${list_match[$i]}" ] + then + create_bond ${list_eth[$i]} ${list_match[$i]} ++ let bondcnt=bondcnt+1 + fi + done diff --git a/patches.suse/msft-hv-1378-vmbus-simplify-hv_ringbuffer_read.patch b/patches.suse/msft-hv-1378-vmbus-simplify-hv_ringbuffer_read.patch new file mode 100644 index 0000000..9b6ede9 --- /dev/null +++ b/patches.suse/msft-hv-1378-vmbus-simplify-hv_ringbuffer_read.patch @@ -0,0 +1,190 @@ +From: Stephen Hemminger +Date: Sun, 25 Jun 2017 12:30:24 -0700 +Patch-mainline: v4.14-rc1 +Subject: vmbus: simplify hv_ringbuffer_read +Git-commit: 4226ff69a3dff78bead7d9a270423cd21f8d40b8 +References: fate#323887 + +With new iterator functions (and the double mapping) the ring buffer +read function can be greatly simplified. + +Signed-off-by: Stephen Hemminger +Signed-off-by: K. Y. Srinivasan +Signed-off-by: Greg Kroah-Hartman +Acked-by: Olaf Hering +--- + drivers/hv/ring_buffer.c | 118 +++++++---------------------------------------- + 1 file changed, 17 insertions(+), 101 deletions(-) + +diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c +--- a/drivers/hv/ring_buffer.c ++++ b/drivers/hv/ring_buffer.c +@@ -94,30 +94,6 @@ hv_set_next_write_location(struct hv_ring_buffer_info *ring_info, + ring_info->ring_buffer->write_index = next_write_location; + } + +-/* Get the next read location for the specified ring buffer. */ +-static inline u32 +-hv_get_next_read_location(const struct hv_ring_buffer_info *ring_info) +-{ +- return ring_info->ring_buffer->read_index; +-} +- +-/* +- * Get the next read location + offset for the specified ring buffer. +- * This allows the caller to skip. +- */ +-static inline u32 +-hv_get_next_readlocation_withoffset(const struct hv_ring_buffer_info *ring_info, +- u32 offset) +-{ +- u32 next = ring_info->ring_buffer->read_index; +- +- next += offset; +- if (next >= ring_info->ring_datasize) +- next -= ring_info->ring_datasize; +- +- return next; +-} +- + /* Set the next read location for the specified ring buffer. */ + static inline void + hv_set_next_read_location(struct hv_ring_buffer_info *ring_info, +@@ -141,29 +117,6 @@ hv_get_ring_bufferindices(struct hv_ring_buffer_info *ring_info) + return (u64)ring_info->ring_buffer->write_index << 32; + } + +-/* +- * Helper routine to copy to source from ring buffer. +- * Assume there is enough room. Handles wrap-around in src case only!! +- */ +-static u32 hv_copyfrom_ringbuffer( +- const struct hv_ring_buffer_info *ring_info, +- void *dest, +- u32 destlen, +- u32 start_read_offset) +-{ +- void *ring_buffer = hv_get_ring_buffer(ring_info); +- u32 ring_buffer_size = hv_get_ring_buffersize(ring_info); +- +- memcpy(dest, ring_buffer + start_read_offset, destlen); +- +- start_read_offset += destlen; +- if (start_read_offset >= ring_buffer_size) +- start_read_offset -= ring_buffer_size; +- +- return start_read_offset; +-} +- +- + /* + * Helper routine to copy from source to ring buffer. + * Assume there is enough room. Handles wrap-around in dest case only!! +@@ -334,33 +287,22 @@ int hv_ringbuffer_write(struct vmbus_channel *channel, + return 0; + } + +-static inline void +-init_cached_read_index(struct hv_ring_buffer_info *rbi) +-{ +- rbi->cached_read_index = rbi->ring_buffer->read_index; +-} +- + int hv_ringbuffer_read(struct vmbus_channel *channel, + void *buffer, u32 buflen, u32 *buffer_actual_len, + u64 *requestid, bool raw) + { +- u32 bytes_avail_toread; +- u32 next_read_location; +- u64 prev_indices = 0; +- struct vmpacket_descriptor desc; +- u32 offset; +- u32 packetlen; +- struct hv_ring_buffer_info *inring_info = &channel->inbound; +- +- if (buflen <= 0) ++ struct vmpacket_descriptor *desc; ++ u32 packetlen, offset; ++ ++ if (unlikely(buflen == 0)) + return -EINVAL; + + *buffer_actual_len = 0; + *requestid = 0; + +- bytes_avail_toread = hv_get_bytes_to_read(inring_info); + /* Make sure there is something to read */ +- if (bytes_avail_toread < sizeof(desc)) { ++ desc = hv_pkt_iter_first(channel); ++ if (desc == NULL) { + /* + * No error is set when there is even no header, drivers are + * supposed to analyze buffer_actual_len. +@@ -368,48 +310,22 @@ int hv_ringbuffer_read(struct vmbus_channel *channel, + return 0; + } + +- init_cached_read_index(inring_info); +- +- next_read_location = hv_get_next_read_location(inring_info); +- next_read_location = hv_copyfrom_ringbuffer(inring_info, &desc, +- sizeof(desc), +- next_read_location); +- +- offset = raw ? 0 : (desc.offset8 << 3); +- packetlen = (desc.len8 << 3) - offset; ++ offset = raw ? 0 : (desc->offset8 << 3); ++ packetlen = (desc->len8 << 3) - offset; + *buffer_actual_len = packetlen; +- *requestid = desc.trans_id; +- +- if (bytes_avail_toread < packetlen + offset) +- return -EAGAIN; ++ *requestid = desc->trans_id; + +- if (packetlen > buflen) ++ if (unlikely(packetlen > buflen)) + return -ENOBUFS; + +- next_read_location = +- hv_get_next_readlocation_withoffset(inring_info, offset); ++ /* since ring is double mapped, only one copy is necessary */ ++ memcpy(buffer, (const char *)desc + offset, packetlen); + +- next_read_location = hv_copyfrom_ringbuffer(inring_info, +- buffer, +- packetlen, +- next_read_location); ++ /* Advance ring index to next packet descriptor */ ++ __hv_pkt_iter_next(channel, desc); + +- next_read_location = hv_copyfrom_ringbuffer(inring_info, +- &prev_indices, +- sizeof(u64), +- next_read_location); +- +- /* +- * Make sure all reads are done before we update the read index since +- * the writer may start writing to the read area once the read index +- * is updated. +- */ +- virt_mb(); +- +- /* Update the read index */ +- hv_set_next_read_location(inring_info, next_read_location); +- +- hv_signal_on_read(channel); ++ /* Notify host of update */ ++ hv_pkt_iter_close(channel); + + return 0; + } +@@ -442,7 +358,7 @@ struct vmpacket_descriptor *hv_pkt_iter_first(struct vmbus_channel *channel) + struct hv_ring_buffer_info *rbi = &channel->inbound; + + /* set state for later hv_signal_on_read() */ +- init_cached_read_index(rbi); ++ rbi->cached_read_index = rbi->ring_buffer->read_index; + + if (hv_pkt_iter_avail(rbi) < sizeof(struct vmpacket_descriptor)) + return NULL; diff --git a/patches.suse/msft-hv-1379-vmbus-drop-unused-ring_buffer_info-elements.patch b/patches.suse/msft-hv-1379-vmbus-drop-unused-ring_buffer_info-elements.patch new file mode 100644 index 0000000..79a504d --- /dev/null +++ b/patches.suse/msft-hv-1379-vmbus-drop-unused-ring_buffer_info-elements.patch @@ -0,0 +1,30 @@ +From: Stephen Hemminger +Date: Sun, 25 Jun 2017 12:30:25 -0700 +Patch-mainline: v4.14-rc1 +Subject: vmbus: drop unused ring_buffer_info elements +Git-commit: 95c40f41cfaf34e1c07812e93aa4b3263f9953f3 +References: fate#323887 + +The elements ring_data_start_offset and priv_write_index +are not used. + +Signed-off-by: Stephen Hemminger +Signed-off-by: K. Y. Srinivasan +Signed-off-by: Greg Kroah-Hartman +Acked-by: Olaf Hering +--- + include/linux/hyperv.h | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h +--- a/include/linux/hyperv.h ++++ b/include/linux/hyperv.h +@@ -124,8 +124,6 @@ struct hv_ring_buffer_info { + spinlock_t ring_lock; + + u32 ring_datasize; /* < ring_size */ +- u32 ring_data_startoffset; +- u32 priv_write_index; + u32 priv_read_index; + u32 cached_read_index; + }; diff --git a/patches.suse/msft-hv-1380-vmbus-refactor-hv_signal_on_read.patch b/patches.suse/msft-hv-1380-vmbus-refactor-hv_signal_on_read.patch new file mode 100644 index 0000000..abdab63 --- /dev/null +++ b/patches.suse/msft-hv-1380-vmbus-refactor-hv_signal_on_read.patch @@ -0,0 +1,141 @@ +From: Stephen Hemminger +Date: Sun, 25 Jun 2017 12:30:26 -0700 +Patch-mainline: v4.14-rc1 +Subject: vmbus: refactor hv_signal_on_read +Git-commit: 8dd45f2ab005a1f3301296059b23b03ec3dbf79b +References: fate#323887 + +The function hv_signal_on_read was defined in hyperv.h and +only used in one place in ring_buffer code. Clearer to just +move it inline there. + +Signed-off-by: Stephen Hemminger +Signed-off-by: K. Y. Srinivasan +Signed-off-by: Greg Kroah-Hartman +Acked-by: Olaf Hering +--- + drivers/hv/ring_buffer.c | 32 +++++++++++++++++++++++++++++-- + include/linux/hyperv.h | 49 ------------------------------------------------ + 2 files changed, 30 insertions(+), 51 deletions(-) + +diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c +--- a/drivers/hv/ring_buffer.c ++++ b/drivers/hv/ring_buffer.c +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + + #include "hyperv_vmbus.h" + +@@ -357,7 +358,7 @@ struct vmpacket_descriptor *hv_pkt_iter_first(struct vmbus_channel *channel) + { + struct hv_ring_buffer_info *rbi = &channel->inbound; + +- /* set state for later hv_signal_on_read() */ ++ /* set state for later hv_pkt_iter_close */ + rbi->cached_read_index = rbi->ring_buffer->read_index; + + if (hv_pkt_iter_avail(rbi) < sizeof(struct vmpacket_descriptor)) +@@ -400,6 +401,8 @@ EXPORT_SYMBOL_GPL(__hv_pkt_iter_next); + void hv_pkt_iter_close(struct vmbus_channel *channel) + { + struct hv_ring_buffer_info *rbi = &channel->inbound; ++ u32 cur_write_sz, cached_write_sz; ++ u32 pending_sz; + + /* + * Make sure all reads are done before we update the read index since +@@ -409,6 +412,31 @@ void hv_pkt_iter_close(struct vmbus_channel *channel) + virt_rmb(); + rbi->ring_buffer->read_index = rbi->priv_read_index; + +- hv_signal_on_read(channel); ++ /* ++ * Issue a full memory barrier before making the signaling decision. ++ * Here is the reason for having this barrier: ++ * If the reading of the pend_sz (in this function) ++ * were to be reordered and read before we commit the new read ++ * index (in the calling function) we could ++ * have a problem. If the host were to set the pending_sz after we ++ * have sampled pending_sz and go to sleep before we commit the ++ * read index, we could miss sending the interrupt. Issue a full ++ * memory barrier to address this. ++ */ ++ virt_mb(); ++ ++ pending_sz = READ_ONCE(rbi->ring_buffer->pending_send_sz); ++ /* If the other end is not blocked on write don't bother. */ ++ if (pending_sz == 0) ++ return; ++ ++ cur_write_sz = hv_get_bytes_to_write(rbi); ++ ++ if (cur_write_sz < pending_sz) ++ return; ++ ++ cached_write_sz = hv_get_cached_bytes_to_write(rbi); ++ if (cached_write_sz < pending_sz) ++ vmbus_setevent(channel); + } + EXPORT_SYMBOL_GPL(hv_pkt_iter_close); +diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h +--- a/include/linux/hyperv.h ++++ b/include/linux/hyperv.h +@@ -1471,55 +1471,6 @@ hv_get_ring_buffer(const struct hv_ring_buffer_info *ring_info) + return ring_info->ring_buffer->buffer; + } + +-/* +- * To optimize the flow management on the send-side, +- * when the sender is blocked because of lack of +- * sufficient space in the ring buffer, potential the +- * consumer of the ring buffer can signal the producer. +- * This is controlled by the following parameters: +- * +- * 1. pending_send_sz: This is the size in bytes that the +- * producer is trying to send. +- * 2. The feature bit feat_pending_send_sz set to indicate if +- * the consumer of the ring will signal when the ring +- * state transitions from being full to a state where +- * there is room for the producer to send the pending packet. +- */ +- +-static inline void hv_signal_on_read(struct vmbus_channel *channel) +-{ +- u32 cur_write_sz, cached_write_sz; +- u32 pending_sz; +- struct hv_ring_buffer_info *rbi = &channel->inbound; +- +- /* +- * Issue a full memory barrier before making the signaling decision. +- * Here is the reason for having this barrier: +- * If the reading of the pend_sz (in this function) +- * were to be reordered and read before we commit the new read +- * index (in the calling function) we could +- * have a problem. If the host were to set the pending_sz after we +- * have sampled pending_sz and go to sleep before we commit the +- * read index, we could miss sending the interrupt. Issue a full +- * memory barrier to address this. +- */ +- virt_mb(); +- +- pending_sz = READ_ONCE(rbi->ring_buffer->pending_send_sz); +- /* If the other end is not blocked on write don't bother. */ +- if (pending_sz == 0) +- return; +- +- cur_write_sz = hv_get_bytes_to_write(rbi); +- +- if (cur_write_sz < pending_sz) +- return; +- +- cached_write_sz = hv_get_cached_bytes_to_write(rbi); +- if (cached_write_sz < pending_sz) +- vmbus_setevent(channel); +-} +- + /* + * Mask off host interrupt callback notifications + */ diff --git a/patches.suse/msft-hv-1381-vmbus-eliminate-duplicate-cached-index.patch b/patches.suse/msft-hv-1381-vmbus-eliminate-duplicate-cached-index.patch new file mode 100644 index 0000000..50f560d --- /dev/null +++ b/patches.suse/msft-hv-1381-vmbus-eliminate-duplicate-cached-index.patch @@ -0,0 +1,101 @@ +From: Stephen Hemminger +Date: Sun, 25 Jun 2017 12:30:27 -0700 +Patch-mainline: v4.14-rc1 +Subject: vmbus: eliminate duplicate cached index +Git-commit: 05d00bc94ac27d220d8a78e365d7fa3a26dcca17 +References: fate#323887 + +Don't need cached read index anymore now that packet iterator +is used. The iterator has the original read index until the +visible read_index is updated. + +Signed-off-by: Stephen Hemminger +Signed-off-by: K. Y. Srinivasan +Signed-off-by: Greg Kroah-Hartman +Acked-by: Olaf Hering +--- + drivers/hv/ring_buffer.c | 17 ++++------------- + include/linux/hyperv.h | 14 -------------- + 2 files changed, 4 insertions(+), 27 deletions(-) + +diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c +--- a/drivers/hv/ring_buffer.c ++++ b/drivers/hv/ring_buffer.c +@@ -358,9 +358,6 @@ struct vmpacket_descriptor *hv_pkt_iter_first(struct vmbus_channel *channel) + { + struct hv_ring_buffer_info *rbi = &channel->inbound; + +- /* set state for later hv_pkt_iter_close */ +- rbi->cached_read_index = rbi->ring_buffer->read_index; +- + if (hv_pkt_iter_avail(rbi) < sizeof(struct vmpacket_descriptor)) + return NULL; + +@@ -388,10 +385,7 @@ __hv_pkt_iter_next(struct vmbus_channel *channel, + rbi->priv_read_index -= dsize; + + /* more data? */ +- if (hv_pkt_iter_avail(rbi) < sizeof(struct vmpacket_descriptor)) +- return NULL; +- else +- return hv_get_ring_buffer(rbi) + rbi->priv_read_index; ++ return hv_pkt_iter_first(channel); + } + EXPORT_SYMBOL_GPL(__hv_pkt_iter_next); + +@@ -401,7 +395,7 @@ EXPORT_SYMBOL_GPL(__hv_pkt_iter_next); + void hv_pkt_iter_close(struct vmbus_channel *channel) + { + struct hv_ring_buffer_info *rbi = &channel->inbound; +- u32 cur_write_sz, cached_write_sz; ++ u32 orig_write_sz = hv_get_bytes_to_write(rbi); + u32 pending_sz; + + /* +@@ -430,13 +424,10 @@ void hv_pkt_iter_close(struct vmbus_channel *channel) + if (pending_sz == 0) + return; + +- cur_write_sz = hv_get_bytes_to_write(rbi); +- +- if (cur_write_sz < pending_sz) ++ if (hv_get_bytes_to_write(rbi) < pending_sz) + return; + +- cached_write_sz = hv_get_cached_bytes_to_write(rbi); +- if (cached_write_sz < pending_sz) ++ if (orig_write_sz < pending_sz) + vmbus_setevent(channel); + } + EXPORT_SYMBOL_GPL(hv_pkt_iter_close); +diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h +--- a/include/linux/hyperv.h ++++ b/include/linux/hyperv.h +@@ -125,7 +125,6 @@ struct hv_ring_buffer_info { + + u32 ring_datasize; /* < ring_size */ + u32 priv_read_index; +- u32 cached_read_index; + }; + + /* +@@ -178,19 +177,6 @@ static inline u32 hv_get_bytes_to_write(const struct hv_ring_buffer_info *rbi) + return write; + } + +-static inline u32 hv_get_cached_bytes_to_write( +- const struct hv_ring_buffer_info *rbi) +-{ +- u32 read_loc, write_loc, dsize, write; +- +- dsize = rbi->ring_datasize; +- read_loc = rbi->cached_read_index; +- write_loc = rbi->ring_buffer->write_index; +- +- write = write_loc >= read_loc ? dsize - (write_loc - read_loc) : +- read_loc - write_loc; +- return write; +-} + /* + * VMBUS version is 32 bit entity broken up into + * two 16 bit quantities: major_number. minor_number. diff --git a/patches.suse/msft-hv-1382-vmbus-more-host-signalling-avoidance.patch b/patches.suse/msft-hv-1382-vmbus-more-host-signalling-avoidance.patch new file mode 100644 index 0000000..9b797ba --- /dev/null +++ b/patches.suse/msft-hv-1382-vmbus-more-host-signalling-avoidance.patch @@ -0,0 +1,65 @@ +From: Stephen Hemminger +Date: Sun, 25 Jun 2017 12:30:28 -0700 +Patch-mainline: v4.14-rc1 +Subject: vmbus: more host signalling avoidance +Git-commit: 03bad714a1619c0074eb44d6f217c505fe27030f +References: fate#323887 + +Don't signal host if it has disabled interrupts for that +ring buffer. Check the feature bit to see if host supports +pending send size flag. + +Signed-off-by: Stephen Hemminger +Signed-off-by: K. Y. Srinivasan +Signed-off-by: Greg Kroah-Hartman +Acked-by: Olaf Hering +--- + drivers/hv/ring_buffer.c | 27 +++++++++++++++++++-------- + 1 file changed, 19 insertions(+), 8 deletions(-) + +diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c +--- a/drivers/hv/ring_buffer.c ++++ b/drivers/hv/ring_buffer.c +@@ -396,7 +396,6 @@ void hv_pkt_iter_close(struct vmbus_channel *channel) + { + struct hv_ring_buffer_info *rbi = &channel->inbound; + u32 orig_write_sz = hv_get_bytes_to_write(rbi); +- u32 pending_sz; + + /* + * Make sure all reads are done before we update the read index since +@@ -419,15 +418,27 @@ void hv_pkt_iter_close(struct vmbus_channel *channel) + */ + virt_mb(); + +- pending_sz = READ_ONCE(rbi->ring_buffer->pending_send_sz); +- /* If the other end is not blocked on write don't bother. */ +- if (pending_sz == 0) ++ /* If host has disabled notifications then skip */ ++ if (rbi->ring_buffer->interrupt_mask) + return; + +- if (hv_get_bytes_to_write(rbi) < pending_sz) +- return; ++ if (rbi->ring_buffer->feature_bits.feat_pending_send_sz) { ++ u32 pending_sz = READ_ONCE(rbi->ring_buffer->pending_send_sz); + +- if (orig_write_sz < pending_sz) +- vmbus_setevent(channel); ++ /* ++ * If there was space before we began iteration, ++ * then host was not blocked. Also handles case where ++ * pending_sz is zero then host has nothing pending ++ * and does not need to be signaled. ++ */ ++ if (orig_write_sz > pending_sz) ++ return; ++ ++ /* If pending write will not fit, don't give false hope. */ ++ if (hv_get_bytes_to_write(rbi) < pending_sz) ++ return; ++ } ++ ++ vmbus_setevent(channel); + } + EXPORT_SYMBOL_GPL(hv_pkt_iter_close); diff --git a/patches.suse/msft-hv-1383-vmbus-add-prefetch-to-ring-buffer-iterator.patch b/patches.suse/msft-hv-1383-vmbus-add-prefetch-to-ring-buffer-iterator.patch new file mode 100644 index 0000000..9424cf1 --- /dev/null +++ b/patches.suse/msft-hv-1383-vmbus-add-prefetch-to-ring-buffer-iterator.patch @@ -0,0 +1,39 @@ +From: Stephen Hemminger +Date: Sun, 25 Jun 2017 12:30:29 -0700 +Patch-mainline: v4.14-rc1 +Subject: vmbus: add prefetch to ring buffer iterator +Git-commit: 15e1674de747d58c5a6154ba6e85bc61e5009b08 +References: fate#323887 + +When iterating over incoming ring elements from the host, prefetch +the next descriptor so that it is cache hot. + +Signed-off-by: Stephen Hemminger +Signed-off-by: K. Y. Srinivasan +Signed-off-by: Greg Kroah-Hartman +Acked-by: Olaf Hering +--- + drivers/hv/ring_buffer.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c +--- a/drivers/hv/ring_buffer.c ++++ b/drivers/hv/ring_buffer.c +@@ -357,11 +357,16 @@ static u32 hv_pkt_iter_avail(const struct hv_ring_buffer_info *rbi) + struct vmpacket_descriptor *hv_pkt_iter_first(struct vmbus_channel *channel) + { + struct hv_ring_buffer_info *rbi = &channel->inbound; ++ struct vmpacket_descriptor *desc; + + if (hv_pkt_iter_avail(rbi) < sizeof(struct vmpacket_descriptor)) + return NULL; + +- return hv_get_ring_buffer(rbi) + rbi->priv_read_index; ++ desc = hv_get_ring_buffer(rbi) + rbi->priv_read_index; ++ if (desc) ++ prefetch((char *)desc + (desc->len8 << 3)); ++ ++ return desc; + } + EXPORT_SYMBOL_GPL(hv_pkt_iter_first); + diff --git a/patches.suse/msft-hv-1384-x86-hyper-v-include-hyperv-only-when-CONFIG_HYPERV-i.patch b/patches.suse/msft-hv-1384-x86-hyper-v-include-hyperv-only-when-CONFIG_HYPERV-i.patch new file mode 100644 index 0000000..86f2c03 --- /dev/null +++ b/patches.suse/msft-hv-1384-x86-hyper-v-include-hyperv-only-when-CONFIG_HYPERV-i.patch @@ -0,0 +1,50 @@ +From: Vitaly Kuznetsov +Date: Sun, 25 Jun 2017 10:06:40 -0700 +Patch-mainline: v4.14-rc1 +Subject: x86/hyper-v: include hyperv/ only when CONFIG_HYPERV is set +Git-commit: 2e252fbf777d3b1250b63a5bf45e2ac1932687d3 +References: fate#323887 + +Code is arch/x86/hyperv/ is only needed when CONFIG_HYPERV is set, the +'basic' support and detection lives in arch/x86/kernel/cpu/mshyperv.c +which is included when CONFIG_HYPERVISOR_GUEST is set. + +Signed-off-by: Vitaly Kuznetsov +Reviewed-by: Andy Shevchenko +Signed-off-by: K. Y. Srinivasan +Signed-off-by: Greg Kroah-Hartman +Acked-by: Olaf Hering +--- + arch/x86/Kbuild | 2 +- + arch/x86/include/asm/mshyperv.h | 7 ++++++- + 2 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/arch/x86/Kbuild b/arch/x86/Kbuild +--- a/arch/x86/Kbuild ++++ b/arch/x86/Kbuild +@@ -8,7 +8,7 @@ obj-$(CONFIG_KVM) += kvm/ + obj-$(CONFIG_XEN) += xen/ + + # Hyper-V paravirtualization support +-obj-$(CONFIG_HYPERVISOR_GUEST) += hyperv/ ++obj-$(subst m,y,$(CONFIG_HYPERV)) += hyperv/ + + # lguest paravirtualization support + obj-$(CONFIG_LGUEST_GUEST) += lguest/ +diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h +--- a/arch/x86/include/asm/mshyperv.h ++++ b/arch/x86/include/asm/mshyperv.h +@@ -173,7 +173,12 @@ void hyperv_init(void); + void hyperv_report_panic(struct pt_regs *regs); + bool hv_is_hypercall_page_setup(void); + void hyperv_cleanup(void); +-#endif ++#else /* CONFIG_HYPERV */ ++static inline void hyperv_init(void) {} ++static inline bool hv_is_hypercall_page_setup(void) { return false; } ++static inline hyperv_cleanup(void) {} ++#endif /* CONFIG_HYPERV */ ++ + #ifdef CONFIG_HYPERV_TSCPAGE + struct ms_hyperv_tsc_page *hv_get_tsc_page(void); + static inline u64 hv_read_tsc_page(const struct ms_hyperv_tsc_page *tsc_pg) diff --git a/patches.suse/msft-hv-1385-x86-hyper-v-stash-the-max-number-of-virtual-logical-.patch b/patches.suse/msft-hv-1385-x86-hyper-v-stash-the-max-number-of-virtual-logical-.patch new file mode 100644 index 0000000..c0f8dc6 --- /dev/null +++ b/patches.suse/msft-hv-1385-x86-hyper-v-stash-the-max-number-of-virtual-logical-.patch @@ -0,0 +1,71 @@ +From: Vitaly Kuznetsov +Date: Sun, 25 Jun 2017 10:06:41 -0700 +Patch-mainline: v4.14-rc1 +Subject: x86/hyper-v: stash the max number of virtual/logical processor +Git-commit: dd018597a074bcd1e5307d3b8e7863e05287bddf +References: fate#323887 + +Max virtual processor will be needed for 'extended' hypercalls supporting +more than 64 vCPUs. While on it, unify on 'Hyper-V' in mshyperv.c as we +currently have a mix, report acquired misc features as well. + +Signed-off-by: Vitaly Kuznetsov +Reviewed-by: Andy Shevchenko +Signed-off-by: K. Y. Srinivasan +Signed-off-by: Greg Kroah-Hartman +Acked-by: Olaf Hering +--- + arch/x86/include/asm/mshyperv.h | 2 ++ + arch/x86/kernel/cpu/mshyperv.c | 12 +++++++++--- + 2 files changed, 11 insertions(+), 3 deletions(-) + +diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h +--- a/arch/x86/include/asm/mshyperv.h ++++ b/arch/x86/include/asm/mshyperv.h +@@ -28,6 +28,8 @@ struct ms_hyperv_info { + u32 features; + u32 misc_features; + u32 hints; ++ u32 max_vp_index; ++ u32 max_lp_index; + }; + + extern struct ms_hyperv_info ms_hyperv; +diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c +--- a/arch/x86/kernel/cpu/mshyperv.c ++++ b/arch/x86/kernel/cpu/mshyperv.c +@@ -184,9 +184,15 @@ static void __init ms_hyperv_init_platform(void) + ms_hyperv.misc_features = cpuid_edx(HYPERV_CPUID_FEATURES); + ms_hyperv.hints = cpuid_eax(HYPERV_CPUID_ENLIGHTMENT_INFO); + +- pr_info("HyperV: features 0x%x, hints 0x%x\n", ++ pr_info("Hyper-V: features 0x%x, hints 0x%x\n", + ms_hyperv.features, ms_hyperv.hints); + ++ ms_hyperv.max_vp_index = cpuid_eax(HVCPUID_IMPLEMENTATION_LIMITS); ++ ms_hyperv.max_lp_index = cpuid_ebx(HVCPUID_IMPLEMENTATION_LIMITS); ++ ++ pr_debug("Hyper-V: max %u virtual processors, %u logical processors\n", ++ ms_hyperv.max_vp_index, ms_hyperv.max_lp_index); ++ + /* + * Extract host information. + */ +@@ -219,7 +225,7 @@ static void __init ms_hyperv_init_platform(void) + rdmsrl(HV_X64_MSR_APIC_FREQUENCY, hv_lapic_frequency); + hv_lapic_frequency = div_u64(hv_lapic_frequency, HZ); + lapic_timer_frequency = hv_lapic_frequency; +- pr_info("HyperV: LAPIC Timer Frequency: %#x\n", ++ pr_info("Hyper-V: LAPIC Timer Frequency: %#x\n", + lapic_timer_frequency); + } + +@@ -253,7 +259,7 @@ static void __init ms_hyperv_init_platform(void) + } + + const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = { +- .name = "Microsoft HyperV", ++ .name = "Microsoft Hyper-V", + .detect = ms_hyperv_platform, + .init_platform = ms_hyperv_init_platform, + }; diff --git a/patches.suse/msft-hv-1394-Revert-x86-hyper-v-include-hyperv-only-when-CONFIG_H.patch b/patches.suse/msft-hv-1394-Revert-x86-hyper-v-include-hyperv-only-when-CONFIG_H.patch new file mode 100644 index 0000000..a5f5824 --- /dev/null +++ b/patches.suse/msft-hv-1394-Revert-x86-hyper-v-include-hyperv-only-when-CONFIG_H.patch @@ -0,0 +1,54 @@ +From: Greg Kroah-Hartman +Date: Thu, 20 Jul 2017 11:12:33 +0200 +Patch-mainline: v4.14-rc1 +Subject: Revert "x86/hyper-v: include hyperv/ only when CONFIG_HYPERV is set" +Git-commit: 91c17449fe04adfb12ff9523f62e9cd0d658a88d +References: fate#323887 + +This reverts commit 2e252fbf777d3b1250b63a5bf45e2ac1932687d3 as it is +obviously not correct. + +And it should have gone in through the x86 tree :( + +Reported-by: Colin King +Reported-by: Ingo Molnar +Reported-by: Stephen Rothwell +Cc: Vitaly Kuznetsov +Cc: Andy Shevchenko +Cc: K. Y. Srinivasan +Signed-off-by: Greg Kroah-Hartman +Acked-by: Olaf Hering +--- + arch/x86/Kbuild | 2 +- + arch/x86/include/asm/mshyperv.h | 7 +------ + 2 files changed, 2 insertions(+), 7 deletions(-) + +diff --git a/arch/x86/Kbuild b/arch/x86/Kbuild +--- a/arch/x86/Kbuild ++++ b/arch/x86/Kbuild +@@ -8,7 +8,7 @@ obj-$(CONFIG_KVM) += kvm/ + obj-$(CONFIG_XEN) += xen/ + + # Hyper-V paravirtualization support +-obj-$(subst m,y,$(CONFIG_HYPERV)) += hyperv/ ++obj-$(CONFIG_HYPERVISOR_GUEST) += hyperv/ + + # lguest paravirtualization support + obj-$(CONFIG_LGUEST_GUEST) += lguest/ +diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h +--- a/arch/x86/include/asm/mshyperv.h ++++ b/arch/x86/include/asm/mshyperv.h +@@ -175,12 +175,7 @@ void hyperv_init(void); + void hyperv_report_panic(struct pt_regs *regs); + bool hv_is_hypercall_page_setup(void); + void hyperv_cleanup(void); +-#else /* CONFIG_HYPERV */ +-static inline void hyperv_init(void) {} +-static inline bool hv_is_hypercall_page_setup(void) { return false; } +-static inline hyperv_cleanup(void) {} +-#endif /* CONFIG_HYPERV */ +- ++#endif + #ifdef CONFIG_HYPERV_TSCPAGE + struct ms_hyperv_tsc_page *hv_get_tsc_page(void); + static inline u64 hv_read_tsc_page(const struct ms_hyperv_tsc_page *tsc_pg) diff --git a/patches.suse/msft-hv-1410-netvsc-Initialize-64-bit-stats-seqcount.patch b/patches.suse/msft-hv-1410-netvsc-Initialize-64-bit-stats-seqcount.patch new file mode 100644 index 0000000..b3aee35 --- /dev/null +++ b/patches.suse/msft-hv-1410-netvsc-Initialize-64-bit-stats-seqcount.patch @@ -0,0 +1,35 @@ +From: Florian Fainelli +Date: Tue, 1 Aug 2017 12:11:12 -0700 +Patch-mainline: v4.13-rc5 +Subject: netvsc: Initialize 64-bit stats seqcount +Git-commit: 4a0dee1ffe0e8f4101e704a325e97f8997b0abcc +References: fate#323887 + +On 32-bit hosts and with CONFIG_DEBUG_LOCK_ALLOC we should be seeing a +lockdep splat indicating this seqcount is not correctly initialized, fix +that. In commit 6c80f3fc2398 ("netvsc: report per-channel stats in +ethtool statistics") netdev_alloc_pcpu_stats() was removed in favor of +open-coding the 64-bits statistics, except that u64_stats_init() was +missed. + +Fixes: 6c80f3fc2398 ("netvsc: report per-channel stats in ethtool statistics") +Signed-off-by: Florian Fainelli +Signed-off-by: Stephen Hemminger +Signed-off-by: David S. Miller +Acked-by: Olaf Hering +--- + drivers/net/hyperv/netvsc.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c +--- a/drivers/net/hyperv/netvsc.c ++++ b/drivers/net/hyperv/netvsc.c +@@ -1302,6 +1302,8 @@ int netvsc_device_add(struct hv_device *device, + + nvchan->channel = device->channel; + nvchan->net_device = net_device; ++ u64_stats_init(&nvchan->tx_stats.syncp); ++ u64_stats_init(&nvchan->rx_stats.syncp); + } + + /* Enable NAPI handler before init callbacks */ diff --git a/patches.suse/msft-hv-1413-netvsc-remove-bonding-setup-script.patch b/patches.suse/msft-hv-1413-netvsc-remove-bonding-setup-script.patch new file mode 100644 index 0000000..43b0b1d --- /dev/null +++ b/patches.suse/msft-hv-1413-netvsc-remove-bonding-setup-script.patch @@ -0,0 +1,278 @@ +From: stephen hemminger +Date: Tue, 1 Aug 2017 19:58:55 -0700 +Patch-mainline: v4.14-rc1 +Subject: netvsc: remove bonding setup script +Git-commit: 12aa7469d101e139b3728e540884bc7d72dca70a +References: fate#323887 + +No longer needed, now all managed by transparent VF logic. + +Signed-off-by: Stephen Hemminger +Signed-off-by: David S. Miller +Acked-by: Olaf Hering +--- + tools/hv/bondvf.sh | 255 ----------------------------------------------------- + 1 file changed, 255 deletions(-) + delete mode 100755 tools/hv/bondvf.sh + +diff --git a/tools/hv/bondvf.sh b/tools/hv/bondvf.sh +deleted file mode 100755 +index 80f102860cf8..000000000000 +--- a/tools/hv/bondvf.sh ++++ /dev/null +@@ -1,255 +0,0 @@ +-#!/bin/bash +- +-# This example script creates bonding network devices based on synthetic NIC +-# (the virtual network adapter usually provided by Hyper-V) and the matching +-# VF NIC (SRIOV virtual function). So the synthetic NIC and VF NIC can +-# function as one network device, and fail over to the synthetic NIC if VF is +-# down. +-# +-# Usage: +-# - After configured vSwitch and vNIC with SRIOV, start Linux virtual +-# machine (VM) +-# - Run this scripts on the VM. It will create configuration files in +-# distro specific directory. +-# - Reboot the VM, so that the bonding config are enabled. +-# +-# The config files are DHCP by default. You may edit them if you need to change +-# to Static IP or change other settings. +-# +- +-sysdir=/sys/class/net +-netvsc_cls={f8615163-df3e-46c5-913f-f2d2f965ed0e} +-bondcnt=0 +- +-# Detect Distro +-if [ -f /etc/redhat-release ]; +-then +- cfgdir=/etc/sysconfig/network-scripts +- distro=redhat +-elif grep -q 'Ubuntu' /etc/issue +-then +- cfgdir=/etc/network +- distro=ubuntu +-elif grep -q 'SUSE' /etc/issue +-then +- cfgdir=/etc/sysconfig/network +- distro=suse +-else +- echo "Unsupported Distro" +- exit 1 +-fi +- +-echo Detected Distro: $distro, or compatible +- +-# Get a list of ethernet names +-list_eth=(`cd $sysdir && ls -d */ | cut -d/ -f1 | grep -v bond`) +-eth_cnt=${#list_eth[@]} +- +-echo List of net devices: +- +-# Get the MAC addresses +-for (( i=0; i < $eth_cnt; i++ )) +-do +- list_mac[$i]=`cat $sysdir/${list_eth[$i]}/address` +- echo ${list_eth[$i]}, ${list_mac[$i]} +-done +- +-# Find NIC with matching MAC +-for (( i=0; i < $eth_cnt-1; i++ )) +-do +- for (( j=i+1; j < $eth_cnt; j++ )) +- do +- if [ "${list_mac[$i]}" = "${list_mac[$j]}" ] +- then +- list_match[$i]=${list_eth[$j]} +- break +- fi +- done +-done +- +-function create_eth_cfg_redhat { +- local fn=$cfgdir/ifcfg-$1 +- +- rm -f $fn +- echo DEVICE=$1 >>$fn +- echo TYPE=Ethernet >>$fn +- echo BOOTPROTO=none >>$fn +- echo UUID=`uuidgen` >>$fn +- echo ONBOOT=yes >>$fn +- echo PEERDNS=yes >>$fn +- echo IPV6INIT=yes >>$fn +- echo MASTER=$2 >>$fn +- echo SLAVE=yes >>$fn +-} +- +-function create_eth_cfg_pri_redhat { +- create_eth_cfg_redhat $1 $2 +-} +- +-function create_bond_cfg_redhat { +- local fn=$cfgdir/ifcfg-$1 +- +- rm -f $fn +- echo DEVICE=$1 >>$fn +- echo TYPE=Bond >>$fn +- echo BOOTPROTO=dhcp >>$fn +- echo UUID=`uuidgen` >>$fn +- echo ONBOOT=yes >>$fn +- echo PEERDNS=yes >>$fn +- echo IPV6INIT=yes >>$fn +- echo BONDING_MASTER=yes >>$fn +- echo BONDING_OPTS=\"mode=active-backup miimon=100 primary=$2\" >>$fn +-} +- +-function del_eth_cfg_ubuntu { +- local mainfn=$cfgdir/interfaces +- local fnlist=( $mainfn ) +- +- local dirlist=(`awk '/^[ \t]*source/{print $2}' $mainfn`) +- +- local i +- for i in "${dirlist[@]}" +- do +- fnlist+=(`ls $i 2>/dev/null`) +- done +- +- local tmpfl=$(mktemp) +- +- local nic_start='^[ \t]*(auto|iface|mapping|allow-.*)[ \t]+'$1 +- local nic_end='^[ \t]*(auto|iface|mapping|allow-.*|source)' +- +- local fn +- for fn in "${fnlist[@]}" +- do +- awk "/$nic_end/{x=0} x{next} /$nic_start/{x=1;next} 1" \ +- $fn >$tmpfl +- +- cp $tmpfl $fn +- done +- +- rm $tmpfl +-} +- +-function create_eth_cfg_ubuntu { +- local fn=$cfgdir/interfaces +- +- del_eth_cfg_ubuntu $1 +- echo $'\n'auto $1 >>$fn +- echo iface $1 inet manual >>$fn +- echo bond-master $2 >>$fn +-} +- +-function create_eth_cfg_pri_ubuntu { +- local fn=$cfgdir/interfaces +- +- del_eth_cfg_ubuntu $1 +- echo $'\n'allow-hotplug $1 >>$fn +- echo iface $1 inet manual >>$fn +- echo bond-master $2 >>$fn +- echo bond-primary $1 >>$fn +-} +- +-function create_bond_cfg_ubuntu { +- local fn=$cfgdir/interfaces +- +- del_eth_cfg_ubuntu $1 +- +- echo $'\n'auto $1 >>$fn +- echo iface $1 inet dhcp >>$fn +- echo bond-mode active-backup >>$fn +- echo bond-miimon 100 >>$fn +- echo bond-slaves none >>$fn +-} +- +-function create_eth_cfg_suse { +- local fn=$cfgdir/ifcfg-$1 +- +- rm -f $fn +- echo BOOTPROTO=none >>$fn +- echo STARTMODE=auto >>$fn +-} +- +-function create_eth_cfg_pri_suse { +- local fn=$cfgdir/ifcfg-$1 +- +- rm -f $fn +- echo BOOTPROTO=none >>$fn +- echo STARTMODE=hotplug >>$fn +-} +- +-function create_bond_cfg_suse { +- local fn=$cfgdir/ifcfg-$1 +- +- rm -f $fn +- echo BOOTPROTO=dhcp >>$fn +- echo STARTMODE=auto >>$fn +- echo BONDING_MASTER=yes >>$fn +- echo BONDING_SLAVE_0=$2 >>$fn +- echo BONDING_SLAVE_1=$3 >>$fn +- echo BONDING_MODULE_OPTS=\'mode=active-backup miimon=100 primary=$2\' >>$fn +-} +- +-function create_bond { +- local bondname=bond$bondcnt +- local primary +- local secondary +- +- local class_id1=`cat $sysdir/$1/device/class_id 2>/dev/null` +- local class_id2=`cat $sysdir/$2/device/class_id 2>/dev/null` +- +- if [ "$class_id1" = "$netvsc_cls" ] +- then +- primary=$2 +- secondary=$1 +- elif [ "$class_id2" = "$netvsc_cls" ] +- then +- primary=$1 +- secondary=$2 +- else +- return 0 +- fi +- +- echo $'\nBond name:' $bondname +- +- if [ $distro == ubuntu ] +- then +- local mainfn=$cfgdir/interfaces +- local s="^[ \t]*(auto|iface|mapping|allow-.*)[ \t]+${bondname}" +- +- grep -E "$s" $mainfn +- if [ $? -eq 0 ] +- then +- echo "WARNING: ${bondname} has been configured already" +- return +- fi +- elif [ $distro == redhat ] || [ $distro == suse ] +- then +- local fn=$cfgdir/ifcfg-$bondname +- if [ -f $fn ] +- then +- echo "WARNING: ${bondname} has been configured already" +- return +- fi +- else +- echo "Unsupported Distro: ${distro}" +- return +- fi +- +- echo configuring $primary +- create_eth_cfg_pri_$distro $primary $bondname +- +- echo configuring $secondary +- create_eth_cfg_$distro $secondary $bondname +- +- echo creating: $bondname with primary slave: $primary +- create_bond_cfg_$distro $bondname $primary $secondary +-} +- +-for (( i=0; i < $eth_cnt-1; i++ )) +-do +- if [ -n "${list_match[$i]}" ] +- then +- create_bond ${list_eth[$i]} ${list_match[$i]} +- let bondcnt=bondcnt+1 +- fi +-done diff --git a/patches.suse/msft-hv-1414-PCI-hv-Do-not-sleep-in-compose_msi_msg.patch b/patches.suse/msft-hv-1414-PCI-hv-Do-not-sleep-in-compose_msi_msg.patch new file mode 100644 index 0000000..345267c --- /dev/null +++ b/patches.suse/msft-hv-1414-PCI-hv-Do-not-sleep-in-compose_msi_msg.patch @@ -0,0 +1,57 @@ +From: Stephen Hemminger +Date: Mon, 31 Jul 2017 16:48:29 -0700 +Patch-mainline: v4.14-rc1 +Subject: PCI: hv: Do not sleep in compose_msi_msg() +Git-commit: 80bfeeb9dd6b54ac108c884c792f0fc7d4912bee +References: fate#323887 + +The setup of MSI with Hyper-V host was sleeping with locks held. This +error is reported when doing SR-IOV hotplug with kernel built with lockdep: + + BUG: sleeping function called from invalid context at kernel/sched/completion.c:93 + in_atomic(): 1, irqs_disabled(): 1, pid: 1405, name: ip + 3 locks held by ip/1405: + #0: (rtnl_mutex){+.+.+.}, at: [] rtnetlink_rcv+0x1b/0x40 + #1: (&desc->request_mutex){+.+...}, at: [] __setup_irq+0xb3/0x720 + #2: (&irq_desc_lock_class){-.-...}, at: [] __setup_irq+0xe5/0x720 + irq event stamp: 3476 + hardirqs last enabled at (3475): [] get_page_from_freelist+0x225/0xc90 + hardirqs last disabled at (3476): [] _raw_spin_lock_irqsave+0x27/0x90 + softirqs last enabled at (2446): [] ixgbevf_configure+0x380/0x7c0 [ixgbevf] + softirqs last disabled at (2444): [] ixgbevf_configure+0x35d/0x7c0 [ixgbevf] + +The workaround is to poll for host response instead of blocking on +completion. + +Signed-off-by: Stephen Hemminger +Signed-off-by: Bjorn Helgaas +Acked-by: Olaf Hering +--- + drivers/pci/host/pci-hyperv.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/pci/host/pci-hyperv.c b/drivers/pci/host/pci-hyperv.c +--- a/drivers/pci/host/pci-hyperv.c ++++ b/drivers/pci/host/pci-hyperv.c +@@ -50,6 +50,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1159,7 +1160,12 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) + goto free_int_desc; + } + +- wait_for_completion(&comp.comp_pkt.host_event); ++ /* ++ * Since this function is called with IRQ locks held, can't ++ * do normal wait for completion; instead poll. ++ */ ++ while (!try_wait_for_completion(&comp.comp_pkt.host_event)) ++ udelay(100); + + if (comp.comp_pkt.completion_status < 0) { + dev_err(&hbus->hdev->device, diff --git a/patches.suse/msft-hv-1415-netvsc-fix-race-on-sub-channel-creation.patch b/patches.suse/msft-hv-1415-netvsc-fix-race-on-sub-channel-creation.patch new file mode 100644 index 0000000..ed74253 --- /dev/null +++ b/patches.suse/msft-hv-1415-netvsc-fix-race-on-sub-channel-creation.patch @@ -0,0 +1,121 @@ +From: stephen hemminger +Date: Thu, 3 Aug 2017 17:13:54 -0700 +Patch-mainline: v4.13-rc5 +Subject: netvsc: fix race on sub channel creation +Git-commit: 732e49850c5e15231e11a0a464748bcbade5e3c2 +References: fate#323887 + +The existing sub channel code did not wait for all the sub-channels +to completely initialize. This could lead to race causing crash +in napi_netif_del() from bad list. The existing code would send +an init message, then wait only for the initial response that +the init message was received. It thought it was waiting for +sub channels but really the init response did the wakeup. + +The new code keeps track of the number of open channels and +waits until that many are open. + +Other issues here were: + * host might return less sub-channels than was requested. + * the new init status is not valid until after init was completed. + +Fixes: b3e6b82a0099 ("hv_netvsc: Wait for sub-channels to be processed during probe") +Signed-off-by: Stephen Hemminger +Signed-off-by: David S. Miller +Acked-by: Olaf Hering +--- + drivers/net/hyperv/hyperv_net.h | 3 ++- + drivers/net/hyperv/netvsc.c | 1 + + drivers/net/hyperv/rndis_filter.c | 14 ++++++++------ + 3 files changed, 11 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h +--- a/drivers/net/hyperv/hyperv_net.h ++++ b/drivers/net/hyperv/hyperv_net.h +@@ -765,7 +765,8 @@ struct netvsc_device { + u32 max_chn; + u32 num_chn; + +- refcount_t sc_offered; ++ atomic_t open_chn; ++ wait_queue_head_t subchan_open; + + struct rndis_device *extension; + +diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c +--- a/drivers/net/hyperv/netvsc.c ++++ b/drivers/net/hyperv/netvsc.c +@@ -78,6 +78,7 @@ static struct netvsc_device *alloc_net_device(void) + net_device->max_pkt = RNDIS_MAX_PKT_DEFAULT; + net_device->pkt_align = RNDIS_PKT_ALIGN_DEFAULT; + init_completion(&net_device->channel_init_wait); ++ init_waitqueue_head(&net_device->subchan_open); + + return net_device; + } +diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c +--- a/drivers/net/hyperv/rndis_filter.c ++++ b/drivers/net/hyperv/rndis_filter.c +@@ -1048,8 +1048,8 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc) + else + netif_napi_del(&nvchan->napi); + +- if (refcount_dec_and_test(&nvscdev->sc_offered)) +- complete(&nvscdev->channel_init_wait); ++ atomic_inc(&nvscdev->open_chn); ++ wake_up(&nvscdev->subchan_open); + } + + struct netvsc_device *rndis_filter_device_add(struct hv_device *dev, +@@ -1090,8 +1090,6 @@ int rndis_filter_device_add(struct hv_device *dev, + net_device->max_chn = 1; + net_device->num_chn = 1; + +- refcount_set(&net_device->sc_offered, 0); +- + net_device->extension = rndis_device; + rndis_device->ndev = net; + +@@ -1221,20 +1219,20 @@ int rndis_filter_device_add(struct hv_device *dev, + rndis_device->ind_table[i] = ethtool_rxfh_indir_default(i, + net_device->num_chn); + ++ atomic_set(&net_device->open_chn, 1); + num_rss_qs = net_device->num_chn - 1; + if (num_rss_qs == 0) + return net_device; + + for (i = 1; i < net_device->num_chn; i++) { + ret = netvsc_alloc_recv_comp_ring(net_device, i); + if (ret) { + while (--i != 0) + vfree(net_device->chan_table[i].mrc.slots); + goto out; + } + } + +- refcount_set(&net_device->sc_offered, num_rss_qs); + vmbus_set_sc_create_callback(dev->channel, netvsc_sc_open); + + init_packet = &net_device->channel_init_pkt; +@@ -1242,15 +1240,19 @@ int rndis_filter_device_add(struct hv_device *dev, + if (ret) + goto out; + ++ wait_for_completion(&net_device->channel_init_wait); + if (init_packet->msg.v5_msg.subchn_comp.status != NVSP_STAT_SUCCESS) { + ret = -ENODEV; + goto out; + } +- wait_for_completion(&net_device->channel_init_wait); + + net_device->num_chn = 1 + + init_packet->msg.v5_msg.subchn_comp.num_subchannels; + ++ /* wait for all sub channels to open */ ++ wait_event(net_device->subchan_open, ++ atomic_read(&net_device->open_chn) == net_device->num_chn); ++ + /* ignore failues from setting rss parameters, still have channels */ + rndis_filter_set_rss_param(rndis_device, netvsc_hash_key, + net_device->num_chn); diff --git a/patches.suse/msft-hv-1418-x86-hyper-v-Include-hyperv-only-when-CONFIG_HYPERV-i.patch b/patches.suse/msft-hv-1418-x86-hyper-v-Include-hyperv-only-when-CONFIG_HYPERV-i.patch new file mode 100644 index 0000000..6117198 --- /dev/null +++ b/patches.suse/msft-hv-1418-x86-hyper-v-Include-hyperv-only-when-CONFIG_HYPERV-i.patch @@ -0,0 +1,61 @@ +From: Vitaly Kuznetsov +Date: Wed, 2 Aug 2017 18:09:13 +0200 +Patch-mainline: v4.14-rc1 +Subject: x86/hyper-v: Include hyperv/ only when CONFIG_HYPERV is set +Git-commit: 79cadff2d92bb8b1448f6dba6861d15adc3dc4cb +References: fate#323887 + +Code is arch/x86/hyperv/ is only needed when CONFIG_HYPERV is set, the +'basic' support and detection lives in arch/x86/kernel/cpu/mshyperv.c +which is included when CONFIG_HYPERVISOR_GUEST is set. + +Signed-off-by: Vitaly Kuznetsov +Reviewed-by: Andy Shevchenko +Reviewed-by: Stephen Hemminger +Cc: Andy Lutomirski +Cc: Haiyang Zhang +Cc: Jork Loeser +Cc: K. Y. Srinivasan +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Simon Xiao +Cc: Steven Rostedt +Cc: Thomas Gleixner +Cc: devel@linuxdriverproject.org +Link: http://lkml.kernel.org/r/20170802160921.21791-2-vkuznets@redhat.com +Signed-off-by: Ingo Molnar +Acked-by: Olaf Hering +--- + arch/x86/Kbuild | 2 +- + arch/x86/include/asm/mshyperv.h | 7 ++++++- + 2 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/arch/x86/Kbuild b/arch/x86/Kbuild +--- a/arch/x86/Kbuild ++++ b/arch/x86/Kbuild +@@ -8,7 +8,7 @@ obj-$(CONFIG_KVM) += kvm/ + obj-$(CONFIG_XEN) += xen/ + + # Hyper-V paravirtualization support +-obj-$(CONFIG_HYPERVISOR_GUEST) += hyperv/ ++obj-$(subst m,y,$(CONFIG_HYPERV)) += hyperv/ + + # lguest paravirtualization support + obj-$(CONFIG_LGUEST_GUEST) += lguest/ +diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h +--- a/arch/x86/include/asm/mshyperv.h ++++ b/arch/x86/include/asm/mshyperv.h +@@ -173,7 +173,12 @@ void hyperv_init(void); + void hyperv_report_panic(struct pt_regs *regs); + bool hv_is_hypercall_page_setup(void); + void hyperv_cleanup(void); +-#endif ++#else /* CONFIG_HYPERV */ ++static inline void hyperv_init(void) {} ++static inline bool hv_is_hypercall_page_setup(void) { return false; } ++static inline void hyperv_cleanup(void) {} ++#endif /* CONFIG_HYPERV */ ++ + #ifdef CONFIG_HYPERV_TSCPAGE + struct ms_hyperv_tsc_page *hv_get_tsc_page(void); + static inline u64 hv_read_tsc_page(const struct ms_hyperv_tsc_page *tsc_pg) diff --git a/patches.suse/msft-hv-1419-x86-hyper-v-Make-hv_do_hypercall-inline.patch b/patches.suse/msft-hv-1419-x86-hyper-v-Make-hv_do_hypercall-inline.patch new file mode 100644 index 0000000..2b995db --- /dev/null +++ b/patches.suse/msft-hv-1419-x86-hyper-v-Make-hv_do_hypercall-inline.patch @@ -0,0 +1,202 @@ +From: Vitaly Kuznetsov +Date: Wed, 2 Aug 2017 18:09:14 +0200 +Patch-mainline: v4.14-rc1 +Subject: x86/hyper-v: Make hv_do_hypercall() inline +Git-commit: fc53662f13b889a5a1c069e79ee1e3d4534df132 +References: fate#323887 + +We have only three call sites for hv_do_hypercall() and we're going to +change HVCALL_SIGNAL_EVENT to doing fast hypercall so we can inline this +function for optimization. + +Hyper-V top level functional specification states that r9-r11 registers +and flags may be clobbered by the hypervisor during hypercall and with +inlining this is somewhat important, add the clobbers. + +Signed-off-by: Vitaly Kuznetsov +Reviewed-by: Andy Shevchenko +Reviewed-by: Stephen Hemminger +Cc: Andy Lutomirski +Cc: Haiyang Zhang +Cc: Jork Loeser +Cc: K. Y. Srinivasan +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Simon Xiao +Cc: Steven Rostedt +Cc: Thomas Gleixner +Cc: devel@linuxdriverproject.org +Link: http://lkml.kernel.org/r/20170802160921.21791-3-vkuznets@redhat.com +Signed-off-by: Ingo Molnar +Acked-by: Olaf Hering +--- + arch/x86/hyperv/hv_init.c | 54 ++++------------------------------------- + arch/x86/include/asm/mshyperv.h | 40 ++++++++++++++++++++++++++++++ + drivers/hv/connection.c | 2 ++ + include/linux/hyperv.h | 1 - + 4 files changed, 47 insertions(+), 50 deletions(-) + +diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c +--- a/arch/x86/hyperv/hv_init.c ++++ b/arch/x86/hyperv/hv_init.c +@@ -75,7 +75,8 @@ static struct clocksource hyperv_cs_msr = { + .flags = CLOCK_SOURCE_IS_CONTINUOUS, + }; + +-static void *hypercall_pg; ++void *hv_hypercall_pg; ++EXPORT_SYMBOL_GPL(hv_hypercall_pg); + struct clocksource *hyperv_cs; + EXPORT_SYMBOL_GPL(hyperv_cs); + +@@ -102,15 +103,15 @@ void hyperv_init(void) + guest_id = generate_guest_id(0, LINUX_VERSION_CODE, 0); + wrmsrl(HV_X64_MSR_GUEST_OS_ID, guest_id); + +- hypercall_pg = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_RX); +- if (hypercall_pg == NULL) { ++ hv_hypercall_pg = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_RX); ++ if (hv_hypercall_pg == NULL) { + wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0); + return; + } + + rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); + hypercall_msr.enable = 1; +- hypercall_msr.guest_physical_address = vmalloc_to_pfn(hypercall_pg); ++ hypercall_msr.guest_physical_address = vmalloc_to_pfn(hv_hypercall_pg); + wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); + + /* +@@ -170,51 +171,6 @@ void hyperv_cleanup(void) + } + EXPORT_SYMBOL_GPL(hyperv_cleanup); + +-/* +- * hv_do_hypercall- Invoke the specified hypercall +- */ +-u64 hv_do_hypercall(u64 control, void *input, void *output) +-{ +- u64 input_address = (input) ? virt_to_phys(input) : 0; +- u64 output_address = (output) ? virt_to_phys(output) : 0; +-#ifdef CONFIG_X86_64 +- u64 hv_status = 0; +- +- if (!hypercall_pg) +- return (u64)ULLONG_MAX; +- +- __asm__ __volatile__("mov %0, %%r8" : : "r" (output_address) : "r8"); +- __asm__ __volatile__("call *%3" : "=a" (hv_status) : +- "c" (control), "d" (input_address), +- "m" (hypercall_pg)); +- +- return hv_status; +- +-#else +- +- u32 control_hi = control >> 32; +- u32 control_lo = control & 0xFFFFFFFF; +- u32 hv_status_hi = 1; +- u32 hv_status_lo = 1; +- u32 input_address_hi = input_address >> 32; +- u32 input_address_lo = input_address & 0xFFFFFFFF; +- u32 output_address_hi = output_address >> 32; +- u32 output_address_lo = output_address & 0xFFFFFFFF; +- +- if (!hypercall_pg) +- return (u64)ULLONG_MAX; +- +- __asm__ __volatile__ ("call *%8" : "=d"(hv_status_hi), +- "=a"(hv_status_lo) : "d" (control_hi), +- "a" (control_lo), "b" (input_address_hi), +- "c" (input_address_lo), "D"(output_address_hi), +- "S"(output_address_lo), "m" (hypercall_pg)); +- +- return hv_status_lo | ((u64)hv_status_hi << 32); +-#endif /* !x86_64 */ +-} +-EXPORT_SYMBOL_GPL(hv_do_hypercall); +- + void hyperv_report_panic(struct pt_regs *regs) + { + static bool panic_reported; +diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h +--- a/arch/x86/include/asm/mshyperv.h ++++ b/arch/x86/include/asm/mshyperv.h +@@ -3,6 +3,7 @@ + + #include + #include ++#include + #include + + /* +@@ -168,6 +169,45 @@ void hv_remove_crash_handler(void); + + #if IS_ENABLED(CONFIG_HYPERV) + extern struct clocksource *hyperv_cs; ++extern void *hv_hypercall_pg; ++ ++static inline u64 hv_do_hypercall(u64 control, void *input, void *output) ++{ ++ u64 input_address = input ? virt_to_phys(input) : 0; ++ u64 output_address = output ? virt_to_phys(output) : 0; ++ u64 hv_status; ++ register void *__sp asm(_ASM_SP); ++ ++#ifdef CONFIG_X86_64 ++ if (!hv_hypercall_pg) ++ return U64_MAX; ++ ++ __asm__ __volatile__("mov %4, %%r8\n" ++ "call *%5" ++ : "=a" (hv_status), "+r" (__sp), ++ "+c" (control), "+d" (input_address) ++ : "r" (output_address), "m" (hv_hypercall_pg) ++ : "cc", "memory", "r8", "r9", "r10", "r11"); ++#else ++ u32 input_address_hi = upper_32_bits(input_address); ++ u32 input_address_lo = lower_32_bits(input_address); ++ u32 output_address_hi = upper_32_bits(output_address); ++ u32 output_address_lo = lower_32_bits(output_address); ++ ++ if (!hv_hypercall_pg) ++ return U64_MAX; ++ ++ __asm__ __volatile__("call *%7" ++ : "=A" (hv_status), ++ "+c" (input_address_lo), "+r" (__sp) ++ : "A" (control), ++ "b" (input_address_hi), ++ "D"(output_address_hi), "S"(output_address_lo), ++ "m" (hv_hypercall_pg) ++ : "cc", "memory"); ++#endif /* !x86_64 */ ++ return hv_status; ++} + + void hyperv_init(void); + void hyperv_report_panic(struct pt_regs *regs); +diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c +--- a/drivers/hv/connection.c ++++ b/drivers/hv/connection.c +@@ -32,6 +32,8 @@ + #include + #include + #include ++#include ++ + #include "hyperv_vmbus.h" + + +diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h +--- a/include/linux/hyperv.h ++++ b/include/linux/hyperv.h +@@ -1187,7 +1187,6 @@ int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj, + bool fb_overlap_ok); + void vmbus_free_mmio(resource_size_t start, resource_size_t size); + int vmbus_cpu_number_to_vp_number(int cpu_number); +-u64 hv_do_hypercall(u64 control, void *input, void *output); + + /* + * GUID definitions of various offer types - services offered to the guest. diff --git a/patches.suse/msft-hv-1420-x86-hyper-v-Introduce-fast-hypercall-implementation.patch b/patches.suse/msft-hv-1420-x86-hyper-v-Introduce-fast-hypercall-implementation.patch new file mode 100644 index 0000000..7da18dd --- /dev/null +++ b/patches.suse/msft-hv-1420-x86-hyper-v-Introduce-fast-hypercall-implementation.patch @@ -0,0 +1,75 @@ +From: Vitaly Kuznetsov +Date: Wed, 2 Aug 2017 18:09:15 +0200 +Patch-mainline: v4.14-rc1 +Subject: x86/hyper-v: Introduce fast hypercall implementation +Git-commit: 6a8edbd0c54ae266b12f4f63e406313481c9d4bc +References: fate#323887 + +Hyper-V supports 'fast' hypercalls when all parameters are passed through +registers. Implement an inline version of a simpliest of these calls: +hypercall with one 8-byte input and no output. + +Signed-off-by: Vitaly Kuznetsov +Reviewed-by: Andy Shevchenko +Reviewed-by: Stephen Hemminger +Cc: Andy Lutomirski +Cc: Haiyang Zhang +Cc: Jork Loeser +Cc: K. Y. Srinivasan +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Simon Xiao +Cc: Steven Rostedt +Cc: Thomas Gleixner +Cc: devel@linuxdriverproject.org +Link: http://lkml.kernel.org/r/20170802160921.21791-4-vkuznets@redhat.com +Signed-off-by: Ingo Molnar +Acked-by: Olaf Hering +--- + arch/x86/include/asm/mshyperv.h | 34 ++++++++++++++++++++++++++++++++++ + 1 file changed, 34 insertions(+) + +diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h +--- a/arch/x86/include/asm/mshyperv.h ++++ b/arch/x86/include/asm/mshyperv.h +@@ -209,6 +209,40 @@ static inline u64 hv_do_hypercall(u64 control, void *input, void *output) + return hv_status; + } + ++#define HV_HYPERCALL_FAST_BIT BIT(16) ++ ++/* Fast hypercall with 8 bytes of input and no output */ ++static inline u64 hv_do_fast_hypercall8(u16 code, u64 input1) ++{ ++ u64 hv_status, control = (u64)code | HV_HYPERCALL_FAST_BIT; ++ register void *__sp asm(_ASM_SP); ++ ++#ifdef CONFIG_X86_64 ++ { ++ __asm__ __volatile__("call *%4" ++ : "=a" (hv_status), "+r" (__sp), ++ "+c" (control), "+d" (input1) ++ : "m" (hv_hypercall_pg) ++ : "cc", "r8", "r9", "r10", "r11"); ++ } ++#else ++ { ++ u32 input1_hi = upper_32_bits(input1); ++ u32 input1_lo = lower_32_bits(input1); ++ ++ __asm__ __volatile__ ("call *%5" ++ : "=A"(hv_status), ++ "+c"(input1_lo), ++ "+r"(__sp) ++ : "A" (control), ++ "b" (input1_hi), ++ "m" (hv_hypercall_pg) ++ : "cc", "edi", "esi"); ++ } ++#endif ++ return hv_status; ++} ++ + void hyperv_init(void); + void hyperv_report_panic(struct pt_regs *regs); + bool hv_is_hypercall_page_setup(void); diff --git a/patches.suse/msft-hv-1421-hyper-v-Use-fast-hypercall-for-HVCALL_SIGNAL_EVENT.patch b/patches.suse/msft-hv-1421-hyper-v-Use-fast-hypercall-for-HVCALL_SIGNAL_EVENT.patch new file mode 100644 index 0000000..cb597ee --- /dev/null +++ b/patches.suse/msft-hv-1421-hyper-v-Use-fast-hypercall-for-HVCALL_SIGNAL_EVENT.patch @@ -0,0 +1,103 @@ +From: Vitaly Kuznetsov +Date: Wed, 2 Aug 2017 18:09:16 +0200 +Patch-mainline: v4.14-rc1 +Subject: hyper-v: Use fast hypercall for HVCALL_SIGNAL_EVENT +Git-commit: 057841713cfff62b4485cdd2b245f05b7ea3ba16 +References: fate#323887 + +We need to pass only 8 bytes of input for HvSignalEvent which makes it a +perfect fit for fast hypercall. hv_input_signal_event_buffer is not needed +any more and hv_input_signal_event is converted to union for convenience. + +Signed-off-by: Vitaly Kuznetsov +Reviewed-by: Andy Shevchenko +Reviewed-by: Stephen Hemminger +Cc: Andy Lutomirski +Cc: Haiyang Zhang +Cc: Jork Loeser +Cc: K. Y. Srinivasan +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Simon Xiao +Cc: Steven Rostedt +Cc: Thomas Gleixner +Cc: devel@linuxdriverproject.org +Link: http://lkml.kernel.org/r/20170802160921.21791-5-vkuznets@redhat.com +Signed-off-by: Ingo Molnar +Acked-by: Olaf Hering +--- + drivers/hv/channel_mgmt.c | 13 ++----------- + drivers/hv/connection.c | 2 +- + include/linux/hyperv.h | 15 +-------------- + 3 files changed, 4 insertions(+), 26 deletions(-) + +diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c +--- a/drivers/hv/channel_mgmt.c ++++ b/drivers/hv/channel_mgmt.c +@@ -805,21 +805,12 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr) + /* + * Setup state for signalling the host. + */ +- newchannel->sig_event = (struct hv_input_signal_event *) +- (ALIGN((unsigned long) +- &newchannel->sig_buf, +- HV_HYPERCALL_PARAM_ALIGN)); +- +- newchannel->sig_event->connectionid.asu32 = 0; +- newchannel->sig_event->connectionid.u.id = VMBUS_EVENT_CONNECTION_ID; +- newchannel->sig_event->flag_number = 0; +- newchannel->sig_event->rsvdz = 0; ++ newchannel->sig_event = VMBUS_EVENT_CONNECTION_ID; + + if (vmbus_proto_version != VERSION_WS2008) { + newchannel->is_dedicated_interrupt = + (offer->is_dedicated_interrupt != 0); +- newchannel->sig_event->connectionid.u.id = +- offer->connection_id; ++ newchannel->sig_event = offer->connection_id; + } + + memcpy(&newchannel->offermsg, offer, +diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c +--- a/drivers/hv/connection.c ++++ b/drivers/hv/connection.c +@@ -408,6 +408,6 @@ void vmbus_set_event(struct vmbus_channel *channel) + if (!channel->is_dedicated_interrupt) + vmbus_send_interrupt(child_relid); + +- hv_do_hypercall(HVCALL_SIGNAL_EVENT, channel->sig_event, NULL); ++ hv_do_fast_hypercall8(HVCALL_SIGNAL_EVENT, channel->sig_event); + } + EXPORT_SYMBOL_GPL(vmbus_set_event); +diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h +--- a/include/linux/hyperv.h ++++ b/include/linux/hyperv.h +@@ -677,18 +677,6 @@ union hv_connection_id { + } u; + }; + +-/* Definition of the hv_signal_event hypercall input structure. */ +-struct hv_input_signal_event { +- union hv_connection_id connectionid; +- u16 flag_number; +- u16 rsvdz; +-}; +- +-struct hv_input_signal_event_buffer { +- u64 align8; +- struct hv_input_signal_event event; +-}; +- + enum hv_numa_policy { + HV_BALANCED = 0, + HV_LOCALIZED, +@@ -770,8 +758,7 @@ struct vmbus_channel { + } callback_mode; + + bool is_dedicated_interrupt; +- struct hv_input_signal_event_buffer sig_buf; +- struct hv_input_signal_event *sig_event; ++ u64 sig_event; + + /* + * Starting with win8, this field will be used to specify diff --git a/patches.suse/msft-hv-1422-x86-hyper-v-Implement-rep-hypercalls.patch b/patches.suse/msft-hv-1422-x86-hyper-v-Implement-rep-hypercalls.patch new file mode 100644 index 0000000..90ba2f7 --- /dev/null +++ b/patches.suse/msft-hv-1422-x86-hyper-v-Implement-rep-hypercalls.patch @@ -0,0 +1,99 @@ +From: Vitaly Kuznetsov +Date: Wed, 2 Aug 2017 18:09:17 +0200 +Patch-mainline: v4.14-rc1 +Subject: x86/hyper-v: Implement rep hypercalls +Git-commit: 806c89273bab0c8af0202a6fb6279f36042cb2e6 +References: fate#323887 + +Rep hypercalls are normal hypercalls which perform multiple actions at +once. Hyper-V guarantees to return exectution to the caller in not more +than 50us and the caller needs to use hypercall continuation. Touch NMI +watchdog between hypercall invocations. + +This is going to be used for HvFlushVirtualAddressList hypercall for +remote TLB flushing. + +Signed-off-by: Vitaly Kuznetsov +Reviewed-by: Andy Shevchenko +Reviewed-by: Stephen Hemminger +Cc: Andy Lutomirski +Cc: Haiyang Zhang +Cc: Jork Loeser +Cc: K. Y. Srinivasan +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Simon Xiao +Cc: Steven Rostedt +Cc: Thomas Gleixner +Cc: devel@linuxdriverproject.org +Link: http://lkml.kernel.org/r/20170802160921.21791-6-vkuznets@redhat.com +Signed-off-by: Ingo Molnar +Acked-by: Olaf Hering +--- + arch/x86/include/asm/mshyperv.h | 39 +++++++++++++++++++++++++++++++++++++++ + 1 file changed, 39 insertions(+) + +diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h +--- a/arch/x86/include/asm/mshyperv.h ++++ b/arch/x86/include/asm/mshyperv.h +@@ -3,6 +3,7 @@ + + #include + #include ++#include + #include + #include + +@@ -209,7 +210,13 @@ static inline u64 hv_do_hypercall(u64 control, void *input, void *output) + return hv_status; + } + ++#define HV_HYPERCALL_RESULT_MASK GENMASK_ULL(15, 0) + #define HV_HYPERCALL_FAST_BIT BIT(16) ++#define HV_HYPERCALL_VARHEAD_OFFSET 17 ++#define HV_HYPERCALL_REP_COMP_OFFSET 32 ++#define HV_HYPERCALL_REP_COMP_MASK GENMASK_ULL(43, 32) ++#define HV_HYPERCALL_REP_START_OFFSET 48 ++#define HV_HYPERCALL_REP_START_MASK GENMASK_ULL(59, 48) + + /* Fast hypercall with 8 bytes of input and no output */ + static inline u64 hv_do_fast_hypercall8(u16 code, u64 input1) +@@ -243,6 +250,38 @@ static inline u64 hv_do_fast_hypercall8(u16 code, u64 input1) + return hv_status; + } + ++/* ++ * Rep hypercalls. Callers of this functions are supposed to ensure that ++ * rep_count and varhead_size comply with Hyper-V hypercall definition. ++ */ ++static inline u64 hv_do_rep_hypercall(u16 code, u16 rep_count, u16 varhead_size, ++ void *input, void *output) ++{ ++ u64 control = code; ++ u64 status; ++ u16 rep_comp; ++ ++ control |= (u64)varhead_size << HV_HYPERCALL_VARHEAD_OFFSET; ++ control |= (u64)rep_count << HV_HYPERCALL_REP_COMP_OFFSET; ++ ++ do { ++ status = hv_do_hypercall(control, input, output); ++ if ((status & HV_HYPERCALL_RESULT_MASK) != HV_STATUS_SUCCESS) ++ return status; ++ ++ /* Bits 32-43 of status have 'Reps completed' data. */ ++ rep_comp = (status & HV_HYPERCALL_REP_COMP_MASK) >> ++ HV_HYPERCALL_REP_COMP_OFFSET; ++ ++ control &= ~HV_HYPERCALL_REP_START_MASK; ++ control |= (u64)rep_comp << HV_HYPERCALL_REP_START_OFFSET; ++ ++ touch_nmi_watchdog(); ++ } while (rep_comp < rep_count); ++ ++ return status; ++} ++ + void hyperv_init(void); + void hyperv_report_panic(struct pt_regs *regs); + bool hv_is_hypercall_page_setup(void); diff --git a/patches.suse/msft-hv-1423-hyper-v-Globalize-vp_index.patch b/patches.suse/msft-hv-1423-hyper-v-Globalize-vp_index.patch new file mode 100644 index 0000000..f9e902c --- /dev/null +++ b/patches.suse/msft-hv-1423-hyper-v-Globalize-vp_index.patch @@ -0,0 +1,366 @@ +From: Vitaly Kuznetsov +Date: Wed, 2 Aug 2017 18:09:18 +0200 +Patch-mainline: v4.14-rc1 +Subject: hyper-v: Globalize vp_index +Git-commit: 7415aea6072bab15969b6c3c5b2a193d88095326 +References: fate#323887 + +To support implementing remote TLB flushing on Hyper-V with a hypercall +we need to make vp_index available outside of vmbus module. Rename and +globalize. + +Signed-off-by: Vitaly Kuznetsov +Reviewed-by: Andy Shevchenko +Reviewed-by: Stephen Hemminger +Cc: Andy Lutomirski +Cc: Haiyang Zhang +Cc: Jork Loeser +Cc: K. Y. Srinivasan +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Simon Xiao +Cc: Steven Rostedt +Cc: Thomas Gleixner +Cc: devel@linuxdriverproject.org +Link: http://lkml.kernel.org/r/20170802160921.21791-7-vkuznets@redhat.com +Signed-off-by: Ingo Molnar +Acked-by: Olaf Hering +--- + arch/x86/hyperv/hv_init.c | 34 +++++++++++++++++++++++++- + arch/x86/include/asm/mshyperv.h | 24 ++++++++++++++++++ + drivers/hv/channel_mgmt.c | 7 +++--- + drivers/hv/connection.c | 3 ++- + drivers/hv/hv.c | 9 ------- + drivers/hv/hyperv_vmbus.h | 11 --------- + drivers/hv/vmbus_drv.c | 17 ------------- + drivers/pci/host/pci-hyperv.c | 54 +++-------------------------------------- + include/linux/hyperv.h | 1 - + 9 files changed, 65 insertions(+), 95 deletions(-) + +diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c +--- a/arch/x86/hyperv/hv_init.c ++++ b/arch/x86/hyperv/hv_init.c +@@ -26,6 +26,8 @@ + #include + #include + #include ++#include ++#include + + #ifdef CONFIG_HYPERV_TSCPAGE + +@@ -80,6 +82,20 @@ EXPORT_SYMBOL_GPL(hv_hypercall_pg); + struct clocksource *hyperv_cs; + EXPORT_SYMBOL_GPL(hyperv_cs); + ++u32 *hv_vp_index; ++EXPORT_SYMBOL_GPL(hv_vp_index); ++ ++static int hv_cpu_init(unsigned int cpu) ++{ ++ u64 msr_vp_index; ++ ++ hv_get_vp_index(msr_vp_index); ++ ++ hv_vp_index[smp_processor_id()] = msr_vp_index; ++ ++ return 0; ++} ++ + /* + * This function is to be invoked early in the boot sequence after the + * hypervisor has been detected. +@@ -95,6 +111,16 @@ void hyperv_init(void) + if (x86_hyper != &x86_hyper_ms_hyperv) + return; + ++ /* Allocate percpu VP index */ ++ hv_vp_index = kmalloc_array(num_possible_cpus(), sizeof(*hv_vp_index), ++ GFP_KERNEL); ++ if (!hv_vp_index) ++ return; ++ ++ if (cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/hyperv_init:online", ++ hv_cpu_init, NULL) < 0) ++ goto free_vp_index; ++ + /* + * Setup the hypercall page and enable hypercalls. + * 1. Register the guest ID +@@ -106,7 +132,7 @@ void hyperv_init(void) + hv_hypercall_pg = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_RX); + if (hv_hypercall_pg == NULL) { + wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0); +- return; ++ goto free_vp_index; + } + + rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); +@@ -149,6 +175,12 @@ register_msr_cs: + hyperv_cs = &hyperv_cs_msr; + if (ms_hyperv.features & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE) + clocksource_register_hz(&hyperv_cs_msr, NSEC_PER_SEC/100); ++ ++ return; ++ ++free_vp_index: ++ kfree(hv_vp_index); ++ hv_vp_index = NULL; + } + + /* +diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h +--- a/arch/x86/include/asm/mshyperv.h ++++ b/arch/x86/include/asm/mshyperv.h +@@ -282,6 +282,30 @@ static inline u64 hv_do_rep_hypercall(u16 code, u16 rep_count, u16 varhead_size, + return status; + } + ++/* ++ * Hypervisor's notion of virtual processor ID is different from ++ * Linux' notion of CPU ID. This information can only be retrieved ++ * in the context of the calling CPU. Setup a map for easy access ++ * to this information. ++ */ ++extern u32 *hv_vp_index; ++ ++/** ++ * hv_cpu_number_to_vp_number() - Map CPU to VP. ++ * @cpu_number: CPU number in Linux terms ++ * ++ * This function returns the mapping between the Linux processor ++ * number and the hypervisor's virtual processor number, useful ++ * in making hypercalls and such that talk about specific ++ * processors. ++ * ++ * Return: Virtual processor number in Hyper-V terms ++ */ ++static inline int hv_cpu_number_to_vp_number(int cpu_number) ++{ ++ return hv_vp_index[cpu_number]; ++} ++ + void hyperv_init(void); + void hyperv_report_panic(struct pt_regs *regs); + bool hv_is_hypercall_page_setup(void); +diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c +--- a/drivers/hv/channel_mgmt.c ++++ b/drivers/hv/channel_mgmt.c +@@ -599,7 +599,7 @@ static void init_vp_index(struct vmbus_channel *channel, u16 dev_type) + */ + channel->numa_node = 0; + channel->target_cpu = 0; +- channel->target_vp = hv_context.vp_index[0]; ++ channel->target_vp = hv_cpu_number_to_vp_number(0); + return; + } + +@@ -683,7 +683,7 @@ static void init_vp_index(struct vmbus_channel *channel, u16 dev_type) + } + + channel->target_cpu = cur_cpu; +- channel->target_vp = hv_context.vp_index[cur_cpu]; ++ channel->target_vp = hv_cpu_number_to_vp_number(cur_cpu); + } + + static void vmbus_wait_for_unload(void) +@@ -1219,8 +1219,7 @@ struct vmbus_channel *vmbus_get_outgoing_channel(struct vmbus_channel *primary) + return outgoing_channel; + } + +- cur_cpu = hv_context.vp_index[get_cpu()]; +- put_cpu(); ++ cur_cpu = hv_cpu_number_to_vp_number(smp_processor_id()); + list_for_each_safe(cur, tmp, &primary->sc_list) { + cur_channel = list_entry(cur, struct vmbus_channel, sc_list); + if (cur_channel->state != CHANNEL_OPENED_STATE) +diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c +--- a/drivers/hv/connection.c ++++ b/drivers/hv/connection.c +@@ -96,7 +96,8 @@ static int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo, + * the CPU attempting to connect may not be CPU 0. + */ + if (version >= VERSION_WIN8_1) { +- msg->target_vcpu = hv_context.vp_index[smp_processor_id()]; ++ msg->target_vcpu = ++ hv_cpu_number_to_vp_number(smp_processor_id()); + vmbus_connection.connect_cpu = smp_processor_id(); + } else { + msg->target_vcpu = 0; +diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c +--- a/drivers/hv/hv.c ++++ b/drivers/hv/hv.c +@@ -234,7 +234,6 @@ int hv_synic_init(unsigned int cpu) + union hv_synic_siefp siefp; + union hv_synic_sint shared_sint; + union hv_synic_scontrol sctrl; +- u64 vp_index; + + /* Setup the Synic's message page */ + hv_get_simp(simp.as_uint64); +@@ -275,14 +274,6 @@ int hv_synic_init(unsigned int cpu) + + hv_context.synic_initialized = true; + +- /* +- * Setup the mapping between Hyper-V's notion +- * of cpuid and Linux' notion of cpuid. +- * This array will be indexed using Linux cpuid. +- */ +- hv_get_vp_index(vp_index); +- hv_context.vp_index[cpu] = (u32)vp_index; +- + /* + * Register the per-cpu clockevent source. + */ +diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h +--- a/drivers/hv/hyperv_vmbus.h ++++ b/drivers/hv/hyperv_vmbus.h +@@ -228,17 +228,6 @@ struct hv_context { + + struct hv_per_cpu_context __percpu *cpu_context; + +- /* +- * Hypervisor's notion of virtual processor ID is different from +- * Linux' notion of CPU ID. This information can only be retrieved +- * in the context of the calling CPU. Setup a map for easy access +- * to this information: +- * +- * vp_index[a] is the Hyper-V's processor ID corresponding to +- * Linux cpuid 'a'. +- */ +- u32 vp_index[NR_CPUS]; +- + /* + * To manage allocations in a NUMA node. + * Array indexed by numa node ID. +diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c +--- a/drivers/hv/vmbus_drv.c ++++ b/drivers/hv/vmbus_drv.c +@@ -1451,23 +1451,6 @@ void vmbus_free_mmio(resource_size_t start, resource_size_t size) + } + EXPORT_SYMBOL_GPL(vmbus_free_mmio); + +-/** +- * vmbus_cpu_number_to_vp_number() - Map CPU to VP. +- * @cpu_number: CPU number in Linux terms +- * +- * This function returns the mapping between the Linux processor +- * number and the hypervisor's virtual processor number, useful +- * in making hypercalls and such that talk about specific +- * processors. +- * +- * Return: Virtual processor number in Hyper-V terms +- */ +-int vmbus_cpu_number_to_vp_number(int cpu_number) +-{ +- return hv_context.vp_index[cpu_number]; +-} +-EXPORT_SYMBOL_GPL(vmbus_cpu_number_to_vp_number); +- + static int vmbus_acpi_add(struct acpi_device *device) + { + acpi_status result; +diff --git a/drivers/pci/host/pci-hyperv.c b/drivers/pci/host/pci-hyperv.c +--- a/drivers/pci/host/pci-hyperv.c ++++ b/drivers/pci/host/pci-hyperv.c +@@ -562,52 +562,6 @@ static void put_pcichild(struct hv_pci_dev *hv_pcidev, + static void get_hvpcibus(struct hv_pcibus_device *hv_pcibus); + static void put_hvpcibus(struct hv_pcibus_device *hv_pcibus); + +- +-/* +- * Temporary CPU to vCPU mapping to address transitioning +- * vmbus_cpu_number_to_vp_number() being migrated to +- * hv_cpu_number_to_vp_number() in a separate patch. Once that patch +- * has been picked up in the main line, remove this code here and use +- * the official code. +- */ +-static struct hv_tmpcpumap +-{ +- bool initialized; +- u32 vp_index[NR_CPUS]; +-} hv_tmpcpumap; +- +-static void hv_tmpcpumap_init_cpu(void *_unused) +-{ +- int cpu = smp_processor_id(); +- u64 vp_index; +- +- hv_get_vp_index(vp_index); +- +- hv_tmpcpumap.vp_index[cpu] = vp_index; +-} +- +-static void hv_tmpcpumap_init(void) +-{ +- if (hv_tmpcpumap.initialized) +- return; +- +- memset(hv_tmpcpumap.vp_index, -1, sizeof(hv_tmpcpumap.vp_index)); +- on_each_cpu(hv_tmpcpumap_init_cpu, NULL, true); +- hv_tmpcpumap.initialized = true; +-} +- +-/** +- * hv_tmp_cpu_nr_to_vp_nr() - Convert Linux CPU nr to Hyper-V vCPU nr +- * +- * Remove once vmbus_cpu_number_to_vp_number() has been converted to +- * hv_cpu_number_to_vp_number() and replace callers appropriately. +- */ +-static u32 hv_tmp_cpu_nr_to_vp_nr(int cpu) +-{ +- return hv_tmpcpumap.vp_index[cpu]; +-} +- +- + /** + * devfn_to_wslot() - Convert from Linux PCI slot to Windows + * @devfn: The Linux representation of PCI slot +@@ -971,7 +925,7 @@ static void hv_irq_unmask(struct irq_data *data) + var_size = 1 + HV_VP_SET_BANK_COUNT_MAX; + + for_each_cpu_and(cpu, dest, cpu_online_mask) { +- cpu_vmbus = hv_tmp_cpu_nr_to_vp_nr(cpu); ++ cpu_vmbus = hv_cpu_number_to_vp_number(cpu); + + if (cpu_vmbus >= HV_VP_SET_BANK_COUNT_MAX * 64) { + dev_err(&hbus->hdev->device, +@@ -986,7 +940,7 @@ static void hv_irq_unmask(struct irq_data *data) + } else { + for_each_cpu_and(cpu, dest, cpu_online_mask) { + params->int_target.vp_mask |= +- (1ULL << hv_tmp_cpu_nr_to_vp_nr(cpu)); ++ (1ULL << hv_cpu_number_to_vp_number(cpu)); + } + } + +@@ -1063,7 +1017,7 @@ static u32 hv_compose_msi_req_v2( + */ + cpu = cpumask_first_and(affinity, cpu_online_mask); + int_pkt->int_desc.processor_array[0] = +- hv_tmp_cpu_nr_to_vp_nr(cpu); ++ hv_cpu_number_to_vp_number(cpu); + int_pkt->int_desc.processor_count = 1; + + return sizeof(*int_pkt); +@@ -2490,8 +2444,6 @@ static int hv_pci_probe(struct hv_device *hdev, + return -ENOMEM; + hbus->state = hv_pcibus_init; + +- hv_tmpcpumap_init(); +- + /* + * The PCI bus "domain" is what is called "segment" in ACPI and + * other specs. Pull it from the instance ID, to get something +diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h +--- a/include/linux/hyperv.h ++++ b/include/linux/hyperv.h +@@ -1173,7 +1173,6 @@ int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj, + resource_size_t size, resource_size_t align, + bool fb_overlap_ok); + void vmbus_free_mmio(resource_size_t start, resource_size_t size); +-int vmbus_cpu_number_to_vp_number(int cpu_number); + + /* + * GUID definitions of various offer types - services offered to the guest. diff --git a/patches.suse/msft-hv-1424-x86-hyper-v-Use-hypercall-for-remote-TLB-flush.patch b/patches.suse/msft-hv-1424-x86-hyper-v-Use-hypercall-for-remote-TLB-flush.patch new file mode 100644 index 0000000..c073f0a --- /dev/null +++ b/patches.suse/msft-hv-1424-x86-hyper-v-Use-hypercall-for-remote-TLB-flush.patch @@ -0,0 +1,278 @@ +From: Vitaly Kuznetsov +Date: Wed, 2 Aug 2017 18:09:19 +0200 +Patch-mainline: v4.14-rc1 +Subject: x86/hyper-v: Use hypercall for remote TLB flush +Git-commit: 2ffd9e33ce4af4e8cfa3e17bf493defe8474e2eb +References: fate#323887 + +Hyper-V host can suggest us to use hypercall for doing remote TLB flush, +this is supposed to work faster than IPIs. + +Implementation details: to do HvFlushVirtualAddress{Space,List} hypercalls +we need to put the input somewhere in memory and we don't really want to +have memory allocation on each call so we pre-allocate per cpu memory areas +on boot. + +pv_ops patching is happening very early so we need to separate +hyperv_setup_mmu_ops() and hyper_alloc_mmu(). + +It is possible and easy to implement local TLB flushing too and there is +even a hint for that. However, I don't see a room for optimization on the +host side as both hypercall and native tlb flush will result in vmexit. The +hint is also not set on modern Hyper-V versions. + +Signed-off-by: Vitaly Kuznetsov +Reviewed-by: Andy Shevchenko +Reviewed-by: Stephen Hemminger +Cc: Andy Lutomirski +Cc: Haiyang Zhang +Cc: Jork Loeser +Cc: K. Y. Srinivasan +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Simon Xiao +Cc: Steven Rostedt +Cc: Thomas Gleixner +Cc: devel@linuxdriverproject.org +Link: http://lkml.kernel.org/r/20170802160921.21791-8-vkuznets@redhat.com +Signed-off-by: Ingo Molnar +Acked-by: Olaf Hering +--- + arch/x86/hyperv/Makefile | 2 +- + arch/x86/hyperv/hv_init.c | 2 + + arch/x86/hyperv/mmu.c | 138 +++++++++++++++++++++++++++++++++++++ + arch/x86/include/asm/mshyperv.h | 3 + + arch/x86/include/uapi/asm/hyperv.h | 7 ++ + arch/x86/kernel/cpu/mshyperv.c | 1 + + drivers/hv/Kconfig | 1 + + 7 files changed, 153 insertions(+), 1 deletion(-) + create mode 100644 arch/x86/hyperv/mmu.c + +diff --git a/arch/x86/hyperv/Makefile b/arch/x86/hyperv/Makefile +--- a/arch/x86/hyperv/Makefile ++++ b/arch/x86/hyperv/Makefile +@@ -1 +1 @@ +-obj-y := hv_init.o ++obj-y := hv_init.o mmu.o +diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c +--- a/arch/x86/hyperv/hv_init.c ++++ b/arch/x86/hyperv/hv_init.c +@@ -140,6 +140,8 @@ void hyperv_init(void) + hypercall_msr.guest_physical_address = vmalloc_to_pfn(hv_hypercall_pg); + wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); + ++ hyper_alloc_mmu(); ++ + /* + * Register Hyper-V specific clocksource. + */ +diff --git a/arch/x86/hyperv/mmu.c b/arch/x86/hyperv/mmu.c +new file mode 100644 +index 000000000000..9419a20b1d75 +--- /dev/null ++++ b/arch/x86/hyperv/mmu.c +@@ -0,0 +1,138 @@ ++#define pr_fmt(fmt) "Hyper-V: " fmt ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++/* HvFlushVirtualAddressSpace, HvFlushVirtualAddressList hypercalls */ ++struct hv_flush_pcpu { ++ u64 address_space; ++ u64 flags; ++ u64 processor_mask; ++ u64 gva_list[]; ++}; ++ ++/* Each gva in gva_list encodes up to 4096 pages to flush */ ++#define HV_TLB_FLUSH_UNIT (4096 * PAGE_SIZE) ++ ++static struct hv_flush_pcpu __percpu *pcpu_flush; ++ ++/* ++ * Fills in gva_list starting from offset. Returns the number of items added. ++ */ ++static inline int fill_gva_list(u64 gva_list[], int offset, ++ unsigned long start, unsigned long end) ++{ ++ int gva_n = offset; ++ unsigned long cur = start, diff; ++ ++ do { ++ diff = end > cur ? end - cur : 0; ++ ++ gva_list[gva_n] = cur & PAGE_MASK; ++ /* ++ * Lower 12 bits encode the number of additional ++ * pages to flush (in addition to the 'cur' page). ++ */ ++ if (diff >= HV_TLB_FLUSH_UNIT) ++ gva_list[gva_n] |= ~PAGE_MASK; ++ else if (diff) ++ gva_list[gva_n] |= (diff - 1) >> PAGE_SHIFT; ++ ++ cur += HV_TLB_FLUSH_UNIT; ++ gva_n++; ++ ++ } while (cur < end); ++ ++ return gva_n - offset; ++} ++ ++static void hyperv_flush_tlb_others(const struct cpumask *cpus, ++struct mm_struct *mm, unsigned long start, unsigned long end) ++{ ++ int cpu, vcpu, gva_n, max_gvas; ++ struct hv_flush_pcpu *flush; ++ u64 status = U64_MAX; ++ unsigned long flags; ++ ++ if (!pcpu_flush || !hv_hypercall_pg) ++ goto do_native; ++ ++ if (cpumask_empty(cpus)) ++ return; ++ ++ local_irq_save(flags); ++ ++ flush = this_cpu_ptr(pcpu_flush); ++ ++ if (mm) { ++ flush->address_space = virt_to_phys(mm->pgd); ++ flush->flags = 0; ++ } else { ++ flush->address_space = 0; ++ flush->flags = HV_FLUSH_ALL_VIRTUAL_ADDRESS_SPACES; ++ } ++ ++ flush->processor_mask = 0; ++ if (cpumask_equal(cpus, cpu_present_mask)) { ++ flush->flags |= HV_FLUSH_ALL_PROCESSORS; ++ } else { ++ for_each_cpu(cpu, cpus) { ++ vcpu = hv_cpu_number_to_vp_number(cpu); ++ if (vcpu >= 64) ++ goto do_native; ++ ++ __set_bit(vcpu, (unsigned long *) ++ &flush->processor_mask); ++ } ++ } ++ ++ /* ++ * We can flush not more than max_gvas with one hypercall. Flush the ++ * whole address space if we were asked to do more. ++ */ ++ max_gvas = (PAGE_SIZE - sizeof(*flush)) / sizeof(flush->gva_list[0]); ++ ++ if (end == TLB_FLUSH_ALL) { ++ flush->flags |= HV_FLUSH_NON_GLOBAL_MAPPINGS_ONLY; ++ status = hv_do_hypercall(HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE, ++ flush, NULL); ++ } else if (end && ++ ((end - start)/HV_TLB_FLUSH_UNIT) > max_gvas) { ++ status = hv_do_hypercall(HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE, ++ flush, NULL); ++ } else { ++ gva_n = fill_gva_list(flush->gva_list, 0, ++ start, end); ++ status = hv_do_rep_hypercall(HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST, ++ gva_n, 0, flush, NULL); ++ } ++ ++ local_irq_restore(flags); ++ ++ if (!(status & HV_HYPERCALL_RESULT_MASK)) ++ return; ++do_native: ++ native_flush_tlb_others(cpus, mm, start, end); ++} ++ ++void hyperv_setup_mmu_ops(void) ++{ ++ if (ms_hyperv.hints & HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED) { ++ pr_info("Using hypercall for remote TLB flush\n"); ++ pv_mmu_ops.flush_tlb_others = hyperv_flush_tlb_others; ++ setup_clear_cpu_cap(X86_FEATURE_PCID); ++ } ++} ++ ++void hyper_alloc_mmu(void) ++{ ++ if (ms_hyperv.hints & HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED) ++ pcpu_flush = __alloc_percpu(PAGE_SIZE, PAGE_SIZE); ++} +diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h +--- a/arch/x86/include/asm/mshyperv.h ++++ b/arch/x86/include/asm/mshyperv.h +@@ -307,6 +307,8 @@ static inline int hv_cpu_number_to_vp_number(int cpu_number) + } + + void hyperv_init(void); ++void hyperv_setup_mmu_ops(void); ++void hyper_alloc_mmu(void); + void hyperv_report_panic(struct pt_regs *regs); + bool hv_is_hypercall_page_setup(void); + void hyperv_cleanup(void); +@@ -314,6 +316,7 @@ void hyperv_cleanup(void); + static inline void hyperv_init(void) {} + static inline bool hv_is_hypercall_page_setup(void) { return false; } + static inline void hyperv_cleanup(void) {} ++static inline void hyperv_setup_mmu_ops(void) {} + #endif /* CONFIG_HYPERV */ + + #ifdef CONFIG_HYPERV_TSCPAGE +diff --git a/arch/x86/include/uapi/asm/hyperv.h b/arch/x86/include/uapi/asm/hyperv.h +--- a/arch/x86/include/uapi/asm/hyperv.h ++++ b/arch/x86/include/uapi/asm/hyperv.h +@@ -242,6 +242,8 @@ + (~((1ull << HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_SHIFT) - 1)) + + /* Declare the various hypercall operations. */ ++#define HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE 0x0002 ++#define HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST 0x0003 + #define HVCALL_NOTIFY_LONG_SPIN_WAIT 0x0008 + #define HVCALL_POST_MESSAGE 0x005c + #define HVCALL_SIGNAL_EVENT 0x005d +@@ -259,6 +261,11 @@ + #define HV_PROCESSOR_POWER_STATE_C2 2 + #define HV_PROCESSOR_POWER_STATE_C3 3 + ++#define HV_FLUSH_ALL_PROCESSORS BIT(0) ++#define HV_FLUSH_ALL_VIRTUAL_ADDRESS_SPACES BIT(1) ++#define HV_FLUSH_NON_GLOBAL_MAPPINGS_ONLY BIT(2) ++#define HV_FLUSH_USE_EXTENDED_RANGE_FORMAT BIT(3) ++ + /* hypercall status code */ + #define HV_STATUS_SUCCESS 0 + #define HV_STATUS_INVALID_HYPERCALL_CODE 2 +diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c +--- a/arch/x86/kernel/cpu/mshyperv.c ++++ b/arch/x86/kernel/cpu/mshyperv.c +@@ -249,6 +249,7 @@ static void __init ms_hyperv_init_platform(void) + * Setup the hook to get control post apic initialization. + */ + x86_platform.apic_post_init = hyperv_init; ++ hyperv_setup_mmu_ops(); + #endif + } + +diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig +--- a/drivers/hv/Kconfig ++++ b/drivers/hv/Kconfig +@@ -3,6 +3,7 @@ menu "Microsoft Hyper-V guest support" + config HYPERV + tristate "Microsoft Hyper-V client drivers" + depends on X86 && ACPI && PCI && X86_LOCAL_APIC && HYPERVISOR_GUEST ++ select PARAVIRT + help + Select this option to run Linux as a Hyper-V client operating + system. diff --git a/patches.suse/msft-hv-1425-netvsc-delay-setup-of-VF-device.patch b/patches.suse/msft-hv-1425-netvsc-delay-setup-of-VF-device.patch new file mode 100644 index 0000000..e2bb690 --- /dev/null +++ b/patches.suse/msft-hv-1425-netvsc-delay-setup-of-VF-device.patch @@ -0,0 +1,95 @@ +From: stephen hemminger +Date: Wed, 9 Aug 2017 17:46:03 -0700 +Patch-mainline: v4.14-rc1 +Subject: netvsc: delay setup of VF device +Git-commit: 6123c66854c174e4982f98195100c1d990f9e5e6 +References: fate#323887 + +When VF device is discovered, delay bring it automatically up in +order to allow userspace to some simple changes (like renaming). + +Reported-by: Vitaly Kuznetsov +Signed-off-by: Stephen Hemminger +Signed-off-by: David S. Miller +Acked-by: Olaf Hering +--- + drivers/net/hyperv/hyperv_net.h | 2 +- + drivers/net/hyperv/netvsc_drv.c | 15 ++++++++------- + 2 files changed, 9 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h +--- a/drivers/net/hyperv/hyperv_net.h ++++ b/drivers/net/hyperv/hyperv_net.h +@@ -723,7 +723,7 @@ struct net_device_context { + /* State to manage the associated VF interface. */ + struct net_device __rcu *vf_netdev; + struct netvsc_vf_pcpu_stats __percpu *vf_stats; +- struct work_struct vf_takeover; ++ struct delayed_work vf_takeover; + + /* 1: allocated, serial number is valid. 0: not allocated */ + u32 vf_alloc; +diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c +--- a/drivers/net/hyperv/netvsc_drv.c ++++ b/drivers/net/hyperv/netvsc_drv.c +@@ -47,6 +47,7 @@ + + #define RING_SIZE_MIN 64 + #define LINKCHANGE_INT (2 * HZ) ++#define VF_TAKEOVER_INT (HZ / 10) + + static int ring_size = 128; + module_param(ring_size, int, S_IRUGO); +@@ -1559,7 +1560,9 @@ static int netvsc_vf_join(struct net_device *vf_netdev, + /* set slave flag before open to prevent IPv6 addrconf */ + vf_netdev->flags |= IFF_SLAVE; + +- schedule_work(&ndev_ctx->vf_takeover); ++ schedule_delayed_work(&ndev_ctx->vf_takeover, VF_TAKEOVER_INT); ++ ++ call_netdevice_notifiers(NETDEV_JOIN, vf_netdev); + + netdev_info(vf_netdev, "joined to %s\n", ndev->name); + return 0; +@@ -1575,8 +1578,6 @@ static void __netvsc_vf_setup(struct net_device *ndev, + { + int ret; + +- call_netdevice_notifiers(NETDEV_JOIN, vf_netdev); +- + /* Align MTU of VF with master */ + ret = dev_set_mtu(vf_netdev, ndev->mtu); + if (ret) +@@ -1597,12 +1598,12 @@ static void __netvsc_vf_setup(struct net_device *ndev, + static void netvsc_vf_setup(struct work_struct *w) + { + struct net_device_context *ndev_ctx +- = container_of(w, struct net_device_context, vf_takeover); ++ = container_of(w, struct net_device_context, vf_takeover.work); + struct net_device *ndev = hv_get_drvdata(ndev_ctx->device_ctx); + struct net_device *vf_netdev; + + if (!rtnl_trylock()) { +- schedule_work(w); ++ schedule_delayed_work(&ndev_ctx->vf_takeover, 0); + return; + } + +@@ -1706,7 +1707,7 @@ static int netvsc_unregister_vf(struct net_device *vf_netdev) + return NOTIFY_DONE; + + net_device_ctx = netdev_priv(ndev); +- cancel_work_sync(&net_device_ctx->vf_takeover); ++ cancel_delayed_work_sync(&net_device_ctx->vf_takeover); + + netdev_info(ndev, "VF unregistering: %s\n", vf_netdev->name); + +@@ -1748,7 +1749,7 @@ static int netvsc_probe(struct hv_device *dev, + + spin_lock_init(&net_device_ctx->lock); + INIT_LIST_HEAD(&net_device_ctx->reconfig_events); +- INIT_WORK(&net_device_ctx->vf_takeover, netvsc_vf_setup); ++ INIT_DELAYED_WORK(&net_device_ctx->vf_takeover, netvsc_vf_setup); + + net_device_ctx->vf_stats + = netdev_alloc_pcpu_stats(struct netvsc_vf_pcpu_stats); diff --git a/patches.suse/msft-hv-1426-netvsc-don-t-signal-host-twice-if-empty.patch b/patches.suse/msft-hv-1426-netvsc-don-t-signal-host-twice-if-empty.patch new file mode 100644 index 0000000..edd75d6 --- /dev/null +++ b/patches.suse/msft-hv-1426-netvsc-don-t-signal-host-twice-if-empty.patch @@ -0,0 +1,31 @@ +From: stephen hemminger +Date: Wed, 9 Aug 2017 17:46:04 -0700 +Patch-mainline: v4.14-rc1 +Subject: netvsc: don't signal host twice if empty +Git-commit: 5e20d55a23a76a876396ba1235bdf019e74d0c6f +References: fate#323887 + +When hv_pkt_iter_next() returns NULL, it has already called +hv_pkt_iter_close(). Calling it twice can lead to extra host signal. + +Signed-off-by: Stephen Hemminger +Signed-off-by: David S. Miller +Acked-by: Olaf Hering +--- + drivers/net/hyperv/netvsc.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c +--- a/drivers/net/hyperv/netvsc.c ++++ b/drivers/net/hyperv/netvsc.c +@@ -1191,10 +1191,6 @@ int netvsc_poll(struct napi_struct *napi, int budget) + nvchan->desc = hv_pkt_iter_next(channel, nvchan->desc); + } + +- /* if ring is empty, signal host */ +- if (!nvchan->desc) +- hv_pkt_iter_close(channel); +- + /* If send of pending receive completions suceeded + * and did not exhaust NAPI budget this time + * and not doing busy poll diff --git a/patches.suse/msft-hv-1427-netvsc-propagate-MAC-address-change-to-VF-slave.patch b/patches.suse/msft-hv-1427-netvsc-propagate-MAC-address-change-to-VF-slave.patch new file mode 100644 index 0000000..9490b24 --- /dev/null +++ b/patches.suse/msft-hv-1427-netvsc-propagate-MAC-address-change-to-VF-slave.patch @@ -0,0 +1,72 @@ +From: stephen hemminger +Date: Wed, 9 Aug 2017 17:46:05 -0700 +Patch-mainline: v4.14-rc1 +Subject: netvsc: propagate MAC address change to VF slave +Git-commit: 16ba3266006be10dc7ec25dd1442f74cef89cb95 +References: fate#323887 + +If VF is slaved to synthetic device, then any change to netvsc +MAC address should be propagated to the slave device. + +If slave device doesn't support MAC address change then it +should also be an error to attempt to change synthetic NIC MAC +address. + +It also fixes the error unwind in the original code. +If give a bad address, the old code would change the device +MAC address anyway. + +Reviewed-by: Haiyang Zhang +Signed-off-by: Stephen Hemminger +Signed-off-by: David S. Miller +Acked-by: Olaf Hering +--- + drivers/net/hyperv/netvsc_drv.c | 26 +++++++++++++++----------- + 1 file changed, 15 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c +--- a/drivers/net/hyperv/netvsc_drv.c ++++ b/drivers/net/hyperv/netvsc_drv.c +@@ -1053,27 +1053,31 @@ static void netvsc_get_stats64(struct net_device *net, + static int netvsc_set_mac_addr(struct net_device *ndev, void *p) + { + struct net_device_context *ndc = netdev_priv(ndev); ++ struct net_device *vf_netdev = rtnl_dereference(ndc->vf_netdev); + struct netvsc_device *nvdev = rtnl_dereference(ndc->nvdev); + struct sockaddr *addr = p; +- char save_adr[ETH_ALEN]; +- unsigned char save_aatype; + int err; + +- memcpy(save_adr, ndev->dev_addr, ETH_ALEN); +- save_aatype = ndev->addr_assign_type; +- +- err = eth_mac_addr(ndev, p); +- if (err != 0) ++ err = eth_prepare_mac_addr_change(ndev, p); ++ if (err) + return err; + + if (!nvdev) + return -ENODEV; + ++ if (vf_netdev) { ++ err = dev_set_mac_address(vf_netdev, addr); ++ if (err) ++ return err; ++ } ++ + err = rndis_filter_set_device_mac(nvdev, addr->sa_data); +- if (err != 0) { +- /* roll back to saved MAC */ +- memcpy(ndev->dev_addr, save_adr, ETH_ALEN); +- ndev->addr_assign_type = save_aatype; ++ if (!err) { ++ eth_commit_mac_addr_change(ndev, p); ++ } else if (vf_netdev) { ++ /* rollback change on VF */ ++ memcpy(addr->sa_data, ndev->dev_addr, ETH_ALEN); ++ dev_set_mac_address(vf_netdev, addr); + } + + return err; diff --git a/patches.suse/msft-hv-1428-netvsc-check-error-return-when-restoring-channels-an.patch b/patches.suse/msft-hv-1428-netvsc-check-error-return-when-restoring-channels-an.patch new file mode 100644 index 0000000..c04374d --- /dev/null +++ b/patches.suse/msft-hv-1428-netvsc-check-error-return-when-restoring-channels-an.patch @@ -0,0 +1,54 @@ +From: stephen hemminger +Date: Wed, 9 Aug 2017 17:46:06 -0700 +Patch-mainline: v4.14-rc1 +Subject: netvsc: check error return when restoring channels and mtu +Git-commit: 68d715f68541d58033199eea80991394a6886eb7 +References: fate#323887 + +If setting new values fails, and the attempt to restore original +settings fails. Then log an error and leave device down. +This should never happen, but if it does don't go down in flames. + +Signed-off-by: Stephen Hemminger +Signed-off-by: David S. Miller +Acked-by: Olaf Hering +--- + drivers/net/hyperv/netvsc_drv.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c +--- a/drivers/net/hyperv/netvsc_drv.c ++++ b/drivers/net/hyperv/netvsc_drv.c +@@ -845,7 +845,13 @@ static int netvsc_set_channels(struct net_device *net, + } else { + ret = PTR_ERR(nvdev); + device_info.num_chn = orig; +- rndis_filter_device_add(dev, &device_info); ++ nvdev = rndis_filter_device_add(dev, &device_info); ++ ++ if (IS_ERR(nvdev)) { ++ netdev_err(net, "restoring channel setting failed: %ld\n", ++ PTR_ERR(nvdev)); ++ return ret; ++ } + } + + if (was_opened) +@@ -953,10 +959,16 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu) + + /* Attempt rollback to original MTU */ + ndev->mtu = orig_mtu; +- rndis_filter_device_add(hdev, &device_info); ++ nvdev = rndis_filter_device_add(hdev, &device_info); + + if (vf_netdev) + dev_set_mtu(vf_netdev, orig_mtu); ++ ++ if (IS_ERR(nvdev)) { ++ netdev_err(ndev, "restoring mtu failed: %ld\n", ++ PTR_ERR(nvdev)); ++ return ret; ++ } + } + + if (was_opened) diff --git a/patches.suse/msft-hv-1429-netvsc-no-need-to-allocate-send-receive-on-numa-node.patch b/patches.suse/msft-hv-1429-netvsc-no-need-to-allocate-send-receive-on-numa-node.patch new file mode 100644 index 0000000..e58a86a --- /dev/null +++ b/patches.suse/msft-hv-1429-netvsc-no-need-to-allocate-send-receive-on-numa-node.patch @@ -0,0 +1,58 @@ +From: stephen hemminger +Date: Wed, 9 Aug 2017 17:46:07 -0700 +Patch-mainline: v4.14-rc1 +Subject: netvsc: no need to allocate send/receive on numa node +Git-commit: 958333708f2877d3855e3bc31dad428e2f2c8096 +References: fate#323887 + +The send and receive buffers are both per-device (not per-channel). +The associated NUMA node is a property of the CPU which is per-channel +therefore it makes no sense to force the receive/send buffer to be +allocated on a particular node (since it is a shared resource). + +Signed-off-by: Stephen Hemminger +Signed-off-by: David S. Miller +Acked-by: Olaf Hering +--- + drivers/net/hyperv/netvsc.c | 19 +++++-------------- + 1 file changed, 5 insertions(+), 14 deletions(-) + +diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c +--- a/drivers/net/hyperv/netvsc.c ++++ b/drivers/net/hyperv/netvsc.c +@@ -246,20 +246,13 @@ int netvsc_alloc_recv_comp_ring(struct netvsc_device *net_device, u32 q_idx) + static int netvsc_init_buf(struct hv_device *device, + struct netvsc_device *net_device) + { +- int ret = 0; +- struct nvsp_message *init_packet; + struct nvsp_1_message_send_receive_buffer_complete *resp; +- struct net_device *ndev; ++ struct net_device *ndev = hv_get_drvdata(device); ++ struct nvsp_message *init_packet; + size_t map_words; +- int node; +- +- ndev = hv_get_drvdata(device); +- +- node = cpu_to_node(device->channel->target_cpu); +- net_device->recv_buf = vzalloc_node(net_device->recv_buf_size, node); +- if (!net_device->recv_buf) +- net_device->recv_buf = vzalloc(net_device->recv_buf_size); ++ int ret = 0; + ++ net_device->recv_buf = vzalloc(net_device->recv_buf_size); + if (!net_device->recv_buf) { + netdev_err(ndev, "unable to allocate receive " + "buffer of size %d\n", net_device->recv_buf_size); +@@ -340,9 +333,7 @@ static int netvsc_init_buf(struct hv_device *device, + goto cleanup; + + /* Now setup the send buffer. */ +- net_device->send_buf = vzalloc_node(net_device->send_buf_size, node); +- if (!net_device->send_buf) +- net_device->send_buf = vzalloc(net_device->send_buf_size); ++ net_device->send_buf = vzalloc(net_device->send_buf_size); + if (!net_device->send_buf) { + netdev_err(ndev, "unable to allocate send " + "buffer of size %d\n", net_device->send_buf_size); diff --git a/patches.suse/msft-hv-1430-netvsc-whitespace-cleanup.patch b/patches.suse/msft-hv-1430-netvsc-whitespace-cleanup.patch new file mode 100644 index 0000000..b07c4d9 --- /dev/null +++ b/patches.suse/msft-hv-1430-netvsc-whitespace-cleanup.patch @@ -0,0 +1,65 @@ +From: stephen hemminger +Date: Wed, 9 Aug 2017 17:46:08 -0700 +Patch-mainline: v4.14-rc1 +Subject: netvsc: whitespace cleanup +Git-commit: 89bb42b11370c2daf19d8820398f7255f8499ab7 +References: fate#323887 + +Fix some minor indentation issues. + +Signed-off-by: Stephen Hemminger +Signed-off-by: David S. Miller +Acked-by: Olaf Hering +--- + drivers/net/hyperv/netvsc_drv.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c +--- a/drivers/net/hyperv/netvsc_drv.c ++++ b/drivers/net/hyperv/netvsc_drv.c +@@ -165,7 +165,7 @@ static int netvsc_close(struct net_device *net) + } + + static void *init_ppi_data(struct rndis_message *msg, u32 ppi_size, +- int pkt_type) ++ int pkt_type) + { + struct rndis_packet *rndis_pkt; + struct rndis_per_packet_info *ppi; +@@ -286,7 +286,7 @@ static u16 netvsc_select_queue(struct net_device *ndev, struct sk_buff *skb, + } + + static u32 fill_pg_buf(struct page *page, u32 offset, u32 len, +- struct hv_page_buffer *pb) ++ struct hv_page_buffer *pb) + { + int j = 0; + +@@ -626,6 +626,7 @@ no_memory: + ++net_device_ctx->eth_stats.tx_no_memory; + goto drop; + } ++ + /* + * netvsc_linkstatus_callback - Link up/down notification + */ +@@ -649,8 +650,8 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj, + if (indicate->status == RNDIS_STATUS_LINK_SPEED_CHANGE) { + u32 speed; + +- speed = *(u32 *)((void *)indicate + indicate-> +- status_buf_offset) / 10000; ++ speed = *(u32 *)((void *)indicate ++ + indicate->status_buf_offset) / 10000; + ndev_ctx->speed = speed; + return; + } +@@ -1018,7 +1019,7 @@ static void netvsc_get_stats64(struct net_device *net, + struct net_device_context *ndev_ctx = netdev_priv(net); + struct netvsc_device *nvdev = rcu_dereference_rtnl(ndev_ctx->nvdev); + struct netvsc_vf_pcpu_stats vf_tot; +- int i; ++ int i; + + if (!nvdev) + return; diff --git a/patches.suse/msft-hv-1431-netvsc-remove-unnecessary-cast-of-void-pointer.patch b/patches.suse/msft-hv-1431-netvsc-remove-unnecessary-cast-of-void-pointer.patch new file mode 100644 index 0000000..f4a35a6 --- /dev/null +++ b/patches.suse/msft-hv-1431-netvsc-remove-unnecessary-cast-of-void-pointer.patch @@ -0,0 +1,43 @@ +From: stephen hemminger +Date: Wed, 9 Aug 2017 17:46:09 -0700 +Patch-mainline: v4.14-rc1 +Subject: netvsc: remove unnecessary cast of void pointer +Git-commit: 00f5024e821e60c0d1d7df44f2577a2c277b5cc9 +References: fate#323887 + +Assignment to a typed pointer is sufficient in C. +No cast is needed. + +Signed-off-by: Stephen Hemminger +Signed-off-by: David S. Miller +Acked-by: Olaf Hering +--- + drivers/net/hyperv/netvsc_drv.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c +--- a/drivers/net/hyperv/netvsc_drv.c ++++ b/drivers/net/hyperv/netvsc_drv.c +@@ -523,9 +523,9 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) + + rndis_msg_size += NDIS_VLAN_PPI_SIZE; + ppi = init_ppi_data(rndis_msg, NDIS_VLAN_PPI_SIZE, +- IEEE_8021Q_INFO); +- vlan = (struct ndis_pkt_8021q_info *)((void *)ppi + +- ppi->ppi_offset); ++ IEEE_8021Q_INFO); ++ ++ vlan = (void *)ppi + ppi->ppi_offset; + vlan->vlanid = skb->vlan_tci & VLAN_VID_MASK; + vlan->pri = (skb->vlan_tci & VLAN_PRIO_MASK) >> + VLAN_PRIO_SHIFT; +@@ -538,8 +538,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) + ppi = init_ppi_data(rndis_msg, NDIS_LSO_PPI_SIZE, + TCP_LARGESEND_PKTINFO); + +- lso_info = (struct ndis_tcp_lso_info *)((void *)ppi + +- ppi->ppi_offset); ++ lso_info = (void *)ppi + ppi->ppi_offset; + + lso_info->lso_v2_transmit.type = NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE; + if (skb->protocol == htons(ETH_P_IP)) { diff --git a/patches.suse/msft-hv-1432-netvsc-remove-unnecessary-check-for-NULL-hdr.patch b/patches.suse/msft-hv-1432-netvsc-remove-unnecessary-check-for-NULL-hdr.patch new file mode 100644 index 0000000..376cef7 --- /dev/null +++ b/patches.suse/msft-hv-1432-netvsc-remove-unnecessary-check-for-NULL-hdr.patch @@ -0,0 +1,34 @@ +From: stephen hemminger +Date: Wed, 9 Aug 2017 17:46:10 -0700 +Patch-mainline: v4.14-rc1 +Subject: netvsc: remove unnecessary check for NULL hdr +Git-commit: ea5a32c00bcacce1d8ac834a70a82f95a1c79425 +References: fate#323887 + +The function init_page_array is always called with a valid pointer +to RNDIS header. No check for NULL is needed. + +Signed-off-by: Stephen Hemminger +Signed-off-by: David S. Miller +Acked-by: Olaf Hering +--- + drivers/net/hyperv/netvsc_drv.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c +--- a/drivers/net/hyperv/netvsc_drv.c ++++ b/drivers/net/hyperv/netvsc_drv.c +@@ -333,10 +333,9 @@ static u32 init_page_array(void *hdr, u32 len, struct sk_buff *skb, + * 2. skb linear data + * 3. skb fragment data + */ +- if (hdr != NULL) +- slots_used += fill_pg_buf(virt_to_page(hdr), +- offset_in_page(hdr), +- len, &pb[slots_used]); ++ slots_used += fill_pg_buf(virt_to_page(hdr), ++ offset_in_page(hdr), ++ len, &pb[slots_used]); + + packet->rmsg_size = len; + packet->rmsg_pgcnt = slots_used; diff --git a/patches.suse/msft-hv-1433-netvsc-allow-controlling-send-recv-buffer-size.patch b/patches.suse/msft-hv-1433-netvsc-allow-controlling-send-recv-buffer-size.patch new file mode 100644 index 0000000..5c5fe94 --- /dev/null +++ b/patches.suse/msft-hv-1433-netvsc-allow-controlling-send-recv-buffer-size.patch @@ -0,0 +1,412 @@ +From: stephen hemminger +Date: Wed, 9 Aug 2017 17:46:11 -0700 +Patch-mainline: v4.14-rc1 +Subject: netvsc: allow controlling send/recv buffer size +Git-commit: 8b5327975ae171ca54dfd93e6c042d1292945867 +References: fate#323887 + +Control the size of the buffer areas via ethtool ring settings. +They aren't really traditional hardware rings, but host API breaks +receive and send buffer into chunks. The final size of the chunks are +controlled by the host. + +The default value of send and receive buffer area for host DMA +is much larger than it needs to be. Experimentation shows that +4M receive and 1M send is sufficient. + +Signed-off-by: Stephen Hemminger +Signed-off-by: David S. Miller +Acked-by: Olaf Hering +--- + drivers/net/hyperv/hyperv_net.h | 9 ++-- + drivers/net/hyperv/netvsc.c | 70 +++++++++++++----------- + drivers/net/hyperv/netvsc_drv.c | 117 ++++++++++++++++++++++++++++++++++++++-- + 3 files changed, 157 insertions(+), 39 deletions(-) + +diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h +--- a/drivers/net/hyperv/hyperv_net.h ++++ b/drivers/net/hyperv/hyperv_net.h +@@ -148,6 +148,8 @@ struct netvsc_device_info { + unsigned char mac_adr[ETH_ALEN]; + int ring_size; + u32 num_chn; ++ u32 send_sections; ++ u32 recv_sections; + }; + + enum rndis_device_state { +@@ -634,12 +636,12 @@ struct nvsp_message { + #define NETVSC_SEND_BUFFER_SIZE (1024 * 1024 * 15) /* 15MB */ + #define NETVSC_INVALID_INDEX -1 + ++#define NETVSC_SEND_SECTION_SIZE 6144 ++#define NETVSC_RECV_SECTION_SIZE 1728 + + #define NETVSC_RECEIVE_BUFFER_ID 0xcafe + #define NETVSC_SEND_BUFFER_ID 0 + +-#define NETVSC_PACKET_SIZE 4096 +- + #define VRSS_SEND_TAB_SIZE 16 /* must be power of 2 */ + #define VRSS_CHANNEL_MAX 64 + #define VRSS_CHANNEL_DEFAULT 8 +@@ -754,14 +756,13 @@ struct netvsc_device { + + /* Receive buffer allocated by us but manages by NetVSP */ + void *recv_buf; +- u32 recv_buf_size; + u32 recv_buf_gpadl_handle; + u32 recv_section_cnt; ++ u32 recv_section_size; + u32 recv_completion_cnt; + + /* Send buffer allocated by us */ + void *send_buf; +- u32 send_buf_size; + u32 send_buf_gpadl_handle; + u32 send_section_cnt; + u32 send_section_size; +diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c +--- a/drivers/net/hyperv/netvsc.c ++++ b/drivers/net/hyperv/netvsc.c +@@ -75,6 +75,10 @@ static struct netvsc_device *alloc_net_device(void) + atomic_set(&net_device->open_cnt, 0); + net_device->max_pkt = RNDIS_MAX_PKT_DEFAULT; + net_device->pkt_align = RNDIS_PKT_ALIGN_DEFAULT; ++ ++ net_device->recv_section_size = NETVSC_RECV_SECTION_SIZE; ++ net_device->send_section_size = NETVSC_SEND_SECTION_SIZE; ++ + init_completion(&net_device->channel_init_wait); + init_waitqueue_head(&net_device->subchan_open); + +@@ -143,6 +147,7 @@ static void netvsc_destroy_buf(struct hv_device *device) + "revoke receive buffer to netvsp\n"); + return; + } ++ net_device->recv_section_cnt = 0; + } + + /* Teardown the gpadl on the vsp end */ +@@ -173,7 +178,7 @@ static void netvsc_destroy_buf(struct hv_device *device) + * NVSP_MSG1_TYPE_SEND_SEND_BUF msg) therefore, we need + * to send a revoke msg here + */ +- if (net_device->send_section_size) { ++ if (net_device->send_section_cnt) { + /* Send the revoke receive buffer */ + revoke_packet = &net_device->revoke_packet; + memset(revoke_packet, 0, sizeof(struct nvsp_message)); +@@ -205,6 +210,7 @@ static void netvsc_destroy_buf(struct hv_device *device) + "revoke send buffer to netvsp\n"); + return; + } ++ net_device->send_section_cnt = 0; + } + /* Teardown the gpadl on the vsp end */ + if (net_device->send_buf_gpadl_handle) { +@@ -244,18 +250,25 @@ int netvsc_alloc_recv_comp_ring(struct netvsc_device *net_device, u32 q_idx) + } + + static int netvsc_init_buf(struct hv_device *device, +- struct netvsc_device *net_device) ++ struct netvsc_device *net_device, ++ const struct netvsc_device_info *device_info) + { + struct nvsp_1_message_send_receive_buffer_complete *resp; + struct net_device *ndev = hv_get_drvdata(device); + struct nvsp_message *init_packet; ++ unsigned int buf_size; + size_t map_words; + int ret = 0; + +- net_device->recv_buf = vzalloc(net_device->recv_buf_size); ++ /* Get receive buffer area. */ ++ buf_size = device_info->recv_sections * net_device->recv_section_size; ++ buf_size = roundup(buf_size, PAGE_SIZE); ++ ++ net_device->recv_buf = vzalloc(buf_size); + if (!net_device->recv_buf) { +- netdev_err(ndev, "unable to allocate receive " +- "buffer of size %d\n", net_device->recv_buf_size); ++ netdev_err(ndev, ++ "unable to allocate receive buffer of size %u\n", ++ buf_size); + ret = -ENOMEM; + goto cleanup; + } +@@ -266,7 +279,7 @@ static int netvsc_init_buf(struct hv_device *device, + * than the channel to establish the gpadl handle. + */ + ret = vmbus_establish_gpadl(device->channel, net_device->recv_buf, +- net_device->recv_buf_size, ++ buf_size, + &net_device->recv_buf_gpadl_handle); + if (ret != 0) { + netdev_err(ndev, +@@ -312,31 +325,31 @@ static int netvsc_init_buf(struct hv_device *device, + resp->num_sections, resp->sections[0].sub_alloc_size, + resp->sections[0].num_sub_allocs); + +- net_device->recv_section_cnt = resp->num_sections; +- +- /* +- * For 1st release, there should only be 1 section that represents the +- * entire receive buffer +- */ +- if (net_device->recv_section_cnt != 1 || +- resp->sections[0].offset != 0) { ++ /* There should only be one section for the entire receive buffer */ ++ if (resp->num_sections != 1 || resp->sections[0].offset != 0) { + ret = -EINVAL; + goto cleanup; + } + ++ net_device->recv_section_size = resp->sections[0].sub_alloc_size; ++ net_device->recv_section_cnt = resp->sections[0].num_sub_allocs; ++ + /* Setup receive completion ring */ + net_device->recv_completion_cnt +- = round_up(resp->sections[0].num_sub_allocs + 1, ++ = round_up(net_device->recv_section_cnt + 1, + PAGE_SIZE / sizeof(u64)); + ret = netvsc_alloc_recv_comp_ring(net_device, 0); + if (ret) + goto cleanup; + + /* Now setup the send buffer. */ +- net_device->send_buf = vzalloc(net_device->send_buf_size); ++ buf_size = device_info->send_sections * net_device->send_section_size; ++ buf_size = round_up(buf_size, PAGE_SIZE); ++ ++ net_device->send_buf = vzalloc(buf_size); + if (!net_device->send_buf) { +- netdev_err(ndev, "unable to allocate send " +- "buffer of size %d\n", net_device->send_buf_size); ++ netdev_err(ndev, "unable to allocate send buffer of size %u\n", ++ buf_size); + ret = -ENOMEM; + goto cleanup; + } +@@ -346,7 +359,7 @@ static int netvsc_init_buf(struct hv_device *device, + * than the channel to establish the gpadl handle. + */ + ret = vmbus_establish_gpadl(device->channel, net_device->send_buf, +- net_device->send_buf_size, ++ buf_size, + &net_device->send_buf_gpadl_handle); + if (ret != 0) { + netdev_err(ndev, +@@ -391,10 +404,8 @@ static int netvsc_init_buf(struct hv_device *device, + net_device->send_section_size = init_packet->msg. + v1_msg.send_send_buf_complete.section_size; + +- /* Section count is simply the size divided by the section size. +- */ +- net_device->send_section_cnt = +- net_device->send_buf_size / net_device->send_section_size; ++ /* Section count is simply the size divided by the section size. */ ++ net_device->send_section_cnt = buf_size / net_device->send_section_size; + + netdev_dbg(ndev, "Send section size: %d, Section count:%d\n", + net_device->send_section_size, net_device->send_section_cnt); +@@ -472,7 +483,8 @@ static int negotiate_nvsp_ver(struct hv_device *device, + } + + static int netvsc_connect_vsp(struct hv_device *device, +- struct netvsc_device *net_device) ++ struct netvsc_device *net_device, ++ const struct netvsc_device_info *device_info) + { + const u32 ver_list[] = { + NVSP_PROTOCOL_VERSION_1, NVSP_PROTOCOL_VERSION_2, +@@ -522,14 +534,8 @@ static int netvsc_connect_vsp(struct hv_device *device, + if (ret != 0) + goto cleanup; + +- /* Post the big receive buffer to NetVSP */ +- if (net_device->nvsp_version <= NVSP_PROTOCOL_VERSION_2) +- net_device->recv_buf_size = NETVSC_RECEIVE_BUFFER_SIZE_LEGACY; +- else +- net_device->recv_buf_size = NETVSC_RECEIVE_BUFFER_SIZE; +- net_device->send_buf_size = NETVSC_SEND_BUFFER_SIZE; + +- ret = netvsc_init_buf(device, net_device); ++ ret = netvsc_init_buf(device, net_device, device_info); + + cleanup: + return ret; +@@ -1287,7 +1293,7 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device, + rcu_assign_pointer(net_device_ctx->nvdev, net_device); + + /* Connect with the NetVsp */ +- ret = netvsc_connect_vsp(device, net_device); ++ ret = netvsc_connect_vsp(device, net_device, device_info); + if (ret != 0) { + netdev_err(ndev, + "unable to connect to NetVSP - %d\n", ret); +diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c +--- a/drivers/net/hyperv/netvsc_drv.c ++++ b/drivers/net/hyperv/netvsc_drv.c +@@ -45,7 +45,12 @@ + + #include "hyperv_net.h" + +-#define RING_SIZE_MIN 64 ++#define RING_SIZE_MIN 64 ++#define NETVSC_MIN_TX_SECTIONS 10 ++#define NETVSC_DEFAULT_TX 192 /* ~1M */ ++#define NETVSC_MIN_RX_SECTIONS 10 /* ~64K */ ++#define NETVSC_DEFAULT_RX 2048 /* ~4M */ ++ + #define LINKCHANGE_INT (2 * HZ) + #define VF_TAKEOVER_INT (HZ / 10) + +@@ -831,11 +836,13 @@ static int netvsc_set_channels(struct net_device *net, + if (was_opened) + rndis_filter_close(nvdev); + +- rndis_filter_device_remove(dev, nvdev); +- + memset(&device_info, 0, sizeof(device_info)); + device_info.num_chn = count; + device_info.ring_size = ring_size; ++ device_info.send_sections = nvdev->send_section_cnt; ++ device_info.recv_sections = nvdev->recv_section_cnt; ++ ++ rndis_filter_device_remove(dev, nvdev); + + nvdev = rndis_filter_device_add(dev, &device_info); + if (!IS_ERR(nvdev)) { +@@ -947,6 +954,8 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu) + memset(&device_info, 0, sizeof(device_info)); + device_info.ring_size = ring_size; + device_info.num_chn = nvdev->num_chn; ++ device_info.send_sections = nvdev->send_section_cnt; ++ device_info.recv_sections = nvdev->recv_section_cnt; + + rndis_filter_device_remove(hdev, nvdev); + +@@ -1351,6 +1360,104 @@ static int netvsc_set_rxfh(struct net_device *dev, const u32 *indir, + return rndis_filter_set_rss_param(rndis_dev, key, ndev->num_chn); + } + ++/* Hyper-V RNDIS protocol does not have ring in the HW sense. ++ * It does have pre-allocated receive area which is divided into sections. ++ */ ++static void __netvsc_get_ringparam(struct netvsc_device *nvdev, ++ struct ethtool_ringparam *ring) ++{ ++ u32 max_buf_size; ++ ++ ring->rx_pending = nvdev->recv_section_cnt; ++ ring->tx_pending = nvdev->send_section_cnt; ++ ++ if (nvdev->nvsp_version <= NVSP_PROTOCOL_VERSION_2) ++ max_buf_size = NETVSC_RECEIVE_BUFFER_SIZE_LEGACY; ++ else ++ max_buf_size = NETVSC_RECEIVE_BUFFER_SIZE; ++ ++ ring->rx_max_pending = max_buf_size / nvdev->recv_section_size; ++ ring->tx_max_pending = NETVSC_SEND_BUFFER_SIZE ++ / nvdev->send_section_size; ++} ++ ++static void netvsc_get_ringparam(struct net_device *ndev, ++ struct ethtool_ringparam *ring) ++{ ++ struct net_device_context *ndevctx = netdev_priv(ndev); ++ struct netvsc_device *nvdev = rtnl_dereference(ndevctx->nvdev); ++ ++ if (!nvdev) ++ return; ++ ++ __netvsc_get_ringparam(nvdev, ring); ++} ++ ++static int netvsc_set_ringparam(struct net_device *ndev, ++ struct ethtool_ringparam *ring) ++{ ++ struct net_device_context *ndevctx = netdev_priv(ndev); ++ struct netvsc_device *nvdev = rtnl_dereference(ndevctx->nvdev); ++ struct hv_device *hdev = ndevctx->device_ctx; ++ struct netvsc_device_info device_info; ++ struct ethtool_ringparam orig; ++ u32 new_tx, new_rx; ++ bool was_opened; ++ int ret = 0; ++ ++ if (!nvdev || nvdev->destroy) ++ return -ENODEV; ++ ++ memset(&orig, 0, sizeof(orig)); ++ __netvsc_get_ringparam(nvdev, &orig); ++ ++ new_tx = clamp_t(u32, ring->tx_pending, ++ NETVSC_MIN_TX_SECTIONS, orig.tx_max_pending); ++ new_rx = clamp_t(u32, ring->rx_pending, ++ NETVSC_MIN_RX_SECTIONS, orig.rx_max_pending); ++ ++ if (new_tx == orig.tx_pending && ++ new_rx == orig.rx_pending) ++ return 0; /* no change */ ++ ++ memset(&device_info, 0, sizeof(device_info)); ++ device_info.num_chn = nvdev->num_chn; ++ device_info.ring_size = ring_size; ++ device_info.send_sections = new_tx; ++ device_info.recv_sections = new_rx; ++ ++ netif_device_detach(ndev); ++ was_opened = rndis_filter_opened(nvdev); ++ if (was_opened) ++ rndis_filter_close(nvdev); ++ ++ rndis_filter_device_remove(hdev, nvdev); ++ ++ nvdev = rndis_filter_device_add(hdev, &device_info); ++ if (IS_ERR(nvdev)) { ++ ret = PTR_ERR(nvdev); ++ ++ device_info.send_sections = orig.tx_pending; ++ device_info.recv_sections = orig.rx_pending; ++ nvdev = rndis_filter_device_add(hdev, &device_info); ++ if (IS_ERR(nvdev)) { ++ netdev_err(ndev, "restoring ringparam failed: %ld\n", ++ PTR_ERR(nvdev)); ++ return ret; ++ } ++ } ++ ++ if (was_opened) ++ rndis_filter_open(nvdev); ++ netif_device_attach(ndev); ++ ++ /* We may have missed link change notifications */ ++ ndevctx->last_reconfig = 0; ++ schedule_delayed_work(&ndevctx->dwork, 0); ++ ++ return ret; ++} ++ + static const struct ethtool_ops ethtool_ops = { + .get_drvinfo = netvsc_get_drvinfo, + .get_link = ethtool_op_get_link, +@@ -1367,6 +1474,8 @@ static const struct ethtool_ops ethtool_ops = { + .set_rxfh = netvsc_set_rxfh, + .get_link_ksettings = netvsc_get_link_ksettings, + .set_link_ksettings = netvsc_set_link_ksettings, ++ .get_ringparam = netvsc_get_ringparam, ++ .set_ringparam = netvsc_set_ringparam, + }; + + static const struct net_device_ops device_ops = { +@@ -1782,6 +1891,8 @@ static int netvsc_probe(struct hv_device *dev, + memset(&device_info, 0, sizeof(device_info)); + device_info.ring_size = ring_size; + device_info.num_chn = VRSS_CHANNEL_DEFAULT; ++ device_info.send_sections = NETVSC_DEFAULT_TX; ++ device_info.recv_sections = NETVSC_DEFAULT_RX; + + nvdev = rndis_filter_device_add(dev, &device_info); + if (IS_ERR(nvdev)) { diff --git a/patches.suse/msft-hv-1434-netvsc-keep-track-of-some-non-fatal-overload-conditi.patch b/patches.suse/msft-hv-1434-netvsc-keep-track-of-some-non-fatal-overload-conditi.patch new file mode 100644 index 0000000..48818b8 --- /dev/null +++ b/patches.suse/msft-hv-1434-netvsc-keep-track-of-some-non-fatal-overload-conditi.patch @@ -0,0 +1,104 @@ +From: stephen hemminger +Date: Wed, 9 Aug 2017 17:46:12 -0700 +Patch-mainline: v4.14-rc1 +Subject: netvsc: keep track of some non-fatal overload conditions +Git-commit: cad5c197704d82faf33ffdbef414f15db08d9ef9 +References: fate#323887 + +Add ethtool statistics for case where send chimmeny buffer is +exhausted and driver has to fall back to doing scatter/gather +send. Also, add statistic for case where ring buffer is full and +receive completions are delayed. + +Signed-off-by: Stephen Hemminger +Signed-off-by: David S. Miller +Acked-by: Olaf Hering +--- + drivers/net/hyperv/hyperv_net.h | 2 ++ + drivers/net/hyperv/netvsc.c | 19 +++++++++++++------ + drivers/net/hyperv/netvsc_drv.c | 2 ++ + 3 files changed, 17 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h +--- a/drivers/net/hyperv/hyperv_net.h ++++ b/drivers/net/hyperv/hyperv_net.h +@@ -680,6 +680,8 @@ struct netvsc_ethtool_stats { + unsigned long tx_no_space; + unsigned long tx_too_big; + unsigned long tx_busy; ++ unsigned long tx_send_full; ++ unsigned long rx_comp_busy; + }; + + struct netvsc_vf_pcpu_stats { +diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c +--- a/drivers/net/hyperv/netvsc.c ++++ b/drivers/net/hyperv/netvsc.c +@@ -883,7 +883,9 @@ int netvsc_send(struct net_device_context *ndev_ctx, + } else if (pktlen + net_device->pkt_align < + net_device->send_section_size) { + section_index = netvsc_get_next_send_section(net_device); +- if (section_index != NETVSC_INVALID_INDEX) { ++ if (unlikely(section_index == NETVSC_INVALID_INDEX)) { ++ ++ndev_ctx->eth_stats.tx_send_full; ++ } else { + move_pkt_msd(&msd_send, &msd_skb, msdp); + msd_len = 0; + } +@@ -949,9 +951,10 @@ send_now: + } + + /* Send pending recv completions */ +-static int send_recv_completions(struct netvsc_channel *nvchan) ++static int send_recv_completions(struct net_device *ndev, ++ struct netvsc_device *nvdev, ++ struct netvsc_channel *nvchan) + { +- struct netvsc_device *nvdev = nvchan->net_device; + struct multi_recv_comp *mrc = &nvchan->mrc; + struct recv_comp_msg { + struct nvsp_message_header hdr; +@@ -969,8 +972,12 @@ static int send_recv_completions(struct netvsc_channel *nvchan) + msg.status = rcd->status; + ret = vmbus_sendpacket(nvchan->channel, &msg, sizeof(msg), + rcd->tid, VM_PKT_COMP, 0); +- if (unlikely(ret)) ++ if (unlikely(ret)) { ++ struct net_device_context *ndev_ctx = netdev_priv(ndev); ++ ++ ++ndev_ctx->eth_stats.rx_comp_busy; + return ret; ++ } + + if (++mrc->first == nvdev->recv_completion_cnt) + mrc->first = 0; +@@ -1011,7 +1018,7 @@ static void enq_receive_complete(struct net_device *ndev, + recv_comp_slot_avail(nvdev, mrc, &filled, &avail); + + if (unlikely(filled > NAPI_POLL_WEIGHT)) { +- send_recv_completions(nvchan); ++ send_recv_completions(ndev, nvdev, nvchan); + recv_comp_slot_avail(nvdev, mrc, &filled, &avail); + } + +@@ -1194,7 +1201,7 @@ int netvsc_poll(struct napi_struct *napi, int budget) + * then re-enable host interrupts + * and reschedule if ring is not empty. + */ +- if (send_recv_completions(nvchan) == 0 && ++ if (send_recv_completions(ndev, net_device, nvchan) == 0 && + work_done < budget && + napi_complete_done(napi, work_done) && + hv_end_read(&channel->inbound)) { +diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c +--- a/drivers/net/hyperv/netvsc_drv.c ++++ b/drivers/net/hyperv/netvsc_drv.c +@@ -1112,6 +1112,8 @@ static const struct { + { "tx_no_space", offsetof(struct netvsc_ethtool_stats, tx_no_space) }, + { "tx_too_big", offsetof(struct netvsc_ethtool_stats, tx_too_big) }, + { "tx_busy", offsetof(struct netvsc_ethtool_stats, tx_busy) }, ++ { "tx_send_full", offsetof(struct netvsc_ethtool_stats, tx_send_full) }, ++ { "rx_comp_busy", offsetof(struct netvsc_ethtool_stats, rx_comp_busy) }, + }, vf_stats[] = { + { "vf_rx_packets", offsetof(struct netvsc_vf_pcpu_stats, rx_packets) }, + { "vf_rx_bytes", offsetof(struct netvsc_vf_pcpu_stats, rx_bytes) }, diff --git a/patches.suse/msft-hv-1435-Tools-hv-vss-Skip-freezing-filesystems-backed-by-loo.patch b/patches.suse/msft-hv-1435-Tools-hv-vss-Skip-freezing-filesystems-backed-by-loo.patch new file mode 100644 index 0000000..84c749b --- /dev/null +++ b/patches.suse/msft-hv-1435-Tools-hv-vss-Skip-freezing-filesystems-backed-by-loo.patch @@ -0,0 +1,63 @@ +From: Alex Ng +Date: Sun, 6 Aug 2017 13:12:52 -0700 +Patch-mainline: v4.14-rc1 +Subject: Tools: hv: vss: Skip freezing filesystems backed by loop +Git-commit: ea81fdf0981d9a4a998a015d325bed67624811f7 +References: fate#323887 + +Since a loop device is backed by a file, a backup will already result in +its parent filesystem being frozen. It's sufficient to just freeze the +parent filesystem, so we can skip the loop device. + +This avoids a situation where a loop device and its parent filesystem are +both frozen and then thawed out of order. For example, if the loop device +is enumerated first, we would thaw it while its parent filesystem is still +frozen. The thaw operation fails and the loop device remains frozen. + +Signed-off-by: Alex Ng +Signed-off-by: Vyronas Tsingaras +Signed-off-by: K. Y. Srinivasan +Signed-off-by: Greg Kroah-Hartman +Acked-by: Olaf Hering +--- + tools/hv/hv_vss_daemon.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c +--- a/tools/hv/hv_vss_daemon.c ++++ b/tools/hv/hv_vss_daemon.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -30,6 +31,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -70,6 +72,7 @@ static int vss_operate(int operation) + char match[] = "/dev/"; + FILE *mounts; + struct mntent *ent; ++ struct stat sb; + char errdir[1024] = {0}; + unsigned int cmd; + int error = 0, root_seen = 0, save_errno = 0; +@@ -92,6 +95,10 @@ static int vss_operate(int operation) + while ((ent = getmntent(mounts))) { + if (strncmp(ent->mnt_fsname, match, strlen(match))) + continue; ++ if (stat(ent->mnt_fsname, &sb) == -1) ++ continue; ++ if (S_ISBLK(sb.st_mode) && major(sb.st_rdev) == LOOP_MAJOR) ++ continue; + if (hasmntopt(ent, MNTOPT_RO) != NULL) + continue; + if (strcmp(ent->mnt_type, "vfat") == 0) diff --git a/patches.suse/msft-hv-1436-Drivers-hv-balloon-Correctly-update-onlined-page-cou.patch b/patches.suse/msft-hv-1436-Drivers-hv-balloon-Correctly-update-onlined-page-cou.patch new file mode 100644 index 0000000..5fda7de --- /dev/null +++ b/patches.suse/msft-hv-1436-Drivers-hv-balloon-Correctly-update-onlined-page-cou.patch @@ -0,0 +1,45 @@ +From: Alex Ng +Date: Sun, 6 Aug 2017 13:12:53 -0700 +Patch-mainline: v4.14-rc1 +Subject: Drivers: hv: balloon: Correctly update onlined page count +Git-commit: 6df8d9aaf3afe25aacf20c69022a4c6d57b77a95 +References: fate#323887 + +Previously, num_pages_onlined was updated using value from memory online +notifier. This is incorrect because they assume that all hot-added pages +are online, even though we only online the amount that's backed by the +host. We should update num_pages_onlined only when the balloon driver +marks a page as online. + +Signed-off-by: Alex Ng +Signed-off-by: K. Y. Srinivasan +Signed-off-by: Greg Kroah-Hartman +Acked-by: Olaf Hering +--- + drivers/hv/hv_balloon.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c +--- a/drivers/hv/hv_balloon.c ++++ b/drivers/hv/hv_balloon.c +@@ -584,10 +584,6 @@ static int hv_memory_notifier(struct notifier_block *nb, unsigned long val, + + switch (val) { + case MEM_ONLINE: +- spin_lock_irqsave(&dm_device.ha_lock, flags); +- dm_device.num_pages_onlined += mem->nr_pages; +- spin_unlock_irqrestore(&dm_device.ha_lock, flags); +- /* Fall through */ + case MEM_CANCEL_ONLINE: + if (dm_device.ha_waiting) { + dm_device.ha_waiting = false; +@@ -644,6 +640,9 @@ static void hv_page_online_one(struct hv_hotadd_state *has, struct page *pg) + __online_page_set_limits(pg); + __online_page_increment_counters(pg); + __online_page_free(pg); ++ ++ WARN_ON_ONCE(!spin_is_locked(&dm_device.ha_lock)); ++ dm_device.num_pages_onlined++; + } + + static void hv_bring_pgs_online(struct hv_hotadd_state *has, diff --git a/patches.suse/msft-hv-1437-Drivers-hv-balloon-Show-the-max-dynamic-memory-assig.patch b/patches.suse/msft-hv-1437-Drivers-hv-balloon-Show-the-max-dynamic-memory-assig.patch new file mode 100644 index 0000000..d31d96e --- /dev/null +++ b/patches.suse/msft-hv-1437-Drivers-hv-balloon-Show-the-max-dynamic-memory-assig.patch @@ -0,0 +1,33 @@ +From: Alex Ng +Date: Sun, 6 Aug 2017 13:12:54 -0700 +Patch-mainline: v4.14-rc1 +Subject: Drivers: hv: balloon: Show the max dynamic memory assigned +Git-commit: 7b6e54b524b66b60e4cf49e8aa7c43045ebb987d +References: fate#323887 + +Previously we were only showing max number of pages. We should make it +more clear that this value is the max amount of dynamic memory that the +Hyper-V host is willing to assign to this guest. + +Signed-off-by: Alex Ng +Signed-off-by: K. Y. Srinivasan +Signed-off-by: Greg Kroah-Hartman +Acked-by: Olaf Hering +--- + drivers/hv/hv_balloon.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c +--- a/drivers/hv/hv_balloon.c ++++ b/drivers/hv/hv_balloon.c +@@ -1035,8 +1035,8 @@ static void process_info(struct hv_dynmem_device *dm, struct dm_info_msg *msg) + if (info_hdr->data_size == sizeof(__u64)) { + __u64 *max_page_count = (__u64 *)&info_hdr[1]; + +- pr_info("INFO_TYPE_MAX_PAGE_CNT = %llu\n", +- *max_page_count); ++ pr_info("Max. dynamic memory size: %llu MB\n", ++ (*max_page_count) >> (20 - PAGE_SHIFT)); + } + + break; diff --git a/patches.suse/msft-hv-1438-Drivers-hv-balloon-Initialize-last_post_time-on-star.patch b/patches.suse/msft-hv-1438-Drivers-hv-balloon-Initialize-last_post_time-on-star.patch new file mode 100644 index 0000000..44e1776 --- /dev/null +++ b/patches.suse/msft-hv-1438-Drivers-hv-balloon-Initialize-last_post_time-on-star.patch @@ -0,0 +1,36 @@ +From: Alex Ng +Date: Sun, 6 Aug 2017 13:12:55 -0700 +Patch-mainline: v4.14-rc1 +Subject: Drivers: hv: balloon: Initialize last_post_time on startup +Git-commit: c548f3957efa57b6f1a1f4c90013232f6f488682 +References: fate#323887 + +When left uninitialized, this sometimes fails the following check in +post_status(): + + if (!time_after(now, (last_post_time + HZ))) { + return; + } + +This causes unnecessary delays in reporting memory pressure to host after +booting up. + +Signed-off-by: Alex Ng +Signed-off-by: K. Y. Srinivasan +Signed-off-by: Greg Kroah-Hartman +Acked-by: Olaf Hering +--- + drivers/hv/hv_balloon.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c +--- a/drivers/hv/hv_balloon.c ++++ b/drivers/hv/hv_balloon.c +@@ -1655,6 +1655,7 @@ static int balloon_probe(struct hv_device *dev, + } + + dm_device.state = DM_INITIALIZED; ++ last_post_time = jiffies; + + return 0; + diff --git a/patches.suse/msft-hv-1439-Drivers-hv-kvp-Use-MAX_ADAPTER_ID_SIZE-for-translati.patch b/patches.suse/msft-hv-1439-Drivers-hv-kvp-Use-MAX_ADAPTER_ID_SIZE-for-translati.patch new file mode 100644 index 0000000..ea8f7e6 --- /dev/null +++ b/patches.suse/msft-hv-1439-Drivers-hv-kvp-Use-MAX_ADAPTER_ID_SIZE-for-translati.patch @@ -0,0 +1,35 @@ +From: Alex Ng +Date: Sun, 6 Aug 2017 13:12:56 -0700 +Patch-mainline: v4.14-rc1 +Subject: Drivers: hv: kvp: Use MAX_ADAPTER_ID_SIZE for translating adapter id +Git-commit: ddce54b6a95ed5ee3011b4771fda69c2d8a6d538 +References: fate#323887 + +There's a bug which passes the output buffer size as MAX_IP_ADDR_SIZE, +when converting the adapter_id field to UTF16. This is much larger than +the actual size (MAX_ADAPTER_ID_SIZE). Fix this by passing the proper +size. + +Fortunately, the translation is limited by the length of the input. This +explains why we haven't seen output buffer overflow conditions. + +Signed-off-by: Alex Ng +Signed-off-by: K. Y. Srinivasan +Signed-off-by: Greg Kroah-Hartman +Acked-by: Olaf Hering +--- + drivers/hv/hv_kvp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c +--- a/drivers/hv/hv_kvp.c ++++ b/drivers/hv/hv_kvp.c +@@ -304,7 +304,7 @@ static int process_ob_ipinfo(void *in_msg, void *out_msg, int op) + strlen((char *)in->body.kvp_ip_val.adapter_id), + UTF16_HOST_ENDIAN, + (wchar_t *)out->kvp_ip_val.adapter_id, +- MAX_IP_ADDR_SIZE); ++ MAX_ADAPTER_ID_SIZE); + if (len < 0) + return len; + diff --git a/patches.suse/msft-hv-1440-Tools-hv-fix-snprintf-warning-in-kvp_daemon.patch b/patches.suse/msft-hv-1440-Tools-hv-fix-snprintf-warning-in-kvp_daemon.patch new file mode 100644 index 0000000..df097a7 --- /dev/null +++ b/patches.suse/msft-hv-1440-Tools-hv-fix-snprintf-warning-in-kvp_daemon.patch @@ -0,0 +1,30 @@ +From: Olaf Hering +Date: Thu, 10 Aug 2017 15:45:15 -0700 +Patch-mainline: v4.14-rc1 +Subject: Tools: hv: fix snprintf warning in kvp_daemon +Git-commit: 3619350cf0d630d83dedd9c0d7d297da211f5ff0 +References: fate#323887 + +Increase buffer size so that "_{-INT_MAX}" will fit. +Spotted by the gcc7 snprintf checker. + +Signed-off-by: Olaf Hering +Signed-off-by: K. Y. Srinivasan +Signed-off-by: Greg Kroah-Hartman +Acked-by: Olaf Hering +--- + tools/hv/hv_kvp_daemon.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c +--- a/tools/hv/hv_kvp_daemon.c ++++ b/tools/hv/hv_kvp_daemon.c +@@ -1136,7 +1136,7 @@ static int process_ip_string(FILE *f, char *ip_string, int type) + int i = 0; + int j = 0; + char str[256]; +- char sub_str[10]; ++ char sub_str[13]; + int offset = 0; + + memset(addr, 0, sizeof(addr)); diff --git a/patches.suse/msft-hv-1441-Tools-hv-update-buffer-handling-in-hv_fcopy_daemon.patch b/patches.suse/msft-hv-1441-Tools-hv-update-buffer-handling-in-hv_fcopy_daemon.patch new file mode 100644 index 0000000..5edddb2 --- /dev/null +++ b/patches.suse/msft-hv-1441-Tools-hv-update-buffer-handling-in-hv_fcopy_daemon.patch @@ -0,0 +1,100 @@ +From: Olaf Hering +Date: Thu, 10 Aug 2017 15:45:16 -0700 +Patch-mainline: v4.14-rc1 +Subject: Tools: hv: update buffer handling in hv_fcopy_daemon +Git-commit: 3f2baa8a7d2efaa836f1dc4b8ee8c3ca4ba9e101 +References: fate#323887 + +Currently this warning is triggered when compiling hv_fcopy_daemon: + +hv_fcopy_daemon.c:216:4: warning: dereferencing type-punned pointer will break +strict-aliasing rules [-Wstrict-aliasing] + kernel_modver = *(__u32 *)buffer; + +Convert the send/receive buffer to a union and pass individual members as +needed. This also gives the correct size for the buffer. + +Signed-off-by: Olaf Hering +Signed-off-by: K. Y. Srinivasan +Signed-off-by: Greg Kroah-Hartman +Acked-by: Olaf Hering +--- + tools/hv/hv_fcopy_daemon.c | 32 +++++++++++++++++--------------- + 1 file changed, 17 insertions(+), 15 deletions(-) + +diff --git a/tools/hv/hv_fcopy_daemon.c b/tools/hv/hv_fcopy_daemon.c +--- a/tools/hv/hv_fcopy_daemon.c ++++ b/tools/hv/hv_fcopy_daemon.c +@@ -138,14 +138,17 @@ void print_usage(char *argv[]) + + int main(int argc, char *argv[]) + { +- int fcopy_fd, len; ++ int fcopy_fd; + int error; + int daemonize = 1, long_index = 0, opt; + int version = FCOPY_CURRENT_VERSION; +- char *buffer[4096 * 2]; +- struct hv_fcopy_hdr *in_msg; ++ union { ++ struct hv_fcopy_hdr hdr; ++ struct hv_start_fcopy start; ++ struct hv_do_fcopy copy; ++ __u32 kernel_modver; ++ } buffer = { }; + int in_handshake = 1; +- __u32 kernel_modver; + + static struct option long_options[] = { + {"help", no_argument, 0, 'h' }, +@@ -195,32 +198,31 @@ int main(int argc, char *argv[]) + * In this loop we process fcopy messages after the + * handshake is complete. + */ +- len = pread(fcopy_fd, buffer, (4096 * 2), 0); ++ ssize_t len; ++ ++ len = pread(fcopy_fd, &buffer, sizeof(buffer), 0); + if (len < 0) { + syslog(LOG_ERR, "pread failed: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + + if (in_handshake) { +- if (len != sizeof(kernel_modver)) { ++ if (len != sizeof(buffer.kernel_modver)) { + syslog(LOG_ERR, "invalid version negotiation"); + exit(EXIT_FAILURE); + } +- kernel_modver = *(__u32 *)buffer; + in_handshake = 0; +- syslog(LOG_INFO, "kernel module version: %d", +- kernel_modver); ++ syslog(LOG_INFO, "kernel module version: %u", ++ buffer.kernel_modver); + continue; + } + +- in_msg = (struct hv_fcopy_hdr *)buffer; +- +- switch (in_msg->operation) { ++ switch (buffer.hdr.operation) { + case START_FILE_COPY: +- error = hv_start_fcopy((struct hv_start_fcopy *)in_msg); ++ error = hv_start_fcopy(&buffer.start); + break; + case WRITE_TO_FILE: +- error = hv_copy_data((struct hv_do_fcopy *)in_msg); ++ error = hv_copy_data(&buffer.copy); + break; + case COMPLETE_FCOPY: + error = hv_copy_finished(); +@@ -231,7 +233,7 @@ int main(int argc, char *argv[]) + + default: + syslog(LOG_ERR, "Unknown operation: %d", +- in_msg->operation); ++ buffer.hdr.operation); + + } + diff --git a/patches.suse/msft-hv-1442-Drivers-hv-vmbus-Fix-rescind-handling-issues.patch b/patches.suse/msft-hv-1442-Drivers-hv-vmbus-Fix-rescind-handling-issues.patch new file mode 100644 index 0000000..3b5d476 --- /dev/null +++ b/patches.suse/msft-hv-1442-Drivers-hv-vmbus-Fix-rescind-handling-issues.patch @@ -0,0 +1,161 @@ +From: "K. Y. Srinivasan" +Date: Fri, 11 Aug 2017 10:03:59 -0700 +Patch-mainline: v4.14-rc1 +Subject: Drivers: hv: vmbus: Fix rescind handling issues +Git-commit: 6f3d791f300618caf82a2be0c27456edd76d5164 +References: fate#323887 + +This patch handles the following issues that were observed when we are +handling racing channel offer message and rescind message for the same +offer: + +1. Since the host does not respond to messages on a rescinded channel, +in the current code, we could be indefinitely blocked on the vmbus_open() call. + +2. When a rescinded channel is being closed, if there is a pending interrupt on the +channel, we could end up freeing the channel that the interrupt handler would run on. + +Signed-off-by: K. Y. Srinivasan +Reviewed-by: Dexuan Cui +Tested-by: Dexuan Cui +Signed-off-by: Greg Kroah-Hartman +Acked-by: Olaf Hering +--- + drivers/hv/channel.c | 14 ++++++++++++++ + drivers/hv/channel_mgmt.c | 29 ++++++++++++++++++++++++++--- + drivers/hv/vmbus_drv.c | 3 +++ + include/linux/hyperv.h | 2 ++ + 4 files changed, 45 insertions(+), 3 deletions(-) + +diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c +--- a/drivers/hv/channel.c ++++ b/drivers/hv/channel.c +@@ -177,6 +177,11 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, + &vmbus_connection.chn_msg_list); + spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); + ++ if (newchannel->rescind) { ++ err = -ENODEV; ++ goto error_free_gpadl; ++ } ++ + ret = vmbus_post_msg(open_msg, + sizeof(struct vmbus_channel_open_channel), true); + +@@ -421,6 +426,11 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer, + + spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); + ++ if (channel->rescind) { ++ ret = -ENODEV; ++ goto cleanup; ++ } ++ + ret = vmbus_post_msg(gpadlmsg, msginfo->msgsize - + sizeof(*msginfo), true); + if (ret != 0) +@@ -494,6 +504,10 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle) + list_add_tail(&info->msglistentry, + &vmbus_connection.chn_msg_list); + spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); ++ ++ if (channel->rescind) ++ goto post_msg_err; ++ + ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_gpadl_teardown), + true); + +diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c +--- a/drivers/hv/channel_mgmt.c ++++ b/drivers/hv/channel_mgmt.c +@@ -451,6 +451,12 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) + /* Make sure this is a new offer */ + mutex_lock(&vmbus_connection.channel_mutex); + ++ /* ++ * Now that we have acquired the channel_mutex, ++ * we can release the potentially racing rescind thread. ++ */ ++ atomic_dec(&vmbus_connection.offer_in_progress); ++ + list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) { + if (!uuid_le_cmp(channel->offermsg.offer.if_type, + newchannel->offermsg.offer.if_type) && +@@ -481,7 +487,6 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) + channel->num_sc++; + spin_unlock_irqrestore(&channel->lock, flags); + } else { +- atomic_dec(&vmbus_connection.offer_in_progress); + goto err_free_chan; + } + } +@@ -510,7 +515,6 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) + if (!fnew) { + if (channel->sc_creation_callback != NULL) + channel->sc_creation_callback(newchannel); +- atomic_dec(&vmbus_connection.offer_in_progress); + return; + } + +@@ -541,7 +545,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) + goto err_deq_chan; + } + +- atomic_dec(&vmbus_connection.offer_in_progress); ++ newchannel->probe_done = true; + return; + + err_deq_chan: +@@ -882,8 +886,27 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) + channel->rescind = true; + spin_unlock_irqrestore(&channel->lock, flags); + ++ /* ++ * Now that we have posted the rescind state, perform ++ * rescind related cleanup. ++ */ + vmbus_rescind_cleanup(channel); + ++ /* ++ * Now wait for offer handling to complete. ++ */ ++ while (READ_ONCE(channel->probe_done) == false) { ++ /* ++ * We wait here until any channel offer is currently ++ * being processed. ++ */ ++ msleep(1); ++ } ++ ++ /* ++ * At this point, the rescind handling can proceed safely. ++ */ ++ + if (channel->device_obj) { + if (channel->chn_rescind_callback) { + channel->chn_rescind_callback(channel); +diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c +--- a/drivers/hv/vmbus_drv.c ++++ b/drivers/hv/vmbus_drv.c +@@ -940,6 +940,9 @@ static void vmbus_chan_sched(struct hv_per_cpu_context *hv_cpu) + if (channel->offermsg.child_relid != relid) + continue; + ++ if (channel->rescind) ++ continue; ++ + switch (channel->callback_mode) { + case HV_CALL_ISR: + vmbus_channel_isr(channel); +diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h +--- a/include/linux/hyperv.h ++++ b/include/linux/hyperv.h +@@ -879,6 +879,8 @@ struct vmbus_channel { + */ + enum hv_numa_policy affinity_policy; + ++ bool probe_done; ++ + }; + + static inline bool is_hvsock_channel(const struct vmbus_channel *c) diff --git a/patches.suse/msft-hv-1443-vmbus-remove-unused-vmbus_sendpacket_multipagebuffer.patch b/patches.suse/msft-hv-1443-vmbus-remove-unused-vmbus_sendpacket_multipagebuffer.patch new file mode 100644 index 0000000..7152fd9 --- /dev/null +++ b/patches.suse/msft-hv-1443-vmbus-remove-unused-vmbus_sendpacket_multipagebuffer.patch @@ -0,0 +1,99 @@ +From: stephen hemminger +Date: Wed, 16 Aug 2017 08:56:24 -0700 +Patch-mainline: v4.14-rc1 +Subject: vmbus: remove unused vmbus_sendpacket_multipagebuffer +Git-commit: 9a603b8e1136f2b55f780fefbcbf84d31844ff2b +References: fate#323887 + +This function is not used anywhere in current code. + +Signed-off-by: Stephen Hemminger +Signed-off-by: David S. Miller +Acked-by: Olaf Hering +--- + drivers/hv/channel.c | 56 -------------------------------------------------- + include/linux/hyperv.h | 6 ------ + 2 files changed, 62 deletions(-) + +diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c +--- a/drivers/hv/channel.c ++++ b/drivers/hv/channel.c +@@ -814,62 +814,6 @@ int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel, + } + EXPORT_SYMBOL_GPL(vmbus_sendpacket_mpb_desc); + +-/* +- * vmbus_sendpacket_multipagebuffer - Send a multi-page buffer packet +- * using a GPADL Direct packet type. +- */ +-int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel, +- struct hv_multipage_buffer *multi_pagebuffer, +- void *buffer, u32 bufferlen, u64 requestid) +-{ +- struct vmbus_channel_packet_multipage_buffer desc; +- u32 descsize; +- u32 packetlen; +- u32 packetlen_aligned; +- struct kvec bufferlist[3]; +- u64 aligned_data = 0; +- u32 pfncount = NUM_PAGES_SPANNED(multi_pagebuffer->offset, +- multi_pagebuffer->len); +- +- if (pfncount > MAX_MULTIPAGE_BUFFER_COUNT) +- return -EINVAL; +- +- /* +- * Adjust the size down since vmbus_channel_packet_multipage_buffer is +- * the largest size we support +- */ +- descsize = sizeof(struct vmbus_channel_packet_multipage_buffer) - +- ((MAX_MULTIPAGE_BUFFER_COUNT - pfncount) * +- sizeof(u64)); +- packetlen = descsize + bufferlen; +- packetlen_aligned = ALIGN(packetlen, sizeof(u64)); +- +- +- /* Setup the descriptor */ +- desc.type = VM_PKT_DATA_USING_GPA_DIRECT; +- desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED; +- desc.dataoffset8 = descsize >> 3; /* in 8-bytes granularity */ +- desc.length8 = (u16)(packetlen_aligned >> 3); +- desc.transactionid = requestid; +- desc.rangecount = 1; +- +- desc.range.len = multi_pagebuffer->len; +- desc.range.offset = multi_pagebuffer->offset; +- +- memcpy(desc.range.pfn_array, multi_pagebuffer->pfn_array, +- pfncount * sizeof(u64)); +- +- bufferlist[0].iov_base = &desc; +- bufferlist[0].iov_len = descsize; +- bufferlist[1].iov_base = buffer; +- bufferlist[1].iov_len = bufferlen; +- bufferlist[2].iov_base = &aligned_data; +- bufferlist[2].iov_len = (packetlen_aligned - packetlen); +- +- return hv_ringbuffer_write(channel, bufferlist, 3); +-} +-EXPORT_SYMBOL_GPL(vmbus_sendpacket_multipagebuffer); +- + /** + * vmbus_recvpacket() - Retrieve the user packet on the specified channel + * @channel: Pointer to vmbus_channel structure. +diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h +--- a/include/linux/hyperv.h ++++ b/include/linux/hyperv.h +@@ -1052,12 +1052,6 @@ extern int vmbus_sendpacket_pagebuffer_ctl(struct vmbus_channel *channel, + u64 requestid, + u32 flags); + +-extern int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel, +- struct hv_multipage_buffer *mpb, +- void *buffer, +- u32 bufferlen, +- u64 requestid); +- + extern int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel, + struct vmbus_packet_mpb_array *mpb, + u32 desc_size, diff --git a/patches.suse/msft-hv-1444-vmbus-remove-unused-vmubs_sendpacket_pagebuffer_ctl.patch b/patches.suse/msft-hv-1444-vmbus-remove-unused-vmubs_sendpacket_pagebuffer_ctl.patch new file mode 100644 index 0000000..7efd160 --- /dev/null +++ b/patches.suse/msft-hv-1444-vmbus-remove-unused-vmubs_sendpacket_pagebuffer_ctl.patch @@ -0,0 +1,116 @@ +From: stephen hemminger +Date: Wed, 16 Aug 2017 08:56:25 -0700 +Patch-mainline: v4.14-rc1 +Subject: vmbus: remove unused vmubs_sendpacket_pagebuffer_ctl +Git-commit: 5a668d8cddbe8bf14379ce110c49ca088a1e9fae +References: fate#323887 + +The function vmbus_sendpacket_pagebuffer_ctl was never used directly. +Just have vmbus_send_pagebuffer + +Signed-off-by: Stephen Hemminger +Signed-off-by: David S. Miller +Acked-by: Olaf Hering +--- + drivers/hv/channel.c | 30 ++++++------------------------ + drivers/net/hyperv/netvsc.c | 10 ++++------ + include/linux/hyperv.h | 8 -------- + 3 files changed, 10 insertions(+), 38 deletions(-) + +diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c +--- a/drivers/hv/channel.c ++++ b/drivers/hv/channel.c +@@ -702,16 +702,16 @@ int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer, + EXPORT_SYMBOL(vmbus_sendpacket); + + /* +- * vmbus_sendpacket_pagebuffer_ctl - Send a range of single-page buffer ++ * vmbus_sendpacket_pagebuffer - Send a range of single-page buffer + * packets using a GPADL Direct packet type. This interface allows you + * to control notifying the host. This will be useful for sending + * batched data. Also the sender can control the send flags + * explicitly. + */ +-int vmbus_sendpacket_pagebuffer_ctl(struct vmbus_channel *channel, +- struct hv_page_buffer pagebuffers[], +- u32 pagecount, void *buffer, u32 bufferlen, +- u64 requestid, u32 flags) ++int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel, ++ struct hv_page_buffer pagebuffers[], ++ u32 pagecount, void *buffer, u32 bufferlen, ++ u64 requestid) + { + int i; + struct vmbus_channel_packet_page_buffer desc; +@@ -736,7 +736,7 @@ int vmbus_sendpacket_pagebuffer_ctl(struct vmbus_channel *channel, + + /* Setup the descriptor */ + desc.type = VM_PKT_DATA_USING_GPA_DIRECT; +- desc.flags = flags; ++ desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED; + desc.dataoffset8 = descsize >> 3; /* in 8-bytes granularity */ + desc.length8 = (u16)(packetlen_aligned >> 3); + desc.transactionid = requestid; +@@ -757,24 +757,6 @@ int vmbus_sendpacket_pagebuffer_ctl(struct vmbus_channel *channel, + + return hv_ringbuffer_write(channel, bufferlist, 3); + } +-EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer_ctl); +- +-/* +- * vmbus_sendpacket_pagebuffer - Send a range of single-page buffer +- * packets using a GPADL Direct packet type. +- */ +-int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel, +- struct hv_page_buffer pagebuffers[], +- u32 pagecount, void *buffer, u32 bufferlen, +- u64 requestid) +-{ +- u32 flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED; +- +- return vmbus_sendpacket_pagebuffer_ctl(channel, pagebuffers, pagecount, +- buffer, bufferlen, +- requestid, flags); +- +-} + EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer); + + /* +diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c +--- a/drivers/net/hyperv/netvsc.c ++++ b/drivers/net/hyperv/netvsc.c +@@ -775,12 +775,10 @@ static inline int netvsc_send_pkt( + if (packet->cp_partial) + pb += packet->rmsg_pgcnt; + +- ret = vmbus_sendpacket_pagebuffer_ctl(out_channel, +- pb, packet->page_buf_cnt, +- &nvmsg, +- sizeof(struct nvsp_message), +- req_id, +- VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); ++ ret = vmbus_sendpacket_pagebuffer(out_channel, ++ pb, packet->page_buf_cnt, ++ &nvmsg, sizeof(nvmsg), ++ req_id); + } else { + ret = vmbus_sendpacket_ctl(out_channel, &nvmsg, + sizeof(struct nvsp_message), +diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h +--- a/include/linux/hyperv.h ++++ b/include/linux/hyperv.h +@@ -1044,14 +1044,6 @@ extern int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel, + u32 bufferlen, + u64 requestid); + +-extern int vmbus_sendpacket_pagebuffer_ctl(struct vmbus_channel *channel, +- struct hv_page_buffer pagebuffers[], +- u32 pagecount, +- void *buffer, +- u32 bufferlen, +- u64 requestid, +- u32 flags); +- + extern int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel, + struct vmbus_packet_mpb_array *mpb, + u32 desc_size, diff --git a/patches.suse/msft-hv-1445-vmbus-remove-unused-vmbus_sendpacket_ctl.patch b/patches.suse/msft-hv-1445-vmbus-remove-unused-vmbus_sendpacket_ctl.patch new file mode 100644 index 0000000..5f2d23e --- /dev/null +++ b/patches.suse/msft-hv-1445-vmbus-remove-unused-vmbus_sendpacket_ctl.patch @@ -0,0 +1,114 @@ +From: stephen hemminger +Date: Wed, 16 Aug 2017 08:56:26 -0700 +Patch-mainline: v4.14-rc1 +Subject: vmbus: remove unused vmbus_sendpacket_ctl +Git-commit: 5dd0fb9b9ffc0ef9b312d05604f4ad0fffc50505 +References: fate#323887 + +The only usage of vmbus_sendpacket_ctl was by vmbus_sendpacket. + +Signed-off-by: Stephen Hemminger +Signed-off-by: David S. Miller +Acked-by: Olaf Hering +--- + drivers/hv/channel.c | 43 +++++++++++++++++-------------------------- + drivers/net/hyperv/netvsc.c | 9 ++++----- + include/linux/hyperv.h | 7 ------- + 3 files changed, 21 insertions(+), 38 deletions(-) + +diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c +--- a/drivers/hv/channel.c ++++ b/drivers/hv/channel.c +@@ -647,9 +647,23 @@ void vmbus_close(struct vmbus_channel *channel) + } + EXPORT_SYMBOL_GPL(vmbus_close); + +-int vmbus_sendpacket_ctl(struct vmbus_channel *channel, void *buffer, +- u32 bufferlen, u64 requestid, +- enum vmbus_packet_type type, u32 flags) ++/** ++ * vmbus_sendpacket() - Send the specified buffer on the given channel ++ * @channel: Pointer to vmbus_channel structure. ++ * @buffer: Pointer to the buffer you want to receive the data into. ++ * @bufferlen: Maximum size of what the the buffer will hold ++ * @requestid: Identifier of the request ++ * @type: Type of packet that is being send e.g. negotiate, time ++ * packet etc. ++ * ++ * Sends data in @buffer directly to hyper-v via the vmbus ++ * This will send the data unparsed to hyper-v. ++ * ++ * Mainly used by Hyper-V drivers. ++ */ ++int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer, ++ u32 bufferlen, u64 requestid, ++ enum vmbus_packet_type type, u32 flags) + { + struct vmpacket_descriptor desc; + u32 packetlen = sizeof(struct vmpacket_descriptor) + bufferlen; +@@ -676,29 +690,6 @@ int vmbus_sendpacket_ctl(struct vmbus_channel *channel, void *buffer, + + return hv_ringbuffer_write(channel, bufferlist, num_vecs); + } +-EXPORT_SYMBOL(vmbus_sendpacket_ctl); +- +-/** +- * vmbus_sendpacket() - Send the specified buffer on the given channel +- * @channel: Pointer to vmbus_channel structure. +- * @buffer: Pointer to the buffer you want to receive the data into. +- * @bufferlen: Maximum size of what the the buffer will hold +- * @requestid: Identifier of the request +- * @type: Type of packet that is being send e.g. negotiate, time +- * packet etc. +- * +- * Sends data in @buffer directly to hyper-v via the vmbus +- * This will send the data unparsed to hyper-v. +- * +- * Mainly used by Hyper-V drivers. +- */ +-int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer, +- u32 bufferlen, u64 requestid, +- enum vmbus_packet_type type, u32 flags) +-{ +- return vmbus_sendpacket_ctl(channel, buffer, bufferlen, requestid, +- type, flags); +-} + EXPORT_SYMBOL(vmbus_sendpacket); + + /* +diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c +--- a/drivers/net/hyperv/netvsc.c ++++ b/drivers/net/hyperv/netvsc.c +@@ -780,11 +780,10 @@ static inline int netvsc_send_pkt( + &nvmsg, sizeof(nvmsg), + req_id); + } else { +- ret = vmbus_sendpacket_ctl(out_channel, &nvmsg, +- sizeof(struct nvsp_message), +- req_id, +- VM_PKT_DATA_INBAND, +- VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); ++ ret = vmbus_sendpacket(out_channel, ++ &nvmsg, sizeof(nvmsg), ++ req_id, VM_PKT_DATA_INBAND, ++ VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + } + + if (ret == 0) { +diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h +--- a/include/linux/hyperv.h ++++ b/include/linux/hyperv.h +@@ -1030,13 +1030,6 @@ extern int vmbus_sendpacket(struct vmbus_channel *channel, + enum vmbus_packet_type type, + u32 flags); + +-extern int vmbus_sendpacket_ctl(struct vmbus_channel *channel, +- void *buffer, +- u32 bufferLen, +- u64 requestid, +- enum vmbus_packet_type type, +- u32 flags); +- + extern int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel, + struct hv_page_buffer pagebuffers[], + u32 pagecount, diff --git a/patches.suse/msft-hv-1446-hv_netvsc-Clean-up-unused-parameter-from-netvsc_get_.patch b/patches.suse/msft-hv-1446-hv_netvsc-Clean-up-unused-parameter-from-netvsc_get_.patch new file mode 100644 index 0000000..bb05737 --- /dev/null +++ b/patches.suse/msft-hv-1446-hv_netvsc-Clean-up-unused-parameter-from-netvsc_get_.patch @@ -0,0 +1,37 @@ +From: Haiyang Zhang +Date: Mon, 21 Aug 2017 19:22:37 -0700 +Patch-mainline: v4.14-rc1 +Subject: hv_netvsc: Clean up unused parameter from netvsc_get_hash() +Git-commit: fcba1569a0c87cea40404af9a29b319f4e491839 +References: fate#323887 + +The parameter "sk" is not in use. + +Signed-off-by: Haiyang Zhang +Signed-off-by: David S. Miller +Acked-by: Olaf Hering +--- + drivers/net/hyperv/netvsc_drv.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c +--- a/drivers/net/hyperv/netvsc_drv.c ++++ b/drivers/net/hyperv/netvsc_drv.c +@@ -193,7 +193,7 @@ static void *init_ppi_data(struct rndis_message *msg, u32 ppi_size, + /* Azure hosts don't support non-TCP port numbers in hashing yet. We compute + * hash for non-TCP traffic with only IP numbers. + */ +-static inline u32 netvsc_get_hash(struct sk_buff *skb, struct sock *sk) ++static inline u32 netvsc_get_hash(struct sk_buff *skb) + { + struct flow_keys flow; + u32 hash; +@@ -227,7 +227,7 @@ static inline int netvsc_get_tx_queue(struct net_device *ndev, + struct sock *sk = skb->sk; + int q_idx; + +- q_idx = ndc->tx_send_table[netvsc_get_hash(skb, sk) & ++ q_idx = ndc->tx_send_table[netvsc_get_hash(skb) & + (VRSS_SEND_TAB_SIZE - 1)]; + + /* If queue index changed record the new value */ diff --git a/patches.suse/msft-hv-1447-hv_netvsc-Clean-up-unused-parameter-from-netvsc_get_.patch b/patches.suse/msft-hv-1447-hv_netvsc-Clean-up-unused-parameter-from-netvsc_get_.patch new file mode 100644 index 0000000..7775178 --- /dev/null +++ b/patches.suse/msft-hv-1447-hv_netvsc-Clean-up-unused-parameter-from-netvsc_get_.patch @@ -0,0 +1,38 @@ +From: Haiyang Zhang +Date: Mon, 21 Aug 2017 19:22:38 -0700 +Patch-mainline: v4.14-rc1 +Subject: hv_netvsc: Clean up unused parameter from netvsc_get_rss_hash_opts() +Git-commit: 4c0e2cbfd9b519722529526f4d87f8aab3c32ffd +References: fate#323887 + +The parameter "nvdev" is not in use. + +Signed-off-by: Haiyang Zhang +Signed-off-by: David S. Miller +Acked-by: Olaf Hering +--- + drivers/net/hyperv/netvsc_drv.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c +--- a/drivers/net/hyperv/netvsc_drv.c ++++ b/drivers/net/hyperv/netvsc_drv.c +@@ -1228,8 +1228,7 @@ static void netvsc_get_strings(struct net_device *dev, u32 stringset, u8 *data) + } + + static int +-netvsc_get_rss_hash_opts(struct netvsc_device *nvdev, +- struct ethtool_rxnfc *info) ++netvsc_get_rss_hash_opts(struct ethtool_rxnfc *info) + { + info->data = RXH_IP_SRC | RXH_IP_DST; + +@@ -1267,7 +1266,7 @@ netvsc_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, + return 0; + + case ETHTOOL_GRXFH: +- return netvsc_get_rss_hash_opts(nvdev, info); ++ return netvsc_get_rss_hash_opts(info); + } + return -EOPNOTSUPP; + } diff --git a/patches.suse/msft-hv-1448-hv_netvsc-Add-ethtool-handler-to-set-and-get-UDP-has.patch b/patches.suse/msft-hv-1448-hv_netvsc-Add-ethtool-handler-to-set-and-get-UDP-has.patch new file mode 100644 index 0000000..61888c2 --- /dev/null +++ b/patches.suse/msft-hv-1448-hv_netvsc-Add-ethtool-handler-to-set-and-get-UDP-has.patch @@ -0,0 +1,187 @@ +From: Haiyang Zhang +Date: Mon, 21 Aug 2017 19:22:39 -0700 +Patch-mainline: v4.14-rc1 +Subject: hv_netvsc: Add ethtool handler to set and get UDP hash levels +Git-commit: 4823eb2f3af44e2b9f7f02bed5a211e9ce79051f +References: fate#323887 + +The patch add the functions to switch UDP hash level between +L3 and L4 by ethtool command. UDP over IPv4 and v6 can be set +differently. The default hash level is L4. We currently only +allow switching TX hash level from within the guests. + +On Azure, fragmented UDP packets have high loss rate with L4 +hashing. Using L3 hashing is recommended in this case. + +For example, for UDP over IPv4 on eth0: +To include UDP port numbers in hasing: + ethtool -N eth0 rx-flow-hash udp4 sdfn +To exclude UDP port numbers in hasing: + ethtool -N eth0 rx-flow-hash udp4 sd +To show UDP hash level: + ethtool -n eth0 rx-flow-hash udp4 + +Signed-off-by: Haiyang Zhang +Signed-off-by: David S. Miller +Acked-by: Olaf Hering +--- + drivers/net/hyperv/hyperv_net.h | 2 ++ + drivers/net/hyperv/netvsc_drv.c | 78 ++++++++++++++++++++++++++++++++++++----- + 2 files changed, 72 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h +--- a/drivers/net/hyperv/hyperv_net.h ++++ b/drivers/net/hyperv/hyperv_net.h +@@ -720,6 +720,8 @@ struct net_device_context { + u32 tx_send_table[VRSS_SEND_TAB_SIZE]; + + /* Ethtool settings */ ++ bool udp4_l4_hash; ++ bool udp6_l4_hash; + u8 duplex; + u32 speed; + struct netvsc_ethtool_stats eth_stats; +diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c +--- a/drivers/net/hyperv/netvsc_drv.c ++++ b/drivers/net/hyperv/netvsc_drv.c +@@ -190,10 +190,12 @@ static void *init_ppi_data(struct rndis_message *msg, u32 ppi_size, + return ppi; + } + +-/* Azure hosts don't support non-TCP port numbers in hashing yet. We compute +- * hash for non-TCP traffic with only IP numbers. ++/* Azure hosts don't support non-TCP port numbers in hashing for fragmented ++ * packets. We can use ethtool to change UDP hash level when necessary. + */ +-static inline u32 netvsc_get_hash(struct sk_buff *skb) ++static inline u32 netvsc_get_hash( ++ struct sk_buff *skb, ++ const struct net_device_context *ndc) + { + struct flow_keys flow; + u32 hash; +@@ -204,7 +206,11 @@ static inline u32 netvsc_get_hash(struct sk_buff *skb) + if (!skb_flow_dissect_flow_keys(skb, &flow, 0)) + return 0; + +- if (flow.basic.ip_proto == IPPROTO_TCP) { ++ if (flow.basic.ip_proto == IPPROTO_TCP || ++ (flow.basic.ip_proto == IPPROTO_UDP && ++ ((flow.basic.n_proto == htons(ETH_P_IP) && ndc->udp4_l4_hash) || ++ (flow.basic.n_proto == htons(ETH_P_IPV6) && ++ ndc->udp6_l4_hash)))) { + return skb_get_hash(skb); + } else { + if (flow.basic.n_proto == htons(ETH_P_IP)) +@@ -227,7 +233,7 @@ static inline int netvsc_get_tx_queue(struct net_device *ndev, + struct sock *sk = skb->sk; + int q_idx; + +- q_idx = ndc->tx_send_table[netvsc_get_hash(skb) & ++ q_idx = ndc->tx_send_table[netvsc_get_hash(skb, ndc) & + (VRSS_SEND_TAB_SIZE - 1)]; + + /* If queue index changed record the new value */ +@@ -891,6 +897,9 @@ static void netvsc_init_settings(struct net_device *dev) + { + struct net_device_context *ndc = netdev_priv(dev); + ++ ndc->udp4_l4_hash = true; ++ ndc->udp6_l4_hash = true; ++ + ndc->speed = SPEED_UNKNOWN; + ndc->duplex = DUPLEX_FULL; + } +@@ -1228,7 +1237,8 @@ static void netvsc_get_strings(struct net_device *dev, u32 stringset, u8 *data) + } + + static int +-netvsc_get_rss_hash_opts(struct ethtool_rxnfc *info) ++netvsc_get_rss_hash_opts(struct net_device_context *ndc, ++ struct ethtool_rxnfc *info) + { + info->data = RXH_IP_SRC | RXH_IP_DST; + +@@ -1236,9 +1246,20 @@ netvsc_get_rss_hash_opts(struct ethtool_rxnfc *info) + case TCP_V4_FLOW: + case TCP_V6_FLOW: + info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; +- /* fallthrough */ ++ break; ++ + case UDP_V4_FLOW: ++ if (ndc->udp4_l4_hash) ++ info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; ++ ++ break; ++ + case UDP_V6_FLOW: ++ if (ndc->udp6_l4_hash) ++ info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; ++ ++ break; ++ + case IPV4_FLOW: + case IPV6_FLOW: + break; +@@ -1266,11 +1287,51 @@ netvsc_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, + return 0; + + case ETHTOOL_GRXFH: +- return netvsc_get_rss_hash_opts(info); ++ return netvsc_get_rss_hash_opts(ndc, info); + } + return -EOPNOTSUPP; + } + ++static int netvsc_set_rss_hash_opts(struct net_device_context *ndc, ++ struct ethtool_rxnfc *info) ++{ ++ if (info->data == (RXH_IP_SRC | RXH_IP_DST | ++ RXH_L4_B_0_1 | RXH_L4_B_2_3)) { ++ if (info->flow_type == UDP_V4_FLOW) ++ ndc->udp4_l4_hash = true; ++ else if (info->flow_type == UDP_V6_FLOW) ++ ndc->udp6_l4_hash = true; ++ else ++ return -EOPNOTSUPP; ++ ++ return 0; ++ } ++ ++ if (info->data == (RXH_IP_SRC | RXH_IP_DST)) { ++ if (info->flow_type == UDP_V4_FLOW) ++ ndc->udp4_l4_hash = false; ++ else if (info->flow_type == UDP_V6_FLOW) ++ ndc->udp6_l4_hash = false; ++ else ++ return -EOPNOTSUPP; ++ ++ return 0; ++ } ++ ++ return -EOPNOTSUPP; ++} ++ ++static int ++netvsc_set_rxnfc(struct net_device *ndev, struct ethtool_rxnfc *info) ++{ ++ struct net_device_context *ndc = netdev_priv(ndev); ++ ++ if (info->cmd == ETHTOOL_SRXFH) ++ return netvsc_set_rss_hash_opts(ndc, info); ++ ++ return -EOPNOTSUPP; ++} ++ + #ifdef CONFIG_NET_POLL_CONTROLLER + static void netvsc_poll_controller(struct net_device *dev) + { +@@ -1469,6 +1530,7 @@ static const struct ethtool_ops ethtool_ops = { + .set_channels = netvsc_set_channels, + .get_ts_info = ethtool_op_get_ts_info, + .get_rxnfc = netvsc_get_rxnfc, ++ .set_rxnfc = netvsc_set_rxnfc, + .get_rxfh_key_size = netvsc_get_rxfh_key_size, + .get_rxfh_indir_size = netvsc_rss_indir_size, + .get_rxfh = netvsc_get_rxfh, diff --git a/patches.suse/msft-hv-1449-hv_netvsc-Fix-rndis_filter_close-error-during-netvsc.patch b/patches.suse/msft-hv-1449-hv_netvsc-Fix-rndis_filter_close-error-during-netvsc.patch new file mode 100644 index 0000000..ed71f30 --- /dev/null +++ b/patches.suse/msft-hv-1449-hv_netvsc-Fix-rndis_filter_close-error-during-netvsc.patch @@ -0,0 +1,48 @@ +From: Haiyang Zhang +Date: Thu, 24 Aug 2017 11:50:02 -0700 +Patch-mainline: v4.14-rc1 +Subject: hv_netvsc: Fix rndis_filter_close error during netvsc_remove +Git-commit: c6f71c418fcc46f59fc87ac93ce9336c12d7898b +References: fate#323887 + +We now remove rndis filter before unregister_netdev(), which calls +device close. It involves closing rndis filter already removed. + +This patch fixes this error. + +Signed-off-by: Haiyang Zhang +Signed-off-by: David S. Miller +Acked-by: Olaf Hering +--- + drivers/net/hyperv/netvsc_drv.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c +--- a/drivers/net/hyperv/netvsc_drv.c ++++ b/drivers/net/hyperv/netvsc_drv.c +@@ -119,12 +119,16 @@ static int netvsc_close(struct net_device *net) + struct net_device *vf_netdev + = rtnl_dereference(net_device_ctx->vf_netdev); + struct netvsc_device *nvdev = rtnl_dereference(net_device_ctx->nvdev); +- int ret; ++ int ret = 0; + u32 aread, i, msec = 10, retry = 0, retry_max = 20; + struct vmbus_channel *chn; + + netif_tx_disable(net); + ++ /* No need to close rndis filter if it is removed already */ ++ if (!nvdev) ++ goto out; ++ + ret = rndis_filter_close(nvdev); + if (ret != 0) { + netdev_err(net, "unable to close device (ret %d).\n", ret); +@@ -163,6 +167,7 @@ static int netvsc_close(struct net_device *net) + ret = -ETIMEDOUT; + } + ++out: + if (vf_netdev) + dev_close(vf_netdev); + diff --git a/patches.suse/msft-hv-1452-scsi-storvsc-fix-memory-leak-on-ring-buffer-busy.patch b/patches.suse/msft-hv-1452-scsi-storvsc-fix-memory-leak-on-ring-buffer-busy.patch new file mode 100644 index 0000000..4c8c1d6 --- /dev/null +++ b/patches.suse/msft-hv-1452-scsi-storvsc-fix-memory-leak-on-ring-buffer-busy.patch @@ -0,0 +1,37 @@ +From: Long Li +Date: Mon, 28 Aug 2017 17:43:59 -0700 +Patch-mainline: v4.14-rc1 +Subject: scsi: storvsc: fix memory leak on ring buffer busy +Git-commit: 0208eeaa650c5c866a3242201678a19e6dc4a14e +References: fate#323887 + +When storvsc is sending I/O to Hyper-v, it may allocate a bigger buffer +descriptor for large data payload that can't fit into a pre-allocated +buffer descriptor. This bigger buffer is freed on return path. + +If I/O request to Hyper-v fails due to ring buffer busy, the storvsc +allocated buffer descriptor should also be freed. + +[mkp: applied by hand] + +Fixes: be0cf6ca301c ("scsi: storvsc: Set the tablesize based on the information given by the host") +Cc: +Signed-off-by: Long Li +Signed-off-by: Martin K. Petersen +Acked-by: Olaf Hering +--- + drivers/scsi/storvsc_drv.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c +--- a/drivers/scsi/storvsc_drv.c ++++ b/drivers/scsi/storvsc_drv.c +@@ -1640,6 +1640,8 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) + put_cpu(); + + if (ret == -EAGAIN) { ++ if (payload_sz > sizeof(cmd_request->mpb)) ++ kfree(payload); + /* no more space */ + return SCSI_MLQUEUE_DEVICE_BUSY; + } diff --git a/patches.suse/msft-hv-1453-x86-hyper-v-Support-extended-CPU-ranges-for-TLB-flus.patch b/patches.suse/msft-hv-1453-x86-hyper-v-Support-extended-CPU-ranges-for-TLB-flus.patch new file mode 100644 index 0000000..566f0b1 --- /dev/null +++ b/patches.suse/msft-hv-1453-x86-hyper-v-Support-extended-CPU-ranges-for-TLB-flus.patch @@ -0,0 +1,236 @@ +From: Vitaly Kuznetsov +Date: Wed, 2 Aug 2017 18:09:20 +0200 +Patch-mainline: v4.14-rc1 +Subject: x86/hyper-v: Support extended CPU ranges for TLB flush hypercalls +Git-commit: 628f54cc6451d2706ba8a56763dbf93be02aaa80 +References: fate#323887 + +Hyper-V hosts may support more than 64 vCPUs, we need to use +HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX/LIST_EX hypercalls in this +case. + +Signed-off-by: Vitaly Kuznetsov +Reviewed-by: Andy Shevchenko +Reviewed-by: Stephen Hemminger +Cc: Andy Lutomirski +Cc: Haiyang Zhang +Cc: Jork Loeser +Cc: K. Y. Srinivasan +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Simon Xiao +Cc: Steven Rostedt +Cc: Thomas Gleixner +Cc: devel@linuxdriverproject.org +Link: http://lkml.kernel.org/r/20170802160921.21791-9-vkuznets@redhat.com +Signed-off-by: Ingo Molnar +Acked-by: Olaf Hering +--- + arch/x86/hyperv/mmu.c | 133 ++++++++++++++++++++++++++++++++++++- + arch/x86/include/uapi/asm/hyperv.h | 10 +++ + 2 files changed, 140 insertions(+), 3 deletions(-) + +diff --git a/arch/x86/hyperv/mmu.c b/arch/x86/hyperv/mmu.c +--- a/arch/x86/hyperv/mmu.c ++++ b/arch/x86/hyperv/mmu.c +@@ -18,11 +18,25 @@ struct hv_flush_pcpu { + u64 gva_list[]; + }; + ++/* HvFlushVirtualAddressSpaceEx, HvFlushVirtualAddressListEx hypercalls */ ++struct hv_flush_pcpu_ex { ++ u64 address_space; ++ u64 flags; ++ struct { ++ u64 format; ++ u64 valid_bank_mask; ++ u64 bank_contents[]; ++ } hv_vp_set; ++ u64 gva_list[]; ++}; ++ + /* Each gva in gva_list encodes up to 4096 pages to flush */ + #define HV_TLB_FLUSH_UNIT (4096 * PAGE_SIZE) + + static struct hv_flush_pcpu __percpu *pcpu_flush; + ++static struct hv_flush_pcpu_ex __percpu *pcpu_flush_ex; ++ + /* + * Fills in gva_list starting from offset. Returns the number of items added. + */ +@@ -53,6 +67,34 @@ static inline int fill_gva_list(u64 gva_list[], int offset, + return gva_n - offset; + } + ++/* Return the number of banks in the resulting vp_set */ ++static inline int cpumask_to_vp_set(struct hv_flush_pcpu_ex *flush, ++ const struct cpumask *cpus) ++{ ++ int cpu, vcpu, vcpu_bank, vcpu_offset, nr_bank = 1; ++ ++ /* ++ * Some banks may end up being empty but this is acceptable. ++ */ ++ for_each_cpu(cpu, cpus) { ++ vcpu = hv_cpu_number_to_vp_number(cpu); ++ vcpu_bank = vcpu / 64; ++ vcpu_offset = vcpu % 64; ++ ++ /* valid_bank_mask can represent up to 64 banks */ ++ if (vcpu_bank >= 64) ++ return 0; ++ ++ __set_bit(vcpu_offset, (unsigned long *) ++ &flush->hv_vp_set.bank_contents[vcpu_bank]); ++ if (vcpu_bank >= nr_bank) ++ nr_bank = vcpu_bank + 1; ++ } ++ flush->hv_vp_set.valid_bank_mask = GENMASK_ULL(nr_bank - 1, 0); ++ ++ return nr_bank; ++} ++ + static void hyperv_flush_tlb_others(const struct cpumask *cpus, + struct mm_struct *mm, unsigned long start, unsigned long end) + { +@@ -122,17 +164,102 @@ do_native: + native_flush_tlb_others(cpus, mm, start, end); + } + ++static void hyperv_flush_tlb_others_ex(const struct cpumask *cpus, ++struct mm_struct *mm, unsigned long start, unsigned long end) ++{ ++ int nr_bank = 0, max_gvas, gva_n; ++ struct hv_flush_pcpu_ex *flush; ++ u64 status = U64_MAX; ++ unsigned long flags; ++ ++ if (!pcpu_flush_ex || !hv_hypercall_pg) ++ goto do_native; ++ ++ if (cpumask_empty(cpus)) ++ return; ++ ++ local_irq_save(flags); ++ ++ flush = this_cpu_ptr(pcpu_flush_ex); ++ ++ if (mm) { ++ flush->address_space = virt_to_phys(mm->pgd); ++ flush->flags = 0; ++ } else { ++ flush->address_space = 0; ++ flush->flags = HV_FLUSH_ALL_VIRTUAL_ADDRESS_SPACES; ++ } ++ ++ flush->hv_vp_set.valid_bank_mask = 0; ++ ++ if (!cpumask_equal(cpus, cpu_present_mask)) { ++ flush->hv_vp_set.format = HV_GENERIC_SET_SPARCE_4K; ++ nr_bank = cpumask_to_vp_set(flush, cpus); ++ } ++ ++ if (!nr_bank) { ++ flush->hv_vp_set.format = HV_GENERIC_SET_ALL; ++ flush->flags |= HV_FLUSH_ALL_PROCESSORS; ++ } ++ ++ /* ++ * We can flush not more than max_gvas with one hypercall. Flush the ++ * whole address space if we were asked to do more. ++ */ ++ max_gvas = ++ (PAGE_SIZE - sizeof(*flush) - nr_bank * ++ sizeof(flush->hv_vp_set.bank_contents[0])) / ++ sizeof(flush->gva_list[0]); ++ ++ if (end == TLB_FLUSH_ALL) { ++ flush->flags |= HV_FLUSH_NON_GLOBAL_MAPPINGS_ONLY; ++ status = hv_do_rep_hypercall( ++ HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX, ++ 0, nr_bank + 2, flush, NULL); ++ } else if (end && ++ ((end - start)/HV_TLB_FLUSH_UNIT) > max_gvas) { ++ status = hv_do_rep_hypercall( ++ HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX, ++ 0, nr_bank + 2, flush, NULL); ++ } else { ++ gva_n = fill_gva_list(flush->gva_list, nr_bank, ++ start, end); ++ status = hv_do_rep_hypercall( ++ HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST_EX, ++ gva_n, nr_bank + 2, flush, NULL); ++ } ++ ++ local_irq_restore(flags); ++ ++ if (!(status & HV_HYPERCALL_RESULT_MASK)) ++ return; ++do_native: ++ native_flush_tlb_others(cpus, mm, start, end); ++} ++ + void hyperv_setup_mmu_ops(void) + { +- if (ms_hyperv.hints & HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED) { ++ if (!(ms_hyperv.hints & HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED)) ++ return; ++ ++ setup_clear_cpu_cap(X86_FEATURE_PCID); ++ ++ if (!(ms_hyperv.hints & HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED)) { + pr_info("Using hypercall for remote TLB flush\n"); + pv_mmu_ops.flush_tlb_others = hyperv_flush_tlb_others; +- setup_clear_cpu_cap(X86_FEATURE_PCID); ++ } else { ++ pr_info("Using ext hypercall for remote TLB flush\n"); ++ pv_mmu_ops.flush_tlb_others = hyperv_flush_tlb_others_ex; + } + } + + void hyper_alloc_mmu(void) + { +- if (ms_hyperv.hints & HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED) ++ if (!(ms_hyperv.hints & HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED)) ++ return; ++ ++ if (!(ms_hyperv.hints & HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED)) + pcpu_flush = __alloc_percpu(PAGE_SIZE, PAGE_SIZE); ++ else ++ pcpu_flush_ex = __alloc_percpu(PAGE_SIZE, PAGE_SIZE); + } +diff --git a/arch/x86/include/uapi/asm/hyperv.h b/arch/x86/include/uapi/asm/hyperv.h +--- a/arch/x86/include/uapi/asm/hyperv.h ++++ b/arch/x86/include/uapi/asm/hyperv.h +@@ -149,6 +149,9 @@ + */ + #define HV_X64_DEPRECATING_AEOI_RECOMMENDED (1 << 9) + ++/* Recommend using the newer ExProcessorMasks interface */ ++#define HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED (1 << 11) ++ + /* + * HV_VP_SET available + */ +@@ -245,6 +248,8 @@ + #define HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE 0x0002 + #define HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST 0x0003 + #define HVCALL_NOTIFY_LONG_SPIN_WAIT 0x0008 ++#define HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX 0x0013 ++#define HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST_EX 0x0014 + #define HVCALL_POST_MESSAGE 0x005c + #define HVCALL_SIGNAL_EVENT 0x005d + +@@ -266,6 +271,11 @@ + #define HV_FLUSH_NON_GLOBAL_MAPPINGS_ONLY BIT(2) + #define HV_FLUSH_USE_EXTENDED_RANGE_FORMAT BIT(3) + ++enum HV_GENERIC_SET_FORMAT { ++ HV_GENERIC_SET_SPARCE_4K, ++ HV_GENERIC_SET_ALL, ++}; ++ + /* hypercall status code */ + #define HV_STATUS_SUCCESS 0 + #define HV_STATUS_INVALID_HYPERCALL_CODE 2 diff --git a/patches.suse/msft-hv-1454-tracing-hyper-v-Trace-hyperv_mmu_flush_tlb_others.patch b/patches.suse/msft-hv-1454-tracing-hyper-v-Trace-hyperv_mmu_flush_tlb_others.patch new file mode 100644 index 0000000..1b38bfd --- /dev/null +++ b/patches.suse/msft-hv-1454-tracing-hyper-v-Trace-hyperv_mmu_flush_tlb_others.patch @@ -0,0 +1,121 @@ +From: Vitaly Kuznetsov +Date: Wed, 2 Aug 2017 18:09:21 +0200 +Patch-mainline: v4.14-rc1 +Subject: tracing/hyper-v: Trace hyperv_mmu_flush_tlb_others() +Git-commit: 773b79f7a7c7839fb9d09c0e206734173a8b0a6b +References: fate#323887 + +Add Hyper-V tracing subsystem and trace hyperv_mmu_flush_tlb_others(). +Tracing is done the same way we do xen_mmu_flush_tlb_others(). + +Signed-off-by: Vitaly Kuznetsov +Reviewed-by: Andy Shevchenko +Reviewed-by: Stephen Hemminger +Reviewed-by: Steven Rostedt (VMware) +Cc: Andy Lutomirski +Cc: Haiyang Zhang +Cc: Jork Loeser +Cc: K. Y. Srinivasan +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Simon Xiao +Cc: Thomas Gleixner +Cc: devel@linuxdriverproject.org +Link: http://lkml.kernel.org/r/20170802160921.21791-10-vkuznets@redhat.com +Signed-off-by: Ingo Molnar +Acked-by: Olaf Hering +--- + MAINTAINERS | 1 + + arch/x86/hyperv/mmu.c | 7 +++++++ + arch/x86/include/asm/trace/hyperv.h | 40 +++++++++++++++++++++++++++++++++++++ + 3 files changed, 48 insertions(+) + create mode 100644 arch/x86/include/asm/trace/hyperv.h + +diff --git a/MAINTAINERS b/MAINTAINERS +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -6258,6 +6258,7 @@ M: Stephen Hemminger + L: devel@linuxdriverproject.org + S: Maintained + F: arch/x86/include/asm/mshyperv.h ++F: arch/x86/include/asm/trace/hyperv.h + F: arch/x86/include/uapi/asm/hyperv.h + F: arch/x86/kernel/cpu/mshyperv.c + F: arch/x86/hyperv +diff --git a/arch/x86/hyperv/mmu.c b/arch/x86/hyperv/mmu.c +--- a/arch/x86/hyperv/mmu.c ++++ b/arch/x86/hyperv/mmu.c +@@ -10,6 +10,9 @@ + #include + #include + ++#define CREATE_TRACE_POINTS ++#include ++ + /* HvFlushVirtualAddressSpace, HvFlushVirtualAddressList hypercalls */ + struct hv_flush_pcpu { + u64 address_space; +@@ -103,6 +106,8 @@ static void hyperv_flush_tlb_others(const struct cpumask *cpus, + u64 status = U64_MAX; + unsigned long flags; + ++ trace_hyperv_mmu_flush_tlb_others(cpus, mm, start, end); ++ + if (!pcpu_flush || !hv_hypercall_pg) + goto do_native; + +@@ -172,6 +177,8 @@ static void hyperv_flush_tlb_others_ex(const struct cpumask *cpus, + u64 status = U64_MAX; + unsigned long flags; + ++ trace_hyperv_mmu_flush_tlb_others(cpus, mm, start, end); ++ + if (!pcpu_flush_ex || !hv_hypercall_pg) + goto do_native; + +diff --git a/arch/x86/include/asm/trace/hyperv.h b/arch/x86/include/asm/trace/hyperv.h +new file mode 100644 +index 000000000000..4253bca99989 +--- /dev/null ++++ b/arch/x86/include/asm/trace/hyperv.h +@@ -0,0 +1,40 @@ ++#undef TRACE_SYSTEM ++#define TRACE_SYSTEM hyperv ++ ++#if !defined(_TRACE_HYPERV_H) || defined(TRACE_HEADER_MULTI_READ) ++#define _TRACE_HYPERV_H ++ ++#include ++ ++#if IS_ENABLED(CONFIG_HYPERV) ++ ++TRACE_EVENT(hyperv_mmu_flush_tlb_others, ++ TP_PROTO(const struct cpumask *cpus, ++ struct mm_struct *mm, unsigned long start, unsigned long end), ++ TP_ARGS(cpus, mm, start, end), ++ TP_STRUCT__entry( ++ __field(unsigned int, ncpus) ++ __field(struct mm_struct *, mm) ++ __field(unsigned long, addr) ++ __field(unsigned long, end) ++ ), ++ TP_fast_assign(__entry->ncpus = cpumask_weight(cpus); ++ __entry->mm = mm; ++ __entry->addr = start; ++ __entry->end = end; ++ ), ++ TP_printk("ncpus %d mm %p addr %lx, end %lx", ++ __entry->ncpus, __entry->mm, ++ __entry->addr, __entry->end) ++ ); ++ ++#endif /* CONFIG_HYPERV */ ++ ++#undef TRACE_INCLUDE_PATH ++#define TRACE_INCLUDE_PATH asm/trace/ ++#undef TRACE_INCLUDE_FILE ++#define TRACE_INCLUDE_FILE hyperv ++#endif /* _TRACE_HYPERV_H */ ++ ++/* This part must be outside protection */ ++#include diff --git a/patches.suse/msft-hv-1455-netvsc-cleanup-datapath-switch.patch b/patches.suse/msft-hv-1455-netvsc-cleanup-datapath-switch.patch new file mode 100644 index 0000000..ecdba38 --- /dev/null +++ b/patches.suse/msft-hv-1455-netvsc-cleanup-datapath-switch.patch @@ -0,0 +1,84 @@ +From: Stephen Hemminger +Date: Thu, 31 Aug 2017 16:16:12 -0700 +Patch-mainline: v4.14-rc1 +Subject: netvsc: cleanup datapath switch +Git-commit: 9a0c48df0d77602da3958a4c8fc2abb9521b0ade +References: fate#323887 + +Use one routine for datapath up/down. Don't need to reopen +the rndis layer. + +Signed-off-by: Stephen Hemminger +Signed-off-by: David S. Miller +Acked-by: Olaf Hering +--- + drivers/net/hyperv/netvsc_drv.c | 38 +++++++------------------------------- + 1 file changed, 7 insertions(+), 31 deletions(-) + +diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c +--- a/drivers/net/hyperv/netvsc_drv.c ++++ b/drivers/net/hyperv/netvsc_drv.c +@@ -1847,11 +1847,13 @@ static int netvsc_register_vf(struct net_device *vf_netdev) + return NOTIFY_OK; + } + +-static int netvsc_vf_up(struct net_device *vf_netdev) ++/* VF up/down change detected, schedule to change data path */ ++static int netvsc_vf_changed(struct net_device *vf_netdev) + { + struct net_device_context *net_device_ctx; + struct netvsc_device *netvsc_dev; + struct net_device *ndev; ++ bool vf_is_up = netif_running(vf_netdev); + + ndev = get_netvsc_byref(vf_netdev); + if (!ndev) +@@ -1862,34 +1864,9 @@ static int netvsc_vf_up(struct net_device *vf_netdev) + if (!netvsc_dev) + return NOTIFY_DONE; + +- /* Bump refcount when datapath is acvive - Why? */ +- rndis_filter_open(netvsc_dev); +- +- /* notify the host to switch the data path. */ +- netvsc_switch_datapath(ndev, true); +- netdev_info(ndev, "Data path switched to VF: %s\n", vf_netdev->name); +- +- return NOTIFY_OK; +-} +- +-static int netvsc_vf_down(struct net_device *vf_netdev) +-{ +- struct net_device_context *net_device_ctx; +- struct netvsc_device *netvsc_dev; +- struct net_device *ndev; +- +- ndev = get_netvsc_byref(vf_netdev); +- if (!ndev) +- return NOTIFY_DONE; +- +- net_device_ctx = netdev_priv(ndev); +- netvsc_dev = rtnl_dereference(net_device_ctx->nvdev); +- if (!netvsc_dev) +- return NOTIFY_DONE; +- +- netvsc_switch_datapath(ndev, false); +- netdev_info(ndev, "Data path switched from VF: %s\n", vf_netdev->name); +- rndis_filter_close(netvsc_dev); ++ netvsc_switch_datapath(ndev, vf_is_up); ++ netdev_info(ndev, "Data path switched %s VF: %s\n", ++ vf_is_up ? "to" : "from", vf_netdev->name); + + return NOTIFY_OK; + } +@@ -2099,9 +2076,8 @@ static int netvsc_netdev_event(struct notifier_block *this, + case NETDEV_UNREGISTER: + return netvsc_unregister_vf(event_dev); + case NETDEV_UP: +- return netvsc_vf_up(event_dev); + case NETDEV_DOWN: +- return netvsc_vf_down(event_dev); ++ return netvsc_vf_changed(event_dev); + default: + return NOTIFY_DONE; + } diff --git a/patches.suse/msft-hv-1456-netvsc-allow-driver-to-be-removed-even-if-VF-is-pres.patch b/patches.suse/msft-hv-1456-netvsc-allow-driver-to-be-removed-even-if-VF-is-pres.patch new file mode 100644 index 0000000..3419399 --- /dev/null +++ b/patches.suse/msft-hv-1456-netvsc-allow-driver-to-be-removed-even-if-VF-is-pres.patch @@ -0,0 +1,77 @@ +From: Stephen Hemminger +Date: Thu, 31 Aug 2017 16:16:13 -0700 +Patch-mainline: v4.14-rc1 +Subject: netvsc: allow driver to be removed even if VF is present +Git-commit: ec158f77def2df084d9f62565357e3037b04bd3f +References: fate#323887 + +If VF is attached then can still allow netvsc driver module to +be removed. Just have to make sure and do the cleanup. + +Also, avoid extra rtnl round trip when calling unregister. + +Signed-off-by: Stephen Hemminger +Signed-off-by: David S. Miller +Acked-by: Olaf Hering +--- + drivers/net/hyperv/netvsc_drv.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c +--- a/drivers/net/hyperv/netvsc_drv.c ++++ b/drivers/net/hyperv/netvsc_drv.c +@@ -1839,9 +1839,6 @@ static int netvsc_register_vf(struct net_device *vf_netdev) + + netdev_info(ndev, "VF registering: %s\n", vf_netdev->name); + +- /* Prevent this module from being unloaded while VF is registered */ +- try_module_get(THIS_MODULE); +- + dev_hold(vf_netdev); + rcu_assign_pointer(net_device_ctx->vf_netdev, vf_netdev); + return NOTIFY_OK; +@@ -1885,10 +1882,11 @@ static int netvsc_unregister_vf(struct net_device *vf_netdev) + + netdev_info(ndev, "VF unregistering: %s\n", vf_netdev->name); + ++ netdev_rx_handler_unregister(vf_netdev); + netdev_upper_dev_unlink(vf_netdev, ndev); + RCU_INIT_POINTER(net_device_ctx->vf_netdev, NULL); + dev_put(vf_netdev); +- module_put(THIS_MODULE); ++ + return NOTIFY_OK; + } + +@@ -1992,11 +1990,11 @@ no_net: + + static int netvsc_remove(struct hv_device *dev) + { +- struct net_device *net; + struct net_device_context *ndev_ctx; ++ struct net_device *vf_netdev; ++ struct net_device *net; + + net = hv_get_drvdata(dev); +- + if (net == NULL) { + dev_err(&dev->device, "No net device to remove\n"); + return 0; +@@ -2013,12 +2011,15 @@ static int netvsc_remove(struct hv_device *dev) + * removed. Also blocks mtu and channel changes. + */ + rtnl_lock(); ++ vf_netdev = rtnl_dereference(ndev_ctx->vf_netdev); ++ if (vf_netdev) ++ netvsc_unregister_vf(vf_netdev); ++ + rndis_filter_device_remove(dev, + rtnl_dereference(ndev_ctx->nvdev)); ++ unregister_netdevice(net); + rtnl_unlock(); + +- unregister_netdev(net); +- + hv_set_drvdata(dev, NULL); + + free_percpu(ndev_ctx->vf_stats); diff --git a/patches.suse/msft-hv-1457-hv_netvsc-Clean-up-an-unused-parameter-in-rndis_filt.patch b/patches.suse/msft-hv-1457-hv_netvsc-Clean-up-an-unused-parameter-in-rndis_filt.patch new file mode 100644 index 0000000..a09a26f --- /dev/null +++ b/patches.suse/msft-hv-1457-hv_netvsc-Clean-up-an-unused-parameter-in-rndis_filt.patch @@ -0,0 +1,65 @@ +From: Haiyang Zhang +Date: Fri, 1 Sep 2017 14:30:04 -0700 +Patch-mainline: v4.14-rc1 +Subject: hv_netvsc: Clean up an unused parameter in rndis_filter_set_rss_param() +Git-commit: 715e2ec532f6bffc8ee1cb9282c9e6cbf8809591 +References: fate#323887 + +This patch removes the parameter, num_queue in +rndis_filter_set_rss_param(), which is no longer in use. + +Signed-off-by: Haiyang Zhang +Signed-off-by: David S. Miller +Acked-by: Olaf Hering +--- + drivers/net/hyperv/hyperv_net.h | 2 +- + drivers/net/hyperv/netvsc_drv.c | 2 +- + drivers/net/hyperv/rndis_filter.c | 5 ++--- + 3 files changed, 4 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h +--- a/drivers/net/hyperv/hyperv_net.h ++++ b/drivers/net/hyperv/hyperv_net.h +@@ -213,7 +213,7 @@ void rndis_filter_update(struct netvsc_device *nvdev); + void rndis_filter_device_remove(struct hv_device *dev, + struct netvsc_device *nvdev); + int rndis_filter_set_rss_param(struct rndis_device *rdev, +- const u8 *key, int num_queue); ++ const u8 *key); + int rndis_filter_receive(struct net_device *ndev, + struct netvsc_device *net_dev, + struct hv_device *dev, +diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c +--- a/drivers/net/hyperv/netvsc_drv.c ++++ b/drivers/net/hyperv/netvsc_drv.c +@@ -1424,7 +1424,7 @@ static int netvsc_set_rxfh(struct net_device *dev, const u32 *indir, + key = rndis_dev->rss_key; + } + +- return rndis_filter_set_rss_param(rndis_dev, key, ndev->num_chn); ++ return rndis_filter_set_rss_param(rndis_dev, key); + } + + /* Hyper-V RNDIS protocol does not have ring in the HW sense. +diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c +--- a/drivers/net/hyperv/rndis_filter.c ++++ b/drivers/net/hyperv/rndis_filter.c +@@ -717,7 +717,7 @@ cleanup: + } + + int rndis_filter_set_rss_param(struct rndis_device *rdev, +- const u8 *rss_key, int num_queue) ++ const u8 *rss_key) + { + struct net_device *ndev = rdev->ndev; + struct rndis_request *request; +@@ -1258,8 +1258,7 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev, + atomic_read(&net_device->open_chn) == net_device->num_chn); + + /* ignore failues from setting rss parameters, still have channels */ +- rndis_filter_set_rss_param(rndis_device, netvsc_hash_key, +- net_device->num_chn); ++ rndis_filter_set_rss_param(rndis_device, netvsc_hash_key); + out: + if (ret) { + net_device->max_chn = 1; diff --git a/patches.suse/msft-hv-1458-hv_netvsc-Simplify-num_chn-checking-in-rndis_filter_.patch b/patches.suse/msft-hv-1458-hv_netvsc-Simplify-num_chn-checking-in-rndis_filter_.patch new file mode 100644 index 0000000..3a298f1 --- /dev/null +++ b/patches.suse/msft-hv-1458-hv_netvsc-Simplify-num_chn-checking-in-rndis_filter_.patch @@ -0,0 +1,40 @@ +From: Haiyang Zhang +Date: Fri, 1 Sep 2017 14:30:05 -0700 +Patch-mainline: v4.14-rc1 +Subject: hv_netvsc: Simplify num_chn checking in rndis_filter_device_add() +Git-commit: 5c4217d05d3258fa9999ad959c9b6da791b70bfa +References: fate#323887 + +The minus one and assignment to a local variable is not necessary. +This patch simplifies it. + +Signed-off-by: Haiyang Zhang +Signed-off-by: David S. Miller +Acked-by: Olaf Hering +--- + drivers/net/hyperv/rndis_filter.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c +--- a/drivers/net/hyperv/rndis_filter.c ++++ b/drivers/net/hyperv/rndis_filter.c +@@ -1067,7 +1067,7 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev, + struct ndis_recv_scale_cap rsscap; + u32 rsscap_size = sizeof(struct ndis_recv_scale_cap); + unsigned int gso_max_size = GSO_MAX_SIZE; +- u32 mtu, size, num_rss_qs; ++ u32 mtu, size; + const struct cpumask *node_cpu_mask; + u32 num_possible_rss_qs; + int i, ret; +@@ -1215,8 +1215,8 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev, + net_device->num_chn); + + atomic_set(&net_device->open_chn, 1); +- num_rss_qs = net_device->num_chn - 1; +- if (num_rss_qs == 0) ++ ++ if (net_device->num_chn == 1) + return net_device; + + for (i = 1; i < net_device->num_chn; i++) { diff --git a/patches.suse/msft-hv-1459-hv_netvsc-Simplify-the-limit-check-in-netvsc_set_cha.patch b/patches.suse/msft-hv-1459-hv_netvsc-Simplify-the-limit-check-in-netvsc_set_cha.patch new file mode 100644 index 0000000..67d0c14 --- /dev/null +++ b/patches.suse/msft-hv-1459-hv_netvsc-Simplify-the-limit-check-in-netvsc_set_cha.patch @@ -0,0 +1,39 @@ +From: Haiyang Zhang +Date: Fri, 1 Sep 2017 14:30:06 -0700 +Patch-mainline: v4.14-rc1 +Subject: hv_netvsc: Simplify the limit check in netvsc_set_channels() +Git-commit: 06be580ac7b650938cb3f2cf8cd02d73ff96d3e4 +References: fate#323887 + +Because of the following code, net->num_tx_queues equals to +VRSS_CHANNEL_MAX, and max_chn is less than or equals to VRSS_CHANNEL_MAX. + +netvsc_drv.c: +alloc_etherdev_mq(sizeof(struct net_device_context), + VRSS_CHANNEL_MAX); +rndis_filter.c: +net_device->max_chn = min_t(u32, VRSS_CHANNEL_MAX, num_possible_rss_qs); + +So this patch removes the unnecessary limit check before comparing +with "max_chn". + +Signed-off-by: Haiyang Zhang +Signed-off-by: David S. Miller +Acked-by: Olaf Hering +--- + drivers/net/hyperv/netvsc_drv.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c +--- a/drivers/net/hyperv/netvsc_drv.c ++++ b/drivers/net/hyperv/netvsc_drv.c +@@ -830,9 +830,6 @@ static int netvsc_set_channels(struct net_device *net, + channels->rx_count || channels->tx_count || channels->other_count) + return -EINVAL; + +- if (count > net->num_tx_queues || count > VRSS_CHANNEL_MAX) +- return -EINVAL; +- + if (!nvdev || nvdev->destroy) + return -ENODEV; + diff --git a/patches.suse/msft-hv-1460-hv_netvsc-Fix-the-channel-limit-in-netvsc_set_rxfh.patch b/patches.suse/msft-hv-1460-hv_netvsc-Fix-the-channel-limit-in-netvsc_set_rxfh.patch new file mode 100644 index 0000000..35140ee --- /dev/null +++ b/patches.suse/msft-hv-1460-hv_netvsc-Fix-the-channel-limit-in-netvsc_set_rxfh.patch @@ -0,0 +1,29 @@ +From: Haiyang Zhang +Date: Fri, 1 Sep 2017 14:30:07 -0700 +Patch-mainline: v4.14-rc1 +Subject: hv_netvsc: Fix the channel limit in netvsc_set_rxfh() +Git-commit: db3cd7af9d0f174475cbcc02c0e96a5408fe2dc2 +References: fate#323887 + +The limit of setting receive indirection table value should be +the current number of channels, not the VRSS_CHANNEL_MAX. + +Signed-off-by: Haiyang Zhang +Signed-off-by: David S. Miller +Acked-by: Olaf Hering +--- + drivers/net/hyperv/netvsc_drv.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c +--- a/drivers/net/hyperv/netvsc_drv.c ++++ b/drivers/net/hyperv/netvsc_drv.c +@@ -1407,7 +1407,7 @@ static int netvsc_set_rxfh(struct net_device *dev, const u32 *indir, + rndis_dev = ndev->extension; + if (indir) { + for (i = 0; i < ITAB_NUM; i++) +- if (indir[i] >= VRSS_CHANNEL_MAX) ++ if (indir[i] >= ndev->num_chn) + return -EINVAL; + + for (i = 0; i < ITAB_NUM; i++) diff --git a/patches.suse/msft-hv-1461-hv_netvsc-fix-deadlock-on-hotplug.patch b/patches.suse/msft-hv-1461-hv_netvsc-fix-deadlock-on-hotplug.patch new file mode 100644 index 0000000..c45504b --- /dev/null +++ b/patches.suse/msft-hv-1461-hv_netvsc-fix-deadlock-on-hotplug.patch @@ -0,0 +1,291 @@ +From: Stephen Hemminger +Date: Wed, 6 Sep 2017 13:53:05 -0700 +Patch-mainline: v4.14-rc1 +Subject: hv_netvsc: fix deadlock on hotplug +Git-commit: 8195b1396ec86dddbba443c74b2188b423556c74 +References: fate#323887 + +When a virtual device is added dynamically (via host console), then +the vmbus sends an offer message for the primary channel. The processing +of this message for networking causes the network device to then +initialize the sub channels. + +The problem is that setting up the sub channels needs to wait until +the subsequent subchannel offers have been processed. These offers +come in on the same ring buffer and work queue as where the primary +offer is being processed; leading to a deadlock. + +This did not happen in older kernels, because the sub channel waiting +logic was broken (it wasn't really waiting). + +The solution is to do the sub channel setup in its own work queue +context that is scheduled by the primary channel setup; and then +happens later. + +Fixes: 732e49850c5e ("netvsc: fix race on sub channel creation") +Reported-by: Dexuan Cui +Signed-off-by: Stephen Hemminger +Signed-off-by: David S. Miller +Acked-by: Olaf Hering +--- + drivers/net/hyperv/hyperv_net.h | 3 + + drivers/net/hyperv/netvsc.c | 3 + + drivers/net/hyperv/netvsc_drv.c | 11 +--- + drivers/net/hyperv/rndis_filter.c | 122 ++++++++++++++++++++++++++------------ + 4 files changed, 94 insertions(+), 45 deletions(-) + +diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h +--- a/drivers/net/hyperv/hyperv_net.h ++++ b/drivers/net/hyperv/hyperv_net.h +@@ -204,6 +204,8 @@ int netvsc_recv_callback(struct net_device *net, + const struct ndis_pkt_8021q_info *vlan); + void netvsc_channel_cb(void *context); + int netvsc_poll(struct napi_struct *napi, int budget); ++ ++void rndis_set_subchannel(struct work_struct *w); + bool rndis_filter_opened(const struct netvsc_device *nvdev); + int rndis_filter_open(struct netvsc_device *nvdev); + int rndis_filter_close(struct netvsc_device *nvdev); +@@ -782,6 +784,7 @@ struct netvsc_device { + u32 num_chn; + + atomic_t open_chn; ++ struct work_struct subchan_work; + wait_queue_head_t subchan_open; + + struct rndis_device *extension; +diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c +--- a/drivers/net/hyperv/netvsc.c ++++ b/drivers/net/hyperv/netvsc.c +@@ -81,6 +81,7 @@ static struct netvsc_device *alloc_net_device(void) + + init_completion(&net_device->channel_init_wait); + init_waitqueue_head(&net_device->subchan_open); ++ INIT_WORK(&net_device->subchan_work, rndis_set_subchannel); + + return net_device; + } +@@ -557,6 +558,8 @@ void netvsc_device_remove(struct hv_device *device) + = rtnl_dereference(net_device_ctx->nvdev); + int i; + ++ cancel_work_sync(&net_device->subchan_work); ++ + netvsc_disconnect_vsp(device); + + RCU_INIT_POINTER(net_device_ctx->nvdev, NULL); +diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c +--- a/drivers/net/hyperv/netvsc_drv.c ++++ b/drivers/net/hyperv/netvsc_drv.c +@@ -853,10 +853,7 @@ static int netvsc_set_channels(struct net_device *net, + rndis_filter_device_remove(dev, nvdev); + + nvdev = rndis_filter_device_add(dev, &device_info); +- if (!IS_ERR(nvdev)) { +- netif_set_real_num_tx_queues(net, nvdev->num_chn); +- netif_set_real_num_rx_queues(net, nvdev->num_chn); +- } else { ++ if (IS_ERR(nvdev)) { + ret = PTR_ERR(nvdev); + device_info.num_chn = orig; + nvdev = rndis_filter_device_add(dev, &device_info); +@@ -1954,9 +1951,6 @@ static int netvsc_probe(struct hv_device *dev, + NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; + net->vlan_features = net->features; + +- netif_set_real_num_tx_queues(net, nvdev->num_chn); +- netif_set_real_num_rx_queues(net, nvdev->num_chn); +- + netdev_lockdep_set_classes(net); + + /* MTU range: 68 - 1500 or 65521 */ +@@ -2012,9 +2006,10 @@ static int netvsc_remove(struct hv_device *dev) + if (vf_netdev) + netvsc_unregister_vf(vf_netdev); + ++ unregister_netdevice(net); ++ + rndis_filter_device_remove(dev, + rtnl_dereference(ndev_ctx->nvdev)); +- unregister_netdevice(net); + rtnl_unlock(); + + hv_set_drvdata(dev, NULL); +diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c +--- a/drivers/net/hyperv/rndis_filter.c ++++ b/drivers/net/hyperv/rndis_filter.c +@@ -1039,8 +1039,6 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc) + + /* Set the channel before opening.*/ + nvchan->channel = new_sc; +- netif_napi_add(ndev, &nvchan->napi, +- netvsc_poll, NAPI_POLL_WEIGHT); + + ret = vmbus_open(new_sc, nvscdev->ring_size * PAGE_SIZE, + nvscdev->ring_size * PAGE_SIZE, NULL, 0, +@@ -1048,12 +1046,88 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc) + if (ret == 0) + napi_enable(&nvchan->napi); + else +- netif_napi_del(&nvchan->napi); ++ netdev_notice(ndev, "sub channel open failed: %d\n", ret); + + atomic_inc(&nvscdev->open_chn); + wake_up(&nvscdev->subchan_open); + } + ++/* Open sub-channels after completing the handling of the device probe. ++ * This breaks overlap of processing the host message for the ++ * new primary channel with the initialization of sub-channels. ++ */ ++void rndis_set_subchannel(struct work_struct *w) ++{ ++ struct netvsc_device *nvdev ++ = container_of(w, struct netvsc_device, subchan_work); ++ struct nvsp_message *init_packet = &nvdev->channel_init_pkt; ++ struct net_device_context *ndev_ctx; ++ struct rndis_device *rdev; ++ struct net_device *ndev; ++ struct hv_device *hv_dev; ++ int i, ret; ++ ++ if (!rtnl_trylock()) { ++ schedule_work(w); ++ return; ++ } ++ ++ rdev = nvdev->extension; ++ if (!rdev) ++ goto unlock; /* device was removed */ ++ ++ ndev = rdev->ndev; ++ ndev_ctx = netdev_priv(ndev); ++ hv_dev = ndev_ctx->device_ctx; ++ ++ memset(init_packet, 0, sizeof(struct nvsp_message)); ++ init_packet->hdr.msg_type = NVSP_MSG5_TYPE_SUBCHANNEL; ++ init_packet->msg.v5_msg.subchn_req.op = NVSP_SUBCHANNEL_ALLOCATE; ++ init_packet->msg.v5_msg.subchn_req.num_subchannels = ++ nvdev->num_chn - 1; ++ ret = vmbus_sendpacket(hv_dev->channel, init_packet, ++ sizeof(struct nvsp_message), ++ (unsigned long)init_packet, ++ VM_PKT_DATA_INBAND, ++ VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); ++ if (ret) { ++ netdev_err(ndev, "sub channel allocate send failed: %d\n", ret); ++ goto failed; ++ } ++ ++ wait_for_completion(&nvdev->channel_init_wait); ++ if (init_packet->msg.v5_msg.subchn_comp.status != NVSP_STAT_SUCCESS) { ++ netdev_err(ndev, "sub channel request failed\n"); ++ goto failed; ++ } ++ ++ nvdev->num_chn = 1 + ++ init_packet->msg.v5_msg.subchn_comp.num_subchannels; ++ ++ /* wait for all sub channels to open */ ++ wait_event(nvdev->subchan_open, ++ atomic_read(&nvdev->open_chn) == nvdev->num_chn); ++ ++ /* ignore failues from setting rss parameters, still have channels */ ++ rndis_filter_set_rss_param(rdev, netvsc_hash_key); ++ ++ netif_set_real_num_tx_queues(ndev, nvdev->num_chn); ++ netif_set_real_num_rx_queues(ndev, nvdev->num_chn); ++ ++ rtnl_unlock(); ++ return; ++ ++failed: ++ /* fallback to only primary channel */ ++ for (i = 1; i < nvdev->num_chn; i++) ++ netif_napi_del(&nvdev->chan_table[i].napi); ++ ++ nvdev->max_chn = 1; ++ nvdev->num_chn = 1; ++unlock: ++ rtnl_unlock(); ++} ++ + struct netvsc_device *rndis_filter_device_add(struct hv_device *dev, + struct netvsc_device_info *device_info) + { +@@ -1063,7 +1137,6 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev, + struct rndis_device *rndis_device; + struct ndis_offload hwcaps; + struct ndis_offload_params offloads; +- struct nvsp_message *init_packet; + struct ndis_recv_scale_cap rsscap; + u32 rsscap_size = sizeof(struct ndis_recv_scale_cap); + unsigned int gso_max_size = GSO_MAX_SIZE; +@@ -1215,9 +1288,7 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev, + net_device->num_chn); + + atomic_set(&net_device->open_chn, 1); +- +- if (net_device->num_chn == 1) +- return net_device; ++ vmbus_set_sc_create_callback(dev->channel, netvsc_sc_open); + + for (i = 1; i < net_device->num_chn; i++) { + ret = netvsc_alloc_recv_comp_ring(net_device, i); +@@ -1228,38 +1299,15 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev, + } + } + +- vmbus_set_sc_create_callback(dev->channel, netvsc_sc_open); ++ for (i = 1; i < net_device->num_chn; i++) ++ netif_napi_add(net, &net_device->chan_table[i].napi, ++ netvsc_poll, NAPI_POLL_WEIGHT); + +- init_packet = &net_device->channel_init_pkt; +- memset(init_packet, 0, sizeof(struct nvsp_message)); +- init_packet->hdr.msg_type = NVSP_MSG5_TYPE_SUBCHANNEL; +- init_packet->msg.v5_msg.subchn_req.op = NVSP_SUBCHANNEL_ALLOCATE; +- init_packet->msg.v5_msg.subchn_req.num_subchannels = +- net_device->num_chn - 1; +- ret = vmbus_sendpacket(dev->channel, init_packet, +- sizeof(struct nvsp_message), +- (unsigned long)init_packet, +- VM_PKT_DATA_INBAND, +- VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); +- if (ret) +- goto out; +- +- wait_for_completion(&net_device->channel_init_wait); +- if (init_packet->msg.v5_msg.subchn_comp.status != NVSP_STAT_SUCCESS) { +- ret = -ENODEV; +- goto out; +- } ++ if (net_device->num_chn > 1) ++ schedule_work(&net_device->subchan_work); + +- net_device->num_chn = 1 + +- init_packet->msg.v5_msg.subchn_comp.num_subchannels; +- +- /* wait for all sub channels to open */ +- wait_event(net_device->subchan_open, +- atomic_read(&net_device->open_chn) == net_device->num_chn); +- +- /* ignore failues from setting rss parameters, still have channels */ +- rndis_filter_set_rss_param(rndis_device, netvsc_hash_key); + out: ++ /* if unavailable, just proceed with one queue */ + if (ret) { + net_device->max_chn = 1; + net_device->num_chn = 1; +@@ -1280,10 +1328,10 @@ void rndis_filter_device_remove(struct hv_device *dev, + /* Halt and release the rndis device */ + rndis_filter_halt_device(rndis_dev); + +- kfree(rndis_dev); + net_dev->extension = NULL; + + netvsc_device_remove(dev); ++ kfree(rndis_dev); + } + + int rndis_filter_open(struct netvsc_device *nvdev) diff --git a/patches.suse/msft-hv-1462-hv_netvsc-avoid-unnecessary-wakeups-on-subchannel-cr.patch b/patches.suse/msft-hv-1462-hv_netvsc-avoid-unnecessary-wakeups-on-subchannel-cr.patch new file mode 100644 index 0000000..fee840d --- /dev/null +++ b/patches.suse/msft-hv-1462-hv_netvsc-avoid-unnecessary-wakeups-on-subchannel-cr.patch @@ -0,0 +1,31 @@ +From: Stephen Hemminger +Date: Wed, 6 Sep 2017 13:53:06 -0700 +Patch-mainline: v4.14-rc1 +Subject: hv_netvsc: avoid unnecessary wakeups on subchannel creation +Git-commit: 8f2bb1de73344dbedd4195016b782bee7bf3598f +References: fate#323887 + +Only need to wakeup the initiator after all sub-channels +are opened. + +Signed-off-by: Stephen Hemminger +Signed-off-by: David S. Miller +Acked-by: Olaf Hering +--- + drivers/net/hyperv/rndis_filter.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c +--- a/drivers/net/hyperv/rndis_filter.c ++++ b/drivers/net/hyperv/rndis_filter.c +@@ -1048,8 +1048,8 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc) + else + netdev_notice(ndev, "sub channel open failed: %d\n", ret); + +- atomic_inc(&nvscdev->open_chn); +- wake_up(&nvscdev->subchan_open); ++ if (atomic_inc_return(&nvscdev->open_chn) == nvscdev->num_chn) ++ wake_up(&nvscdev->subchan_open); + } + + /* Open sub-channels after completing the handling of the device probe. diff --git a/patches.suse/msft-hv-1464-x86-hyper-v-Remove-duplicated-HV_X64_EX_PROCESSOR_MA.patch b/patches.suse/msft-hv-1464-x86-hyper-v-Remove-duplicated-HV_X64_EX_PROCESSOR_MA.patch new file mode 100644 index 0000000..737334d --- /dev/null +++ b/patches.suse/msft-hv-1464-x86-hyper-v-Remove-duplicated-HV_X64_EX_PROCESSOR_MA.patch @@ -0,0 +1,46 @@ +From: Vitaly Kuznetsov +Date: Mon, 11 Sep 2017 17:06:20 +0200 +Patch-mainline: v4.14-rc1 +Subject: x86/hyper-v: Remove duplicated HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED definition +Git-commit: 1278f58cdee63cfbb04e5624474a291c81a7a13b +References: fate#323887 + +Commits: + + 7dcf90e9e032 ("PCI: hv: Use vPCI protocol version 1.2") + 628f54cc6451 ("x86/hyper-v: Support extended CPU ranges for TLB flush hypercalls") + +added the same definition and they came in through different trees. +Fix the duplication. + +Signed-off-by: Vitaly Kuznetsov +Cc: Haiyang Zhang +Cc: K. Y. Srinivasan +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Stephen Hemminger +Cc: Thomas Gleixner +Cc: devel@linuxdriverproject.org +Link: http://lkml.kernel.org/r/20170911150620.3998-1-vkuznets@redhat.com +Signed-off-by: Ingo Molnar +Acked-by: Olaf Hering +--- + arch/x86/include/uapi/asm/hyperv.h | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/arch/x86/include/uapi/asm/hyperv.h b/arch/x86/include/uapi/asm/hyperv.h +--- a/arch/x86/include/uapi/asm/hyperv.h ++++ b/arch/x86/include/uapi/asm/hyperv.h +@@ -152,12 +152,6 @@ + /* Recommend using the newer ExProcessorMasks interface */ + #define HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED (1 << 11) + +-/* +- * HV_VP_SET available +- */ +-#define HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED (1 << 11) +- +- + /* + * Crash notification flag. + */ diff --git a/patches.suse/msft-hv-1465-netvsc-increase-default-receive-buffer-size.patch b/patches.suse/msft-hv-1465-netvsc-increase-default-receive-buffer-size.patch new file mode 100644 index 0000000..ceb3205 --- /dev/null +++ b/patches.suse/msft-hv-1465-netvsc-increase-default-receive-buffer-size.patch @@ -0,0 +1,32 @@ +From: Stephen Hemminger +Date: Thu, 14 Sep 2017 09:31:07 -0700 +Patch-mainline: v4.14-rc1 +Subject: netvsc: increase default receive buffer size +Git-commit: 5023a6db73196695f4cc2db1a0eb37957ca27772 +References: fate#323887 + +The default receive buffer size was reduced by recent change +to a value which was appropriate for 10G and Windows Server 2016. +But the value is too small for full performance with 40G on Azure. +Increase the default back to maximum supported by host. + +Fixes: 8b5327975ae1 ("netvsc: allow controlling send/recv buffer size") +Signed-off-by: Stephen Hemminger +Signed-off-by: David S. Miller +Acked-by: Olaf Hering +--- + drivers/net/hyperv/netvsc_drv.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c +--- a/drivers/net/hyperv/netvsc_drv.c ++++ b/drivers/net/hyperv/netvsc_drv.c +@@ -49,7 +49,7 @@ + #define NETVSC_MIN_TX_SECTIONS 10 + #define NETVSC_DEFAULT_TX 192 /* ~1M */ + #define NETVSC_MIN_RX_SECTIONS 10 /* ~64K */ +-#define NETVSC_DEFAULT_RX 2048 /* ~4M */ ++#define NETVSC_DEFAULT_RX 10485 /* Max ~16M */ + + #define LINKCHANGE_INT (2 * HZ) + #define VF_TAKEOVER_INT (HZ / 10) diff --git a/patches.suse/msft-hv-1466-hv_netvsc-fix-send-buffer-failure-on-MTU-change.patch b/patches.suse/msft-hv-1466-hv_netvsc-fix-send-buffer-failure-on-MTU-change.patch new file mode 100644 index 0000000..d1c01d2 --- /dev/null +++ b/patches.suse/msft-hv-1466-hv_netvsc-fix-send-buffer-failure-on-MTU-change.patch @@ -0,0 +1,122 @@ +From: Alex Ng +Date: Wed, 20 Sep 2017 11:17:35 -0700 +Patch-mainline: v4.14-rc2 +Subject: hv_netvsc: fix send buffer failure on MTU change +Git-commit: 0ab09befdbb7ca9b969d6206108629ddff43876e +References: fate#323887 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If MTU is changed the host would reject the send buffer change. +This problem is result of recent change to allow changing send +buffer size. + +Every time we change the MTU, we store the previous net_device section +count before destroying the buffer, but we don’t store the previous +section size. When we reinitialize the buffer, its size is calculated +by multiplying the previous count and previous size. Since we +continuously increase the MTU, the host returns us a decreasing count +value while the section size is reinitialized to 1728 bytes every +time. + +This eventually leads to a condition where the calculated buf_size is +so small that the host rejects it. + +Fixes: 8b5327975ae1 ("netvsc: allow controlling send/recv buffer size") +Signed-off-by: Alex Ng +Signed-off-by: Stephen Hemminger +Signed-off-by: David S. Miller +Acked-by: Olaf Hering +--- + drivers/net/hyperv/hyperv_net.h | 2 ++ + drivers/net/hyperv/netvsc.c | 7 ++----- + drivers/net/hyperv/netvsc_drv.c | 8 ++++++++ + 3 files changed, 12 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h +--- a/drivers/net/hyperv/hyperv_net.h ++++ b/drivers/net/hyperv/hyperv_net.h +@@ -150,6 +150,8 @@ struct netvsc_device_info { + u32 num_chn; + u32 send_sections; + u32 recv_sections; ++ u32 send_section_size; ++ u32 recv_section_size; + }; + + enum rndis_device_state { +diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c +--- a/drivers/net/hyperv/netvsc.c ++++ b/drivers/net/hyperv/netvsc.c +@@ -76,9 +76,6 @@ static struct netvsc_device *alloc_net_device(void) + net_device->max_pkt = RNDIS_MAX_PKT_DEFAULT; + net_device->pkt_align = RNDIS_PKT_ALIGN_DEFAULT; + +- net_device->recv_section_size = NETVSC_RECV_SECTION_SIZE; +- net_device->send_section_size = NETVSC_SEND_SECTION_SIZE; +- + init_completion(&net_device->channel_init_wait); + init_waitqueue_head(&net_device->subchan_open); + INIT_WORK(&net_device->subchan_work, rndis_set_subchannel); +@@ -262,7 +259,7 @@ static int netvsc_init_buf(struct hv_device *device, + int ret = 0; + + /* Get receive buffer area. */ +- buf_size = device_info->recv_sections * net_device->recv_section_size; ++ buf_size = device_info->recv_sections * device_info->recv_section_size; + buf_size = roundup(buf_size, PAGE_SIZE); + + net_device->recv_buf = vzalloc(buf_size); +@@ -344,7 +341,7 @@ static int netvsc_init_buf(struct hv_device *device, + goto cleanup; + + /* Now setup the send buffer. */ +- buf_size = device_info->send_sections * net_device->send_section_size; ++ buf_size = device_info->send_sections * device_info->send_section_size; + buf_size = round_up(buf_size, PAGE_SIZE); + + net_device->send_buf = vzalloc(buf_size); +diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c +--- a/drivers/net/hyperv/netvsc_drv.c ++++ b/drivers/net/hyperv/netvsc_drv.c +@@ -848,7 +848,9 @@ static int netvsc_set_channels(struct net_device *net, + device_info.num_chn = count; + device_info.ring_size = ring_size; + device_info.send_sections = nvdev->send_section_cnt; ++ device_info.send_section_size = nvdev->send_section_size; + device_info.recv_sections = nvdev->recv_section_cnt; ++ device_info.recv_section_size = nvdev->recv_section_size; + + rndis_filter_device_remove(dev, nvdev); + +@@ -963,7 +965,9 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu) + device_info.ring_size = ring_size; + device_info.num_chn = nvdev->num_chn; + device_info.send_sections = nvdev->send_section_cnt; ++ device_info.send_section_size = nvdev->send_section_size; + device_info.recv_sections = nvdev->recv_section_cnt; ++ device_info.recv_section_size = nvdev->recv_section_size; + + rndis_filter_device_remove(hdev, nvdev); + +@@ -1485,7 +1489,9 @@ static int netvsc_set_ringparam(struct net_device *ndev, + device_info.num_chn = nvdev->num_chn; + device_info.ring_size = ring_size; + device_info.send_sections = new_tx; ++ device_info.send_section_size = nvdev->send_section_size; + device_info.recv_sections = new_rx; ++ device_info.recv_section_size = nvdev->recv_section_size; + + netif_device_detach(ndev); + was_opened = rndis_filter_opened(nvdev); +@@ -1934,7 +1940,9 @@ static int netvsc_probe(struct hv_device *dev, + device_info.ring_size = ring_size; + device_info.num_chn = VRSS_CHANNEL_DEFAULT; + device_info.send_sections = NETVSC_DEFAULT_TX; ++ device_info.send_section_size = NETVSC_SEND_SECTION_SIZE; + device_info.recv_sections = NETVSC_DEFAULT_RX; ++ device_info.recv_section_size = NETVSC_RECV_SECTION_SIZE; + + nvdev = rndis_filter_device_add(dev, &device_info); + if (IS_ERR(nvdev)) { diff --git a/patches.suse/msft-hv-1467-vmbus-don-t-acquire-the-mutex-in-vmbus_hvsock_device.patch b/patches.suse/msft-hv-1467-vmbus-don-t-acquire-the-mutex-in-vmbus_hvsock_device.patch new file mode 100644 index 0000000..9515e26 --- /dev/null +++ b/patches.suse/msft-hv-1467-vmbus-don-t-acquire-the-mutex-in-vmbus_hvsock_device.patch @@ -0,0 +1,45 @@ +From: Dexuan Cui +Date: Thu, 21 Sep 2017 23:41:47 -0700 +Patch-mainline: v4.14-rc4 +Subject: vmbus: don't acquire the mutex in vmbus_hvsock_device_unregister() +Git-commit: 33c150c2ee4a65a59190a124b45d05b1abf9478e +References: fate#323887 + +Due to commit 54a66265d675 ("Drivers: hv: vmbus: Fix rescind handling"), +we need this patch to resolve the below deadlock: + +after we get the mutex in vmbus_hvsock_device_unregister() and call +vmbus_device_unregister() -> device_unregister() -> ... -> device_release() +-> vmbus_device_release(), we'll get a deadlock, because +vmbus_device_release() tries to get the same mutex. + +Signed-off-by: Dexuan Cui +Cc: K. Y. Srinivasan +Cc: Haiyang Zhang +Cc: Stephen Hemminger +Signed-off-by: K. Y. Srinivasan +Cc: stable@vger.kernel.org (4.13 and above) +Signed-off-by: Greg Kroah-Hartman +Acked-by: Olaf Hering +--- + drivers/hv/channel_mgmt.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c +--- a/drivers/hv/channel_mgmt.c ++++ b/drivers/hv/channel_mgmt.c +@@ -936,14 +936,10 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) + + void vmbus_hvsock_device_unregister(struct vmbus_channel *channel) + { +- mutex_lock(&vmbus_connection.channel_mutex); +- + BUG_ON(!is_hvsock_channel(channel)); + + channel->rescind = true; + vmbus_device_unregister(channel->device_obj); +- +- mutex_unlock(&vmbus_connection.channel_mutex); + } + EXPORT_SYMBOL_GPL(vmbus_hvsock_device_unregister); + diff --git a/patches.suse/msft-hv-1468-Drivers-hv-fcopy-restore-correct-transfer-length.patch b/patches.suse/msft-hv-1468-Drivers-hv-fcopy-restore-correct-transfer-length.patch new file mode 100644 index 0000000..37be9e5 --- /dev/null +++ b/patches.suse/msft-hv-1468-Drivers-hv-fcopy-restore-correct-transfer-length.patch @@ -0,0 +1,52 @@ +From: Olaf Hering +Date: Thu, 21 Sep 2017 23:41:48 -0700 +Patch-mainline: v4.14-rc4 +Subject: Drivers: hv: fcopy: restore correct transfer length +Git-commit: 549e658a0919e355a2b2144dc380b3729bef7f3e +References: fate#323887 + +Till recently the expected length of bytes read by the +daemon did depend on the context. It was either hv_start_fcopy or +hv_do_fcopy. The daemon had a buffer size of two pages, which was much +larger than needed. + +Now the expected length of bytes read by the +daemon changed slightly. For START_FILE_COPY it is still the size of +hv_start_fcopy. But for WRITE_TO_FILE and the other operations it is as +large as the buffer that arrived via vmbus. In case of WRITE_TO_FILE +that is slightly larger than a struct hv_do_fcopy. Since the buffer in +the daemon was still larger everything was fine. + +Currently, the daemon reads only what is actually needed. +The new buffer layout is as large as a struct hv_do_fcopy, for the +WRITE_TO_FILE operation. Since the kernel expects a slightly larger +size, hvt_op_read will return -EINVAL because the daemon will read +slightly less than expected. Address this by restoring the expected +buffer size in case of WRITE_TO_FILE. + +Fixes: 'c7e490fc23eb ("Drivers: hv: fcopy: convert to hv_utils_transport")' +Fixes: '3f2baa8a7d2e ("Tools: hv: update buffer handling in hv_fcopy_daemon")' + +Signed-off-by: Olaf Hering +Signed-off-by: K. Y. Srinivasan +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +Acked-by: Olaf Hering +--- + drivers/hv/hv_fcopy.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/hv/hv_fcopy.c b/drivers/hv/hv_fcopy.c +--- a/drivers/hv/hv_fcopy.c ++++ b/drivers/hv/hv_fcopy.c +@@ -170,6 +170,10 @@ static void fcopy_send_data(struct work_struct *dummy) + out_src = smsg_out; + break; + ++ case WRITE_TO_FILE: ++ out_src = fcopy_transaction.fcopy_msg; ++ out_len = sizeof(struct hv_do_fcopy); ++ break; + default: + out_src = fcopy_transaction.fcopy_msg; + out_len = fcopy_transaction.recv_len; diff --git a/patches.suse/msft-hv-1470-Drivers-hv-vmbus-Fix-bugs-in-rescind-handling.patch b/patches.suse/msft-hv-1470-Drivers-hv-vmbus-Fix-bugs-in-rescind-handling.patch new file mode 100644 index 0000000..4ab7090 --- /dev/null +++ b/patches.suse/msft-hv-1470-Drivers-hv-vmbus-Fix-bugs-in-rescind-handling.patch @@ -0,0 +1,196 @@ +From: "K. Y. Srinivasan" +Date: Fri, 29 Sep 2017 21:09:36 -0700 +Patch-mainline: v4.14-rc5 +Subject: Drivers: hv: vmbus: Fix bugs in rescind handling +Git-commit: 192b2d78722ffea188e5ec6ae5d55010dce05a4b +References: fate#323887 + +This patch addresses the following bugs in the current rescind handling code: + +1. Fixes a race condition where we may be invoking hv_process_channel_removal() +on an already freed channel. + +2. Prevents indefinite wait when rescinding sub-channels by correctly setting +the probe_complete state. + +I would like to thank Dexuan for patiently reviewing earlier versions of this +patch and identifying many of the issues fixed here. + +Greg, please apply this to 4.14-final. + +Fixes: '54a66265d675 ("Drivers: hv: vmbus: Fix rescind handling")' + +Signed-off-by: K. Y. Srinivasan +Reviewed-by: Dexuan Cui +Cc: stable@vger.kernel.org # (4.13 and above) +Signed-off-by: Greg Kroah-Hartman +Acked-by: Olaf Hering +--- + drivers/hv/channel.c | 6 +++--- + drivers/hv/channel_mgmt.c | 37 ++++++++++++++++++------------------- + drivers/hv/vmbus_drv.c | 3 +-- + include/linux/hyperv.h | 2 +- + 4 files changed, 23 insertions(+), 25 deletions(-) + +diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c +--- a/drivers/hv/channel.c ++++ b/drivers/hv/channel.c +@@ -640,6 +640,7 @@ void vmbus_close(struct vmbus_channel *channel) + */ + return; + } ++ mutex_lock(&vmbus_connection.channel_mutex); + /* + * Close all the sub-channels first and then close the + * primary channel. +@@ -648,16 +649,15 @@ void vmbus_close(struct vmbus_channel *channel) + cur_channel = list_entry(cur, struct vmbus_channel, sc_list); + vmbus_close_internal(cur_channel); + if (cur_channel->rescind) { +- mutex_lock(&vmbus_connection.channel_mutex); +- hv_process_channel_removal(cur_channel, ++ hv_process_channel_removal( + cur_channel->offermsg.child_relid); +- mutex_unlock(&vmbus_connection.channel_mutex); + } + } + /* + * Now close the primary. + */ + vmbus_close_internal(channel); ++ mutex_unlock(&vmbus_connection.channel_mutex); + } + EXPORT_SYMBOL_GPL(vmbus_close); + +diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c +--- a/drivers/hv/channel_mgmt.c ++++ b/drivers/hv/channel_mgmt.c +@@ -159,7 +159,7 @@ static void vmbus_rescind_cleanup(struct vmbus_channel *channel) + + + spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); +- ++ channel->rescind = true; + list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list, + msglistentry) { + +@@ -381,14 +381,21 @@ static void vmbus_release_relid(u32 relid) + true); + } + +-void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid) ++void hv_process_channel_removal(u32 relid) + { + unsigned long flags; +- struct vmbus_channel *primary_channel; ++ struct vmbus_channel *primary_channel, *channel; + +- BUG_ON(!channel->rescind); + BUG_ON(!mutex_is_locked(&vmbus_connection.channel_mutex)); + ++ /* ++ * Make sure channel is valid as we may have raced. ++ */ ++ channel = relid2channel(relid); ++ if (!channel) ++ return; ++ ++ BUG_ON(!channel->rescind); + if (channel->target_cpu != get_cpu()) { + put_cpu(); + smp_call_function_single(channel->target_cpu, +@@ -515,6 +522,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) + if (!fnew) { + if (channel->sc_creation_callback != NULL) + channel->sc_creation_callback(newchannel); ++ newchannel->probe_done = true; + return; + } + +@@ -834,7 +842,6 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) + { + struct vmbus_channel_rescind_offer *rescind; + struct vmbus_channel *channel; +- unsigned long flags; + struct device *dev; + + rescind = (struct vmbus_channel_rescind_offer *)hdr; +@@ -873,16 +880,6 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) + return; + } + +- spin_lock_irqsave(&channel->lock, flags); +- channel->rescind = true; +- spin_unlock_irqrestore(&channel->lock, flags); +- +- /* +- * Now that we have posted the rescind state, perform +- * rescind related cleanup. +- */ +- vmbus_rescind_cleanup(channel); +- + /* + * Now wait for offer handling to complete. + */ +@@ -901,6 +898,7 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) + if (channel->device_obj) { + if (channel->chn_rescind_callback) { + channel->chn_rescind_callback(channel); ++ vmbus_rescind_cleanup(channel); + return; + } + /* +@@ -909,6 +907,7 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) + */ + dev = get_device(&channel->device_obj->device); + if (dev) { ++ vmbus_rescind_cleanup(channel); + vmbus_device_unregister(channel->device_obj); + put_device(dev); + } +@@ -921,16 +920,16 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) + * 1. Close all sub-channels first + * 2. Then close the primary channel. + */ ++ mutex_lock(&vmbus_connection.channel_mutex); ++ vmbus_rescind_cleanup(channel); + if (channel->state == CHANNEL_OPEN_STATE) { + /* + * The channel is currently not open; + * it is safe for us to cleanup the channel. + */ +- mutex_lock(&vmbus_connection.channel_mutex); +- hv_process_channel_removal(channel, +- channel->offermsg.child_relid); +- mutex_unlock(&vmbus_connection.channel_mutex); ++ hv_process_channel_removal(rescind->child_relid); + } ++ mutex_unlock(&vmbus_connection.channel_mutex); + } + } + +diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c +--- a/drivers/hv/vmbus_drv.c ++++ b/drivers/hv/vmbus_drv.c +@@ -768,8 +768,7 @@ static void vmbus_device_release(struct device *device) + struct vmbus_channel *channel = hv_dev->channel; + + mutex_lock(&vmbus_connection.channel_mutex); +- hv_process_channel_removal(channel, +- channel->offermsg.child_relid); ++ hv_process_channel_removal(channel->offermsg.child_relid); + mutex_unlock(&vmbus_connection.channel_mutex); + kfree(hv_dev); + +diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h +--- a/include/linux/hyperv.h ++++ b/include/linux/hyperv.h +@@ -1403,7 +1403,7 @@ extern bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, u8 *buf, + const int *srv_version, int srv_vercnt, + int *nego_fw_version, int *nego_srv_version); + +-void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid); ++void hv_process_channel_removal(u32 relid); + + void vmbus_setevent(struct vmbus_channel *channel); + /* diff --git a/patches.suse/msft-hv-1471-x86-hyperv-Clear-vCPU-banks-between-calls-to-avoid-f.patch b/patches.suse/msft-hv-1471-x86-hyperv-Clear-vCPU-banks-between-calls-to-avoid-f.patch new file mode 100644 index 0000000..1e2bcd9 --- /dev/null +++ b/patches.suse/msft-hv-1471-x86-hyperv-Clear-vCPU-banks-between-calls-to-avoid-f.patch @@ -0,0 +1,101 @@ +From: Vitaly Kuznetsov +Date: Fri, 6 Oct 2017 17:48:54 +0200 +Patch-mainline: v4.14-rc5 +Subject: x86/hyperv: Clear vCPU banks between calls to avoid flushing unneeded vCPUs +Git-commit: a3b7424392924e778b608e30ee321f7b10cc94b8 +References: fate#323887 + +hv_flush_pcpu_ex structures are not cleared between calls for performance +reasons (they're variable size up to PAGE_SIZE each) but we must clear +hv_vp_set.bank_contents part of it to avoid flushing unneeded vCPUs. The +rest of the structure is formed correctly. + +To do the clearing in an efficient way stash the maximum possible vCPU +number (this may differ from Linux CPU id). + +Reported-by: Jork Loeser +Signed-off-by: Vitaly Kuznetsov +Cc: Dexuan Cui +Cc: Haiyang Zhang +Cc: K. Y. Srinivasan +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Stephen Hemminger +Cc: Thomas Gleixner +Cc: devel@linuxdriverproject.org +Link: http://lkml.kernel.org/r/20171006154854.18092-1-vkuznets@redhat.com +Signed-off-by: Ingo Molnar +Acked-by: Olaf Hering +--- + arch/x86/hyperv/hv_init.c | 5 +++++ + arch/x86/hyperv/mmu.c | 17 ++++++++++++----- + arch/x86/include/asm/mshyperv.h | 1 + + 3 files changed, 18 insertions(+), 5 deletions(-) + +diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c +--- a/arch/x86/hyperv/hv_init.c ++++ b/arch/x86/hyperv/hv_init.c +@@ -85,6 +85,8 @@ EXPORT_SYMBOL_GPL(hyperv_cs); + u32 *hv_vp_index; + EXPORT_SYMBOL_GPL(hv_vp_index); + ++u32 hv_max_vp_index; ++ + static int hv_cpu_init(unsigned int cpu) + { + u64 msr_vp_index; +@@ -93,6 +95,9 @@ static int hv_cpu_init(unsigned int cpu) + + hv_vp_index[smp_processor_id()] = msr_vp_index; + ++ if (msr_vp_index > hv_max_vp_index) ++ hv_max_vp_index = msr_vp_index; ++ + return 0; + } + +diff --git a/arch/x86/hyperv/mmu.c b/arch/x86/hyperv/mmu.c +--- a/arch/x86/hyperv/mmu.c ++++ b/arch/x86/hyperv/mmu.c +@@ -76,6 +76,18 @@ static inline int cpumask_to_vp_set(struct hv_flush_pcpu_ex *flush, + { + int cpu, vcpu, vcpu_bank, vcpu_offset, nr_bank = 1; + ++ /* valid_bank_mask can represent up to 64 banks */ ++ if (hv_max_vp_index / 64 >= 64) ++ return 0; ++ ++ /* ++ * Clear all banks up to the maximum possible bank as hv_flush_pcpu_ex ++ * structs are not cleared between calls, we risk flushing unneeded ++ * vCPUs otherwise. ++ */ ++ for (vcpu_bank = 0; vcpu_bank <= hv_max_vp_index / 64; vcpu_bank++) ++ flush->hv_vp_set.bank_contents[vcpu_bank] = 0; ++ + /* + * Some banks may end up being empty but this is acceptable. + */ +@@ -83,11 +95,6 @@ static inline int cpumask_to_vp_set(struct hv_flush_pcpu_ex *flush, + vcpu = hv_cpu_number_to_vp_number(cpu); + vcpu_bank = vcpu / 64; + vcpu_offset = vcpu % 64; +- +- /* valid_bank_mask can represent up to 64 banks */ +- if (vcpu_bank >= 64) +- return 0; +- + __set_bit(vcpu_offset, (unsigned long *) + &flush->hv_vp_set.bank_contents[vcpu_bank]); + if (vcpu_bank >= nr_bank) +diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h +--- a/arch/x86/include/asm/mshyperv.h ++++ b/arch/x86/include/asm/mshyperv.h +@@ -289,6 +289,7 @@ static inline u64 hv_do_rep_hypercall(u16 code, u16 rep_count, u16 varhead_size, + * to this information. + */ + extern u32 *hv_vp_index; ++extern u32 hv_max_vp_index; + + /** + * hv_cpu_number_to_vp_number() - Map CPU to VP. diff --git a/patches.suse/msft-hv-1472-x86-hyperv-Don-t-use-percpu-areas-for-pcpu_flush-pcp.patch b/patches.suse/msft-hv-1472-x86-hyperv-Don-t-use-percpu-areas-for-pcpu_flush-pcp.patch new file mode 100644 index 0000000..2f7a9c1 --- /dev/null +++ b/patches.suse/msft-hv-1472-x86-hyperv-Don-t-use-percpu-areas-for-pcpu_flush-pcp.patch @@ -0,0 +1,115 @@ +From: Vitaly Kuznetsov +Date: Thu, 5 Oct 2017 13:39:24 +0200 +Patch-mainline: v4.14-rc5 +Subject: x86/hyperv: Don't use percpu areas for pcpu_flush/pcpu_flush_ex structures +Git-commit: 60d73a7c96601434dfdb56d5b9167ff3b850d8d7 +References: fate#323887 + +hv_do_hypercall() does virt_to_phys() translation and with some configs +(CONFIG_SLAB) this doesn't work for percpu areas, we pass wrong memory to +hypervisor and get #GP. We could use working slow_virt_to_phys() instead +but doing so kills the performance. + +Move pcpu_flush/pcpu_flush_ex structures out of percpu areas and +allocate memory on first call. The additional level of indirection gives +us a small performance penalty, in future we may consider introducing +hypercall functions which avoid virt_to_phys() conversion and cache +physical addresses of pcpu_flush/pcpu_flush_ex structures somewhere. + +Reported-by: Simon Xiao +Signed-off-by: Vitaly Kuznetsov +Cc: Dexuan Cui +Cc: Haiyang Zhang +Cc: Jork Loeser +Cc: K. Y. Srinivasan +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Stephen Hemminger +Cc: Thomas Gleixner +Cc: devel@linuxdriverproject.org +Link: http://lkml.kernel.org/r/20171005113924.28021-1-vkuznets@redhat.com +Signed-off-by: Ingo Molnar +Acked-by: Olaf Hering +--- + arch/x86/hyperv/mmu.c | 34 ++++++++++++++++++++++++++++------ + 1 file changed, 28 insertions(+), 6 deletions(-) + +diff --git a/arch/x86/hyperv/mmu.c b/arch/x86/hyperv/mmu.c +--- a/arch/x86/hyperv/mmu.c ++++ b/arch/x86/hyperv/mmu.c +@@ -36,9 +36,9 @@ struct hv_flush_pcpu_ex { + /* Each gva in gva_list encodes up to 4096 pages to flush */ + #define HV_TLB_FLUSH_UNIT (4096 * PAGE_SIZE) + +-static struct hv_flush_pcpu __percpu *pcpu_flush; ++static struct hv_flush_pcpu __percpu **pcpu_flush; + +-static struct hv_flush_pcpu_ex __percpu *pcpu_flush_ex; ++static struct hv_flush_pcpu_ex __percpu **pcpu_flush_ex; + + /* + * Fills in gva_list starting from offset. Returns the number of items added. +@@ -109,6 +109,7 @@ static void hyperv_flush_tlb_others(const struct cpumask *cpus, + struct mm_struct *mm, unsigned long start, unsigned long end) + { + int cpu, vcpu, gva_n, max_gvas; ++ struct hv_flush_pcpu **flush_pcpu; + struct hv_flush_pcpu *flush; + u64 status = U64_MAX; + unsigned long flags; +@@ -123,7 +124,17 @@ static void hyperv_flush_tlb_others(const struct cpumask *cpus, + + local_irq_save(flags); + +- flush = this_cpu_ptr(pcpu_flush); ++ flush_pcpu = this_cpu_ptr(pcpu_flush); ++ ++ if (unlikely(!*flush_pcpu)) ++ *flush_pcpu = page_address(alloc_page(GFP_ATOMIC)); ++ ++ flush = *flush_pcpu; ++ ++ if (unlikely(!flush)) { ++ local_irq_restore(flags); ++ goto do_native; ++ } + + if (mm) { + flush->address_space = virt_to_phys(mm->pgd); +@@ -180,6 +191,7 @@ static void hyperv_flush_tlb_others_ex(const struct cpumask *cpus, + struct mm_struct *mm, unsigned long start, unsigned long end) + { + int nr_bank = 0, max_gvas, gva_n; ++ struct hv_flush_pcpu_ex **flush_pcpu; + struct hv_flush_pcpu_ex *flush; + u64 status = U64_MAX; + unsigned long flags; +@@ -194,7 +206,17 @@ static void hyperv_flush_tlb_others_ex(const struct cpumask *cpus, + + local_irq_save(flags); + +- flush = this_cpu_ptr(pcpu_flush_ex); ++ flush_pcpu = this_cpu_ptr(pcpu_flush_ex); ++ ++ if (unlikely(!*flush_pcpu)) ++ *flush_pcpu = page_address(alloc_page(GFP_ATOMIC)); ++ ++ flush = *flush_pcpu; ++ ++ if (unlikely(!flush)) { ++ local_irq_restore(flags); ++ goto do_native; ++ } + + if (mm) { + flush->address_space = virt_to_phys(mm->pgd); +@@ -273,7 +295,7 @@ void hyper_alloc_mmu(void) + return; + + if (!(ms_hyperv.hints & HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED)) +- pcpu_flush = __alloc_percpu(PAGE_SIZE, PAGE_SIZE); ++ pcpu_flush = alloc_percpu(struct hv_flush_pcpu *); + else +- pcpu_flush_ex = __alloc_percpu(PAGE_SIZE, PAGE_SIZE); ++ pcpu_flush_ex = alloc_percpu(struct hv_flush_pcpu_ex *); + } diff --git a/patches.suse/msft-hv-1473-x86-hyperv-Fix-hypercalls-with-extended-CPU-ranges-f.patch b/patches.suse/msft-hv-1473-x86-hyperv-Fix-hypercalls-with-extended-CPU-ranges-f.patch new file mode 100644 index 0000000..890e960 --- /dev/null +++ b/patches.suse/msft-hv-1473-x86-hyperv-Fix-hypercalls-with-extended-CPU-ranges-f.patch @@ -0,0 +1,66 @@ +From: Marcelo Henrique Cerri +Date: Thu, 5 Oct 2017 10:34:29 -0300 +Patch-mainline: v4.14-rc5 +Subject: x86/hyperv: Fix hypercalls with extended CPU ranges for TLB flushing +Git-commit: ab7ff471aa5db670197070760f022622793da7e5 +References: fate#323887 + +Do not consider the fixed size of hv_vp_set when passing the variable +header size to hv_do_rep_hypercall(). + +The Hyper-V hypervisor specification states that for a hypercall with a +variable header only the size of the variable portion should be supplied +via the input control. + +For HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX/LIST_EX calls that means the +fixed portion of hv_vp_set should not be considered. + +That fixes random failures of some applications that are unexpectedly +killed with SIGBUS or SIGSEGV. + +Signed-off-by: Marcelo Henrique Cerri +Cc: Dexuan Cui +Cc: Haiyang Zhang +Cc: Jork Loeser +Cc: Josh Poulson +Cc: K. Y. Srinivasan +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Simon Xiao +Cc: Stephen Hemminger +Cc: Thomas Gleixner +Cc: Vitaly Kuznetsov +Cc: devel@linuxdriverproject.org +Fixes: 628f54cc6451 ("x86/hyper-v: Support extended CPU ranges for TLB flush hypercalls") +Link: http://lkml.kernel.org/r/1507210469-29065-1-git-send-email-marcelo.cerri@canonical.com +Signed-off-by: Ingo Molnar +Acked-by: Olaf Hering +--- + arch/x86/hyperv/mmu.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/arch/x86/hyperv/mmu.c b/arch/x86/hyperv/mmu.c +--- a/arch/x86/hyperv/mmu.c ++++ b/arch/x86/hyperv/mmu.c +@@ -251,18 +251,18 @@ static void hyperv_flush_tlb_others_ex(const struct cpumask *cpus, + flush->flags |= HV_FLUSH_NON_GLOBAL_MAPPINGS_ONLY; + status = hv_do_rep_hypercall( + HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX, +- 0, nr_bank + 2, flush, NULL); ++ 0, nr_bank, flush, NULL); + } else if (end && + ((end - start)/HV_TLB_FLUSH_UNIT) > max_gvas) { + status = hv_do_rep_hypercall( + HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX, +- 0, nr_bank + 2, flush, NULL); ++ 0, nr_bank, flush, NULL); + } else { + gva_n = fill_gva_list(flush->gva_list, nr_bank, + start, end); + status = hv_do_rep_hypercall( + HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST_EX, +- gva_n, nr_bank + 2, flush, NULL); ++ gva_n, nr_bank, flush, NULL); + } + + local_irq_restore(flags); diff --git a/patches.suse/suse-hv-guest-os-id.patch b/patches.suse/suse-hv-guest-os-id.patch index 9bb4986..dfd2a00 100644 --- a/patches.suse/suse-hv-guest-os-id.patch +++ b/patches.suse/suse-hv-guest-os-id.patch @@ -32,4 +32,4 @@ Acked-by: Olaf Hering + guest_id = generate_guest_id(d1, LINUX_VERSION_CODE, d2); wrmsrl(HV_X64_MSR_GUEST_OS_ID, guest_id); - hypercall_pg = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_RX); + hv_hypercall_pg = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_RX); diff --git a/series.conf b/series.conf index ff3eec1..68205ad 100644 --- a/series.conf +++ b/series.conf @@ -1629,7 +1629,16 @@ patches.suse/msft-hv-1373-PCI-hv-Temporary-own-CPU-number-to-vCPU-number-infra.patch patches.suse/msft-hv-1374-PCI-hv-Add-vPCI-version-protocol-negotiation.patch patches.suse/msft-hv-1375-PCI-hv-Use-vPCI-protocol-version-1.2.patch + patches.suse/msft-hv-1376-tools-hv-ignore-a-NIC-if-it-has-been-configured.patch patches.suse/msft-hv-1377-Revert-netvsc-optimize-calculation-of-number-of-slot.patch + patches.suse/msft-hv-1378-vmbus-simplify-hv_ringbuffer_read.patch + patches.suse/msft-hv-1379-vmbus-drop-unused-ring_buffer_info-elements.patch + patches.suse/msft-hv-1380-vmbus-refactor-hv_signal_on_read.patch + patches.suse/msft-hv-1381-vmbus-eliminate-duplicate-cached-index.patch + patches.suse/msft-hv-1382-vmbus-more-host-signalling-avoidance.patch + patches.suse/msft-hv-1383-vmbus-add-prefetch-to-ring-buffer-iterator.patch + patches.suse/msft-hv-1384-x86-hyper-v-include-hyperv-only-when-CONFIG_HYPERV-i.patch + patches.suse/msft-hv-1385-x86-hyper-v-stash-the-max-number-of-virtual-logical-.patch patches.suse/msft-hv-1386-netvsc-force-link-update-after-MTU-change.patch patches.suse/msft-hv-1387-netvsc-add-some-rtnl_dereference-annotations.patch patches.suse/msft-hv-1388-netvsc-change-order-of-steps-in-setting-queues.patch @@ -1638,6 +1647,7 @@ patches.suse/msft-hv-1391-netvsc-need-rcu_derefence-when-accessing-internal-de.patch patches.suse/msft-hv-1392-netvsc-save-pointer-to-parent-netvsc_device-in-chann.patch patches.suse/msft-hv-1393-netvsc-add-rtnl-annotations-in-rndis.patch + patches.suse/msft-hv-1394-Revert-x86-hyper-v-include-hyperv-only-when-CONFIG_H.patch patches.suse/msft-hv-1395-netvsc-fix-ptr_ret.cocci-warnings.patch patches.suse/msft-hv-1396-netvsc-remove-bogus-rtnl_unlock.patch patches.suse/msft-hv-1397-netvsc-Remove-redundant-use-of-ipv6_hdr.patch @@ -1652,10 +1662,66 @@ patches.suse/msft-hv-1407-netvsc-optimize-receive-completions.patch patches.suse/msft-hv-1408-netvsc-fix-error-unwind-on-device-setup-failure.patch patches.suse/msft-hv-1409-netvsc-signal-host-if-receive-ring-is-emptied.patch + patches.suse/msft-hv-1410-netvsc-Initialize-64-bit-stats-seqcount.patch patches.suse/msft-hv-1411-hyperv-netvsc-Neaten-netvsc_send_pkt-by-using-a-temp.patch patches.suse/msft-hv-1412-netvsc-transparent-VF-management.patch + patches.suse/msft-hv-1413-netvsc-remove-bonding-setup-script.patch + patches.suse/msft-hv-1414-PCI-hv-Do-not-sleep-in-compose_msi_msg.patch + patches.suse/msft-hv-1415-netvsc-fix-race-on-sub-channel-creation.patch patches.suse/msft-hv-1416-netvsc-fix-rtnl-deadlock-on-unregister-of-vf.patch patches.suse/msft-hv-1417-netvsc-make-sure-and-unregister-datapath.patch + patches.suse/msft-hv-1418-x86-hyper-v-Include-hyperv-only-when-CONFIG_HYPERV-i.patch + patches.suse/msft-hv-1419-x86-hyper-v-Make-hv_do_hypercall-inline.patch + patches.suse/msft-hv-1420-x86-hyper-v-Introduce-fast-hypercall-implementation.patch + patches.suse/msft-hv-1421-hyper-v-Use-fast-hypercall-for-HVCALL_SIGNAL_EVENT.patch + patches.suse/msft-hv-1422-x86-hyper-v-Implement-rep-hypercalls.patch + patches.suse/msft-hv-1423-hyper-v-Globalize-vp_index.patch + patches.suse/msft-hv-1424-x86-hyper-v-Use-hypercall-for-remote-TLB-flush.patch + patches.suse/msft-hv-1425-netvsc-delay-setup-of-VF-device.patch + patches.suse/msft-hv-1426-netvsc-don-t-signal-host-twice-if-empty.patch + patches.suse/msft-hv-1427-netvsc-propagate-MAC-address-change-to-VF-slave.patch + patches.suse/msft-hv-1428-netvsc-check-error-return-when-restoring-channels-an.patch + patches.suse/msft-hv-1429-netvsc-no-need-to-allocate-send-receive-on-numa-node.patch + patches.suse/msft-hv-1430-netvsc-whitespace-cleanup.patch + patches.suse/msft-hv-1431-netvsc-remove-unnecessary-cast-of-void-pointer.patch + patches.suse/msft-hv-1432-netvsc-remove-unnecessary-check-for-NULL-hdr.patch + patches.suse/msft-hv-1433-netvsc-allow-controlling-send-recv-buffer-size.patch + patches.suse/msft-hv-1434-netvsc-keep-track-of-some-non-fatal-overload-conditi.patch + patches.suse/msft-hv-1435-Tools-hv-vss-Skip-freezing-filesystems-backed-by-loo.patch + patches.suse/msft-hv-1436-Drivers-hv-balloon-Correctly-update-onlined-page-cou.patch + patches.suse/msft-hv-1437-Drivers-hv-balloon-Show-the-max-dynamic-memory-assig.patch + patches.suse/msft-hv-1438-Drivers-hv-balloon-Initialize-last_post_time-on-star.patch + patches.suse/msft-hv-1439-Drivers-hv-kvp-Use-MAX_ADAPTER_ID_SIZE-for-translati.patch + patches.suse/msft-hv-1440-Tools-hv-fix-snprintf-warning-in-kvp_daemon.patch + patches.suse/msft-hv-1441-Tools-hv-update-buffer-handling-in-hv_fcopy_daemon.patch + patches.suse/msft-hv-1442-Drivers-hv-vmbus-Fix-rescind-handling-issues.patch + patches.suse/msft-hv-1443-vmbus-remove-unused-vmbus_sendpacket_multipagebuffer.patch + patches.suse/msft-hv-1444-vmbus-remove-unused-vmubs_sendpacket_pagebuffer_ctl.patch + patches.suse/msft-hv-1445-vmbus-remove-unused-vmbus_sendpacket_ctl.patch + patches.suse/msft-hv-1446-hv_netvsc-Clean-up-unused-parameter-from-netvsc_get_.patch + patches.suse/msft-hv-1447-hv_netvsc-Clean-up-unused-parameter-from-netvsc_get_.patch + patches.suse/msft-hv-1448-hv_netvsc-Add-ethtool-handler-to-set-and-get-UDP-has.patch + patches.suse/msft-hv-1449-hv_netvsc-Fix-rndis_filter_close-error-during-netvsc.patch + patches.suse/msft-hv-1452-scsi-storvsc-fix-memory-leak-on-ring-buffer-busy.patch + patches.suse/msft-hv-1453-x86-hyper-v-Support-extended-CPU-ranges-for-TLB-flus.patch + patches.suse/msft-hv-1454-tracing-hyper-v-Trace-hyperv_mmu_flush_tlb_others.patch + patches.suse/msft-hv-1455-netvsc-cleanup-datapath-switch.patch + patches.suse/msft-hv-1456-netvsc-allow-driver-to-be-removed-even-if-VF-is-pres.patch + patches.suse/msft-hv-1457-hv_netvsc-Clean-up-an-unused-parameter-in-rndis_filt.patch + patches.suse/msft-hv-1458-hv_netvsc-Simplify-num_chn-checking-in-rndis_filter_.patch + patches.suse/msft-hv-1459-hv_netvsc-Simplify-the-limit-check-in-netvsc_set_cha.patch + patches.suse/msft-hv-1460-hv_netvsc-Fix-the-channel-limit-in-netvsc_set_rxfh.patch + patches.suse/msft-hv-1461-hv_netvsc-fix-deadlock-on-hotplug.patch + patches.suse/msft-hv-1462-hv_netvsc-avoid-unnecessary-wakeups-on-subchannel-cr.patch + patches.suse/msft-hv-1464-x86-hyper-v-Remove-duplicated-HV_X64_EX_PROCESSOR_MA.patch + patches.suse/msft-hv-1465-netvsc-increase-default-receive-buffer-size.patch + patches.suse/msft-hv-1466-hv_netvsc-fix-send-buffer-failure-on-MTU-change.patch + patches.suse/msft-hv-1467-vmbus-don-t-acquire-the-mutex-in-vmbus_hvsock_device.patch + patches.suse/msft-hv-1468-Drivers-hv-fcopy-restore-correct-transfer-length.patch + patches.suse/msft-hv-1470-Drivers-hv-vmbus-Fix-bugs-in-rescind-handling.patch + patches.suse/msft-hv-1471-x86-hyperv-Clear-vCPU-banks-between-calls-to-avoid-f.patch + patches.suse/msft-hv-1472-x86-hyperv-Don-t-use-percpu-areas-for-pcpu_flush-pcp.patch + patches.suse/msft-hv-1473-x86-hyperv-Fix-hypercalls-with-extended-CPU-ranges-f.patch patches.suse/suse-hv-guest-os-id.patch patches.suse/suse-hv-kvp_on_msg.dbg.patch