kernel: updated to 4.9.8

at the moment its only for x86_64 and layer7 is disabled because it crashs.

Signed-off-by: Arne Fitzenreiter <arne_f@ipfire.org>
This commit is contained in:
Arne Fitzenreiter
2017-02-12 19:58:43 +01:00
parent cfcd1ec588
commit 91648bd166
73 changed files with 2724 additions and 17999 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -53,6 +53,7 @@
#usr/include/asm/ist.h
#usr/include/asm/kvm.h
#usr/include/asm/kvm_para.h
#usr/include/asm/kvm_perf.h
#usr/include/asm/ldt.h
#usr/include/asm/mce.h
#usr/include/asm/mman.h
@@ -97,6 +98,7 @@
#usr/include/asm/vmx.h
#usr/include/asm/vsyscall.h
#usr/include/drm
#usr/include/drm/amdgpu_drm.h
#usr/include/drm/drm.h
#usr/include/drm/drm_fourcc.h
#usr/include/drm/drm_mode.h
@@ -113,7 +115,9 @@
#usr/include/drm/savage_drm.h
#usr/include/drm/sis_drm.h
#usr/include/drm/tegra_drm.h
#usr/include/drm/vc4_drm.h
#usr/include/drm/via_drm.h
#usr/include/drm/virtgpu_drm.h
#usr/include/drm/vmwgfx_drm.h
#usr/include/linux
#usr/include/linux/a.out.h
@@ -123,6 +127,9 @@
#usr/include/linux/affs_hardblocks.h
#usr/include/linux/agpgart.h
#usr/include/linux/aio_abi.h
#usr/include/linux/am437x-vpfe.h
#usr/include/linux/android
#usr/include/linux/android/binder.h
#usr/include/linux/apm_bios.h
#usr/include/linux/arcfb.h
#usr/include/linux/atalk.h
@@ -156,8 +163,12 @@
#usr/include/linux/binfmts.h
#usr/include/linux/blkpg.h
#usr/include/linux/blktrace_api.h
#usr/include/linux/bpf.h
#usr/include/linux/bpf_common.h
#usr/include/linux/bpf_perf_event.h
#usr/include/linux/bpqether.h
#usr/include/linux/bsg.h
#usr/include/linux/bt-bmc.h
#usr/include/linux/btrfs.h
#usr/include/linux/byteorder
#usr/include/linux/byteorder/big_endian.h
@@ -192,6 +203,7 @@
#usr/include/linux/cycx_cfm.h
#usr/include/linux/dcbnl.h
#usr/include/linux/dccp.h
#usr/include/linux/devlink.h
#usr/include/linux/dlm.h
#usr/include/linux/dlm_device.h
#usr/include/linux/dlm_netlink.h
@@ -233,6 +245,7 @@
#usr/include/linux/firewire-cdev.h
#usr/include/linux/firewire-constants.h
#usr/include/linux/flat.h
#usr/include/linux/fou.h
#usr/include/linux/fs.h
#usr/include/linux/fsl_hypervisor.h
#usr/include/linux/fuse.h
@@ -242,6 +255,9 @@
#usr/include/linux/genetlink.h
#usr/include/linux/gfs2_ondisk.h
#usr/include/linux/gigaset_dev.h
#usr/include/linux/gpio.h
#usr/include/linux/gsmmux.h
#usr/include/linux/gtp.h
#usr/include/linux/hdlc
#usr/include/linux/hdlc.h
#usr/include/linux/hdlc/ioctl.h
@@ -252,8 +268,11 @@
#usr/include/linux/hidraw.h
#usr/include/linux/hpet.h
#usr/include/linux/hsi
#usr/include/linux/hsi/cs-protocol.h
#usr/include/linux/hsi/hsi_char.h
#usr/include/linux/hsr_netlink.h
#usr/include/linux/hw_breakpoint.h
#usr/include/linux/hyperv.h
#usr/include/linux/hysdn_if.h
#usr/include/linux/i2c-dev.h
#usr/include/linux/i2c.h
@@ -279,6 +298,7 @@
#usr/include/linux/if_infiniband.h
#usr/include/linux/if_link.h
#usr/include/linux/if_ltalk.h
#usr/include/linux/if_macsec.h
#usr/include/linux/if_packet.h
#usr/include/linux/if_phonet.h
#usr/include/linux/if_plip.h
@@ -292,11 +312,16 @@
#usr/include/linux/if_vlan.h
#usr/include/linux/if_x25.h
#usr/include/linux/igmp.h
#usr/include/linux/iio
#usr/include/linux/iio/events.h
#usr/include/linux/iio/types.h
#usr/include/linux/ila.h
#usr/include/linux/in.h
#usr/include/linux/in6.h
#usr/include/linux/in_route.h
#usr/include/linux/inet_diag.h
#usr/include/linux/inotify.h
#usr/include/linux/input-event-codes.h
#usr/include/linux/input.h
#usr/include/linux/ioctl.h
#usr/include/linux/ip.h
@@ -323,6 +348,7 @@
#usr/include/linux/ixjuser.h
#usr/include/linux/jffs2.h
#usr/include/linux/joystick.h
#usr/include/linux/kcmp.h
#usr/include/linux/kd.h
#usr/include/linux/kdev_t.h
#usr/include/linux/kernel-page-flags.h
@@ -336,16 +362,21 @@
#usr/include/linux/l2tp.h
#usr/include/linux/libc-compat.h
#usr/include/linux/limits.h
#usr/include/linux/lirc.h
#usr/include/linux/llc.h
#usr/include/linux/loop.h
#usr/include/linux/lp.h
#usr/include/linux/lwtunnel.h
#usr/include/linux/magic.h
#usr/include/linux/major.h
#usr/include/linux/map_to_7segment.h
#usr/include/linux/matroxfb.h
#usr/include/linux/mdio.h
#usr/include/linux/media-bus-format.h
#usr/include/linux/media.h
#usr/include/linux/mei.h
#usr/include/linux/membarrier.h
#usr/include/linux/memfd.h
#usr/include/linux/mempolicy.h
#usr/include/linux/meye.h
#usr/include/linux/mic_common.h
@@ -356,6 +387,8 @@
#usr/include/linux/mmc
#usr/include/linux/mmc/ioctl.h
#usr/include/linux/mmtimer.h
#usr/include/linux/mpls.h
#usr/include/linux/mpls_iptunnel.h
#usr/include/linux/mqueue.h
#usr/include/linux/mroute.h
#usr/include/linux/mroute6.h
@@ -368,9 +401,11 @@
#usr/include/linux/ncp_fs.h
#usr/include/linux/ncp_mount.h
#usr/include/linux/ncp_no.h
#usr/include/linux/ndctl.h
#usr/include/linux/neighbour.h
#usr/include/linux/net.h
#usr/include/linux/net_dropmon.h
#usr/include/linux/net_namespace.h
#usr/include/linux/net_tstamp.h
#usr/include/linux/netconf.h
#usr/include/linux/netdevice.h
@@ -386,6 +421,7 @@
#usr/include/linux/netfilter/nf_conntrack_sctp.h
#usr/include/linux/netfilter/nf_conntrack_tcp.h
#usr/include/linux/netfilter/nf_conntrack_tuple_common.h
#usr/include/linux/netfilter/nf_log.h
#usr/include/linux/netfilter/nf_nat.h
#usr/include/linux/netfilter/nf_tables.h
#usr/include/linux/netfilter/nf_tables_compat.h
@@ -414,6 +450,7 @@
#usr/include/linux/netfilter/xt_NFQUEUE.h
#usr/include/linux/netfilter/xt_RATEEST.h
#usr/include/linux/netfilter/xt_SECMARK.h
#usr/include/linux/netfilter/xt_SYNPROXY.h
#usr/include/linux/netfilter/xt_TCPMSS.h
#usr/include/linux/netfilter/xt_TCPOPTSTRIP.h
#usr/include/linux/netfilter/xt_TEE.h
@@ -440,7 +477,6 @@
#usr/include/linux/netfilter/xt_iprange.h
#usr/include/linux/netfilter/xt_ipvs.h
#usr/include/linux/netfilter/xt_l2tp.h
#usr/include/linux/netfilter/xt_layer7.h
#usr/include/linux/netfilter/xt_length.h
#usr/include/linux/netfilter/xt_limit.h
#usr/include/linux/netfilter/xt_mac.h
@@ -488,7 +524,6 @@
#usr/include/linux/netfilter_bridge/ebt_pkttype.h
#usr/include/linux/netfilter_bridge/ebt_redirect.h
#usr/include/linux/netfilter_bridge/ebt_stp.h
#usr/include/linux/netfilter_bridge/ebt_ulog.h
#usr/include/linux/netfilter_bridge/ebt_vlan.h
#usr/include/linux/netfilter_bridge/ebtables.h
#usr/include/linux/netfilter_decnet.h
@@ -500,7 +535,6 @@
#usr/include/linux/netfilter_ipv4/ipt_LOG.h
#usr/include/linux/netfilter_ipv4/ipt_REJECT.h
#usr/include/linux/netfilter_ipv4/ipt_TTL.h
#usr/include/linux/netfilter_ipv4/ipt_ULOG.h
#usr/include/linux/netfilter_ipv4/ipt_ah.h
#usr/include/linux/netfilter_ipv4/ipt_ecn.h
#usr/include/linux/netfilter_ipv4/ipt_ttl.h
@@ -539,7 +573,7 @@
#usr/include/linux/nfsd/stats.h
#usr/include/linux/nl80211.h
#usr/include/linux/nubus.h
#usr/include/linux/nvme.h
#usr/include/linux/nvme_ioctl.h
#usr/include/linux/nvram.h
#usr/include/linux/omap3isp.h
#usr/include/linux/omapfb.h
@@ -562,6 +596,8 @@
#usr/include/linux/pktcdvd.h
#usr/include/linux/pmu.h
#usr/include/linux/poll.h
#usr/include/linux/posix_acl.h
#usr/include/linux/posix_acl_xattr.h
#usr/include/linux/posix_types.h
#usr/include/linux/ppdev.h
#usr/include/linux/ppp-comp.h
@@ -569,6 +605,7 @@
#usr/include/linux/ppp_defs.h
#usr/include/linux/pps.h
#usr/include/linux/prctl.h
#usr/include/linux/psci.h
#usr/include/linux/ptp_clock.h
#usr/include/linux/ptrace.h
#usr/include/linux/qnx4_fs.h
@@ -586,6 +623,8 @@
#usr/include/linux/reiserfs_xattr.h
#usr/include/linux/resource.h
#usr/include/linux/rfkill.h
#usr/include/linux/rio_cm_cdev.h
#usr/include/linux/rio_mport_cdev.h
#usr/include/linux/romfs_fs.h
#usr/include/linux/rose.h
#usr/include/linux/route.h
@@ -593,6 +632,7 @@
#usr/include/linux/rtnetlink.h
#usr/include/linux/scc.h
#usr/include/linux/sched.h
#usr/include/linux/scif_ioctl.h
#usr/include/linux/screen_info.h
#usr/include/linux/sctp.h
#usr/include/linux/sdla.h
@@ -607,11 +647,11 @@
#usr/include/linux/shm.h
#usr/include/linux/signal.h
#usr/include/linux/signalfd.h
#usr/include/linux/smiapp.h
#usr/include/linux/snmp.h
#usr/include/linux/sock_diag.h
#usr/include/linux/socket.h
#usr/include/linux/sockios.h
#usr/include/linux/som.h
#usr/include/linux/sonet.h
#usr/include/linux/sonypi.h
#usr/include/linux/sound.h
@@ -625,19 +665,27 @@
#usr/include/linux/sunrpc/debug.h
#usr/include/linux/suspend_ioctls.h
#usr/include/linux/swab.h
#usr/include/linux/sync_file.h
#usr/include/linux/synclink.h
#usr/include/linux/sysctl.h
#usr/include/linux/sysinfo.h
#usr/include/linux/target_core_user.h
#usr/include/linux/taskstats.h
#usr/include/linux/tc_act
#usr/include/linux/tc_act/tc_bpf.h
#usr/include/linux/tc_act/tc_connmark.h
#usr/include/linux/tc_act/tc_csum.h
#usr/include/linux/tc_act/tc_defact.h
#usr/include/linux/tc_act/tc_gact.h
#usr/include/linux/tc_act/tc_ife.h
#usr/include/linux/tc_act/tc_ipt.h
#usr/include/linux/tc_act/tc_mirred.h
#usr/include/linux/tc_act/tc_nat.h
#usr/include/linux/tc_act/tc_pedit.h
#usr/include/linux/tc_act/tc_skbedit.h
#usr/include/linux/tc_act/tc_skbmod.h
#usr/include/linux/tc_act/tc_tunnel_key.h
#usr/include/linux/tc_act/tc_vlan.h
#usr/include/linux/tc_ematch
#usr/include/linux/tc_ematch/tc_em_cmp.h
#usr/include/linux/tc_ematch/tc_em_meta.h
@@ -647,12 +695,14 @@
#usr/include/linux/tcp_metrics.h
#usr/include/linux/telephony.h
#usr/include/linux/termios.h
#usr/include/linux/thermal.h
#usr/include/linux/time.h
#usr/include/linux/times.h
#usr/include/linux/timex.h
#usr/include/linux/tiocl.h
#usr/include/linux/tipc.h
#usr/include/linux/tipc_config.h
#usr/include/linux/tipc_netlink.h
#usr/include/linux/toshiba.h
#usr/include/linux/tty.h
#usr/include/linux/tty_flags.h
@@ -679,6 +729,8 @@
#usr/include/linux/usb/tmc.h
#usr/include/linux/usb/video.h
#usr/include/linux/usbdevice_fs.h
#usr/include/linux/usbip.h
#usr/include/linux/userfaultfd.h
#usr/include/linux/utime.h
#usr/include/linux/utsname.h
#usr/include/linux/uuid.h
@@ -698,12 +750,19 @@
#usr/include/linux/virtio_blk.h
#usr/include/linux/virtio_config.h
#usr/include/linux/virtio_console.h
#usr/include/linux/virtio_gpu.h
#usr/include/linux/virtio_ids.h
#usr/include/linux/virtio_input.h
#usr/include/linux/virtio_net.h
#usr/include/linux/virtio_pci.h
#usr/include/linux/virtio_ring.h
#usr/include/linux/virtio_rng.h
#usr/include/linux/virtio_scsi.h
#usr/include/linux/virtio_types.h
#usr/include/linux/virtio_vsock.h
#usr/include/linux/vm_sockets.h
#usr/include/linux/vt.h
#usr/include/linux/vtpm_proxy.h
#usr/include/linux/wait.h
#usr/include/linux/wanrouter.h
#usr/include/linux/watchdog.h
@@ -714,8 +773,11 @@
#usr/include/linux/x25.h
#usr/include/linux/xattr.h
#usr/include/linux/xfrm.h
#usr/include/linux/xilinx-v4l2-controls.h
#usr/include/linux/zorro.h
#usr/include/linux/zorro_ids.h
#usr/include/misc
#usr/include/misc/cxl.h
#usr/include/mtd
#usr/include/mtd/inftl-user.h
#usr/include/mtd/mtd-abi.h
@@ -723,13 +785,24 @@
#usr/include/mtd/nftl-user.h
#usr/include/mtd/ubi-user.h
#usr/include/rdma
#usr/include/rdma/cxgb3-abi.h
#usr/include/rdma/cxgb4-abi.h
#usr/include/rdma/hfi
#usr/include/rdma/hfi/hfi1_user.h
#usr/include/rdma/ib_user_cm.h
#usr/include/rdma/ib_user_mad.h
#usr/include/rdma/ib_user_sa.h
#usr/include/rdma/ib_user_verbs.h
#usr/include/rdma/mlx4-abi.h
#usr/include/rdma/mlx5-abi.h
#usr/include/rdma/mthca-abi.h
#usr/include/rdma/nes-abi.h
#usr/include/rdma/ocrdma-abi.h
#usr/include/rdma/rdma_netlink.h
#usr/include/rdma/rdma_user_cm.h
#usr/include/rdma/rdma_user_rxe.h
#usr/include/scsi
#usr/include/scsi/cxlflash_ioctl.h
#usr/include/scsi/fc
#usr/include/scsi/fc/fc_els.h
#usr/include/scsi/fc/fc_fs.h
@@ -740,6 +813,7 @@
#usr/include/scsi/scsi_netlink_fc.h
#usr/include/sound
#usr/include/sound/asequencer.h
#usr/include/sound/asoc.h
#usr/include/sound/asound.h
#usr/include/sound/asound_fm.h
#usr/include/sound/compress_offload.h
@@ -750,6 +824,9 @@
#usr/include/sound/hdspm.h
#usr/include/sound/sb16_csp.h
#usr/include/sound/sfnt_info.h
#usr/include/sound/snd_sst_tokens.h
#usr/include/sound/tlv.h
#usr/include/sound/usb_stream.h
#usr/include/uapi
#usr/include/video
#usr/include/video/edid.h

View File

@@ -24,10 +24,11 @@
include Config
VER = 3.14.79
VER = 4.9.8
RPI_PATCHES = 3.14.79-grsec-ipfire1
A7M_PATCHES = 3.14.79-grsec-ipfire1
GRS_PATCHES = grsecurity-3.1ipfire-3.14.79-v1.patch.xz
GRS_PATCHES = grsecurity-3.1-4.9.8-201702060653.patch.xz
THISAPP = linux-$(VER)
@@ -83,10 +84,11 @@ rpi-patches-$(RPI_PATCHES).patch.xz = $(URL_IPFIRE)/rpi-patches-$(RPI_PATCHES).
arm7-multi-patches-$(A7M_PATCHES).patch.xz = $(URL_IPFIRE)/arm7-multi-patches-$(A7M_PATCHES).patch.xz
$(GRS_PATCHES) = $(URL_IPFIRE)/$(GRS_PATCHES)
$(DL_FILE)_MD5 = ec5b09d8ad2ebf92e6f51a727a338559
$(DL_FILE)_MD5 = 7b56bb1196642f0f6625906c6720a6b1
rpi-patches-$(RPI_PATCHES).patch.xz_MD5 = a02a7fd54c642c1e3578a00ed22f54f8
arm7-multi-patches-$(A7M_PATCHES).patch.xz_MD5 = 6c3b11e51caa278dbeacd1e23c2b171b
$(GRS_PATCHES)_MD5 = 7fe448b53558082395f68c5db94af1a7
$(GRS_PATCHES)_MD5 = 6c4e14c9a189676a3ff92f47b5ec77c4
install : $(TARGET)
@@ -122,98 +124,43 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
ln -svf linux-$(VER) $(DIR_SRC)/linux
# Linux Intermediate Queueing Device
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-3.14.22-imq.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/linux-4.9-imq.diff
# Layer7-patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-3.14-layer7-filter.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/linux-4.9.8-layer7-filter.patch
ifneq "$(KCFG)" "-headers"
# Grsecurity-patches
cd $(DIR_APP) && xz -c -d $(DIR_DL)/$(GRS_PATCHES) | patch -Np1
cd $(DIR_APP) && rm localversion-grsec
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-3.7-disable-compat_vdso.patch
endif
# DVB Patches
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-3.14.22-dvbsky.patch
cd $(DIR_APP) && patch -Np2 < $(DIR_SRC)/src/patches/v4l-dvb_fix_tua6034_pll.patch
# Wlan Patches
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/compat-drivers-3.8.3-ath_ignore_eeprom_regdomain.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-3.14.22-iwlwifi-noibss_only_on_radar_chan.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-3.10.37-rt2800usb_add_dlink_dwa137_usbid.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-3.10.55-rt2800usb-change_queue_warn_to_debug.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-3.14.25_rt2x00_fix_bss_bcn_num.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-3.14.25-rt5592_no_special_txop_init.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-3.10.39-add_libertas_uap.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/backports-4.2.6-1_ath10k_remove_logspam.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/linux-4.9.8-ath_ignore_eeprom_regd.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/linux-4.9.8-iwlwifi-noibss_only_on_radar_chan.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/linux-4.9.8-rt2x00usb_suppress_queue_warnings.patch
# cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-3.10.39-add_libertas_uap.patch
# mISDN Patches
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/mISDN_hfc-s_add_id.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/mISDN-hfcusb-reportl1down.patch
# Add LED trigger
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-3.14.22-ledtrig_netdev.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/linux-4.9.8-ledtrig_netdev.patch
# cs5535audio spams syslog if no ac97 was present (geos router)
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-3.10.30_cs5535audio_fix_logspam_on_geos.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/linux-4.9.8_cs5535audio_fix_logspam_on_geos.patch
# Add PC Engines APU led support
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-3.14-apu_leds.patch
# Add APU2 SoC ID to k10temp
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-3.14.65-k10temp_add_16H_M30H_id.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/linux-4.9.8-apu_leds.patch
# Fix uevent PHYSDEVDRIVER
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-3.2.33_ipg-fix-driver-name.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-2.6.32.27_mcs7830-fix-driver-name.patch
# r8169 L23 patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-3.14.32-r8169_disable_L23.patch
# update the queued trim blacklist from kernel 4.2rc1
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-3.14.43_new_qtrim_blacklist.patch
# remove eMMC EXT_CSD revision check to use newer eMMC modules
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-3.14.79_mmc_remove_EXT_CSD_revision_check.patch
# Hyper-V patches
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/0001-Drivers-net-hyperv-Get-rid-of-the-rndis_filter_packe.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/0002-Drivers-net-hyperv-Cleanup-the-receive-path.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/0003-Drivers-net-hyperv-Cleanup-the-netvsc-receive-callba.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/0004-hyperv-Add-latest-NetVSP-versions-to-auto-negotiatio.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/0005-Drivers-net-hyperv-Enable-scatter-gather-I-O.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/0006-Drivers-net-hyperv-Cleanup-the-send-path.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/0007-Drivers-net-hyperv-Enable-offloads-on-the-host.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/0008-Drivers-net-hyperv-Enable-receive-side-IP-checksum-o.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/0009-Drivers-net-hyperv-Enable-send-side-checksum-offload.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/0010-Drivers-net-hyperv-Enable-large-send-offload.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/0011-hyperv-Change-the-receive-buffer-size-for-legacy-hos.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/0012-Drivers-net-hyperv-Allocate-memory-for-all-possible-.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/0013-Drivers-net-hyperv-Negotiate-suitable-ndis-version-f.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/0014-Drivers-net-hyperv-Address-UDP-checksum-issues.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/0015-hyperv-Properly-handle-checksum-offload.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/0016-hyperv-Add-support-for-virtual-Receive-Side-Scaling-.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/0017-hyperv-Remove-recv_pkt_list-and-lock.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/0018-hyperv-Simplify-the-send_completion-variables.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/0019-hyperv-Enable-sendbuf-mechanism-on-the-send-path.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/0020-Add-support-for-netvsc-build-without-CONFIG_SYSFS-fl.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/0021-hyperv-Add-hash-value-into-RNDIS-Per-packet-info.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/0022-hyperv-fix-apparent-cut-n-paste-error-in-send-path-t.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/0023-hyperv-Fix-error-return-code-in-netvsc_init_buf.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/0024-hyperv-Fix-a-bug-in-netvsc_send.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/0025-Drivers-hv-vmbus-Support-per-channel-driver-state.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-hyperv_Mark_the_Hyoer-V_TSC_as_unstable.patch
ifneq "$(KCFG)" "-headers"
# fix AES-NI 192 and 256 bits / grsec is needed for this patch version
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/0100-crypto-aesni-Add-support-for-192-256-bit-keys-to-AES.patch
endif
# fix CVE-2016-5195 (Dirty COW)
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/0110-mm-remove-gup_flags-FOLL_WRITE-games-from-__get_user.patch
# fix empty symbol crc's
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-genksyms_fix_typeof_handling.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/linux-2.6.32.27_mcs7830-fix-driver-name.patch
ifeq "$(KCFG)" "-kirkwood"
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-3.10.10-mv_cesa_disable_failing_hmac_sha1.patch

View File

@@ -428,10 +428,10 @@ buildipfire() {
case "${TARGET_ARCH}" in
x86_64)
ipfiremake linux KCFG=""
ipfiremake backports KCFG=""
ipfiremake e1000e KCFG=""
ipfiremake igb KCFG=""
ipfiremake ixgbe KCFG=""
# ipfiremake backports KCFG=""
# ipfiremake e1000e KCFG=""
# ipfiremake igb KCFG=""
# ipfiremake ixgbe KCFG=""
ipfiremake xtables-addons KCFG=""
ipfiremake linux-initrd KCFG=""
;;

View File

@@ -1,60 +0,0 @@
From 5bb6f6e1d44aa91323857715dfddb63337f8307b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= <bjorn@mork.no>
Date: Sun, 3 Jul 2016 22:24:50 +0200
Subject: cdc_ncm: workaround for EM7455 "silent" data interface
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
[ Upstream commit c086e7096170390594c425114d98172bc9aceb8a ]
Several Lenovo users have reported problems with their Sierra
Wireless EM7455 modem. The driver has loaded successfully and
the MBIM management channel has appeared to work, including
establishing a connection to the mobile network. But no frames
have been received over the data interface.
The problem affects all EM7455 and MC7455, and is assumed to
affect other modems based on the same Qualcomm chipset and
baseband firmware.
Testing narrowed the problem down to what seems to be a
firmware timing bug during initialization. Adding a short sleep
while probing is sufficient to make the problem disappear.
Experiments have shown that 1-2 ms is too little to have any
effect, while 10-20 ms is enough to reliably succeed.
Reported-by: Stefan Armbruster <ml001@armbruster-it.de>
Reported-by: Ralph Plawetzki <ralph@purejava.org>
Reported-by: Andreas Fett <andreas.fett@secunet.com>
Reported-by: Rasmus Lerdorf <rasmus@lerdorf.com>
Reported-by: Samo Ratnik <samo.ratnik@gmail.com>
Reported-and-tested-by: Aleksander Morgado <aleksander@aleksander.es>
Signed-off-by: Bjørn Mork <bjorn@mork.no>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/usb/cdc_ncm.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index c663722..584504e 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -438,6 +438,13 @@ advance:
if (cdc_ncm_setup(dev))
goto error2;
+ /* Some firmwares need a pause here or they will silently fail
+ * to set up the interface properly. This value was decided
+ * empirically on a Sierra Wireless MC7455 running 02.08.02.00
+ * firmware.
+ */
+ usleep_range(10000, 20000);
+
/* configure data interface */
temp = usb_set_interface(dev->udev, iface_no, data_altsetting);
if (temp) {
--
cgit v0.12

View File

@@ -1,43 +0,0 @@
From d6b8a68ac7b6d2e241f8d34b769c98a1793d9124 Mon Sep 17 00:00:00 2001
From: Ben Hutchings <ben@decadent.org.uk>
Date: Wed, 20 Apr 2016 23:23:08 +0100
Subject: atl2: Disable unimplemented scatter/gather feature
[ Upstream commit f43bfaeddc79effbf3d0fcb53ca477cca66f3db8 ]
atl2 includes NETIF_F_SG in hw_features even though it has no support
for non-linear skbs. This bug was originally harmless since the
driver does not claim to implement checksum offload and that used to
be a requirement for SG.
Now that SG and checksum offload are independent features, if you
explicitly enable SG *and* use one of the rare protocols that can use
SG without checkusm offload, this potentially leaks sensitive
information (before you notice that it just isn't working). Therefore
this obscure bug has been designated CVE-2016-2117.
Reported-by: Justin Yackoski <jyackoski@crypto-nite.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Fixes: ec5f06156423 ("net: Kill link between CSUM and SG features.")
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/atheros/atlx/atl2.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c
index 265ce1b..96fe542 100644
--- a/drivers/net/ethernet/atheros/atlx/atl2.c
+++ b/drivers/net/ethernet/atheros/atlx/atl2.c
@@ -1413,7 +1413,7 @@ static int atl2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
err = -EIO;
- netdev->hw_features = NETIF_F_SG | NETIF_F_HW_VLAN_CTAG_RX;
+ netdev->hw_features = NETIF_F_HW_VLAN_CTAG_RX;
netdev->features |= (NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX);
/* Init PHY as early as possible due to power saving issue */
--
cgit v0.12

View File

@@ -1,53 +0,0 @@
From fc70a4a5cb616bf390cee03390265045de5cf06a Mon Sep 17 00:00:00 2001
From: Feng Tang <feng.tang@intel.com>
Date: Fri, 24 Jun 2016 15:26:05 +0800
Subject: net: alx: Work around the DMA RX overflow issue
[ Upstream commit 881d0327db37ad917a367c77aff1afa1ee41e0a9 ]
Note: This is a verified backported patch for stable 4.4 kernel, and it
could also be applied to 4.3/4.2/4.1/3.18/3.16
There is a problem with alx devices, that the network link will be
lost in 1-5 minutes after the device is up.
>From debugging without datasheet, we found the error always
happen when the DMA RX address is set to 0x....fc0, which is very
likely to be a HW/silicon problem.
This patch will apply rx skb with 64 bytes longer space, and if the
allocated skb has a 0x...fc0 address, it will use skb_resever(skb, 64)
to advance the address, so that the RX overflow can be avoided.
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=70761
Signed-off-by: Feng Tang <feng.tang@intel.com>
Suggested-by: Eric Dumazet <edumazet@google.com>
Tested-by: Ole Lukoie <olelukoie@mail.ru>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/atheros/alx/main.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c
index 3e1d7d2..7585960 100644
--- a/drivers/net/ethernet/atheros/alx/main.c
+++ b/drivers/net/ethernet/atheros/alx/main.c
@@ -86,9 +86,14 @@ static int alx_refill_rx_ring(struct alx_priv *alx, gfp_t gfp)
while (!cur_buf->skb && next != rxq->read_idx) {
struct alx_rfd *rfd = &rxq->rfd[cur];
- skb = __netdev_alloc_skb(alx->dev, alx->rxbuf_size, gfp);
+ skb = __netdev_alloc_skb(alx->dev, alx->rxbuf_size + 64, gfp);
if (!skb)
break;
+
+ /* Workround for the HW RX DMA overflow issue */
+ if (((unsigned long)skb->data & 0xfff) == 0xfc0)
+ skb_reserve(skb, 64);
+
dma = dma_map_single(&alx->hw.pdev->dev,
skb->data, alx->rxbuf_size,
DMA_FROM_DEVICE);
--
cgit v0.12

File diff suppressed because it is too large Load Diff

View File

@@ -1,27 +0,0 @@
diff -Naur linux-3.10.30.org/sound/pci/cs5535audio/cs5535audio.c linux-3.10.30/sound/pci/cs5535audio/cs5535audio.c
--- linux-3.10.30.org/sound/pci/cs5535audio/cs5535audio.c 2014-02-13 22:48:15.000000000 +0100
+++ linux-3.10.30/sound/pci/cs5535audio/cs5535audio.c 2014-02-15 12:45:49.545688703 +0100
@@ -83,8 +83,8 @@
break;
udelay(1);
} while (--timeout);
- if (!timeout)
- snd_printk(KERN_ERR "Failure writing to cs5535 codec\n");
+// if (!timeout)
+// snd_printk(KERN_ERR "Failure writing to cs5535 codec\n");
}
static unsigned short snd_cs5535audio_codec_read(struct cs5535audio *cs5535au,
@@ -108,9 +108,9 @@
break;
udelay(1);
} while (--timeout);
- if (!timeout)
- snd_printk(KERN_ERR "Failure reading codec reg 0x%x,"
- "Last value=0x%x\n", reg, val);
+// if (!timeout)
+// snd_printk(KERN_ERR "Failure reading codec reg 0x%x,"
+// "Last value=0x%x\n", reg, val);
return (unsigned short) val;
}

View File

@@ -1,11 +0,0 @@
diff -Naur linux-3.10.37.org/drivers/net/wireless/rt2x00/rt2800usb.c linux-3.10.37/drivers/net/wireless/rt2x00/rt2800usb.c
--- linux-3.10.37.org/drivers/net/wireless/rt2x00/rt2800usb.c 2014-04-14 15:42:31.000000000 +0200
+++ linux-3.10.37/drivers/net/wireless/rt2x00/rt2800usb.c 2014-04-25 10:25:12.796630526 +0200
@@ -1175,6 +1175,7 @@
/* Belkin */
{ USB_DEVICE(0x050d, 0x945b) },
/* D-Link */
+ { USB_DEVICE(0x2001, 0x3317) },
{ USB_DEVICE(0x2001, 0x3c17) },
/* Panasonic */
{ USB_DEVICE(0x083a, 0xb511) },

View File

@@ -1,30 +0,0 @@
diff -Naur linux-3.10.55.org/drivers/net/wireless/rt2x00/rt2800usb.c linux-3.10.55/drivers/net/wireless/rt2x00/rt2800usb.c
--- linux-3.10.55.org/drivers/net/wireless/rt2x00/rt2800usb.c 2014-09-17 18:04:18.000000000 +0200
+++ linux-3.10.55/drivers/net/wireless/rt2x00/rt2800usb.c 2014-10-05 19:25:25.070972490 +0200
@@ -128,7 +128,7 @@
tout = time_after(jiffies, entry->last_action + msecs_to_jiffies(100));
if (unlikely(tout))
- rt2x00_warn(entry->queue->rt2x00dev,
+ rt2x00_dbg(entry->queue->rt2x00dev,
"TX status timeout for entry %d in queue %d\n",
entry->entry_idx, entry->queue->qid);
return tout;
@@ -569,7 +569,7 @@
queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
if (unlikely(rt2x00queue_empty(queue))) {
- rt2x00_warn(rt2x00dev, "Got TX status for an empty queue %u, dropping\n",
+ rt2x00_dbg(rt2x00dev, "Got TX status for an empty queue %u, dropping\n",
qid);
break;
}
@@ -578,7 +578,7 @@
if (unlikely(test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
!test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))) {
- rt2x00_warn(rt2x00dev, "Data pending for entry %u in queue %u\n",
+ rt2x00_dbg(rt2x00dev, "Data pending for entry %u in queue %u\n",
entry->entry_idx, qid);
break;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +0,0 @@
diff -Naur linux-3.14.25.org/drivers/net/wireless/rt2x00/rt2800lib.c linux-3.14.25/drivers/net/wireless/rt2x00/rt2800lib.c
--- linux-3.14.25.org/drivers/net/wireless/rt2x00/rt2800lib.c 2014-11-21 18:23:44.000000000 +0100
+++ linux-3.14.25/drivers/net/wireless/rt2x00/rt2800lib.c 2014-12-03 11:30:58.813355413 +0100
@@ -4847,7 +4847,8 @@
rt2x00_set_field32(&reg, TXOP_CTRL_CFG_EXT_CWMIN, 0);
rt2800_register_write(rt2x00dev, TXOP_CTRL_CFG, reg);
- reg = rt2x00_rt(rt2x00dev, RT5592) ? 0x00000082 : 0x00000002;
+// reg = rt2x00_rt(rt2x00dev, RT5592) ? 0x00000082 : 0x00000002;
+ reg = 0x00000002;
rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, reg);
rt2800_register_read(rt2x00dev, TX_RTS_CFG, &reg);

View File

@@ -1,12 +0,0 @@
diff -Naur linux-3.14.25.org/drivers/net/wireless/rt2x00/rt2800lib.c linux-3.14.25/drivers/net/wireless/rt2x00/rt2800lib.c
--- linux-3.14.25.org/drivers/net/wireless/rt2x00/rt2800lib.c 2014-12-03 11:30:58.000000000 +0100
+++ linux-3.14.25/drivers/net/wireless/rt2x00/rt2800lib.c 2014-12-03 12:15:45.743454351 +0100
@@ -1557,7 +1557,7 @@
if (!is_zero_ether_addr((const u8 *)conf->bssid)) {
reg = le32_to_cpu(conf->bssid[1]);
rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_ID_MASK, 3);
- rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_BCN_NUM, 7);
+ rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_BCN_NUM, 0);
conf->bssid[1] = cpu_to_le32(reg);
}

View File

@@ -1,100 +0,0 @@
From 77e3b7f055f824e4d6587faa73bd4aacd0c307e8 Mon Sep 17 00:00:00 2001
From: hayeswang <hayeswang@realtek.com>
Date: Wed, 9 Jul 2014 14:52:51 +0800
Subject: [PATCH] r8169: disable L23
For RTL8411, RTL8111G, RTL8402, RTL8105, and RTL8106, disable the feature
of entering the L2/L3 link state of the PCIe. When the nic starts the process
of entering the L2/L3 link state and the PCI reset occurs before the work
is finished, the work would be queued and continue after the next the PCI
reset occurs. This causes the device stays in L2/L3 link state, and the system
couldn't find the device.
Signed-off-by: Hayes Wang <hayeswang@realtek.com>
Acked-by: Francois Romieu <romieu@fr.zoreil.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/ethernet/realtek/r8169.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 3ff7bc3..b94f658 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -538,6 +538,7 @@ enum rtl_register_content {
MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */
LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */
Jumbo_En0 = (1 << 2), /* 8168 only. Reserved in the 8168b */
+ Rdy_to_L23 = (1 << 1), /* L23 Enable */
Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */
/* Config4 register */
@@ -4897,6 +4898,21 @@ static void rtl_enable_clock_request(struct pci_dev *pdev)
PCI_EXP_LNKCTL_CLKREQ_EN);
}
+static void rtl_pcie_state_l2l3_enable(struct rtl8169_private *tp, bool enable)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+ u8 data;
+
+ data = RTL_R8(Config3);
+
+ if (enable)
+ data |= Rdy_to_L23;
+ else
+ data &= ~Rdy_to_L23;
+
+ RTL_W8(Config3, data);
+}
+
#define R8168_CPCMD_QUIRK_MASK (\
EnableBist | \
Mac_dbgo_oe | \
@@ -5246,6 +5262,7 @@ static void rtl_hw_start_8411(struct rtl8169_private *tp)
};
rtl_hw_start_8168f(tp);
+ rtl_pcie_state_l2l3_enable(tp, false);
rtl_ephy_init(tp, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1));
@@ -5284,6 +5301,8 @@ static void rtl_hw_start_8168g_1(struct rtl8169_private *tp)
rtl_w1w0_eri(tp, 0x2fc, ERIAR_MASK_0001, 0x01, 0x06, ERIAR_EXGMAC);
rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, 0x1000, ERIAR_EXGMAC);
+
+ rtl_pcie_state_l2l3_enable(tp, false);
}
static void rtl_hw_start_8168g_2(struct rtl8169_private *tp)
@@ -5536,6 +5555,8 @@ static void rtl_hw_start_8105e_1(struct rtl8169_private *tp)
RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
rtl_ephy_init(tp, e_info_8105e_1, ARRAY_SIZE(e_info_8105e_1));
+
+ rtl_pcie_state_l2l3_enable(tp, false);
}
static void rtl_hw_start_8105e_2(struct rtl8169_private *tp)
@@ -5571,6 +5592,8 @@ static void rtl_hw_start_8402(struct rtl8169_private *tp)
rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0e00, 0xff00, ERIAR_EXGMAC);
+
+ rtl_pcie_state_l2l3_enable(tp, false);
}
static void rtl_hw_start_8106(struct rtl8169_private *tp)
@@ -5583,6 +5606,8 @@ static void rtl_hw_start_8106(struct rtl8169_private *tp)
RTL_W32(MISC, (RTL_R32(MISC) | DISABLE_LAN_EN) & ~EARLY_TALLY_EN);
RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET);
RTL_W8(DLLPR, RTL_R8(DLLPR) & ~PFM_EN);
+
+ rtl_pcie_state_l2l3_enable(tp, false);
}
static void rtl_hw_start_8101(struct net_device *dev)
--
1.8.5.2

View File

@@ -1,47 +0,0 @@
diff -Naur linux-3.14.43.org/drivers/ata/libata-core.c linux-3.14.43/drivers/ata/libata-core.c
--- linux-3.14.43.org/drivers/ata/libata-core.c 2015-05-17 18:54:01.000000000 +0200
+++ linux-3.14.43/drivers/ata/libata-core.c 2015-07-11 19:15:01.450041507 +0200
@@ -4229,6 +4229,9 @@
{ "Micron_M550*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, },
{ "Crucial_CT*M550SSD*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, },
+ /* devices that don't properly handle TRIM commands */
+ { "SuperSSpeed S238*", NULL, ATA_HORKAGE_NOTRIM, },
+
/*
* Some WD SATA-I drives spin up and down erratically when the link
* is put into the slumber mode. We don't have full list of the
diff -Naur linux-3.14.43.org/drivers/ata/libata-scsi.c linux-3.14.43/drivers/ata/libata-scsi.c
--- linux-3.14.43.org/drivers/ata/libata-scsi.c 2015-05-17 18:54:01.000000000 +0200
+++ linux-3.14.43/drivers/ata/libata-scsi.c 2015-07-11 20:47:22.570021716 +0200
@@ -2510,11 +2513,15 @@
rbuf[14] = (lowest_aligned >> 8) & 0x3f;
rbuf[15] = lowest_aligned;
- if (ata_id_has_trim(args->id)) {
- rbuf[14] |= 0x80; /* TPE */
- if (ata_id_has_zero_after_trim(args->id))
- rbuf[14] |= 0x40; /* TPRZ */
+
+ if (!(dev->horkage & ATA_HORKAGE_NOTRIM)) {
+ if (ata_id_has_trim(args->id)) {
+ rbuf[14] |= 0x80; /* TPE */
+
+ if (ata_id_has_zero_after_trim(args->id))
+ rbuf[14] |= 0x40; /* TPRZ */
+ }
}
}
diff -Naur linux-3.14.43.org/include/linux/libata.h linux-3.14.43/include/linux/libata.h
--- linux-3.14.43.org/include/linux/libata.h 2015-05-17 18:54:01.000000000 +0200
+++ linux-3.14.43/include/linux/libata.h 2015-07-11 19:13:03.190682173 +0200
@@ -421,6 +421,7 @@
ATA_HORKAGE_NO_NCQ_TRIM = (1 << 19), /* don't use queued TRIM */
ATA_HORKAGE_NOLPM = (1 << 20), /* don't use LPM */
ATA_HORKAGE_WD_BROKEN_LPM = (1 << 21), /* some WDs have broken LPM */
+ ATA_HORKAGE_NOTRIM = (1 << 22), /* don't use TRIM */
/* DMA mask for user DMA control: User visible values; DO NOT
renumber */

View File

@@ -1,18 +0,0 @@
diff -Naur linux-3.14.43.org/drivers/ata/libata-core.c linux-3.14.43/drivers/ata/libata-core.c
--- linux-3.14.43.org/drivers/ata/libata-core.c 2015-07-13 17:58:28.126607225 +0200
+++ linux-3.14.43/drivers/ata/libata-core.c 2015-07-13 18:06:07.430782102 +0200
@@ -4225,9 +4225,11 @@
/* devices that don't properly handle queued TRIM commands */
{ "Micron_M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, },
- { "Crucial_CT???M500SSD*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, },
- { "Micron_M550*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, },
- { "Crucial_CT*M550SSD*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, },
+ { "Crucial_CT*M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, },
+ { "Micron_M5[15]0*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM, },
+ { "Crucial_CT*M550*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM, },
+ { "Crucial_CT*MX100*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM, },
+ { "Samsung SSD 8*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, },
/* devices that don't properly handle TRIM commands */
{ "SuperSSpeed S238*", NULL, ATA_HORKAGE_NOTRIM, },

View File

@@ -1,12 +0,0 @@
diff -Naur linux-3.14.65.org/drivers/hwmon/k10temp.c linux-3.14.65/drivers/hwmon/k10temp.c
--- linux-3.14.65.org/drivers/hwmon/k10temp.c 2016-03-16 16:42:30.000000000 +0100
+++ linux-3.14.65/drivers/hwmon/k10temp.c 2016-03-25 15:52:21.920190727 +0100
@@ -212,6 +212,8 @@
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M10H_F3) },
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F3) },
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F3) },
+// { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F3) },
+ { PCI_VDEVICE(AMD, 0x1583) },
{}
};
MODULE_DEVICE_TABLE(pci, k10temp_id_table);

View File

@@ -1,18 +0,0 @@
diff -Naur linux-3.14.77.org/net/ipv4/tcp_input.c linux-3.14.77/net/ipv4/tcp_input.c
--- linux-3.14.77.org/net/ipv4/tcp_input.c 2016-08-21 19:58:45.000000000 +0200
+++ linux-3.14.77/net/ipv4/tcp_input.c 2016-08-21 21:11:24.336757369 +0200
@@ -3299,12 +3299,12 @@
u32 half = (sysctl_tcp_challenge_ack_limit + 1) >> 1;
challenge_timestamp = now;
- ACCESS_ONCE(challenge_count) = half +
+ ACCESS_ONCE_RW(challenge_count) = half +
prandom_u32_max(sysctl_tcp_challenge_ack_limit);
}
count = ACCESS_ONCE(challenge_count);
if (count > 0) {
- ACCESS_ONCE(challenge_count) = count - 1;
+ ACCESS_ONCE_RW(challenge_count) = count - 1;
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK);
tcp_send_ack(sk);
}

View File

@@ -1,16 +0,0 @@
diff -Naur linux-3.14.79.org/drivers/mmc/core/mmc.c linux-3.14.79/drivers/mmc/core/mmc.c
--- linux-3.14.79.org/drivers/mmc/core/mmc.c 2016-09-11 10:00:18.000000000 +0200
+++ linux-3.14.79/drivers/mmc/core/mmc.c 2017-01-19 18:15:07.940781595 +0100
@@ -297,12 +297,6 @@
}
card->ext_csd.rev = ext_csd[EXT_CSD_REV];
- if (card->ext_csd.rev > 7) {
- pr_err("%s: unrecognised EXT_CSD revision %d\n",
- mmc_hostname(card->host), card->ext_csd.rev);
- err = -EINVAL;
- goto out;
- }
card->ext_csd.raw_sectors[0] = ext_csd[EXT_CSD_SEC_CNT + 0];
card->ext_csd.raw_sectors[1] = ext_csd[EXT_CSD_SEC_CNT + 1];

View File

@@ -1,15 +0,0 @@
Patch by Arne Fitzenreiter <arne_f@ipfire.org>
Fix PHYSDEVDRIVER from "Sundance IPG ..." to the modulname (ipg)
diff -Naur linux-3.2.33.org/drivers/net/ethernet/icplus/ipg.c linux-3.2.33/drivers/net/ethernet/icplus/ipg.c
--- linux-3.2.33.org/drivers/net/ethernet/icplus/ipg.c 2012-10-31 00:27:11.000000000 +0100
+++ linux-3.2.33/drivers/net/ethernet/icplus/ipg.c 2012-11-05 20:02:36.529101528 +0100
@@ -2304,7 +2304,7 @@
}
static struct pci_driver ipg_pci_driver = {
- .name = IPG_DRIVER_NAME,
+ .name = DRV_NAME,
.id_table = ipg_pci_tbl,
.probe = ipg_probe,
.remove = __devexit_p(ipg_remove),

View File

@@ -1,46 +0,0 @@
No need to wrap vdso calls as gentoo does not use any version of
glibc <=2.3.3
---
From: Gordon Malm <gengor@gentoo.org>
From: Kerin Millar <kerframil@gmail.com>
From: Jory A. Pratt <anarchy@gentoo.org>
COMPAT_VDSO is inappropriate for any modern Hardened Gentoo system. It
conflicts with various parts of PaX, crashing the system if enabled
while PaX's NOEXEC or UDEREF features are active. Moreover, it prevents
a number of important PaX options from appearing in the configuration
menu, including all PaX NOEXEC implementations. Unfortunately, the
reason for the disappearance of these PaX configuration options is
often far from obvious to inexperienced users.
Therefore, we disable the COMPAT_VDSO menu entry entirely. However,
COMPAT_VDSO operation can still be enabled via bootparam and sysctl
interfaces. Consequently, we must also disable the ability to select
COMPAT_VDSO operation at boot or runtime. Here we patch the kernel so
that selecting COMPAT_VDSO operation at boot/runtime has no effect if
conflicting PaX options are enabled, leaving VDSO_ENABLED operation
intact.
Closes bug: http://bugs.gentoo.org/show_bug.cgi?id=210138
diff -urp a/arch/x86/Kconfig b/arch/x86/Kconfig
--- a/arch/x86/Kconfig 2009-07-31 01:36:57.323857684 +0100
+++ b/arch/x86/Kconfig 2009-07-31 01:51:39.395749681 +0100
@@ -1651,17 +1651,8 @@
config COMPAT_VDSO
def_bool n
- prompt "Compat VDSO support"
depends on X86_32 || IA32_EMULATION
depends on !PAX_PAGEEXEC && !PAX_SEGMEXEC && !PAX_KERNEXEC && !PAX_MEMORY_UDEREF
- ---help---
- Map the 32-bit VDSO to the predictable old-style address too.
-
- Say N here if you are running a sufficiently recent glibc
- version (2.3.3 or later), to remove the high-mapped
- VDSO mapping and to exclusively use the randomized VDSO.
-
- If unsure, say Y.
config CMDLINE_BOOL
bool "Built-in kernel command line"

File diff suppressed because it is too large Load Diff

View File

@@ -1,47 +0,0 @@
From 88c9281a9fba67636ab26c1fd6afbc78a632374f Mon Sep 17 00:00:00 2001
From: Vitaly Kuznetsov <vkuznets@redhat.com>
Date: Wed, 19 Aug 2015 09:54:24 -0700
Subject: x86/hyperv: Mark the Hyper-V TSC as unstable
The Hyper-V top-level functional specification states, that
"algorithms should be resilient to sudden jumps forward or
backward in the TSC value", this means that we should consider
TSC as unstable. In some cases tsc tests are able to detect the
instability, it was detected in 543 out of 646 boots in my
testing:
Measured 6277 cycles TSC warp between CPUs, turning off TSC clock.
tsc: Marking TSC unstable due to check_tsc_sync_source failed
This is, however, just a heuristic. On Hyper-V platform there
are two good clocksources: MSR-based hyperv_clocksource and
recently introduced TSC page.
Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Cc: Haiyang Zhang <haiyangz@microsoft.com>
Cc: K. Y. Srinivasan <kys@microsoft.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: devel@linuxdriverproject.org
Link: http://lkml.kernel.org/r/1440003264-9949-1-git-send-email-vkuznets@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
arch/x86/kernel/cpu/mshyperv.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index aad4bd8..6fd023d 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -141,6 +141,7 @@ static void __init ms_hyperv_init_platform(void)
no_timer_check = 1;
#endif
+ mark_tsc_unstable("running on Hyper-V");
}
const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
--
cgit v0.12

View File

@@ -1,129 +0,0 @@
From f3f885fa684ff18fa4d223dc22b782f5e5d32560 Mon Sep 17 00:00:00 2001
From: KY Srinivasan <kys@microsoft.com>
Date: Sun, 16 Feb 2014 16:38:43 -0800
Subject: [PATCH 01/25] Drivers: net: hyperv: Get rid of the
rndis_filter_packet structure
This structure is redundant; get rid of it make the code little more efficient -
get rid of the unnecessary indirection.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/hyperv/hyperv_net.h | 6 ------
drivers/net/hyperv/netvsc_drv.c | 2 +-
drivers/net/hyperv/rndis_filter.c | 41 +++------------------------------------
3 files changed, 4 insertions(+), 45 deletions(-)
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 7b594ce3f21d..7645ba38bde8 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -846,12 +846,6 @@ struct rndis_message {
};
-struct rndis_filter_packet {
- void *completion_ctx;
- void (*completion)(void *context);
- struct rndis_message msg;
-};
-
/* Handy macros */
/* get the size of an RNDIS message. Pass in the message type, */
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 3c1c33ceffba..28020f83ba6f 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -156,7 +156,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
/* Allocate a netvsc packet based on # of frags. */
packet = kzalloc(sizeof(struct hv_netvsc_packet) +
(num_pages * sizeof(struct hv_page_buffer)) +
- sizeof(struct rndis_filter_packet) +
+ sizeof(struct rndis_message) +
NDIS_VLAN_PPI_SIZE, GFP_ATOMIC);
if (!packet) {
/* out of memory, drop packet */
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index b54fd257652b..6a9f6021f09c 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -58,9 +58,6 @@ struct rndis_request {
u8 request_ext[RNDIS_EXT_LEN];
};
-static void rndis_filter_send_completion(void *ctx);
-
-
static struct rndis_device *get_rndis_device(void)
{
struct rndis_device *device;
@@ -297,7 +294,7 @@ static void rndis_filter_receive_response(struct rndis_device *dev,
"rndis response buffer overflow "
"detected (size %u max %zu)\n",
resp->msg_len,
- sizeof(struct rndis_filter_packet));
+ sizeof(struct rndis_message));
if (resp->ndis_msg_type ==
RNDIS_MSG_RESET_C) {
@@ -917,17 +914,14 @@ int rndis_filter_close(struct hv_device *dev)
int rndis_filter_send(struct hv_device *dev,
struct hv_netvsc_packet *pkt)
{
- int ret;
- struct rndis_filter_packet *filter_pkt;
struct rndis_message *rndis_msg;
struct rndis_packet *rndis_pkt;
u32 rndis_msg_size;
bool isvlan = pkt->vlan_tci & VLAN_TAG_PRESENT;
/* Add the rndis header */
- filter_pkt = (struct rndis_filter_packet *)pkt->extension;
+ rndis_msg = (struct rndis_message *)pkt->extension;
- rndis_msg = &filter_pkt->msg;
rndis_msg_size = RNDIS_MESSAGE_SIZE(struct rndis_packet);
if (isvlan)
rndis_msg_size += NDIS_VLAN_PPI_SIZE;
@@ -980,34 +974,5 @@ int rndis_filter_send(struct hv_device *dev,
pkt->page_buf[1].len = rndis_msg_size - pkt->page_buf[0].len;
}
- /* Save the packet send completion and context */
- filter_pkt->completion = pkt->completion.send.send_completion;
- filter_pkt->completion_ctx =
- pkt->completion.send.send_completion_ctx;
-
- /* Use ours */
- pkt->completion.send.send_completion = rndis_filter_send_completion;
- pkt->completion.send.send_completion_ctx = filter_pkt;
-
- ret = netvsc_send(dev, pkt);
- if (ret != 0) {
- /*
- * Reset the completion to originals to allow retries from
- * above
- */
- pkt->completion.send.send_completion =
- filter_pkt->completion;
- pkt->completion.send.send_completion_ctx =
- filter_pkt->completion_ctx;
- }
-
- return ret;
-}
-
-static void rndis_filter_send_completion(void *ctx)
-{
- struct rndis_filter_packet *filter_pkt = ctx;
-
- /* Pass it back to the original handler */
- filter_pkt->completion(filter_pkt->completion_ctx);
+ return netvsc_send(dev, pkt);
}
--
2.4.3

View File

@@ -1,917 +0,0 @@
From 5b54dac856cb5bd6f33f4159012773e4a33704f7 Mon Sep 17 00:00:00 2001
From: Haiyang Zhang <haiyangz@microsoft.com>
Date: Mon, 21 Apr 2014 10:20:28 -0700
Subject: [PATCH 01/11] hyperv: Add support for virtual Receive Side Scaling
(vRSS)
This feature allows multiple channels to be used by each virtual NIC.
It is available on Hyper-V host 2012 R2.
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/hyperv/hyperv_net.h | 110 +++++++++++++++++++++-
drivers/net/hyperv/netvsc.c | 136 +++++++++++++++++++++------
drivers/net/hyperv/netvsc_drv.c | 103 ++++++++++++++++++++-
drivers/net/hyperv/rndis_filter.c | 189 +++++++++++++++++++++++++++++++++++++-
4 files changed, 504 insertions(+), 34 deletions(-)
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index d18f711d0b0c..57eb3f906d64 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -28,6 +28,96 @@
#include <linux/hyperv.h>
#include <linux/rndis.h>
+/* RSS related */
+#define OID_GEN_RECEIVE_SCALE_CAPABILITIES 0x00010203 /* query only */
+#define OID_GEN_RECEIVE_SCALE_PARAMETERS 0x00010204 /* query and set */
+
+#define NDIS_OBJECT_TYPE_RSS_CAPABILITIES 0x88
+#define NDIS_OBJECT_TYPE_RSS_PARAMETERS 0x89
+
+#define NDIS_RECEIVE_SCALE_CAPABILITIES_REVISION_2 2
+#define NDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2 2
+
+struct ndis_obj_header {
+ u8 type;
+ u8 rev;
+ u16 size;
+} __packed;
+
+/* ndis_recv_scale_cap/cap_flag */
+#define NDIS_RSS_CAPS_MESSAGE_SIGNALED_INTERRUPTS 0x01000000
+#define NDIS_RSS_CAPS_CLASSIFICATION_AT_ISR 0x02000000
+#define NDIS_RSS_CAPS_CLASSIFICATION_AT_DPC 0x04000000
+#define NDIS_RSS_CAPS_USING_MSI_X 0x08000000
+#define NDIS_RSS_CAPS_RSS_AVAILABLE_ON_PORTS 0x10000000
+#define NDIS_RSS_CAPS_SUPPORTS_MSI_X 0x20000000
+#define NDIS_RSS_CAPS_HASH_TYPE_TCP_IPV4 0x00000100
+#define NDIS_RSS_CAPS_HASH_TYPE_TCP_IPV6 0x00000200
+#define NDIS_RSS_CAPS_HASH_TYPE_TCP_IPV6_EX 0x00000400
+
+struct ndis_recv_scale_cap { /* NDIS_RECEIVE_SCALE_CAPABILITIES */
+ struct ndis_obj_header hdr;
+ u32 cap_flag;
+ u32 num_int_msg;
+ u32 num_recv_que;
+ u16 num_indirect_tabent;
+} __packed;
+
+
+/* ndis_recv_scale_param flags */
+#define NDIS_RSS_PARAM_FLAG_BASE_CPU_UNCHANGED 0x0001
+#define NDIS_RSS_PARAM_FLAG_HASH_INFO_UNCHANGED 0x0002
+#define NDIS_RSS_PARAM_FLAG_ITABLE_UNCHANGED 0x0004
+#define NDIS_RSS_PARAM_FLAG_HASH_KEY_UNCHANGED 0x0008
+#define NDIS_RSS_PARAM_FLAG_DISABLE_RSS 0x0010
+
+/* Hash info bits */
+#define NDIS_HASH_FUNC_TOEPLITZ 0x00000001
+#define NDIS_HASH_IPV4 0x00000100
+#define NDIS_HASH_TCP_IPV4 0x00000200
+#define NDIS_HASH_IPV6 0x00000400
+#define NDIS_HASH_IPV6_EX 0x00000800
+#define NDIS_HASH_TCP_IPV6 0x00001000
+#define NDIS_HASH_TCP_IPV6_EX 0x00002000
+
+#define NDIS_RSS_INDIRECTION_TABLE_MAX_SIZE_REVISION_2 (128 * 4)
+#define NDIS_RSS_HASH_SECRET_KEY_MAX_SIZE_REVISION_2 40
+
+#define ITAB_NUM 128
+#define HASH_KEYLEN NDIS_RSS_HASH_SECRET_KEY_MAX_SIZE_REVISION_2
+extern u8 netvsc_hash_key[];
+
+struct ndis_recv_scale_param { /* NDIS_RECEIVE_SCALE_PARAMETERS */
+ struct ndis_obj_header hdr;
+
+ /* Qualifies the rest of the information */
+ u16 flag;
+
+ /* The base CPU number to do receive processing. not used */
+ u16 base_cpu_number;
+
+ /* This describes the hash function and type being enabled */
+ u32 hashinfo;
+
+ /* The size of indirection table array */
+ u16 indirect_tabsize;
+
+ /* The offset of the indirection table from the beginning of this
+ * structure
+ */
+ u32 indirect_taboffset;
+
+ /* The size of the hash secret key */
+ u16 hashkey_size;
+
+ /* The offset of the secret key from the beginning of this structure */
+ u32 kashkey_offset;
+
+ u32 processor_masks_offset;
+ u32 num_processor_masks;
+ u32 processor_masks_entry_size;
+};
+
/* Fwd declaration */
struct hv_netvsc_packet;
struct ndis_tcp_ip_checksum_info;
@@ -39,6 +129,8 @@ struct xferpage_packet {
/* # of netvsc packets this xfer packet contains */
u32 count;
+
+ struct vmbus_channel *channel;
};
/*
@@ -54,6 +146,9 @@ struct hv_netvsc_packet {
bool is_data_pkt;
u16 vlan_tci;
+ u16 q_idx;
+ struct vmbus_channel *channel;
+
/*
* Valid only for receives when we break a xfer page packet
* into multiple netvsc packets
@@ -120,6 +215,7 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj,
int netvsc_recv_callback(struct hv_device *device_obj,
struct hv_netvsc_packet *packet,
struct ndis_tcp_ip_checksum_info *csum_info);
+void netvsc_channel_cb(void *context);
int rndis_filter_open(struct hv_device *dev);
int rndis_filter_close(struct hv_device *dev);
int rndis_filter_device_add(struct hv_device *dev,
@@ -522,6 +618,8 @@ struct nvsp_message {
#define NETVSC_PACKET_SIZE 2048
+#define VRSS_SEND_TAB_SIZE 16
+
/* Per netvsc channel-specific */
struct netvsc_device {
struct hv_device *dev;
@@ -555,10 +653,20 @@ struct netvsc_device {
struct net_device *ndev;
+ struct vmbus_channel *chn_table[NR_CPUS];
+ u32 send_table[VRSS_SEND_TAB_SIZE];
+ u32 num_chn;
+ atomic_t queue_sends[NR_CPUS];
+
/* Holds rndis device info */
void *extension;
- /* The recive buffer for this device */
+
+ int ring_size;
+
+ /* The primary channel callback buffer */
unsigned char cb_buffer[NETVSC_PACKET_SIZE];
+ /* The sub channel callback buffer */
+ unsigned char *sub_cb_buf;
};
/* NdisInitialize message */
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index f7629ecefa84..e7e77f12bc38 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -422,6 +422,9 @@ int netvsc_device_remove(struct hv_device *device)
kfree(netvsc_packet);
}
+ if (net_device->sub_cb_buf)
+ vfree(net_device->sub_cb_buf);
+
kfree(net_device);
return 0;
}
@@ -461,7 +464,9 @@ static void netvsc_send_completion(struct netvsc_device *net_device,
(nvsp_packet->hdr.msg_type ==
NVSP_MSG1_TYPE_SEND_RECV_BUF_COMPLETE) ||
(nvsp_packet->hdr.msg_type ==
- NVSP_MSG1_TYPE_SEND_SEND_BUF_COMPLETE)) {
+ NVSP_MSG1_TYPE_SEND_SEND_BUF_COMPLETE) ||
+ (nvsp_packet->hdr.msg_type ==
+ NVSP_MSG5_TYPE_SUBCHANNEL)) {
/* Copy the response back */
memcpy(&net_device->channel_init_pkt, nvsp_packet,
sizeof(struct nvsp_message));
@@ -469,28 +474,37 @@ static void netvsc_send_completion(struct netvsc_device *net_device,
} else if (nvsp_packet->hdr.msg_type ==
NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE) {
int num_outstanding_sends;
+ u16 q_idx = 0;
+ struct vmbus_channel *channel = device->channel;
+ int queue_sends;
/* Get the send context */
nvsc_packet = (struct hv_netvsc_packet *)(unsigned long)
packet->trans_id;
/* Notify the layer above us */
- if (nvsc_packet)
+ if (nvsc_packet) {
+ q_idx = nvsc_packet->q_idx;
+ channel = nvsc_packet->channel;
nvsc_packet->completion.send.send_completion(
nvsc_packet->completion.send.
send_completion_ctx);
+ }
num_outstanding_sends =
atomic_dec_return(&net_device->num_outstanding_sends);
+ queue_sends = atomic_dec_return(&net_device->
+ queue_sends[q_idx]);
if (net_device->destroy && num_outstanding_sends == 0)
wake_up(&net_device->wait_drain);
- if (netif_queue_stopped(ndev) && !net_device->start_remove &&
- (hv_ringbuf_avail_percent(&device->channel->outbound)
- > RING_AVAIL_PERCENT_HIWATER ||
- num_outstanding_sends < 1))
- netif_wake_queue(ndev);
+ if (netif_tx_queue_stopped(netdev_get_tx_queue(ndev, q_idx)) &&
+ !net_device->start_remove &&
+ (hv_ringbuf_avail_percent(&channel->outbound) >
+ RING_AVAIL_PERCENT_HIWATER || queue_sends < 1))
+ netif_tx_wake_queue(netdev_get_tx_queue(
+ ndev, q_idx));
} else {
netdev_err(ndev, "Unknown send completion packet type- "
"%d received!!\n", nvsp_packet->hdr.msg_type);
@@ -505,6 +519,7 @@ int netvsc_send(struct hv_device *device,
int ret = 0;
struct nvsp_message sendMessage;
struct net_device *ndev;
+ struct vmbus_channel *out_channel = NULL;
u64 req_id;
net_device = get_outbound_net_device(device);
@@ -531,15 +546,20 @@ int netvsc_send(struct hv_device *device,
else
req_id = 0;
+ out_channel = net_device->chn_table[packet->q_idx];
+ if (out_channel == NULL)
+ out_channel = device->channel;
+ packet->channel = out_channel;
+
if (packet->page_buf_cnt) {
- ret = vmbus_sendpacket_pagebuffer(device->channel,
+ ret = vmbus_sendpacket_pagebuffer(out_channel,
packet->page_buf,
packet->page_buf_cnt,
&sendMessage,
sizeof(struct nvsp_message),
req_id);
} else {
- ret = vmbus_sendpacket(device->channel, &sendMessage,
+ ret = vmbus_sendpacket(out_channel, &sendMessage,
sizeof(struct nvsp_message),
req_id,
VM_PKT_DATA_INBAND,
@@ -548,17 +568,24 @@ int netvsc_send(struct hv_device *device,
if (ret == 0) {
atomic_inc(&net_device->num_outstanding_sends);
- if (hv_ringbuf_avail_percent(&device->channel->outbound) <
+ atomic_inc(&net_device->queue_sends[packet->q_idx]);
+
+ if (hv_ringbuf_avail_percent(&out_channel->outbound) <
RING_AVAIL_PERCENT_LOWATER) {
- netif_stop_queue(ndev);
+ netif_tx_stop_queue(netdev_get_tx_queue(
+ ndev, packet->q_idx));
+
if (atomic_read(&net_device->
- num_outstanding_sends) < 1)
- netif_wake_queue(ndev);
+ queue_sends[packet->q_idx]) < 1)
+ netif_tx_wake_queue(netdev_get_tx_queue(
+ ndev, packet->q_idx));
}
} else if (ret == -EAGAIN) {
- netif_stop_queue(ndev);
- if (atomic_read(&net_device->num_outstanding_sends) < 1) {
- netif_wake_queue(ndev);
+ netif_tx_stop_queue(netdev_get_tx_queue(
+ ndev, packet->q_idx));
+ if (atomic_read(&net_device->queue_sends[packet->q_idx]) < 1) {
+ netif_tx_wake_queue(netdev_get_tx_queue(
+ ndev, packet->q_idx));
ret = -ENOSPC;
}
} else {
@@ -570,6 +597,7 @@ int netvsc_send(struct hv_device *device,
}
static void netvsc_send_recv_completion(struct hv_device *device,
+ struct vmbus_channel *channel,
struct netvsc_device *net_device,
u64 transaction_id, u32 status)
{
@@ -587,7 +615,7 @@ static void netvsc_send_recv_completion(struct hv_device *device,
retry_send_cmplt:
/* Send the completion */
- ret = vmbus_sendpacket(device->channel, &recvcompMessage,
+ ret = vmbus_sendpacket(channel, &recvcompMessage,
sizeof(struct nvsp_message), transaction_id,
VM_PKT_COMP, 0);
if (ret == 0) {
@@ -618,6 +646,7 @@ static void netvsc_receive_completion(void *context)
{
struct hv_netvsc_packet *packet = context;
struct hv_device *device = packet->device;
+ struct vmbus_channel *channel;
struct netvsc_device *net_device;
u64 transaction_id = 0;
bool fsend_receive_comp = false;
@@ -649,6 +678,7 @@ static void netvsc_receive_completion(void *context)
*/
if (packet->xfer_page_pkt->count == 0) {
fsend_receive_comp = true;
+ channel = packet->xfer_page_pkt->channel;
transaction_id = packet->completion.recv.recv_completion_tid;
status = packet->xfer_page_pkt->status;
list_add_tail(&packet->xfer_page_pkt->list_ent,
@@ -662,12 +692,13 @@ static void netvsc_receive_completion(void *context)
/* Send a receive completion for the xfer page packet */
if (fsend_receive_comp)
- netvsc_send_recv_completion(device, net_device, transaction_id,
- status);
+ netvsc_send_recv_completion(device, channel, net_device,
+ transaction_id, status);
}
static void netvsc_receive(struct netvsc_device *net_device,
+ struct vmbus_channel *channel,
struct hv_device *device,
struct vmpacket_descriptor *packet)
{
@@ -748,7 +779,7 @@ static void netvsc_receive(struct netvsc_device *net_device,
spin_unlock_irqrestore(&net_device->recv_pkt_list_lock,
flags);
- netvsc_send_recv_completion(device, net_device,
+ netvsc_send_recv_completion(device, channel, net_device,
vmxferpage_packet->d.trans_id,
NVSP_STAT_FAIL);
@@ -759,6 +790,7 @@ static void netvsc_receive(struct netvsc_device *net_device,
xferpage_packet = (struct xferpage_packet *)listHead.next;
list_del(&xferpage_packet->list_ent);
xferpage_packet->status = NVSP_STAT_SUCCESS;
+ xferpage_packet->channel = channel;
/* This is how much we can satisfy */
xferpage_packet->count = count - 1;
@@ -800,10 +832,45 @@ static void netvsc_receive(struct netvsc_device *net_device,
}
-static void netvsc_channel_cb(void *context)
+
+static void netvsc_send_table(struct hv_device *hdev,
+ struct vmpacket_descriptor *vmpkt)
+{
+ struct netvsc_device *nvscdev;
+ struct net_device *ndev;
+ struct nvsp_message *nvmsg;
+ int i;
+ u32 count, *tab;
+
+ nvscdev = get_outbound_net_device(hdev);
+ if (!nvscdev)
+ return;
+ ndev = nvscdev->ndev;
+
+ nvmsg = (struct nvsp_message *)((unsigned long)vmpkt +
+ (vmpkt->offset8 << 3));
+
+ if (nvmsg->hdr.msg_type != NVSP_MSG5_TYPE_SEND_INDIRECTION_TABLE)
+ return;
+
+ count = nvmsg->msg.v5_msg.send_table.count;
+ if (count != VRSS_SEND_TAB_SIZE) {
+ netdev_err(ndev, "Received wrong send-table size:%u\n", count);
+ return;
+ }
+
+ tab = (u32 *)((unsigned long)&nvmsg->msg.v5_msg.send_table +
+ nvmsg->msg.v5_msg.send_table.offset);
+
+ for (i = 0; i < count; i++)
+ nvscdev->send_table[i] = tab[i];
+}
+
+void netvsc_channel_cb(void *context)
{
int ret;
- struct hv_device *device = context;
+ struct vmbus_channel *channel = (struct vmbus_channel *)context;
+ struct hv_device *device;
struct netvsc_device *net_device;
u32 bytes_recvd;
u64 request_id;
@@ -812,14 +879,19 @@ static void netvsc_channel_cb(void *context)
int bufferlen = NETVSC_PACKET_SIZE;
struct net_device *ndev;
+ if (channel->primary_channel != NULL)
+ device = channel->primary_channel->device_obj;
+ else
+ device = channel->device_obj;
+
net_device = get_inbound_net_device(device);
if (!net_device)
return;
ndev = net_device->ndev;
- buffer = net_device->cb_buffer;
+ buffer = get_per_channel_state(channel);
do {
- ret = vmbus_recvpacket_raw(device->channel, buffer, bufferlen,
+ ret = vmbus_recvpacket_raw(channel, buffer, bufferlen,
&bytes_recvd, &request_id);
if (ret == 0) {
if (bytes_recvd > 0) {
@@ -831,8 +903,12 @@ static void netvsc_channel_cb(void *context)
break;
case VM_PKT_DATA_USING_XFER_PAGES:
- netvsc_receive(net_device,
- device, desc);
+ netvsc_receive(net_device, channel,
+ device, desc);
+ break;
+
+ case VM_PKT_DATA_INBAND:
+ netvsc_send_table(device, desc);
break;
default:
@@ -893,6 +969,8 @@ int netvsc_device_add(struct hv_device *device, void *additional_info)
goto cleanup;
}
+ net_device->ring_size = ring_size;
+
/*
* Coming into this function, struct net_device * is
* registered as the driver private data.
@@ -917,10 +995,12 @@ int netvsc_device_add(struct hv_device *device, void *additional_info)
}
init_completion(&net_device->channel_init_wait);
+ set_per_channel_state(device->channel, net_device->cb_buffer);
+
/* Open the channel */
ret = vmbus_open(device->channel, ring_size * PAGE_SIZE,
ring_size * PAGE_SIZE, NULL, 0,
- netvsc_channel_cb, device);
+ netvsc_channel_cb, device->channel);
if (ret != 0) {
netdev_err(ndev, "unable to open channel: %d\n", ret);
@@ -930,6 +1010,8 @@ int netvsc_device_add(struct hv_device *device, void *additional_info)
/* Channel is opened */
pr_info("hv_netvsc channel opened successfully\n");
+ net_device->chn_table[0] = device->channel;
+
/* Connect with the NetVsp */
ret = netvsc_connect_vsp(device);
if (ret != 0) {
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 31e55fba7cad..093cf3fc46b8 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -101,7 +101,7 @@ static int netvsc_open(struct net_device *net)
return ret;
}
- netif_start_queue(net);
+ netif_tx_start_all_queues(net);
nvdev = hv_get_drvdata(device_obj);
rdev = nvdev->extension;
@@ -149,6 +149,88 @@ static void *init_ppi_data(struct rndis_message *msg, u32 ppi_size,
return ppi;
}
+union sub_key {
+ u64 k;
+ struct {
+ u8 pad[3];
+ u8 kb;
+ u32 ka;
+ };
+};
+
+/* Toeplitz hash function
+ * data: network byte order
+ * return: host byte order
+ */
+static u32 comp_hash(u8 *key, int klen, u8 *data, int dlen)
+{
+ union sub_key subk;
+ int k_next = 4;
+ u8 dt;
+ int i, j;
+ u32 ret = 0;
+
+ subk.k = 0;
+ subk.ka = ntohl(*(u32 *)key);
+
+ for (i = 0; i < dlen; i++) {
+ subk.kb = key[k_next];
+ k_next = (k_next + 1) % klen;
+ dt = data[i];
+ for (j = 0; j < 8; j++) {
+ if (dt & 0x80)
+ ret ^= subk.ka;
+ dt <<= 1;
+ subk.k <<= 1;
+ }
+ }
+
+ return ret;
+}
+
+static bool netvsc_set_hash(u32 *hash, struct sk_buff *skb)
+{
+ struct iphdr *iphdr;
+ int data_len;
+ bool ret = false;
+
+ if (eth_hdr(skb)->h_proto != htons(ETH_P_IP))
+ return false;
+
+ iphdr = ip_hdr(skb);
+
+ if (iphdr->version == 4) {
+ if (iphdr->protocol == IPPROTO_TCP)
+ data_len = 12;
+ else
+ data_len = 8;
+ *hash = comp_hash(netvsc_hash_key, HASH_KEYLEN,
+ (u8 *)&iphdr->saddr, data_len);
+ ret = true;
+ }
+
+ return ret;
+}
+
+static u16 netvsc_select_queue(struct net_device *ndev, struct sk_buff *skb,
+ void *accel_priv, select_queue_fallback_t fallback)
+{
+ struct net_device_context *net_device_ctx = netdev_priv(ndev);
+ struct hv_device *hdev = net_device_ctx->device_ctx;
+ struct netvsc_device *nvsc_dev = hv_get_drvdata(hdev);
+ u32 hash;
+ u16 q_idx = 0;
+
+ if (nvsc_dev == NULL || ndev->real_num_tx_queues <= 1)
+ return 0;
+
+ if (netvsc_set_hash(&hash, skb))
+ q_idx = nvsc_dev->send_table[hash % VRSS_SEND_TAB_SIZE] %
+ ndev->real_num_tx_queues;
+
+ return q_idx;
+}
+
static void netvsc_xmit_completion(void *context)
{
struct hv_netvsc_packet *packet = (struct hv_netvsc_packet *)context;
@@ -333,6 +415,8 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
packet->vlan_tci = skb->vlan_tci;
+ packet->q_idx = skb_get_queue_mapping(skb);
+
packet->is_data_pkt = true;
packet->total_data_buflen = skb->len;
@@ -554,6 +638,10 @@ int netvsc_recv_callback(struct hv_device *device_obj,
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
packet->vlan_tci);
+ skb_record_rx_queue(skb, packet->xfer_page_pkt->channel->
+ offermsg.offer.sub_channel_index %
+ net->real_num_rx_queues);
+
net->stats.rx_packets++;
net->stats.rx_bytes += packet->total_data_buflen;
@@ -602,7 +690,7 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
hv_set_drvdata(hdev, ndev);
device_info.ring_size = ring_size;
rndis_filter_device_add(hdev, &device_info);
- netif_wake_queue(ndev);
+ netif_tx_wake_all_queues(ndev);
return 0;
}
@@ -648,6 +736,7 @@ static const struct net_device_ops device_ops = {
.ndo_change_mtu = netvsc_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = netvsc_set_mac_addr,
+ .ndo_select_queue = netvsc_select_queue,
};
/*
@@ -694,9 +783,11 @@ static int netvsc_probe(struct hv_device *dev,
struct net_device *net = NULL;
struct net_device_context *net_device_ctx;
struct netvsc_device_info device_info;
+ struct netvsc_device *nvdev;
int ret;
- net = alloc_etherdev(sizeof(struct net_device_context));
+ net = alloc_etherdev_mq(sizeof(struct net_device_context),
+ num_online_cpus());
if (!net)
return -ENOMEM;
@@ -729,6 +820,12 @@ static int netvsc_probe(struct hv_device *dev,
}
memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN);
+ nvdev = hv_get_drvdata(dev);
+ netif_set_real_num_tx_queues(net, nvdev->num_chn);
+ netif_set_real_num_rx_queues(net, nvdev->num_chn);
+ dev_info(&dev->device, "real num tx,rx queues:%u, %u\n",
+ net->real_num_tx_queues, net->real_num_rx_queues);
+
ret = register_netdev(net);
if (ret != 0) {
pr_err("Unable to register netdev.\n");
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 143a98caf618..d92cfbe43410 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -31,7 +31,7 @@
#include "hyperv_net.h"
-#define RNDIS_EXT_LEN 100
+#define RNDIS_EXT_LEN PAGE_SIZE
struct rndis_request {
struct list_head list_ent;
struct completion wait_event;
@@ -94,6 +94,8 @@ static struct rndis_request *get_rndis_request(struct rndis_device *dev,
rndis_msg->ndis_msg_type = msg_type;
rndis_msg->msg_len = msg_len;
+ request->pkt.q_idx = 0;
+
/*
* Set the request id. This field is always after the rndis header for
* request/response packet types so we just used the SetRequest as a
@@ -509,6 +511,19 @@ static int rndis_filter_query_device(struct rndis_device *dev, u32 oid,
query->info_buflen = 0;
query->dev_vc_handle = 0;
+ if (oid == OID_GEN_RECEIVE_SCALE_CAPABILITIES) {
+ struct ndis_recv_scale_cap *cap;
+
+ request->request_msg.msg_len +=
+ sizeof(struct ndis_recv_scale_cap);
+ query->info_buflen = sizeof(struct ndis_recv_scale_cap);
+ cap = (struct ndis_recv_scale_cap *)((unsigned long)query +
+ query->info_buf_offset);
+ cap->hdr.type = NDIS_OBJECT_TYPE_RSS_CAPABILITIES;
+ cap->hdr.rev = NDIS_RECEIVE_SCALE_CAPABILITIES_REVISION_2;
+ cap->hdr.size = sizeof(struct ndis_recv_scale_cap);
+ }
+
ret = rndis_filter_send_request(dev, request);
if (ret != 0)
goto cleanup;
@@ -695,6 +710,89 @@ cleanup:
return ret;
}
+u8 netvsc_hash_key[HASH_KEYLEN] = {
+ 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
+ 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
+ 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
+ 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
+ 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa
+};
+
+int rndis_filter_set_rss_param(struct rndis_device *rdev, int num_queue)
+{
+ struct net_device *ndev = rdev->net_dev->ndev;
+ struct rndis_request *request;
+ struct rndis_set_request *set;
+ struct rndis_set_complete *set_complete;
+ u32 extlen = sizeof(struct ndis_recv_scale_param) +
+ 4*ITAB_NUM + HASH_KEYLEN;
+ struct ndis_recv_scale_param *rssp;
+ u32 *itab;
+ u8 *keyp;
+ int i, t, ret;
+
+ request = get_rndis_request(
+ rdev, RNDIS_MSG_SET,
+ RNDIS_MESSAGE_SIZE(struct rndis_set_request) + extlen);
+ if (!request)
+ return -ENOMEM;
+
+ set = &request->request_msg.msg.set_req;
+ set->oid = OID_GEN_RECEIVE_SCALE_PARAMETERS;
+ set->info_buflen = extlen;
+ set->info_buf_offset = sizeof(struct rndis_set_request);
+ set->dev_vc_handle = 0;
+
+ rssp = (struct ndis_recv_scale_param *)(set + 1);
+ rssp->hdr.type = NDIS_OBJECT_TYPE_RSS_PARAMETERS;
+ rssp->hdr.rev = NDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2;
+ rssp->hdr.size = sizeof(struct ndis_recv_scale_param);
+ rssp->flag = 0;
+ rssp->hashinfo = NDIS_HASH_FUNC_TOEPLITZ | NDIS_HASH_IPV4 |
+ NDIS_HASH_TCP_IPV4;
+ rssp->indirect_tabsize = 4*ITAB_NUM;
+ rssp->indirect_taboffset = sizeof(struct ndis_recv_scale_param);
+ rssp->hashkey_size = HASH_KEYLEN;
+ rssp->kashkey_offset = rssp->indirect_taboffset +
+ rssp->indirect_tabsize;
+
+ /* Set indirection table entries */
+ itab = (u32 *)(rssp + 1);
+ for (i = 0; i < ITAB_NUM; i++)
+ itab[i] = i % num_queue;
+
+ /* Set hask key values */
+ keyp = (u8 *)((unsigned long)rssp + rssp->kashkey_offset);
+ for (i = 0; i < HASH_KEYLEN; i++)
+ keyp[i] = netvsc_hash_key[i];
+
+
+ ret = rndis_filter_send_request(rdev, request);
+ if (ret != 0)
+ goto cleanup;
+
+ t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
+ if (t == 0) {
+ netdev_err(ndev, "timeout before we got a set response...\n");
+ /* can't put_rndis_request, since we may still receive a
+ * send-completion.
+ */
+ return -ETIMEDOUT;
+ } else {
+ set_complete = &request->response_msg.msg.set_complete;
+ if (set_complete->status != RNDIS_STATUS_SUCCESS) {
+ netdev_err(ndev, "Fail to set RSS parameters:0x%x\n",
+ set_complete->status);
+ ret = -EINVAL;
+ }
+ }
+
+cleanup:
+ put_rndis_request(rdev, request);
+ return ret;
+}
+
+
static int rndis_filter_query_device_link_status(struct rndis_device *dev)
{
u32 size = sizeof(u32);
@@ -886,6 +984,28 @@ static int rndis_filter_close_device(struct rndis_device *dev)
return ret;
}
+static void netvsc_sc_open(struct vmbus_channel *new_sc)
+{
+ struct netvsc_device *nvscdev;
+ u16 chn_index = new_sc->offermsg.offer.sub_channel_index;
+ int ret;
+
+ nvscdev = hv_get_drvdata(new_sc->primary_channel->device_obj);
+
+ if (chn_index >= nvscdev->num_chn)
+ return;
+
+ set_per_channel_state(new_sc, nvscdev->sub_cb_buf + (chn_index - 1) *
+ NETVSC_PACKET_SIZE);
+
+ ret = vmbus_open(new_sc, nvscdev->ring_size * PAGE_SIZE,
+ nvscdev->ring_size * PAGE_SIZE, NULL, 0,
+ netvsc_channel_cb, new_sc);
+
+ if (ret == 0)
+ nvscdev->chn_table[chn_index] = new_sc;
+}
+
int rndis_filter_device_add(struct hv_device *dev,
void *additional_info)
{
@@ -894,6 +1014,10 @@ int rndis_filter_device_add(struct hv_device *dev,
struct rndis_device *rndis_device;
struct netvsc_device_info *device_info = additional_info;
struct ndis_offload_params offloads;
+ struct nvsp_message *init_packet;
+ int t;
+ struct ndis_recv_scale_cap rsscap;
+ u32 rsscap_size = sizeof(struct ndis_recv_scale_cap);
rndis_device = get_rndis_device();
if (!rndis_device)
@@ -913,6 +1037,7 @@ int rndis_filter_device_add(struct hv_device *dev,
/* Initialize the rndis device */
net_device = hv_get_drvdata(dev);
+ net_device->num_chn = 1;
net_device->extension = rndis_device;
rndis_device->net_dev = net_device;
@@ -952,7 +1077,6 @@ int rndis_filter_device_add(struct hv_device *dev,
if (ret)
goto err_dev_remv;
-
rndis_filter_query_device_link_status(rndis_device);
device_info->link_state = rndis_device->link_state;
@@ -961,7 +1085,66 @@ int rndis_filter_device_add(struct hv_device *dev,
rndis_device->hw_mac_adr,
device_info->link_state ? "down" : "up");
- return ret;
+ if (net_device->nvsp_version < NVSP_PROTOCOL_VERSION_5)
+ return 0;
+
+ /* vRSS setup */
+ memset(&rsscap, 0, rsscap_size);
+ ret = rndis_filter_query_device(rndis_device,
+ OID_GEN_RECEIVE_SCALE_CAPABILITIES,
+ &rsscap, &rsscap_size);
+ if (ret || rsscap.num_recv_que < 2)
+ goto out;
+
+ net_device->num_chn = (num_online_cpus() < rsscap.num_recv_que) ?
+ num_online_cpus() : rsscap.num_recv_que;
+ if (net_device->num_chn == 1)
+ goto out;
+
+ net_device->sub_cb_buf = vzalloc((net_device->num_chn - 1) *
+ NETVSC_PACKET_SIZE);
+ if (!net_device->sub_cb_buf) {
+ net_device->num_chn = 1;
+ dev_info(&dev->device, "No memory for subchannels.\n");
+ goto out;
+ }
+
+ vmbus_set_sc_create_callback(dev->channel, netvsc_sc_open);
+
+ 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;
+ t = wait_for_completion_timeout(&net_device->channel_init_wait, 5*HZ);
+ if (t == 0) {
+ ret = -ETIMEDOUT;
+ goto out;
+ }
+ if (init_packet->msg.v5_msg.subchn_comp.status !=
+ NVSP_STAT_SUCCESS) {
+ ret = -ENODEV;
+ goto out;
+ }
+ net_device->num_chn = 1 +
+ init_packet->msg.v5_msg.subchn_comp.num_subchannels;
+
+ vmbus_are_subchannels_present(dev->channel);
+
+ ret = rndis_filter_set_rss_param(rndis_device, net_device->num_chn);
+
+out:
+ if (ret)
+ net_device->num_chn = 1;
+ return 0; /* return 0 because primary channel can be used alone */
err_dev_remv:
rndis_filter_device_remove(dev);
--
2.4.3

View File

@@ -1,112 +0,0 @@
From 348a5d691d84759dda8cdd3cbf9f071115c1240e Mon Sep 17 00:00:00 2001
From: KY Srinivasan <kys@microsoft.com>
Date: Sun, 16 Feb 2014 16:38:44 -0800
Subject: [PATCH 02/25] Drivers: net: hyperv: Cleanup the receive path
Make the receive path a little more efficient by parameterizing the
required state rather than re-establishing that state.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/hyperv/netvsc.c | 29 +++++++++++++----------------
1 file changed, 13 insertions(+), 16 deletions(-)
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 03a2c6e17158..7fa2bbade327 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -432,17 +432,14 @@ static inline u32 hv_ringbuf_avail_percent(
return avail_write * 100 / ring_info->ring_datasize;
}
-static void netvsc_send_completion(struct hv_device *device,
+static void netvsc_send_completion(struct netvsc_device *net_device,
+ struct hv_device *device,
struct vmpacket_descriptor *packet)
{
- struct netvsc_device *net_device;
struct nvsp_message *nvsp_packet;
struct hv_netvsc_packet *nvsc_packet;
struct net_device *ndev;
- net_device = get_inbound_net_device(device);
- if (!net_device)
- return;
ndev = net_device->ndev;
nvsp_packet = (struct nvsp_message *)((unsigned long)packet +
@@ -561,13 +558,13 @@ int netvsc_send(struct hv_device *device,
}
static void netvsc_send_recv_completion(struct hv_device *device,
+ struct netvsc_device *net_device,
u64 transaction_id, u32 status)
{
struct nvsp_message recvcompMessage;
int retries = 0;
int ret;
struct net_device *ndev;
- struct netvsc_device *net_device = hv_get_drvdata(device);
ndev = net_device->ndev;
@@ -653,14 +650,15 @@ static void netvsc_receive_completion(void *context)
/* Send a receive completion for the xfer page packet */
if (fsend_receive_comp)
- netvsc_send_recv_completion(device, transaction_id, status);
+ netvsc_send_recv_completion(device, net_device, transaction_id,
+ status);
}
-static void netvsc_receive(struct hv_device *device,
- struct vmpacket_descriptor *packet)
+static void netvsc_receive(struct netvsc_device *net_device,
+ struct hv_device *device,
+ struct vmpacket_descriptor *packet)
{
- struct netvsc_device *net_device;
struct vmtransfer_page_packet_header *vmxferpage_packet;
struct nvsp_message *nvsp_packet;
struct hv_netvsc_packet *netvsc_packet = NULL;
@@ -673,9 +671,6 @@ static void netvsc_receive(struct hv_device *device,
LIST_HEAD(listHead);
- net_device = get_inbound_net_device(device);
- if (!net_device)
- return;
ndev = net_device->ndev;
/*
@@ -741,7 +736,7 @@ static void netvsc_receive(struct hv_device *device,
spin_unlock_irqrestore(&net_device->recv_pkt_list_lock,
flags);
- netvsc_send_recv_completion(device,
+ netvsc_send_recv_completion(device, net_device,
vmxferpage_packet->d.trans_id,
NVSP_STAT_FAIL);
@@ -825,11 +820,13 @@ static void netvsc_channel_cb(void *context)
desc = (struct vmpacket_descriptor *)buffer;
switch (desc->type) {
case VM_PKT_COMP:
- netvsc_send_completion(device, desc);
+ netvsc_send_completion(net_device,
+ device, desc);
break;
case VM_PKT_DATA_USING_XFER_PAGES:
- netvsc_receive(device, desc);
+ netvsc_receive(net_device,
+ device, desc);
break;
default:
--
2.4.3

View File

@@ -1,384 +0,0 @@
From 4baab26129e0540746744232022110dbe9e011e7 Mon Sep 17 00:00:00 2001
From: Haiyang Zhang <haiyangz@microsoft.com>
Date: Mon, 21 Apr 2014 14:54:43 -0700
Subject: [PATCH 02/11] hyperv: Remove recv_pkt_list and lock
Removed recv_pkt_list and lock, and updated related code, so that
the locking overhead is reduced especially when multiple channels
are in use.
The recv_pkt_list isn't actually necessary because the packets are
processed sequentially in each channel. It has been replaced by a
local variable, and the related lock for this list is also removed.
The is_data_pkt field is not used in receive path, so its assignment
is cleaned up.
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/hyperv/hyperv_net.h | 33 --------
drivers/net/hyperv/netvsc.c | 174 +++-----------------------------------
drivers/net/hyperv/netvsc_drv.c | 2 +-
drivers/net/hyperv/rndis_filter.c | 2 -
4 files changed, 13 insertions(+), 198 deletions(-)
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 57eb3f906d64..a1af0f7711e2 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -119,27 +119,14 @@ struct ndis_recv_scale_param { /* NDIS_RECEIVE_SCALE_PARAMETERS */
};
/* Fwd declaration */
-struct hv_netvsc_packet;
struct ndis_tcp_ip_checksum_info;
-/* Represent the xfer page packet which contains 1 or more netvsc packet */
-struct xferpage_packet {
- struct list_head list_ent;
- u32 status;
-
- /* # of netvsc packets this xfer packet contains */
- u32 count;
-
- struct vmbus_channel *channel;
-};
-
/*
* Represent netvsc packet which contains 1 RNDIS and 1 ethernet frame
* within the RNDIS
*/
struct hv_netvsc_packet {
/* Bookkeeping stuff */
- struct list_head list_ent;
u32 status;
struct hv_device *device;
@@ -149,19 +136,8 @@ struct hv_netvsc_packet {
u16 q_idx;
struct vmbus_channel *channel;
- /*
- * Valid only for receives when we break a xfer page packet
- * into multiple netvsc packets
- */
- struct xferpage_packet *xfer_page_pkt;
-
union {
struct {
- u64 recv_completion_tid;
- void *recv_completion_ctx;
- void (*recv_completion)(void *context);
- } recv;
- struct {
u64 send_completion_tid;
void *send_completion_ctx;
void (*send_completion)(void *context);
@@ -613,9 +589,6 @@ struct nvsp_message {
#define NETVSC_RECEIVE_BUFFER_ID 0xcafe
-/* Preallocated receive packets */
-#define NETVSC_RECEIVE_PACKETLIST_COUNT 256
-
#define NETVSC_PACKET_SIZE 2048
#define VRSS_SEND_TAB_SIZE 16
@@ -630,12 +603,6 @@ struct netvsc_device {
wait_queue_head_t wait_drain;
bool start_remove;
bool destroy;
- /*
- * List of free preallocated hv_netvsc_packet to represent receive
- * packet
- */
- struct list_head recv_pkt_list;
- spinlock_t recv_pkt_list_lock;
/* Receive buffer allocated by us but manages by NetVSP */
void *recv_buf;
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index e7e77f12bc38..b10334773b32 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -387,7 +387,6 @@ static void netvsc_disconnect_vsp(struct netvsc_device *net_device)
int netvsc_device_remove(struct hv_device *device)
{
struct netvsc_device *net_device;
- struct hv_netvsc_packet *netvsc_packet, *pos;
unsigned long flags;
net_device = hv_get_drvdata(device);
@@ -416,12 +415,6 @@ int netvsc_device_remove(struct hv_device *device)
vmbus_close(device->channel);
/* Release all resources */
- list_for_each_entry_safe(netvsc_packet, pos,
- &net_device->recv_pkt_list, list_ent) {
- list_del(&netvsc_packet->list_ent);
- kfree(netvsc_packet);
- }
-
if (net_device->sub_cb_buf)
vfree(net_device->sub_cb_buf);
@@ -641,62 +634,6 @@ retry_send_cmplt:
}
}
-/* Send a receive completion packet to RNDIS device (ie NetVsp) */
-static void netvsc_receive_completion(void *context)
-{
- struct hv_netvsc_packet *packet = context;
- struct hv_device *device = packet->device;
- struct vmbus_channel *channel;
- struct netvsc_device *net_device;
- u64 transaction_id = 0;
- bool fsend_receive_comp = false;
- unsigned long flags;
- struct net_device *ndev;
- u32 status = NVSP_STAT_NONE;
-
- /*
- * Even though it seems logical to do a GetOutboundNetDevice() here to
- * send out receive completion, we are using GetInboundNetDevice()
- * since we may have disable outbound traffic already.
- */
- net_device = get_inbound_net_device(device);
- if (!net_device)
- return;
- ndev = net_device->ndev;
-
- /* Overloading use of the lock. */
- spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags);
-
- if (packet->status != NVSP_STAT_SUCCESS)
- packet->xfer_page_pkt->status = NVSP_STAT_FAIL;
-
- packet->xfer_page_pkt->count--;
-
- /*
- * Last one in the line that represent 1 xfer page packet.
- * Return the xfer page packet itself to the freelist
- */
- if (packet->xfer_page_pkt->count == 0) {
- fsend_receive_comp = true;
- channel = packet->xfer_page_pkt->channel;
- transaction_id = packet->completion.recv.recv_completion_tid;
- status = packet->xfer_page_pkt->status;
- list_add_tail(&packet->xfer_page_pkt->list_ent,
- &net_device->recv_pkt_list);
-
- }
-
- /* Put the packet back */
- list_add_tail(&packet->list_ent, &net_device->recv_pkt_list);
- spin_unlock_irqrestore(&net_device->recv_pkt_list_lock, flags);
-
- /* Send a receive completion for the xfer page packet */
- if (fsend_receive_comp)
- netvsc_send_recv_completion(device, channel, net_device,
- transaction_id, status);
-
-}
-
static void netvsc_receive(struct netvsc_device *net_device,
struct vmbus_channel *channel,
struct hv_device *device,
@@ -704,16 +641,13 @@ static void netvsc_receive(struct netvsc_device *net_device,
{
struct vmtransfer_page_packet_header *vmxferpage_packet;
struct nvsp_message *nvsp_packet;
- struct hv_netvsc_packet *netvsc_packet = NULL;
- /* struct netvsc_driver *netvscDriver; */
- struct xferpage_packet *xferpage_packet = NULL;
+ struct hv_netvsc_packet nv_pkt;
+ struct hv_netvsc_packet *netvsc_packet = &nv_pkt;
+ u32 status = NVSP_STAT_SUCCESS;
int i;
int count = 0;
- unsigned long flags;
struct net_device *ndev;
- LIST_HEAD(listHead);
-
ndev = net_device->ndev;
/*
@@ -746,78 +680,14 @@ static void netvsc_receive(struct netvsc_device *net_device,
return;
}
- /*
- * Grab free packets (range count + 1) to represent this xfer
- * page packet. +1 to represent the xfer page packet itself.
- * We grab it here so that we know exactly how many we can
- * fulfil
- */
- spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags);
- while (!list_empty(&net_device->recv_pkt_list)) {
- list_move_tail(net_device->recv_pkt_list.next, &listHead);
- if (++count == vmxferpage_packet->range_cnt + 1)
- break;
- }
- spin_unlock_irqrestore(&net_device->recv_pkt_list_lock, flags);
-
- /*
- * We need at least 2 netvsc pkts (1 to represent the xfer
- * page and at least 1 for the range) i.e. we can handled
- * some of the xfer page packet ranges...
- */
- if (count < 2) {
- netdev_err(ndev, "Got only %d netvsc pkt...needed "
- "%d pkts. Dropping this xfer page packet completely!\n",
- count, vmxferpage_packet->range_cnt + 1);
-
- /* Return it to the freelist */
- spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags);
- for (i = count; i != 0; i--) {
- list_move_tail(listHead.next,
- &net_device->recv_pkt_list);
- }
- spin_unlock_irqrestore(&net_device->recv_pkt_list_lock,
- flags);
-
- netvsc_send_recv_completion(device, channel, net_device,
- vmxferpage_packet->d.trans_id,
- NVSP_STAT_FAIL);
-
- return;
- }
-
- /* Remove the 1st packet to represent the xfer page packet itself */
- xferpage_packet = (struct xferpage_packet *)listHead.next;
- list_del(&xferpage_packet->list_ent);
- xferpage_packet->status = NVSP_STAT_SUCCESS;
- xferpage_packet->channel = channel;
-
- /* This is how much we can satisfy */
- xferpage_packet->count = count - 1;
-
- if (xferpage_packet->count != vmxferpage_packet->range_cnt) {
- netdev_err(ndev, "Needed %d netvsc pkts to satisfy "
- "this xfer page...got %d\n",
- vmxferpage_packet->range_cnt, xferpage_packet->count);
- }
+ count = vmxferpage_packet->range_cnt;
+ netvsc_packet->device = device;
+ netvsc_packet->channel = channel;
/* Each range represents 1 RNDIS pkt that contains 1 ethernet frame */
- for (i = 0; i < (count - 1); i++) {
- netvsc_packet = (struct hv_netvsc_packet *)listHead.next;
- list_del(&netvsc_packet->list_ent);
-
+ for (i = 0; i < count; i++) {
/* Initialize the netvsc packet */
netvsc_packet->status = NVSP_STAT_SUCCESS;
- netvsc_packet->xfer_page_pkt = xferpage_packet;
- netvsc_packet->completion.recv.recv_completion =
- netvsc_receive_completion;
- netvsc_packet->completion.recv.recv_completion_ctx =
- netvsc_packet;
- netvsc_packet->device = device;
- /* Save this so that we can send it back */
- netvsc_packet->completion.recv.recv_completion_tid =
- vmxferpage_packet->d.trans_id;
-
netvsc_packet->data = (void *)((unsigned long)net_device->
recv_buf + vmxferpage_packet->ranges[i].byte_offset);
netvsc_packet->total_data_buflen =
@@ -826,10 +696,12 @@ static void netvsc_receive(struct netvsc_device *net_device,
/* Pass it to the upper layer */
rndis_filter_receive(device, netvsc_packet);
- netvsc_receive_completion(netvsc_packet->
- completion.recv.recv_completion_ctx);
+ if (netvsc_packet->status != NVSP_STAT_SUCCESS)
+ status = NVSP_STAT_FAIL;
}
+ netvsc_send_recv_completion(device, channel, net_device,
+ vmxferpage_packet->d.trans_id, status);
}
@@ -956,11 +828,9 @@ void netvsc_channel_cb(void *context)
int netvsc_device_add(struct hv_device *device, void *additional_info)
{
int ret = 0;
- int i;
int ring_size =
((struct netvsc_device_info *)additional_info)->ring_size;
struct netvsc_device *net_device;
- struct hv_netvsc_packet *packet, *pos;
struct net_device *ndev;
net_device = alloc_net_device(device);
@@ -981,18 +851,6 @@ int netvsc_device_add(struct hv_device *device, void *additional_info)
ndev = net_device->ndev;
/* Initialize the NetVSC channel extension */
- spin_lock_init(&net_device->recv_pkt_list_lock);
-
- INIT_LIST_HEAD(&net_device->recv_pkt_list);
-
- for (i = 0; i < NETVSC_RECEIVE_PACKETLIST_COUNT; i++) {
- packet = kzalloc(sizeof(struct hv_netvsc_packet), GFP_KERNEL);
- if (!packet)
- break;
-
- list_add_tail(&packet->list_ent,
- &net_device->recv_pkt_list);
- }
init_completion(&net_device->channel_init_wait);
set_per_channel_state(device->channel, net_device->cb_buffer);
@@ -1028,16 +886,8 @@ close:
cleanup:
- if (net_device) {
- list_for_each_entry_safe(packet, pos,
- &net_device->recv_pkt_list,
- list_ent) {
- list_del(&packet->list_ent);
- kfree(packet);
- }
-
+ if (net_device)
kfree(net_device);
- }
return ret;
}
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 093cf3fc46b8..8f6d53a2ed95 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -638,7 +638,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
packet->vlan_tci);
- skb_record_rx_queue(skb, packet->xfer_page_pkt->channel->
+ skb_record_rx_queue(skb, packet->channel->
offermsg.offer.sub_channel_index %
net->real_num_rx_queues);
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index d92cfbe43410..48f5a0fbd674 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -401,8 +401,6 @@ static void rndis_filter_receive_data(struct rndis_device *dev,
pkt->total_data_buflen = rndis_pkt->data_len;
pkt->data = (void *)((unsigned long)pkt->data + data_offset);
- pkt->is_data_pkt = true;
-
vlan = rndis_get_ppi(rndis_pkt, IEEE_8021Q_INFO);
if (vlan) {
pkt->vlan_tci = VLAN_TAG_PRESENT | vlan->vlanid |
--
2.4.3

View File

@@ -1,101 +0,0 @@
From c9f2db35ac4f789930522d9d36200cb71b442bed Mon Sep 17 00:00:00 2001
From: KY Srinivasan <kys@microsoft.com>
Date: Sun, 16 Feb 2014 16:38:45 -0800
Subject: [PATCH 03/25] Drivers: net: hyperv: Cleanup the netvsc receive
callback functio
Get rid of the buffer allocation in the receive path for normal packets.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/hyperv/hyperv_net.h | 2 ++
drivers/net/hyperv/netvsc.c | 33 ++++++++++-----------------------
2 files changed, 12 insertions(+), 23 deletions(-)
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 7645ba38bde8..01a16ea77a5a 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -506,6 +506,8 @@ struct netvsc_device {
/* Holds rndis device info */
void *extension;
+ /* The recive buffer for this device */
+ unsigned char cb_buffer[NETVSC_PACKET_SIZE];
};
/* NdisInitialize message */
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 7fa2bbade327..9a0e9c6f1414 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -795,22 +795,16 @@ static void netvsc_channel_cb(void *context)
struct netvsc_device *net_device;
u32 bytes_recvd;
u64 request_id;
- unsigned char *packet;
struct vmpacket_descriptor *desc;
unsigned char *buffer;
int bufferlen = NETVSC_PACKET_SIZE;
struct net_device *ndev;
- packet = kzalloc(NETVSC_PACKET_SIZE * sizeof(unsigned char),
- GFP_ATOMIC);
- if (!packet)
- return;
- buffer = packet;
-
net_device = get_inbound_net_device(device);
if (!net_device)
- goto out;
+ return;
ndev = net_device->ndev;
+ buffer = net_device->cb_buffer;
do {
ret = vmbus_recvpacket_raw(device->channel, buffer, bufferlen,
@@ -838,23 +832,16 @@ static void netvsc_channel_cb(void *context)
break;
}
- /* reset */
- if (bufferlen > NETVSC_PACKET_SIZE) {
- kfree(buffer);
- buffer = packet;
- bufferlen = NETVSC_PACKET_SIZE;
- }
} else {
- /* reset */
- if (bufferlen > NETVSC_PACKET_SIZE) {
- kfree(buffer);
- buffer = packet;
- bufferlen = NETVSC_PACKET_SIZE;
- }
-
+ /*
+ * We are done for this pass.
+ */
break;
}
+
} else if (ret == -ENOBUFS) {
+ if (bufferlen > NETVSC_PACKET_SIZE)
+ kfree(buffer);
/* Handle large packet */
buffer = kmalloc(bytes_recvd, GFP_ATOMIC);
if (buffer == NULL) {
@@ -869,8 +856,8 @@ static void netvsc_channel_cb(void *context)
}
} while (1);
-out:
- kfree(buffer);
+ if (bufferlen > NETVSC_PACKET_SIZE)
+ kfree(buffer);
return;
}
--
2.4.3

View File

@@ -1,105 +0,0 @@
From 893f66277799cd46bdf97429cc5d16a815a51273 Mon Sep 17 00:00:00 2001
From: Haiyang Zhang <haiyangz@microsoft.com>
Date: Mon, 21 Apr 2014 14:54:44 -0700
Subject: [PATCH 03/11] hyperv: Simplify the send_completion variables
The union contains only one member now, so we use the variables in it directly.
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/hyperv/hyperv_net.h | 10 +++-------
drivers/net/hyperv/netvsc.c | 7 +++----
drivers/net/hyperv/netvsc_drv.c | 8 ++++----
drivers/net/hyperv/rndis_filter.c | 2 +-
4 files changed, 11 insertions(+), 16 deletions(-)
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index a1af0f7711e2..d1f7826aa75f 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -136,13 +136,9 @@ struct hv_netvsc_packet {
u16 q_idx;
struct vmbus_channel *channel;
- union {
- struct {
- u64 send_completion_tid;
- void *send_completion_ctx;
- void (*send_completion)(void *context);
- } send;
- } completion;
+ u64 send_completion_tid;
+ void *send_completion_ctx;
+ void (*send_completion)(void *context);
/* This points to the memory after page_buf */
struct rndis_message *rndis_msg;
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index b10334773b32..bbee44635035 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -479,9 +479,8 @@ static void netvsc_send_completion(struct netvsc_device *net_device,
if (nvsc_packet) {
q_idx = nvsc_packet->q_idx;
channel = nvsc_packet->channel;
- nvsc_packet->completion.send.send_completion(
- nvsc_packet->completion.send.
- send_completion_ctx);
+ nvsc_packet->send_completion(nvsc_packet->
+ send_completion_ctx);
}
num_outstanding_sends =
@@ -534,7 +533,7 @@ int netvsc_send(struct hv_device *device,
0xFFFFFFFF;
sendMessage.msg.v1_msg.send_rndis_pkt.send_buf_section_size = 0;
- if (packet->completion.send.send_completion)
+ if (packet->send_completion)
req_id = (ulong)packet;
else
req_id = 0;
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 8f6d53a2ed95..c76b66515e92 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -235,7 +235,7 @@ static void netvsc_xmit_completion(void *context)
{
struct hv_netvsc_packet *packet = (struct hv_netvsc_packet *)context;
struct sk_buff *skb = (struct sk_buff *)
- (unsigned long)packet->completion.send.send_completion_tid;
+ (unsigned long)packet->send_completion_tid;
kfree(packet);
@@ -425,9 +425,9 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
(num_data_pgs * sizeof(struct hv_page_buffer)));
/* Set the completion routine */
- packet->completion.send.send_completion = netvsc_xmit_completion;
- packet->completion.send.send_completion_ctx = packet;
- packet->completion.send.send_completion_tid = (unsigned long)skb;
+ packet->send_completion = netvsc_xmit_completion;
+ packet->send_completion_ctx = packet;
+ packet->send_completion_tid = (unsigned long)skb;
isvlan = packet->vlan_tci & VLAN_TAG_PRESENT;
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 48f5a0fbd674..99c527adae5b 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -236,7 +236,7 @@ static int rndis_filter_send_request(struct rndis_device *dev,
packet->page_buf[0].len;
}
- packet->completion.send.send_completion = NULL;
+ packet->send_completion = NULL;
ret = netvsc_send(dev->net_dev->dev, packet);
return ret;
--
2.4.3

View File

@@ -1,171 +0,0 @@
From 3c2a271d9681cc017947c5e027acc64707c30dee Mon Sep 17 00:00:00 2001
From: Haiyang Zhang <haiyangz@microsoft.com>
Date: Wed, 19 Feb 2014 15:49:45 -0800
Subject: [PATCH 04/25] hyperv: Add latest NetVSP versions to auto negotiation
It auto negotiates the highest NetVSP version supported by both guest and host.
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/hyperv/hyperv_net.h | 53 +++++++++++++++++++++++++++++++++++++++++
drivers/net/hyperv/netvsc.c | 25 ++++++++++++-------
drivers/net/hyperv/netvsc_drv.c | 2 +-
3 files changed, 70 insertions(+), 10 deletions(-)
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 01a16ea77a5a..39fc230f5c20 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -139,6 +139,8 @@ int rndis_filter_set_device_mac(struct hv_device *hdev, char *mac);
#define NVSP_PROTOCOL_VERSION_1 2
#define NVSP_PROTOCOL_VERSION_2 0x30002
+#define NVSP_PROTOCOL_VERSION_4 0x40000
+#define NVSP_PROTOCOL_VERSION_5 0x50000
enum {
NVSP_MSG_TYPE_NONE = 0,
@@ -193,6 +195,23 @@ enum {
NVSP_MSG2_TYPE_ALLOC_CHIMNEY_HANDLE,
NVSP_MSG2_TYPE_ALLOC_CHIMNEY_HANDLE_COMP,
+
+ NVSP_MSG2_MAX = NVSP_MSG2_TYPE_ALLOC_CHIMNEY_HANDLE_COMP,
+
+ /* Version 4 messages */
+ NVSP_MSG4_TYPE_SEND_VF_ASSOCIATION,
+ NVSP_MSG4_TYPE_SWITCH_DATA_PATH,
+ NVSP_MSG4_TYPE_UPLINK_CONNECT_STATE_DEPRECATED,
+
+ NVSP_MSG4_MAX = NVSP_MSG4_TYPE_UPLINK_CONNECT_STATE_DEPRECATED,
+
+ /* Version 5 messages */
+ NVSP_MSG5_TYPE_OID_QUERY_EX,
+ NVSP_MSG5_TYPE_OID_QUERY_EX_COMP,
+ NVSP_MSG5_TYPE_SUBCHANNEL,
+ NVSP_MSG5_TYPE_SEND_INDIRECTION_TABLE,
+
+ NVSP_MSG5_MAX = NVSP_MSG5_TYPE_SEND_INDIRECTION_TABLE,
};
enum {
@@ -447,10 +466,44 @@ union nvsp_2_message_uber {
struct nvsp_2_free_rxbuf free_rxbuf;
} __packed;
+enum nvsp_subchannel_operation {
+ NVSP_SUBCHANNEL_NONE = 0,
+ NVSP_SUBCHANNEL_ALLOCATE,
+ NVSP_SUBCHANNEL_MAX
+};
+
+struct nvsp_5_subchannel_request {
+ u32 op;
+ u32 num_subchannels;
+} __packed;
+
+struct nvsp_5_subchannel_complete {
+ u32 status;
+ u32 num_subchannels; /* Actual number of subchannels allocated */
+} __packed;
+
+struct nvsp_5_send_indirect_table {
+ /* The number of entries in the send indirection table */
+ u32 count;
+
+ /* The offset of the send indireciton table from top of this struct.
+ * The send indirection table tells which channel to put the send
+ * traffic on. Each entry is a channel number.
+ */
+ u32 offset;
+} __packed;
+
+union nvsp_5_message_uber {
+ struct nvsp_5_subchannel_request subchn_req;
+ struct nvsp_5_subchannel_complete subchn_comp;
+ struct nvsp_5_send_indirect_table send_table;
+} __packed;
+
union nvsp_all_messages {
union nvsp_message_init_uber init_msg;
union nvsp_1_message_uber v1_msg;
union nvsp_2_message_uber v2_msg;
+ union nvsp_5_message_uber v5_msg;
} __packed;
/* ALL Messages */
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 9a0e9c6f1414..1a0280dcba7e 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -290,7 +290,7 @@ static int negotiate_nvsp_ver(struct hv_device *device,
NVSP_STAT_SUCCESS)
return -EINVAL;
- if (nvsp_ver != NVSP_PROTOCOL_VERSION_2)
+ if (nvsp_ver == NVSP_PROTOCOL_VERSION_1)
return 0;
/* NVSPv2 only: Send NDIS config */
@@ -314,6 +314,9 @@ static int netvsc_connect_vsp(struct hv_device *device)
struct nvsp_message *init_packet;
int ndis_version;
struct net_device *ndev;
+ u32 ver_list[] = { NVSP_PROTOCOL_VERSION_1, NVSP_PROTOCOL_VERSION_2,
+ NVSP_PROTOCOL_VERSION_4, NVSP_PROTOCOL_VERSION_5 };
+ int i, num_ver = 4; /* number of different NVSP versions */
net_device = get_outbound_net_device(device);
if (!net_device)
@@ -323,13 +326,14 @@ static int netvsc_connect_vsp(struct hv_device *device)
init_packet = &net_device->channel_init_pkt;
/* Negotiate the latest NVSP protocol supported */
- if (negotiate_nvsp_ver(device, net_device, init_packet,
- NVSP_PROTOCOL_VERSION_2) == 0) {
- net_device->nvsp_version = NVSP_PROTOCOL_VERSION_2;
- } else if (negotiate_nvsp_ver(device, net_device, init_packet,
- NVSP_PROTOCOL_VERSION_1) == 0) {
- net_device->nvsp_version = NVSP_PROTOCOL_VERSION_1;
- } else {
+ for (i = num_ver - 1; i >= 0; i--)
+ if (negotiate_nvsp_ver(device, net_device, init_packet,
+ ver_list[i]) == 0) {
+ net_device->nvsp_version = ver_list[i];
+ break;
+ }
+
+ if (i < 0) {
ret = -EPROTO;
goto cleanup;
}
@@ -339,7 +343,10 @@ static int netvsc_connect_vsp(struct hv_device *device)
/* Send the ndis version */
memset(init_packet, 0, sizeof(struct nvsp_message));
- ndis_version = 0x00050001;
+ if (net_device->nvsp_version <= NVSP_PROTOCOL_VERSION_4)
+ ndis_version = 0x00050001;
+ else
+ ndis_version = 0x0006001e;
init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_NDIS_VER;
init_packet->msg.v1_msg.
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 28020f83ba6f..8e3a0b00099b 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -328,7 +328,7 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
if (nvdev == NULL || nvdev->destroy)
return -ENODEV;
- if (nvdev->nvsp_version == NVSP_PROTOCOL_VERSION_2)
+ if (nvdev->nvsp_version >= NVSP_PROTOCOL_VERSION_2)
limit = NETVSC_MTU;
if (mtu < 68 || mtu > limit)
--
2.4.3

View File

@@ -1,407 +0,0 @@
From c25aaf814a63f9d9c4e45416f13d70ef0aa0be2e Mon Sep 17 00:00:00 2001
From: KY Srinivasan <kys@microsoft.com>
Date: Wed, 30 Apr 2014 10:14:31 -0700
Subject: [PATCH 04/11] hyperv: Enable sendbuf mechanism on the send path
We send packets using a copy-free mechanism (this is the Guest to Host transport
via VMBUS). While this is obviously optimal for large packets,
it may not be optimal for small packets. Hyper-V host supports
a second mechanism for sending packets that is "copy based". We implement that
mechanism in this patch.
In this version of the patch I have addressed a comment from David Miller.
With this patch (and all of the other offload and VRSS patches), we are now able
to almost saturate a 10G interface between Linux VMs on Hyper-V
on different hosts - close to 9 Gbps as measured via iperf.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/hyperv/hyperv_net.h | 14 +++
drivers/net/hyperv/netvsc.c | 226 ++++++++++++++++++++++++++++++++++++++--
drivers/net/hyperv/netvsc_drv.c | 3 +-
3 files changed, 234 insertions(+), 9 deletions(-)
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index d1f7826aa75f..4b7df5a5c966 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -140,6 +140,8 @@ struct hv_netvsc_packet {
void *send_completion_ctx;
void (*send_completion)(void *context);
+ u32 send_buf_index;
+
/* This points to the memory after page_buf */
struct rndis_message *rndis_msg;
@@ -582,6 +584,9 @@ struct nvsp_message {
#define NETVSC_RECEIVE_BUFFER_SIZE (1024*1024*16) /* 16MB */
#define NETVSC_RECEIVE_BUFFER_SIZE_LEGACY (1024*1024*15) /* 15MB */
+#define NETVSC_SEND_BUFFER_SIZE (1024 * 1024) /* 1MB */
+#define NETVSC_INVALID_INDEX -1
+
#define NETVSC_RECEIVE_BUFFER_ID 0xcafe
@@ -607,6 +612,15 @@ struct netvsc_device {
u32 recv_section_cnt;
struct nvsp_1_receive_buffer_section *recv_section;
+ /* 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;
+ unsigned long *send_section_map;
+ int map_words;
+
/* Used for NetVSP initialization protocol */
struct completion channel_init_wait;
struct nvsp_message channel_init_pkt;
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index bbee44635035..c041f63a6d30 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -28,6 +28,7 @@
#include <linux/slab.h>
#include <linux/netdevice.h>
#include <linux/if_ether.h>
+#include <asm/sync_bitops.h>
#include "hyperv_net.h"
@@ -80,7 +81,7 @@ get_in_err:
}
-static int netvsc_destroy_recv_buf(struct netvsc_device *net_device)
+static int netvsc_destroy_buf(struct netvsc_device *net_device)
{
struct nvsp_message *revoke_packet;
int ret = 0;
@@ -146,10 +147,62 @@ static int netvsc_destroy_recv_buf(struct netvsc_device *net_device)
net_device->recv_section = NULL;
}
+ /* Deal with the send buffer we may have setup.
+ * If we got a send section size, it means we received a
+ * SendsendBufferComplete msg (ie sent
+ * NvspMessage1TypeSendReceiveBuffer msg) therefore, we need
+ * to send a revoke msg here
+ */
+ if (net_device->send_section_size) {
+ /* Send the revoke receive buffer */
+ revoke_packet = &net_device->revoke_packet;
+ memset(revoke_packet, 0, sizeof(struct nvsp_message));
+
+ revoke_packet->hdr.msg_type =
+ NVSP_MSG1_TYPE_REVOKE_SEND_BUF;
+ revoke_packet->msg.v1_msg.revoke_recv_buf.id = 0;
+
+ ret = vmbus_sendpacket(net_device->dev->channel,
+ revoke_packet,
+ sizeof(struct nvsp_message),
+ (unsigned long)revoke_packet,
+ VM_PKT_DATA_INBAND, 0);
+ /* If we failed here, we might as well return and
+ * have a leak rather than continue and a bugchk
+ */
+ if (ret != 0) {
+ netdev_err(ndev, "unable to send "
+ "revoke send buffer to netvsp\n");
+ return ret;
+ }
+ }
+ /* Teardown the gpadl on the vsp end */
+ if (net_device->send_buf_gpadl_handle) {
+ ret = vmbus_teardown_gpadl(net_device->dev->channel,
+ net_device->send_buf_gpadl_handle);
+
+ /* If we failed here, we might as well return and have a leak
+ * rather than continue and a bugchk
+ */
+ if (ret != 0) {
+ netdev_err(ndev,
+ "unable to teardown send buffer's gpadl\n");
+ return ret;
+ }
+ net_device->recv_buf_gpadl_handle = 0;
+ }
+ if (net_device->send_buf) {
+ /* Free up the receive buffer */
+ free_pages((unsigned long)net_device->send_buf,
+ get_order(net_device->send_buf_size));
+ net_device->send_buf = NULL;
+ }
+ kfree(net_device->send_section_map);
+
return ret;
}
-static int netvsc_init_recv_buf(struct hv_device *device)
+static int netvsc_init_buf(struct hv_device *device)
{
int ret = 0;
int t;
@@ -248,10 +301,90 @@ static int netvsc_init_recv_buf(struct hv_device *device)
goto cleanup;
}
+ /* Now setup the send buffer.
+ */
+ net_device->send_buf =
+ (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
+ get_order(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);
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+
+ /* Establish the gpadl handle for this buffer on this
+ * channel. Note: This call uses the vmbus connection rather
+ * than the channel to establish the gpadl handle.
+ */
+ ret = vmbus_establish_gpadl(device->channel, net_device->send_buf,
+ net_device->send_buf_size,
+ &net_device->send_buf_gpadl_handle);
+ if (ret != 0) {
+ netdev_err(ndev,
+ "unable to establish send buffer's gpadl\n");
+ goto cleanup;
+ }
+
+ /* Notify the NetVsp of the gpadl handle */
+ init_packet = &net_device->channel_init_pkt;
+ memset(init_packet, 0, sizeof(struct nvsp_message));
+ init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_SEND_BUF;
+ init_packet->msg.v1_msg.send_recv_buf.gpadl_handle =
+ net_device->send_buf_gpadl_handle;
+ init_packet->msg.v1_msg.send_recv_buf.id = 0;
+
+ /* Send the gpadl notification request */
+ ret = vmbus_sendpacket(device->channel, init_packet,
+ sizeof(struct nvsp_message),
+ (unsigned long)init_packet,
+ VM_PKT_DATA_INBAND,
+ VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+ if (ret != 0) {
+ netdev_err(ndev,
+ "unable to send send buffer's gpadl to netvsp\n");
+ goto cleanup;
+ }
+
+ t = wait_for_completion_timeout(&net_device->channel_init_wait, 5*HZ);
+ BUG_ON(t == 0);
+
+ /* Check the response */
+ if (init_packet->msg.v1_msg.
+ send_send_buf_complete.status != NVSP_STAT_SUCCESS) {
+ netdev_err(ndev, "Unable to complete send buffer "
+ "initialization with NetVsp - status %d\n",
+ init_packet->msg.v1_msg.
+ send_recv_buf_complete.status);
+ ret = -EINVAL;
+ goto cleanup;
+ }
+
+ /* Parse the response */
+ 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;
+
+ dev_info(&device->device, "Send section size: %d, Section count:%d\n",
+ net_device->send_section_size, net_device->send_section_cnt);
+
+ /* Setup state for managing the send buffer. */
+ net_device->map_words = DIV_ROUND_UP(net_device->send_section_cnt,
+ BITS_PER_LONG);
+
+ net_device->send_section_map =
+ kzalloc(net_device->map_words * sizeof(ulong), GFP_KERNEL);
+ if (net_device->send_section_map == NULL)
+ goto cleanup;
+
goto exit;
cleanup:
- netvsc_destroy_recv_buf(net_device);
+ netvsc_destroy_buf(net_device);
exit:
return ret;
@@ -369,8 +502,9 @@ static int netvsc_connect_vsp(struct hv_device *device)
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_recv_buf(device);
+ ret = netvsc_init_buf(device);
cleanup:
return ret;
@@ -378,7 +512,7 @@ cleanup:
static void netvsc_disconnect_vsp(struct netvsc_device *net_device)
{
- netvsc_destroy_recv_buf(net_device);
+ netvsc_destroy_buf(net_device);
}
/*
@@ -440,6 +574,12 @@ static inline u32 hv_ringbuf_avail_percent(
return avail_write * 100 / ring_info->ring_datasize;
}
+static inline void netvsc_free_send_slot(struct netvsc_device *net_device,
+ u32 index)
+{
+ sync_change_bit(index, net_device->send_section_map);
+}
+
static void netvsc_send_completion(struct netvsc_device *net_device,
struct hv_device *device,
struct vmpacket_descriptor *packet)
@@ -447,6 +587,7 @@ static void netvsc_send_completion(struct netvsc_device *net_device,
struct nvsp_message *nvsp_packet;
struct hv_netvsc_packet *nvsc_packet;
struct net_device *ndev;
+ u32 send_index;
ndev = net_device->ndev;
@@ -477,6 +618,9 @@ static void netvsc_send_completion(struct netvsc_device *net_device,
/* Notify the layer above us */
if (nvsc_packet) {
+ send_index = nvsc_packet->send_buf_index;
+ if (send_index != NETVSC_INVALID_INDEX)
+ netvsc_free_send_slot(net_device, send_index);
q_idx = nvsc_packet->q_idx;
channel = nvsc_packet->channel;
nvsc_packet->send_completion(nvsc_packet->
@@ -504,6 +648,52 @@ static void netvsc_send_completion(struct netvsc_device *net_device,
}
+static u32 netvsc_get_next_send_section(struct netvsc_device *net_device)
+{
+ unsigned long index;
+ u32 max_words = net_device->map_words;
+ unsigned long *map_addr = (unsigned long *)net_device->send_section_map;
+ u32 section_cnt = net_device->send_section_cnt;
+ int ret_val = NETVSC_INVALID_INDEX;
+ int i;
+ int prev_val;
+
+ for (i = 0; i < max_words; i++) {
+ if (!~(map_addr[i]))
+ continue;
+ index = ffz(map_addr[i]);
+ prev_val = sync_test_and_set_bit(index, &map_addr[i]);
+ if (prev_val)
+ continue;
+ if ((index + (i * BITS_PER_LONG)) >= section_cnt)
+ break;
+ ret_val = (index + (i * BITS_PER_LONG));
+ break;
+ }
+ return ret_val;
+}
+
+u32 netvsc_copy_to_send_buf(struct netvsc_device *net_device,
+ unsigned int section_index,
+ struct hv_netvsc_packet *packet)
+{
+ char *start = net_device->send_buf;
+ char *dest = (start + (section_index * net_device->send_section_size));
+ int i;
+ u32 msg_size = 0;
+
+ for (i = 0; i < packet->page_buf_cnt; i++) {
+ char *src = phys_to_virt(packet->page_buf[i].pfn << PAGE_SHIFT);
+ u32 offset = packet->page_buf[i].offset;
+ u32 len = packet->page_buf[i].len;
+
+ memcpy(dest, (src + offset), len);
+ msg_size += len;
+ dest += len;
+ }
+ return msg_size;
+}
+
int netvsc_send(struct hv_device *device,
struct hv_netvsc_packet *packet)
{
@@ -513,6 +703,10 @@ int netvsc_send(struct hv_device *device,
struct net_device *ndev;
struct vmbus_channel *out_channel = NULL;
u64 req_id;
+ unsigned int section_index = NETVSC_INVALID_INDEX;
+ u32 msg_size = 0;
+ struct sk_buff *skb;
+
net_device = get_outbound_net_device(device);
if (!net_device)
@@ -528,10 +722,26 @@ int netvsc_send(struct hv_device *device,
sendMessage.msg.v1_msg.send_rndis_pkt.channel_type = 1;
}
- /* Not using send buffer section */
+ /* Attempt to send via sendbuf */
+ if (packet->total_data_buflen < net_device->send_section_size) {
+ section_index = netvsc_get_next_send_section(net_device);
+ if (section_index != NETVSC_INVALID_INDEX) {
+ msg_size = netvsc_copy_to_send_buf(net_device,
+ section_index,
+ packet);
+ skb = (struct sk_buff *)
+ (unsigned long)packet->send_completion_tid;
+ if (skb)
+ dev_kfree_skb_any(skb);
+ packet->page_buf_cnt = 0;
+ }
+ }
+ packet->send_buf_index = section_index;
+
+
sendMessage.msg.v1_msg.send_rndis_pkt.send_buf_section_index =
- 0xFFFFFFFF;
- sendMessage.msg.v1_msg.send_rndis_pkt.send_buf_section_size = 0;
+ section_index;
+ sendMessage.msg.v1_msg.send_rndis_pkt.send_buf_section_size = msg_size;
if (packet->send_completion)
req_id = (ulong)packet;
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index c76b66515e92..939e3af60ec4 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -236,10 +236,11 @@ static void netvsc_xmit_completion(void *context)
struct hv_netvsc_packet *packet = (struct hv_netvsc_packet *)context;
struct sk_buff *skb = (struct sk_buff *)
(unsigned long)packet->send_completion_tid;
+ u32 index = packet->send_buf_index;
kfree(packet);
- if (skb)
+ if (skb && (index == NETVSC_INVALID_INDEX))
dev_kfree_skb_any(skb);
}
--
2.4.3

View File

@@ -1,42 +0,0 @@
From e565e803d437b36c4fb4ced5e346827981183284 Mon Sep 17 00:00:00 2001
From: Haiyang Zhang <haiyangz@microsoft.com>
Date: Thu, 8 May 2014 15:14:10 -0700
Subject: [PATCH 05/11] Add support for netvsc build without CONFIG_SYSFS flag
This change ensures the driver can be built successfully without the
CONFIG_SYSFS flag.
MS-TFS: 182270
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/hyperv/netvsc_drv.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 939e3af60ec4..083d084396d3 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -640,8 +640,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
packet->vlan_tci);
skb_record_rx_queue(skb, packet->channel->
- offermsg.offer.sub_channel_index %
- net->real_num_rx_queues);
+ offermsg.offer.sub_channel_index);
net->stats.rx_packets++;
net->stats.rx_bytes += packet->total_data_buflen;
@@ -824,8 +823,6 @@ static int netvsc_probe(struct hv_device *dev,
nvdev = hv_get_drvdata(dev);
netif_set_real_num_tx_queues(net, nvdev->num_chn);
netif_set_real_num_rx_queues(net, nvdev->num_chn);
- dev_info(&dev->device, "real num tx,rx queues:%u, %u\n",
- net->real_num_tx_queues, net->real_num_rx_queues);
ret = register_netdev(net);
if (ret != 0) {
--
2.4.3

View File

@@ -1,212 +0,0 @@
From 4c06034001e20ff9f6e2a1a3dfa155bf3f31440c Mon Sep 17 00:00:00 2001
From: KY Srinivasan <kys@microsoft.com>
Date: Sat, 8 Mar 2014 19:23:13 -0800
Subject: [PATCH 05/25] Drivers: net: hyperv: Enable scatter gather I/O
Cleanup the code and enable scatter gather I/O.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/hyperv/netvsc_drv.c | 153 ++++++++++++++++++++++++++++++----------
1 file changed, 114 insertions(+), 39 deletions(-)
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 8e3a0b00099b..72961741be54 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -140,22 +140,124 @@ static void netvsc_xmit_completion(void *context)
dev_kfree_skb_any(skb);
}
+static u32 fill_pg_buf(struct page *page, u32 offset, u32 len,
+ struct hv_page_buffer *pb)
+{
+ int j = 0;
+
+ /* Deal with compund pages by ignoring unused part
+ * of the page.
+ */
+ page += (offset >> PAGE_SHIFT);
+ offset &= ~PAGE_MASK;
+
+ while (len > 0) {
+ unsigned long bytes;
+
+ bytes = PAGE_SIZE - offset;
+ if (bytes > len)
+ bytes = len;
+ pb[j].pfn = page_to_pfn(page);
+ pb[j].offset = offset;
+ pb[j].len = bytes;
+
+ offset += bytes;
+ len -= bytes;
+
+ if (offset == PAGE_SIZE && len) {
+ page++;
+ offset = 0;
+ j++;
+ }
+ }
+
+ return j + 1;
+}
+
+static void init_page_array(void *hdr, u32 len, struct sk_buff *skb,
+ struct hv_page_buffer *pb)
+{
+ u32 slots_used = 0;
+ char *data = skb->data;
+ int frags = skb_shinfo(skb)->nr_frags;
+ int i;
+
+ /* The packet is laid out thus:
+ * 1. hdr
+ * 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(data),
+ offset_in_page(data),
+ skb_headlen(skb), &pb[slots_used]);
+
+ for (i = 0; i < frags; i++) {
+ skb_frag_t *frag = skb_shinfo(skb)->frags + i;
+
+ slots_used += fill_pg_buf(skb_frag_page(frag),
+ frag->page_offset,
+ skb_frag_size(frag), &pb[slots_used]);
+ }
+}
+
+static int count_skb_frag_slots(struct sk_buff *skb)
+{
+ int i, frags = skb_shinfo(skb)->nr_frags;
+ int pages = 0;
+
+ for (i = 0; i < frags; i++) {
+ skb_frag_t *frag = skb_shinfo(skb)->frags + i;
+ unsigned long size = skb_frag_size(frag);
+ unsigned long offset = frag->page_offset;
+
+ /* Skip unused frames from start of page */
+ offset &= ~PAGE_MASK;
+ pages += PFN_UP(offset + size);
+ }
+ return pages;
+}
+
+static int netvsc_get_slots(struct sk_buff *skb)
+{
+ char *data = skb->data;
+ unsigned int offset = offset_in_page(data);
+ unsigned int len = skb_headlen(skb);
+ int slots;
+ int frag_slots;
+
+ slots = DIV_ROUND_UP(offset + len, PAGE_SIZE);
+ frag_slots = count_skb_frag_slots(skb);
+ return slots + frag_slots;
+}
+
static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
{
struct net_device_context *net_device_ctx = netdev_priv(net);
struct hv_netvsc_packet *packet;
int ret;
- unsigned int i, num_pages, npg_data;
+ unsigned int num_data_pages;
u32 skb_length = skb->len;
- /* Add multipages for skb->data and additional 2 for RNDIS */
- npg_data = (((unsigned long)skb->data + skb_headlen(skb) - 1)
- >> PAGE_SHIFT) - ((unsigned long)skb->data >> PAGE_SHIFT) + 1;
- num_pages = skb_shinfo(skb)->nr_frags + npg_data + 2;
+ /* We will atmost need two pages to describe the rndis
+ * header. We can only transmit MAX_PAGE_BUFFER_COUNT number
+ * of pages in a single packet.
+ */
+ num_data_pages = netvsc_get_slots(skb) + 2;
+ if (num_data_pages > MAX_PAGE_BUFFER_COUNT) {
+ netdev_err(net, "Packet too big: %u\n", skb->len);
+ dev_kfree_skb(skb);
+ net->stats.tx_dropped++;
+ return NETDEV_TX_OK;
+ }
/* Allocate a netvsc packet based on # of frags. */
packet = kzalloc(sizeof(struct hv_netvsc_packet) +
- (num_pages * sizeof(struct hv_page_buffer)) +
+ (num_data_pages * sizeof(struct hv_page_buffer)) +
sizeof(struct rndis_message) +
NDIS_VLAN_PPI_SIZE, GFP_ATOMIC);
if (!packet) {
@@ -170,44 +272,17 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
packet->vlan_tci = skb->vlan_tci;
packet->extension = (void *)(unsigned long)packet +
- sizeof(struct hv_netvsc_packet) +
- (num_pages * sizeof(struct hv_page_buffer));
+ sizeof(struct hv_netvsc_packet) +
+ (num_data_pages * sizeof(struct hv_page_buffer));
/* If the rndis msg goes beyond 1 page, we will add 1 later */
- packet->page_buf_cnt = num_pages - 1;
+ packet->page_buf_cnt = num_data_pages - 1;
/* Initialize it from the skb */
packet->total_data_buflen = skb->len;
/* Start filling in the page buffers starting after RNDIS buffer. */
- packet->page_buf[1].pfn = virt_to_phys(skb->data) >> PAGE_SHIFT;
- packet->page_buf[1].offset
- = (unsigned long)skb->data & (PAGE_SIZE - 1);
- if (npg_data == 1)
- packet->page_buf[1].len = skb_headlen(skb);
- else
- packet->page_buf[1].len = PAGE_SIZE
- - packet->page_buf[1].offset;
-
- for (i = 2; i <= npg_data; i++) {
- packet->page_buf[i].pfn = virt_to_phys(skb->data
- + PAGE_SIZE * (i-1)) >> PAGE_SHIFT;
- packet->page_buf[i].offset = 0;
- packet->page_buf[i].len = PAGE_SIZE;
- }
- if (npg_data > 1)
- packet->page_buf[npg_data].len = (((unsigned long)skb->data
- + skb_headlen(skb) - 1) & (PAGE_SIZE - 1)) + 1;
-
- /* Additional fragments are after SKB data */
- for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- const skb_frag_t *f = &skb_shinfo(skb)->frags[i];
-
- packet->page_buf[i+npg_data+1].pfn =
- page_to_pfn(skb_frag_page(f));
- packet->page_buf[i+npg_data+1].offset = f->page_offset;
- packet->page_buf[i+npg_data+1].len = skb_frag_size(f);
- }
+ init_page_array(NULL, 0, skb, &packet->page_buf[1]);
/* Set the completion routine */
packet->completion.send.send_completion = netvsc_xmit_completion;
@@ -454,8 +529,8 @@ static int netvsc_probe(struct hv_device *dev,
net->netdev_ops = &device_ops;
/* TODO: Add GSO and Checksum offload */
- net->hw_features = 0;
- net->features = NETIF_F_HW_VLAN_CTAG_TX;
+ net->hw_features = NETIF_F_SG;
+ net->features = NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_SG;
SET_ETHTOOL_OPS(net, &ethtool_ops);
SET_NETDEV_DEV(net, &dev->device);
--
2.4.3

View File

@@ -1,266 +0,0 @@
From d972eb71fb95660fe74616901b55b0d7a336daed Mon Sep 17 00:00:00 2001
From: KY Srinivasan <kys@microsoft.com>
Date: Sat, 8 Mar 2014 19:23:14 -0800
Subject: [PATCH 06/25] Drivers: net: hyperv: Cleanup the send path
In preparation for enabling offloads, cleanup the send path.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/hyperv/hyperv_net.h | 7 +---
drivers/net/hyperv/netvsc_drv.c | 88 +++++++++++++++++++++++++++++++--------
drivers/net/hyperv/rndis_filter.c | 66 -----------------------------
3 files changed, 71 insertions(+), 90 deletions(-)
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 39fc230f5c20..694bf7cada90 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -73,7 +73,7 @@ struct hv_netvsc_packet {
} completion;
/* This points to the memory after page_buf */
- void *extension;
+ struct rndis_message *rndis_msg;
u32 total_data_buflen;
/* Points to the send/receive buffer where the ethernet frame is */
@@ -126,11 +126,6 @@ void rndis_filter_device_remove(struct hv_device *dev);
int rndis_filter_receive(struct hv_device *dev,
struct hv_netvsc_packet *pkt);
-
-
-int rndis_filter_send(struct hv_device *dev,
- struct hv_netvsc_packet *pkt);
-
int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter);
int rndis_filter_set_device_mac(struct hv_device *hdev, char *mac);
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 72961741be54..87293a15e470 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -128,6 +128,27 @@ static int netvsc_close(struct net_device *net)
return ret;
}
+static void *init_ppi_data(struct rndis_message *msg, u32 ppi_size,
+ int pkt_type)
+{
+ struct rndis_packet *rndis_pkt;
+ struct rndis_per_packet_info *ppi;
+
+ rndis_pkt = &msg->msg.pkt;
+ rndis_pkt->data_offset += ppi_size;
+
+ ppi = (struct rndis_per_packet_info *)((void *)rndis_pkt +
+ rndis_pkt->per_pkt_info_offset + rndis_pkt->per_pkt_info_len);
+
+ ppi->size = ppi_size;
+ ppi->type = pkt_type;
+ ppi->ppi_offset = sizeof(struct rndis_per_packet_info);
+
+ rndis_pkt->per_pkt_info_len += ppi_size;
+
+ return ppi;
+}
+
static void netvsc_xmit_completion(void *context)
{
struct hv_netvsc_packet *packet = (struct hv_netvsc_packet *)context;
@@ -174,8 +195,8 @@ static u32 fill_pg_buf(struct page *page, u32 offset, u32 len,
return j + 1;
}
-static void init_page_array(void *hdr, u32 len, struct sk_buff *skb,
- struct hv_page_buffer *pb)
+static u32 init_page_array(void *hdr, u32 len, struct sk_buff *skb,
+ struct hv_page_buffer *pb)
{
u32 slots_used = 0;
char *data = skb->data;
@@ -203,6 +224,7 @@ static void init_page_array(void *hdr, u32 len, struct sk_buff *skb,
frag->page_offset,
skb_frag_size(frag), &pb[slots_used]);
}
+ return slots_used;
}
static int count_skb_frag_slots(struct sk_buff *skb)
@@ -240,15 +262,20 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
struct net_device_context *net_device_ctx = netdev_priv(net);
struct hv_netvsc_packet *packet;
int ret;
- unsigned int num_data_pages;
u32 skb_length = skb->len;
+ unsigned int num_data_pgs;
+ struct rndis_message *rndis_msg;
+ struct rndis_packet *rndis_pkt;
+ u32 rndis_msg_size;
+ bool isvlan;
+ struct rndis_per_packet_info *ppi;
/* We will atmost need two pages to describe the rndis
* header. We can only transmit MAX_PAGE_BUFFER_COUNT number
* of pages in a single packet.
*/
- num_data_pages = netvsc_get_slots(skb) + 2;
- if (num_data_pages > MAX_PAGE_BUFFER_COUNT) {
+ num_data_pgs = netvsc_get_slots(skb) + 2;
+ if (num_data_pgs > MAX_PAGE_BUFFER_COUNT) {
netdev_err(net, "Packet too big: %u\n", skb->len);
dev_kfree_skb(skb);
net->stats.tx_dropped++;
@@ -257,7 +284,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
/* Allocate a netvsc packet based on # of frags. */
packet = kzalloc(sizeof(struct hv_netvsc_packet) +
- (num_data_pages * sizeof(struct hv_page_buffer)) +
+ (num_data_pgs * sizeof(struct hv_page_buffer)) +
sizeof(struct rndis_message) +
NDIS_VLAN_PPI_SIZE, GFP_ATOMIC);
if (!packet) {
@@ -271,26 +298,51 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
packet->vlan_tci = skb->vlan_tci;
- packet->extension = (void *)(unsigned long)packet +
- sizeof(struct hv_netvsc_packet) +
- (num_data_pages * sizeof(struct hv_page_buffer));
-
- /* If the rndis msg goes beyond 1 page, we will add 1 later */
- packet->page_buf_cnt = num_data_pages - 1;
-
- /* Initialize it from the skb */
+ packet->is_data_pkt = true;
packet->total_data_buflen = skb->len;
- /* Start filling in the page buffers starting after RNDIS buffer. */
- init_page_array(NULL, 0, skb, &packet->page_buf[1]);
+ packet->rndis_msg = (struct rndis_message *)((unsigned long)packet +
+ sizeof(struct hv_netvsc_packet) +
+ (num_data_pgs * sizeof(struct hv_page_buffer)));
/* Set the completion routine */
packet->completion.send.send_completion = netvsc_xmit_completion;
packet->completion.send.send_completion_ctx = packet;
packet->completion.send.send_completion_tid = (unsigned long)skb;
- ret = rndis_filter_send(net_device_ctx->device_ctx,
- packet);
+ isvlan = packet->vlan_tci & VLAN_TAG_PRESENT;
+
+ /* Add the rndis header */
+ rndis_msg = packet->rndis_msg;
+ rndis_msg->ndis_msg_type = RNDIS_MSG_PACKET;
+ rndis_msg->msg_len = packet->total_data_buflen;
+ rndis_pkt = &rndis_msg->msg.pkt;
+ rndis_pkt->data_offset = sizeof(struct rndis_packet);
+ rndis_pkt->data_len = packet->total_data_buflen;
+ rndis_pkt->per_pkt_info_offset = sizeof(struct rndis_packet);
+
+ rndis_msg_size = RNDIS_MESSAGE_SIZE(struct rndis_packet);
+
+ if (isvlan) {
+ struct ndis_pkt_8021q_info *vlan;
+
+ 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);
+ vlan->vlanid = packet->vlan_tci & VLAN_VID_MASK;
+ vlan->pri = (packet->vlan_tci & VLAN_PRIO_MASK) >>
+ VLAN_PRIO_SHIFT;
+ }
+
+ /* Start filling in the page buffers with the rndis hdr */
+ rndis_msg->msg_len += rndis_msg_size;
+ packet->page_buf_cnt = init_page_array(rndis_msg, rndis_msg_size,
+ skb, &packet->page_buf[0]);
+
+ ret = netvsc_send(net_device_ctx->device_ctx, packet);
+
if (ret == 0) {
net->stats.tx_bytes += skb_length;
net->stats.tx_packets++;
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 6a9f6021f09c..dcbf144ea7da 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -910,69 +910,3 @@ int rndis_filter_close(struct hv_device *dev)
return rndis_filter_close_device(nvdev->extension);
}
-
-int rndis_filter_send(struct hv_device *dev,
- struct hv_netvsc_packet *pkt)
-{
- struct rndis_message *rndis_msg;
- struct rndis_packet *rndis_pkt;
- u32 rndis_msg_size;
- bool isvlan = pkt->vlan_tci & VLAN_TAG_PRESENT;
-
- /* Add the rndis header */
- rndis_msg = (struct rndis_message *)pkt->extension;
-
- rndis_msg_size = RNDIS_MESSAGE_SIZE(struct rndis_packet);
- if (isvlan)
- rndis_msg_size += NDIS_VLAN_PPI_SIZE;
-
- rndis_msg->ndis_msg_type = RNDIS_MSG_PACKET;
- rndis_msg->msg_len = pkt->total_data_buflen +
- rndis_msg_size;
-
- rndis_pkt = &rndis_msg->msg.pkt;
- rndis_pkt->data_offset = sizeof(struct rndis_packet);
- if (isvlan)
- rndis_pkt->data_offset += NDIS_VLAN_PPI_SIZE;
- rndis_pkt->data_len = pkt->total_data_buflen;
-
- if (isvlan) {
- struct rndis_per_packet_info *ppi;
- struct ndis_pkt_8021q_info *vlan;
-
- rndis_pkt->per_pkt_info_offset = sizeof(struct rndis_packet);
- rndis_pkt->per_pkt_info_len = NDIS_VLAN_PPI_SIZE;
-
- ppi = (struct rndis_per_packet_info *)((ulong)rndis_pkt +
- rndis_pkt->per_pkt_info_offset);
- ppi->size = NDIS_VLAN_PPI_SIZE;
- ppi->type = IEEE_8021Q_INFO;
- ppi->ppi_offset = sizeof(struct rndis_per_packet_info);
-
- vlan = (struct ndis_pkt_8021q_info *)((ulong)ppi +
- ppi->ppi_offset);
- vlan->vlanid = pkt->vlan_tci & VLAN_VID_MASK;
- vlan->pri = (pkt->vlan_tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
- }
-
- pkt->is_data_pkt = true;
- pkt->page_buf[0].pfn = virt_to_phys(rndis_msg) >> PAGE_SHIFT;
- pkt->page_buf[0].offset =
- (unsigned long)rndis_msg & (PAGE_SIZE-1);
- pkt->page_buf[0].len = rndis_msg_size;
-
- /* Add one page_buf if the rndis msg goes beyond page boundary */
- if (pkt->page_buf[0].offset + rndis_msg_size > PAGE_SIZE) {
- int i;
- for (i = pkt->page_buf_cnt; i > 1; i--)
- pkt->page_buf[i] = pkt->page_buf[i-1];
- pkt->page_buf_cnt++;
- pkt->page_buf[0].len = PAGE_SIZE - pkt->page_buf[0].offset;
- pkt->page_buf[1].pfn = virt_to_phys((void *)((ulong)
- rndis_msg + pkt->page_buf[0].len)) >> PAGE_SHIFT;
- pkt->page_buf[1].offset = 0;
- pkt->page_buf[1].len = rndis_msg_size - pkt->page_buf[0].len;
- }
-
- return netvsc_send(dev, pkt);
-}
--
2.4.3

View File

@@ -1,44 +0,0 @@
From 7ad24ea4bf620a32631d7b3069c3e30c078b0c3e Mon Sep 17 00:00:00 2001
From: Wilfried Klaebe <w-lkml@lebenslange-mailadresse.de>
Date: Sun, 11 May 2014 00:12:32 +0000
Subject: [PATCH 06/11] net: get rid of SET_ETHTOOL_OPS
net: get rid of SET_ETHTOOL_OPS
Dave Miller mentioned he'd like to see SET_ETHTOOL_OPS gone.
This does that.
Mostly done via coccinelle script:
@@
struct ethtool_ops *ops;
struct net_device *dev;
@@
- SET_ETHTOOL_OPS(dev, ops);
+ dev->ethtool_ops = ops;
Compile tested only, but I'd seriously wonder if this broke anything.
Suggested-by: Dave Miller <davem@davemloft.net>
Signed-off-by: Wilfried Klaebe <w-lkml@lebenslange-mailadresse.de>
Acked-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
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
index 1de3ef5dd5d2..2e967a7bdb33 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -810,7 +810,7 @@ static int netvsc_probe(struct hv_device *dev,
net->features = NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_SG | NETIF_F_RXCSUM |
NETIF_F_IP_CSUM | NETIF_F_TSO;
- SET_ETHTOOL_OPS(net, &ethtool_ops);
+ net->ethtool_ops = &ethtool_ops;
SET_NETDEV_DEV(net, &dev->device);
/* Notify the netvsc driver of the new device */
--
2.4.3

View File

@@ -1,196 +0,0 @@
From 6b15b5f37e976a5f3840c7ea59560e10c6251250 Mon Sep 17 00:00:00 2001
From: KY Srinivasan <kys@microsoft.com>
Date: Sat, 8 Mar 2014 19:23:15 -0800
Subject: [PATCH 07/25] Drivers: net: hyperv: Enable offloads on the host
Prior to enabling guest side offloads, enable the offloads on the host.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/hyperv/hyperv_net.h | 55 +++++++++++++++++++++++++++
drivers/net/hyperv/rndis_filter.c | 80 +++++++++++++++++++++++++++++++++++++++
2 files changed, 135 insertions(+)
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 694bf7cada90..8bc4e766589b 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -721,6 +721,61 @@ struct ndis_pkt_8021q_info {
};
};
+struct ndis_oject_header {
+ u8 type;
+ u8 revision;
+ u16 size;
+};
+
+#define NDIS_OBJECT_TYPE_DEFAULT 0x80
+#define NDIS_OFFLOAD_PARAMETERS_REVISION_3 3
+#define NDIS_OFFLOAD_PARAMETERS_NO_CHANGE 0
+#define NDIS_OFFLOAD_PARAMETERS_LSOV2_DISABLED 1
+#define NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED 2
+#define NDIS_OFFLOAD_PARAMETERS_LSOV1_ENABLED 2
+#define NDIS_OFFLOAD_PARAMETERS_RSC_DISABLED 1
+#define NDIS_OFFLOAD_PARAMETERS_RSC_ENABLED 2
+#define NDIS_OFFLOAD_PARAMETERS_TX_RX_DISABLED 1
+#define NDIS_OFFLOAD_PARAMETERS_TX_ENABLED_RX_DISABLED 2
+#define NDIS_OFFLOAD_PARAMETERS_RX_ENABLED_TX_DISABLED 3
+#define NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED 4
+
+/*
+ * New offload OIDs for NDIS 6
+ */
+#define OID_TCP_OFFLOAD_CURRENT_CONFIG 0xFC01020B /* query only */
+#define OID_TCP_OFFLOAD_PARAMETERS 0xFC01020C /* set only */
+#define OID_TCP_OFFLOAD_HARDWARE_CAPABILITIES 0xFC01020D/* query only */
+#define OID_TCP_CONNECTION_OFFLOAD_CURRENT_CONFIG 0xFC01020E /* query only */
+#define OID_TCP_CONNECTION_OFFLOAD_HARDWARE_CAPABILITIES 0xFC01020F /* query */
+#define OID_OFFLOAD_ENCAPSULATION 0x0101010A /* set/query */
+
+struct ndis_offload_params {
+ struct ndis_oject_header header;
+ u8 ip_v4_csum;
+ u8 tcp_ip_v4_csum;
+ u8 udp_ip_v4_csum;
+ u8 tcp_ip_v6_csum;
+ u8 udp_ip_v6_csum;
+ u8 lso_v1;
+ u8 ip_sec_v1;
+ u8 lso_v2_ipv4;
+ u8 lso_v2_ipv6;
+ u8 tcp_connection_ip_v4;
+ u8 tcp_connection_ip_v6;
+ u32 flags;
+ u8 ip_sec_v2;
+ u8 ip_sec_v2_ip_v4;
+ struct {
+ u8 rsc_ip_v4;
+ u8 rsc_ip_v6;
+ };
+ struct {
+ u8 encapsulated_packet_task_offload;
+ u8 encapsulation_types;
+ };
+};
+
#define NDIS_VLAN_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \
sizeof(struct ndis_pkt_8021q_info))
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index dcbf144ea7da..9b02f21097a7 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -627,6 +627,61 @@ cleanup:
return ret;
}
+int rndis_filter_set_offload_params(struct hv_device *hdev,
+ struct ndis_offload_params *req_offloads)
+{
+ struct netvsc_device *nvdev = hv_get_drvdata(hdev);
+ struct rndis_device *rdev = nvdev->extension;
+ struct net_device *ndev = nvdev->ndev;
+ struct rndis_request *request;
+ struct rndis_set_request *set;
+ struct ndis_offload_params *offload_params;
+ struct rndis_set_complete *set_complete;
+ u32 extlen = sizeof(struct ndis_offload_params);
+ int ret, t;
+
+ request = get_rndis_request(rdev, RNDIS_MSG_SET,
+ RNDIS_MESSAGE_SIZE(struct rndis_set_request) + extlen);
+ if (!request)
+ return -ENOMEM;
+
+ set = &request->request_msg.msg.set_req;
+ set->oid = OID_TCP_OFFLOAD_PARAMETERS;
+ set->info_buflen = extlen;
+ set->info_buf_offset = sizeof(struct rndis_set_request);
+ set->dev_vc_handle = 0;
+
+ offload_params = (struct ndis_offload_params *)((ulong)set +
+ set->info_buf_offset);
+ *offload_params = *req_offloads;
+ offload_params->header.type = NDIS_OBJECT_TYPE_DEFAULT;
+ offload_params->header.revision = NDIS_OFFLOAD_PARAMETERS_REVISION_3;
+ offload_params->header.size = extlen;
+
+ ret = rndis_filter_send_request(rdev, request);
+ if (ret != 0)
+ goto cleanup;
+
+ t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
+ if (t == 0) {
+ netdev_err(ndev, "timeout before we got aOFFLOAD set response...\n");
+ /* can't put_rndis_request, since we may still receive a
+ * send-completion.
+ */
+ return -EBUSY;
+ } else {
+ set_complete = &request->response_msg.msg.set_complete;
+ if (set_complete->status != RNDIS_STATUS_SUCCESS) {
+ netdev_err(ndev, "Fail to set MAC on host side:0x%x\n",
+ set_complete->status);
+ ret = -EINVAL;
+ }
+ }
+
+cleanup:
+ put_rndis_request(rdev, request);
+ return ret;
+}
static int rndis_filter_query_device_link_status(struct rndis_device *dev)
{
@@ -826,6 +881,7 @@ int rndis_filter_device_add(struct hv_device *dev,
struct netvsc_device *net_device;
struct rndis_device *rndis_device;
struct netvsc_device_info *device_info = additional_info;
+ struct ndis_offload_params offloads;
rndis_device = get_rndis_device();
if (!rndis_device)
@@ -865,6 +921,26 @@ int rndis_filter_device_add(struct hv_device *dev,
memcpy(device_info->mac_adr, rndis_device->hw_mac_adr, ETH_ALEN);
+ /* Turn on the offloads; the host supports all of the relevant
+ * offloads.
+ */
+ memset(&offloads, 0, sizeof(struct ndis_offload_params));
+ /* A value of zero means "no change"; now turn on what we
+ * want.
+ */
+ offloads.ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
+ offloads.tcp_ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
+ offloads.udp_ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
+ offloads.tcp_ip_v6_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
+ offloads.udp_ip_v6_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
+ offloads.lso_v2_ipv4 = NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED;
+
+
+ ret = rndis_filter_set_offload_params(dev, &offloads);
+ if (ret)
+ goto err_dev_remv;
+
+
rndis_filter_query_device_link_status(rndis_device);
device_info->link_state = rndis_device->link_state;
@@ -874,6 +950,10 @@ int rndis_filter_device_add(struct hv_device *dev,
device_info->link_state ? "down" : "up");
return ret;
+
+err_dev_remv:
+ rndis_filter_device_remove(dev);
+ return ret;
}
void rndis_filter_device_remove(struct hv_device *dev)
--
2.4.3

View File

@@ -1,93 +0,0 @@
From 307f099520b66504cf6c5638f3f404c48b9fb45b Mon Sep 17 00:00:00 2001
From: Haiyang Zhang <haiyangz@microsoft.com>
Date: Wed, 21 May 2014 12:55:39 -0700
Subject: [PATCH 07/11] hyperv: Add hash value into RNDIS Per-packet info
It passes the hash value as the RNDIS Per-packet info to the Hyper-V host,
so that the send completion notices can be spread across multiple channels.
MS-TFS: 140273
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/hyperv/hyperv_net.h | 4 ++++
drivers/net/hyperv/netvsc_drv.c | 18 ++++++++++++++----
2 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 4b7df5a5c966..6cc37c15e0bf 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -791,6 +791,7 @@ enum ndis_per_pkt_info_type {
IEEE_8021Q_INFO,
ORIGINAL_PKTINFO,
PACKET_CANCEL_ID,
+ NBL_HASH_VALUE = PACKET_CANCEL_ID,
ORIGINAL_NET_BUFLIST,
CACHED_NET_BUFLIST,
SHORT_PKT_PADINFO,
@@ -937,6 +938,9 @@ struct ndis_tcp_lso_info {
#define NDIS_LSO_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \
sizeof(struct ndis_tcp_lso_info))
+#define NDIS_HASH_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \
+ sizeof(u32))
+
/* Format of Information buffer passed in a SetRequest for the OID */
/* OID_GEN_RNDIS_CONFIG_PARAMETER. */
struct rndis_config_parameter_info {
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 2e967a7bdb33..4fd71b75e666 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -224,9 +224,11 @@ static u16 netvsc_select_queue(struct net_device *ndev, struct sk_buff *skb,
if (nvsc_dev == NULL || ndev->real_num_tx_queues <= 1)
return 0;
- if (netvsc_set_hash(&hash, skb))
+ if (netvsc_set_hash(&hash, skb)) {
q_idx = nvsc_dev->send_table[hash % VRSS_SEND_TAB_SIZE] %
ndev->real_num_tx_queues;
+ skb_set_hash(skb, hash, PKT_HASH_TYPE_L3);
+ }
return q_idx;
}
@@ -384,6 +386,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
struct ndis_tcp_lso_info *lso_info;
int hdr_offset;
u32 net_trans_info;
+ u32 hash;
/* We will atmost need two pages to describe the rndis
@@ -402,9 +405,8 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
packet = kzalloc(sizeof(struct hv_netvsc_packet) +
(num_data_pgs * sizeof(struct hv_page_buffer)) +
sizeof(struct rndis_message) +
- NDIS_VLAN_PPI_SIZE +
- NDIS_CSUM_PPI_SIZE +
- NDIS_LSO_PPI_SIZE, GFP_ATOMIC);
+ NDIS_VLAN_PPI_SIZE + NDIS_CSUM_PPI_SIZE +
+ NDIS_LSO_PPI_SIZE + NDIS_HASH_PPI_SIZE, GFP_ATOMIC);
if (!packet) {
/* out of memory, drop packet */
netdev_err(net, "unable to allocate hv_netvsc_packet\n");
@@ -443,6 +445,14 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
rndis_msg_size = RNDIS_MESSAGE_SIZE(struct rndis_packet);
+ hash = skb_get_hash_raw(skb);
+ if (hash != 0 && net->real_num_tx_queues > 1) {
+ rndis_msg_size += NDIS_HASH_PPI_SIZE;
+ ppi = init_ppi_data(rndis_msg, NDIS_HASH_PPI_SIZE,
+ NBL_HASH_VALUE);
+ *(u32 *)((void *)ppi + ppi->ppi_offset) = hash;
+ }
+
if (isvlan) {
struct ndis_pkt_8021q_info *vlan;
--
2.4.3

View File

@@ -1,147 +0,0 @@
From 59e0c70c618668522a9431686f7e3a69ef396dff Mon Sep 17 00:00:00 2001
From: KY Srinivasan <kys@microsoft.com>
Date: Sat, 8 Mar 2014 19:23:16 -0800
Subject: [PATCH 08/25] Drivers: net: hyperv: Enable receive side IP checksum
offload
Enable receive side checksum offload.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/hyperv/hyperv_net.h | 33 ++++++++++++++++++++++++++++++++-
drivers/net/hyperv/netvsc_drv.c | 19 +++++++++++++++----
drivers/net/hyperv/rndis_filter.c | 4 +++-
3 files changed, 50 insertions(+), 6 deletions(-)
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 8bc4e766589b..faeb74623fbd 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -30,6 +30,7 @@
/* Fwd declaration */
struct hv_netvsc_packet;
+struct ndis_tcp_ip_checksum_info;
/* Represent the xfer page packet which contains 1 or more netvsc packet */
struct xferpage_packet {
@@ -117,7 +118,8 @@ int netvsc_send(struct hv_device *device,
void netvsc_linkstatus_callback(struct hv_device *device_obj,
unsigned int status);
int netvsc_recv_callback(struct hv_device *device_obj,
- struct hv_netvsc_packet *packet);
+ struct hv_netvsc_packet *packet,
+ struct ndis_tcp_ip_checksum_info *csum_info);
int rndis_filter_open(struct hv_device *dev);
int rndis_filter_close(struct hv_device *dev);
int rndis_filter_device_add(struct hv_device *dev,
@@ -776,9 +778,38 @@ struct ndis_offload_params {
};
};
+struct ndis_tcp_ip_checksum_info {
+ union {
+ struct {
+ u32 is_ipv4:1;
+ u32 is_ipv6:1;
+ u32 tcp_checksum:1;
+ u32 udp_checksum:1;
+ u32 ip_header_checksum:1;
+ u32 reserved:11;
+ u32 tcp_header_offset:10;
+ } transmit;
+ struct {
+ u32 tcp_checksum_failed:1;
+ u32 udp_checksum_failed:1;
+ u32 ip_checksum_failed:1;
+ u32 tcp_checksum_succeeded:1;
+ u32 udp_checksum_succeeded:1;
+ u32 ip_checksum_succeeded:1;
+ u32 loopback:1;
+ u32 tcp_checksum_value_invalid:1;
+ u32 ip_checksum_value_invalid:1;
+ } receive;
+ u32 value;
+ };
+};
+
#define NDIS_VLAN_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \
sizeof(struct ndis_pkt_8021q_info))
+#define NDIS_CSUM_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \
+ sizeof(struct ndis_tcp_ip_checksum_info))
+
/* Format of Information buffer passed in a SetRequest for the OID */
/* OID_GEN_RNDIS_CONFIG_PARAMETER. */
struct rndis_config_parameter_info {
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 87293a15e470..7438360b7a02 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -392,7 +392,8 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj,
* "wire" on the specified device.
*/
int netvsc_recv_callback(struct hv_device *device_obj,
- struct hv_netvsc_packet *packet)
+ struct hv_netvsc_packet *packet,
+ struct ndis_tcp_ip_checksum_info *csum_info)
{
struct net_device *net;
struct sk_buff *skb;
@@ -419,7 +420,17 @@ int netvsc_recv_callback(struct hv_device *device_obj,
packet->total_data_buflen);
skb->protocol = eth_type_trans(skb, net);
- skb->ip_summed = CHECKSUM_NONE;
+ if (csum_info) {
+ /* We only look at the IP checksum here.
+ * Should we be dropping the packet if checksum
+ * failed? How do we deal with other checksums - TCP/UDP?
+ */
+ if (csum_info->receive.ip_checksum_succeeded)
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ else
+ skb->ip_summed = CHECKSUM_NONE;
+ }
+
if (packet->vlan_tci & VLAN_TAG_PRESENT)
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
packet->vlan_tci);
@@ -581,8 +592,8 @@ static int netvsc_probe(struct hv_device *dev,
net->netdev_ops = &device_ops;
/* TODO: Add GSO and Checksum offload */
- net->hw_features = NETIF_F_SG;
- net->features = NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_SG;
+ net->hw_features = NETIF_F_RXCSUM | NETIF_F_SG;
+ net->features = NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_SG | NETIF_F_RXCSUM;
SET_ETHTOOL_OPS(net, &ethtool_ops);
SET_NETDEV_DEV(net, &dev->device);
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 9b02f21097a7..4a37e3db9e32 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -370,6 +370,7 @@ static void rndis_filter_receive_data(struct rndis_device *dev,
struct rndis_packet *rndis_pkt;
u32 data_offset;
struct ndis_pkt_8021q_info *vlan;
+ struct ndis_tcp_ip_checksum_info *csum_info;
rndis_pkt = &msg->msg.pkt;
@@ -408,7 +409,8 @@ static void rndis_filter_receive_data(struct rndis_device *dev,
pkt->vlan_tci = 0;
}
- netvsc_recv_callback(dev->net_dev->dev, pkt);
+ csum_info = rndis_get_ppi(rndis_pkt, TCPIP_CHKSUM_PKTINFO);
+ netvsc_recv_callback(dev->net_dev->dev, pkt, csum_info);
}
int rndis_filter_receive(struct hv_device *dev,
--
2.4.3

View File

@@ -1,32 +0,0 @@
From 2f18423d7ebf8044a9edaca840be5ae199fb32f6 Mon Sep 17 00:00:00 2001
From: Dave Jones <davej@redhat.com>
Date: Mon, 16 Jun 2014 16:59:02 -0400
Subject: [PATCH 08/11] hyperv: fix apparent cut-n-paste error in send path
teardown
c25aaf814a63: "hyperv: Enable sendbuf mechanism on the send path" added
some teardown code that looks like it was copied from the recieve path
above, but missed a variable name replacement.
Signed-off-by: Dave Jones <davej@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/hyperv/netvsc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index c041f63a6d30..4ed38eaecea8 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -189,7 +189,7 @@ static int netvsc_destroy_buf(struct netvsc_device *net_device)
"unable to teardown send buffer's gpadl\n");
return ret;
}
- net_device->recv_buf_gpadl_handle = 0;
+ net_device->send_buf_gpadl_handle = 0;
}
if (net_device->send_buf) {
/* Free up the receive buffer */
--
2.4.3

View File

@@ -1,140 +0,0 @@
From d2a0be7f4263eb669af84240c5424a72cce4cdb4 Mon Sep 17 00:00:00 2001
From: KY Srinivasan <kys@microsoft.com>
Date: Sat, 8 Mar 2014 19:23:17 -0800
Subject: [PATCH 09/25] Drivers: net: hyperv: Enable send side checksum offload
Enable send side checksum offload.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/hyperv/hyperv_net.h | 10 ++++++
drivers/net/hyperv/netvsc_drv.c | 69 +++++++++++++++++++++++++++++++++++++++--
2 files changed, 77 insertions(+), 2 deletions(-)
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index faeb74623fbd..4cf238234321 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -1035,6 +1035,16 @@ struct rndis_message {
#define NDIS_PACKET_TYPE_FUNCTIONAL 0x00000400
#define NDIS_PACKET_TYPE_MAC_FRAME 0x00000800
+#define INFO_IPV4 2
+#define INFO_IPV6 4
+#define INFO_TCP 2
+#define INFO_UDP 4
+
+#define TRANSPORT_INFO_NOT_IP 0
+#define TRANSPORT_INFO_IPV4_TCP ((INFO_IPV4 << 16) | INFO_TCP)
+#define TRANSPORT_INFO_IPV4_UDP ((INFO_IPV4 << 16) | INFO_UDP)
+#define TRANSPORT_INFO_IPV6_TCP ((INFO_IPV6 << 16) | INFO_TCP)
+#define TRANSPORT_INFO_IPV6_UDP ((INFO_IPV6 << 16) | INFO_UDP)
#endif /* _HYPERV_NET_H */
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 7438360b7a02..2fab69ac61ef 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -257,6 +257,35 @@ static int netvsc_get_slots(struct sk_buff *skb)
return slots + frag_slots;
}
+static u32 get_net_transport_info(struct sk_buff *skb, u32 *trans_off)
+{
+ u32 ret_val = TRANSPORT_INFO_NOT_IP;
+
+ if ((eth_hdr(skb)->h_proto != htons(ETH_P_IP)) &&
+ (eth_hdr(skb)->h_proto != htons(ETH_P_IPV6))) {
+ goto not_ip;
+ }
+
+ *trans_off = skb_transport_offset(skb);
+
+ if ((eth_hdr(skb)->h_proto == htons(ETH_P_IP))) {
+ struct iphdr *iphdr = ip_hdr(skb);
+
+ if (iphdr->protocol == IPPROTO_TCP)
+ ret_val = TRANSPORT_INFO_IPV4_TCP;
+ else if (iphdr->protocol == IPPROTO_UDP)
+ ret_val = TRANSPORT_INFO_IPV4_UDP;
+ } else {
+ if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
+ ret_val = TRANSPORT_INFO_IPV6_TCP;
+ else if (ipv6_hdr(skb)->nexthdr == IPPROTO_UDP)
+ ret_val = TRANSPORT_INFO_IPV6_UDP;
+ }
+
+not_ip:
+ return ret_val;
+}
+
static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
{
struct net_device_context *net_device_ctx = netdev_priv(net);
@@ -269,6 +298,10 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
u32 rndis_msg_size;
bool isvlan;
struct rndis_per_packet_info *ppi;
+ struct ndis_tcp_ip_checksum_info *csum_info;
+ int hdr_offset;
+ u32 net_trans_info;
+
/* We will atmost need two pages to describe the rndis
* header. We can only transmit MAX_PAGE_BUFFER_COUNT number
@@ -336,6 +369,37 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
VLAN_PRIO_SHIFT;
}
+ net_trans_info = get_net_transport_info(skb, &hdr_offset);
+ if (net_trans_info == TRANSPORT_INFO_NOT_IP)
+ goto do_send;
+
+ /*
+ * Setup the sendside checksum offload only if this is not a
+ * GSO packet.
+ */
+ if (skb_is_gso(skb))
+ goto do_send;
+
+ rndis_msg_size += NDIS_CSUM_PPI_SIZE;
+ ppi = init_ppi_data(rndis_msg, NDIS_CSUM_PPI_SIZE,
+ TCPIP_CHKSUM_PKTINFO);
+
+ csum_info = (struct ndis_tcp_ip_checksum_info *)((void *)ppi +
+ ppi->ppi_offset);
+
+ if (net_trans_info & (INFO_IPV4 << 16))
+ csum_info->transmit.is_ipv4 = 1;
+ else
+ csum_info->transmit.is_ipv6 = 1;
+
+ if (net_trans_info & INFO_TCP) {
+ csum_info->transmit.tcp_checksum = 1;
+ csum_info->transmit.tcp_header_offset = hdr_offset;
+ } else if (net_trans_info & INFO_UDP) {
+ csum_info->transmit.udp_checksum = 1;
+ }
+
+do_send:
/* Start filling in the page buffers with the rndis hdr */
rndis_msg->msg_len += rndis_msg_size;
packet->page_buf_cnt = init_page_array(rndis_msg, rndis_msg_size,
@@ -592,8 +656,9 @@ static int netvsc_probe(struct hv_device *dev,
net->netdev_ops = &device_ops;
/* TODO: Add GSO and Checksum offload */
- net->hw_features = NETIF_F_RXCSUM | NETIF_F_SG;
- net->features = NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_SG | NETIF_F_RXCSUM;
+ net->hw_features = NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_IP_CSUM;
+ net->features = NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_SG | NETIF_F_RXCSUM |
+ NETIF_F_IP_CSUM;
SET_ETHTOOL_OPS(net, &ethtool_ops);
SET_NETDEV_DEV(net, &dev->device);
--
2.4.3

View File

@@ -1,34 +0,0 @@
From dd1d3f8f9920926aa426589e542eed6bf58b7354 Mon Sep 17 00:00:00 2001
From: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
Date: Wed, 23 Jul 2014 09:00:35 +0800
Subject: [PATCH 09/11] hyperv: Fix error return code in netvsc_init_buf()
Fix to return -ENOMEM from the kalloc error handling
case instead of 0.
Signed-off-by: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/hyperv/netvsc.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 4ed38eaecea8..d97d5f39a04e 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -378,8 +378,10 @@ static int netvsc_init_buf(struct hv_device *device)
net_device->send_section_map =
kzalloc(net_device->map_words * sizeof(ulong), GFP_KERNEL);
- if (net_device->send_section_map == NULL)
+ if (net_device->send_section_map == NULL) {
+ ret = -ENOMEM;
goto cleanup;
+ }
goto exit;
--
2.4.3

View File

@@ -1,153 +0,0 @@
From a4ec4f58017b456281ee17c35fb82dfe4eab2193 Mon Sep 17 00:00:00 2001
From: KY Srinivasan <kys@microsoft.com>
Date: Sat, 8 Mar 2014 19:23:18 -0800
Subject: [PATCH 10/25] Drivers: net: hyperv: Enable large send offload
Enable segmentation offload.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/hyperv/hyperv_net.h | 40 ++++++++++++++++++++++++++++++++++++++++
drivers/net/hyperv/netvsc_drv.c | 38 ++++++++++++++++++++++++++++++++++----
2 files changed, 74 insertions(+), 4 deletions(-)
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 4cf238234321..7d06b4959383 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -742,6 +742,10 @@ struct ndis_oject_header {
#define NDIS_OFFLOAD_PARAMETERS_RX_ENABLED_TX_DISABLED 3
#define NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED 4
+#define NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE 1
+#define NDIS_TCP_LARGE_SEND_OFFLOAD_IPV4 0
+#define NDIS_TCP_LARGE_SEND_OFFLOAD_IPV6 1
+
/*
* New offload OIDs for NDIS 6
*/
@@ -804,12 +808,48 @@ struct ndis_tcp_ip_checksum_info {
};
};
+struct ndis_tcp_lso_info {
+ union {
+ struct {
+ u32 unused:30;
+ u32 type:1;
+ u32 reserved2:1;
+ } transmit;
+ struct {
+ u32 mss:20;
+ u32 tcp_header_offset:10;
+ u32 type:1;
+ u32 reserved2:1;
+ } lso_v1_transmit;
+ struct {
+ u32 tcp_payload:30;
+ u32 type:1;
+ u32 reserved2:1;
+ } lso_v1_transmit_complete;
+ struct {
+ u32 mss:20;
+ u32 tcp_header_offset:10;
+ u32 type:1;
+ u32 ip_version:1;
+ } lso_v2_transmit;
+ struct {
+ u32 reserved:30;
+ u32 type:1;
+ u32 reserved2:1;
+ } lso_v2_transmit_complete;
+ u32 value;
+ };
+};
+
#define NDIS_VLAN_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \
sizeof(struct ndis_pkt_8021q_info))
#define NDIS_CSUM_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \
sizeof(struct ndis_tcp_ip_checksum_info))
+#define NDIS_LSO_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \
+ sizeof(struct ndis_tcp_lso_info))
+
/* Format of Information buffer passed in a SetRequest for the OID */
/* OID_GEN_RNDIS_CONFIG_PARAMETER. */
struct rndis_config_parameter_info {
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 2fab69ac61ef..5baa1fa7e692 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -299,6 +299,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
bool isvlan;
struct rndis_per_packet_info *ppi;
struct ndis_tcp_ip_checksum_info *csum_info;
+ struct ndis_tcp_lso_info *lso_info;
int hdr_offset;
u32 net_trans_info;
@@ -378,7 +379,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
* GSO packet.
*/
if (skb_is_gso(skb))
- goto do_send;
+ goto do_lso;
rndis_msg_size += NDIS_CSUM_PPI_SIZE;
ppi = init_ppi_data(rndis_msg, NDIS_CSUM_PPI_SIZE,
@@ -398,6 +399,35 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
} else if (net_trans_info & INFO_UDP) {
csum_info->transmit.udp_checksum = 1;
}
+ goto do_send;
+
+do_lso:
+ rndis_msg_size += NDIS_LSO_PPI_SIZE;
+ 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->lso_v2_transmit.type = NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE;
+ if (net_trans_info & (INFO_IPV4 << 16)) {
+ lso_info->lso_v2_transmit.ip_version =
+ NDIS_TCP_LARGE_SEND_OFFLOAD_IPV4;
+ ip_hdr(skb)->tot_len = 0;
+ ip_hdr(skb)->check = 0;
+ tcp_hdr(skb)->check =
+ ~csum_tcpudp_magic(ip_hdr(skb)->saddr,
+ ip_hdr(skb)->daddr, 0, IPPROTO_TCP, 0);
+ } else {
+ lso_info->lso_v2_transmit.ip_version =
+ NDIS_TCP_LARGE_SEND_OFFLOAD_IPV6;
+ ipv6_hdr(skb)->payload_len = 0;
+ tcp_hdr(skb)->check =
+ ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
+ &ipv6_hdr(skb)->daddr, 0, IPPROTO_TCP, 0);
+ }
+ lso_info->lso_v2_transmit.tcp_header_offset = hdr_offset;
+ lso_info->lso_v2_transmit.mss = skb_shinfo(skb)->gso_size;
do_send:
/* Start filling in the page buffers with the rndis hdr */
@@ -655,10 +685,10 @@ static int netvsc_probe(struct hv_device *dev,
net->netdev_ops = &device_ops;
- /* TODO: Add GSO and Checksum offload */
- net->hw_features = NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_IP_CSUM;
+ net->hw_features = NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_IP_CSUM |
+ NETIF_F_TSO;
net->features = NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_SG | NETIF_F_RXCSUM |
- NETIF_F_IP_CSUM;
+ NETIF_F_IP_CSUM | NETIF_F_TSO;
SET_ETHTOOL_OPS(net, &ethtool_ops);
SET_NETDEV_DEV(net, &dev->device);
--
2.4.3

View File

@@ -1,47 +0,0 @@
From b3e774263908a834c1c0d5abf3a7658280e42fc7 Mon Sep 17 00:00:00 2001
From: KY Srinivasan <kys@microsoft.com>
Date: Sun, 28 Sep 2014 22:16:43 -0700
Subject: [PATCH 10/11] hyperv: Fix a bug in netvsc_start_xmit()
[ Upstream commit dedb845ded56ded1c62f5398a94ffa8615d4592d ]
After the packet is successfully sent, we should not touch the skb
as it may have been freed. This patch is based on the work done by
Long Li <longli@microsoft.com>.
In this version of the patch I have fixed issues pointed out by David.
David, please queue this up for stable.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Tested-by: Long Li <longli@microsoft.com>
Tested-by: Sitsofe Wheeler <sitsofe@yahoo.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/hyperv/netvsc_drv.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 4fd71b75e666..f15297201777 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -387,6 +387,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
int hdr_offset;
u32 net_trans_info;
u32 hash;
+ u32 skb_length = skb->len;
/* We will atmost need two pages to describe the rndis
@@ -562,7 +563,7 @@ do_send:
drop:
if (ret == 0) {
- net->stats.tx_bytes += skb->len;
+ net->stats.tx_bytes += skb_length;
net->stats.tx_packets++;
} else {
kfree(packet);
--
2.4.3

View File

@@ -1,54 +0,0 @@
From 56b3f72d3fed7f9b8d17dcf5d81455fa1b4327d7 Mon Sep 17 00:00:00 2001
From: Haiyang Zhang <haiyangz@microsoft.com>
Date: Sun, 9 Mar 2014 16:10:59 -0700
Subject: [PATCH 11/25] hyperv: Change the receive buffer size for legacy hosts
Due to a bug in the Hyper-V host verion 2008R2, we need to use a slightly smaller
receive buffer size, otherwise the buffer will not be accepted by the legacy hosts.
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/hyperv/hyperv_net.h | 1 +
drivers/net/hyperv/netvsc.c | 6 +++++-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 7d06b4959383..13010b4dae5b 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -513,6 +513,7 @@ struct nvsp_message {
#define NETVSC_MTU 65536
#define NETVSC_RECEIVE_BUFFER_SIZE (1024*1024*16) /* 16MB */
+#define NETVSC_RECEIVE_BUFFER_SIZE_LEGACY (1024*1024*15) /* 15MB */
#define NETVSC_RECEIVE_BUFFER_ID 0xcafe
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 1a0280dcba7e..daddea2654ce 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -365,6 +365,11 @@ static int netvsc_connect_vsp(struct hv_device *device)
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;
+
ret = netvsc_init_recv_buf(device);
cleanup:
@@ -898,7 +903,6 @@ int netvsc_device_add(struct hv_device *device, void *additional_info)
ndev = net_device->ndev;
/* Initialize the NetVSC channel extension */
- net_device->recv_buf_size = NETVSC_RECEIVE_BUFFER_SIZE;
spin_lock_init(&net_device->recv_pkt_list_lock);
INIT_LIST_HEAD(&net_device->recv_pkt_list);
--
2.4.3

View File

@@ -1,68 +0,0 @@
From 26875bba869bd91a1d8fef9229a56a1e6d9fef2b Mon Sep 17 00:00:00 2001
From: KY Srinivasan <kys@microsoft.com>
Date: Sun, 5 Oct 2014 10:42:51 -0700
Subject: [PATCH 11/11] hyperv: Fix a bug in netvsc_send()
[ Upstream commit 3a67c9ccad926a168d8b7891537a452018368a5b ]
After the packet is successfully sent, we should not touch the packet
as it may have been freed. This patch is based on the work done by
Long Li <longli@microsoft.com>.
David, please queue this up for stable.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reported-by: Sitsofe Wheeler <sitsofe@yahoo.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/hyperv/netvsc.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index d97d5f39a04e..7edf976ecfa0 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -708,6 +708,7 @@ int netvsc_send(struct hv_device *device,
unsigned int section_index = NETVSC_INVALID_INDEX;
u32 msg_size = 0;
struct sk_buff *skb;
+ u16 q_idx = packet->q_idx;
net_device = get_outbound_net_device(device);
@@ -772,24 +773,24 @@ int netvsc_send(struct hv_device *device,
if (ret == 0) {
atomic_inc(&net_device->num_outstanding_sends);
- atomic_inc(&net_device->queue_sends[packet->q_idx]);
+ atomic_inc(&net_device->queue_sends[q_idx]);
if (hv_ringbuf_avail_percent(&out_channel->outbound) <
RING_AVAIL_PERCENT_LOWATER) {
netif_tx_stop_queue(netdev_get_tx_queue(
- ndev, packet->q_idx));
+ ndev, q_idx));
if (atomic_read(&net_device->
- queue_sends[packet->q_idx]) < 1)
+ queue_sends[q_idx]) < 1)
netif_tx_wake_queue(netdev_get_tx_queue(
- ndev, packet->q_idx));
+ ndev, q_idx));
}
} else if (ret == -EAGAIN) {
netif_tx_stop_queue(netdev_get_tx_queue(
- ndev, packet->q_idx));
- if (atomic_read(&net_device->queue_sends[packet->q_idx]) < 1) {
+ ndev, q_idx));
+ if (atomic_read(&net_device->queue_sends[q_idx]) < 1) {
netif_tx_wake_queue(netdev_get_tx_queue(
- ndev, packet->q_idx));
+ ndev, q_idx));
ret = -ENOSPC;
}
} else {
--
2.4.3

View File

@@ -1,34 +0,0 @@
From e0f6906eb7e5b395370da9499189d13b59020382 Mon Sep 17 00:00:00 2001
From: KY Srinivasan <kys@microsoft.com>
Date: Wed, 9 Apr 2014 15:00:45 -0700
Subject: [PATCH 12/25] Drivers: net: hyperv: Allocate memory for all possible
per-pecket information
An outgoing packet can potentially need per-packet information for
all the offloads and VLAN tagging. Fix this issue.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/hyperv/netvsc_drv.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 5baa1fa7e692..c76c85176644 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -320,7 +320,9 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
packet = kzalloc(sizeof(struct hv_netvsc_packet) +
(num_data_pgs * sizeof(struct hv_page_buffer)) +
sizeof(struct rndis_message) +
- NDIS_VLAN_PPI_SIZE, GFP_ATOMIC);
+ NDIS_VLAN_PPI_SIZE +
+ NDIS_CSUM_PPI_SIZE +
+ NDIS_LSO_PPI_SIZE, GFP_ATOMIC);
if (!packet) {
/* out of memory, drop packet */
netdev_err(net, "unable to allocate hv_netvsc_packet\n");
--
2.4.3

View File

@@ -1,32 +0,0 @@
From 8a7882bada78e7d7355aafc0ca3c5696d25eb443 Mon Sep 17 00:00:00 2001
From: KY Srinivasan <kys@microsoft.com>
Date: Wed, 9 Apr 2014 15:00:46 -0700
Subject: [PATCH 13/25] Drivers: net: hyperv: Negotiate suitable ndis version
for offload support
Ws2008R2 supports ndis_version 6.1 and 6.1 is the minimal version required
for various offloads. Negotiate ndis_version 6.1 when on ws2008r2.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/hyperv/netvsc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index daddea2654ce..f7629ecefa84 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -344,7 +344,7 @@ static int netvsc_connect_vsp(struct hv_device *device)
memset(init_packet, 0, sizeof(struct nvsp_message));
if (net_device->nvsp_version <= NVSP_PROTOCOL_VERSION_4)
- ndis_version = 0x00050001;
+ ndis_version = 0x00060001;
else
ndis_version = 0x0006001e;
--
2.4.3

View File

@@ -1,111 +0,0 @@
From b822ee7a17efd1bc8c7584da5d0a2c042e9ca5b6 Mon Sep 17 00:00:00 2001
From: KY Srinivasan <kys@microsoft.com>
Date: Wed, 9 Apr 2014 15:00:47 -0700
Subject: [PATCH 14/25] Drivers: net: hyperv: Address UDP checksum issues
ws2008r2 does not support UDP checksum offload. Thus, we cannnot turn on
UDP offload in the host. Also, on ws2012 and ws2012 r2, there appear to be
an issue with UDP checksum offload.
Fix this issue by computing the UDP checksum in the Hyper-V driver.
Based on Dave Miller's comments, in this version, I have COWed the skb
before modifying the UDP header (the checksum field).
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/hyperv/hyperv_net.h | 1 +
drivers/net/hyperv/netvsc_drv.c | 26 +++++++++++++++++++++++++-
drivers/net/hyperv/rndis_filter.c | 12 +++++++++++-
3 files changed, 37 insertions(+), 2 deletions(-)
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 13010b4dae5b..d18f711d0b0c 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -747,6 +747,7 @@ struct ndis_oject_header {
#define NDIS_TCP_LARGE_SEND_OFFLOAD_IPV4 0
#define NDIS_TCP_LARGE_SEND_OFFLOAD_IPV6 1
+#define VERSION_4_OFFLOAD_SIZE 22
/*
* New offload OIDs for NDIS 6
*/
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index c76c85176644..0d898876689e 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -399,7 +399,30 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
csum_info->transmit.tcp_checksum = 1;
csum_info->transmit.tcp_header_offset = hdr_offset;
} else if (net_trans_info & INFO_UDP) {
- csum_info->transmit.udp_checksum = 1;
+ /* UDP checksum offload is not supported on ws2008r2.
+ * Furthermore, on ws2012 and ws2012r2, there are some
+ * issues with udp checksum offload from Linux guests.
+ * (these are host issues).
+ * For now compute the checksum here.
+ */
+ struct udphdr *uh;
+ u16 udp_len;
+
+ ret = skb_cow_head(skb, 0);
+ if (ret)
+ goto drop;
+
+ uh = udp_hdr(skb);
+ udp_len = ntohs(uh->len);
+ uh->check = 0;
+ uh->check = csum_tcpudp_magic(ip_hdr(skb)->saddr,
+ ip_hdr(skb)->daddr,
+ udp_len, IPPROTO_UDP,
+ csum_partial(uh, udp_len, 0));
+ if (uh->check == 0)
+ uh->check = CSUM_MANGLED_0;
+
+ csum_info->transmit.udp_checksum = 0;
}
goto do_send;
@@ -439,6 +462,7 @@ do_send:
ret = netvsc_send(net_device_ctx->device_ctx, packet);
+drop:
if (ret == 0) {
net->stats.tx_bytes += skb_length;
net->stats.tx_packets++;
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 4a37e3db9e32..143a98caf618 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -641,6 +641,16 @@ int rndis_filter_set_offload_params(struct hv_device *hdev,
struct rndis_set_complete *set_complete;
u32 extlen = sizeof(struct ndis_offload_params);
int ret, t;
+ u32 vsp_version = nvdev->nvsp_version;
+
+ if (vsp_version <= NVSP_PROTOCOL_VERSION_4) {
+ extlen = VERSION_4_OFFLOAD_SIZE;
+ /* On NVSP_PROTOCOL_VERSION_4 and below, we do not support
+ * UDP checksum offload.
+ */
+ req_offloads->udp_ip_v4_csum = 0;
+ req_offloads->udp_ip_v6_csum = 0;
+ }
request = get_rndis_request(rdev, RNDIS_MSG_SET,
RNDIS_MESSAGE_SIZE(struct rndis_set_request) + extlen);
@@ -674,7 +684,7 @@ int rndis_filter_set_offload_params(struct hv_device *hdev,
} else {
set_complete = &request->response_msg.msg.set_complete;
if (set_complete->status != RNDIS_STATUS_SUCCESS) {
- netdev_err(ndev, "Fail to set MAC on host side:0x%x\n",
+ netdev_err(ndev, "Fail to set offload on host side:0x%x\n",
set_complete->status);
ret = -EINVAL;
}
--
2.4.3

View File

@@ -1,42 +0,0 @@
From 540360773bad2b81f14c38ca92b62797fa32cbc6 Mon Sep 17 00:00:00 2001
From: KY Srinivasan <kys@microsoft.com>
Date: Wed, 30 Apr 2014 11:58:25 -0700
Subject: [PATCH 15/25] hyperv: Properly handle checksum offload
Do checksum offload only if the client of the driver wants checksum to be
offloaded.
In V1 version of this patch, I addressed comments from
Stephen Hemminger <stephen@networkplumber.org> and
Eric Dumazet <eric.dumazet@gmail.com>.
In this version of the patch I have addressed comments from
David Miller.
This patch fixes a bug that is exposed in gateway scenarios.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/hyperv/netvsc_drv.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 0d898876689e..ce6d870dd7ae 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -383,6 +383,10 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
if (skb_is_gso(skb))
goto do_lso;
+ if ((skb->ip_summed == CHECKSUM_NONE) ||
+ (skb->ip_summed == CHECKSUM_UNNECESSARY))
+ goto do_send;
+
rndis_msg_size += NDIS_CSUM_PPI_SIZE;
ppi = init_ppi_data(rndis_msg, NDIS_CSUM_PPI_SIZE,
TCPIP_CHKSUM_PKTINFO);
--
2.4.3

View File

@@ -1,917 +0,0 @@
From 44559a96c6864eb6e95db0ae896c621b82e605f3 Mon Sep 17 00:00:00 2001
From: Haiyang Zhang <haiyangz@microsoft.com>
Date: Mon, 21 Apr 2014 10:20:28 -0700
Subject: [PATCH 16/25] hyperv: Add support for virtual Receive Side Scaling
(vRSS)
This feature allows multiple channels to be used by each virtual NIC.
It is available on Hyper-V host 2012 R2.
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/hyperv/hyperv_net.h | 110 +++++++++++++++++++++-
drivers/net/hyperv/netvsc.c | 136 +++++++++++++++++++++------
drivers/net/hyperv/netvsc_drv.c | 103 ++++++++++++++++++++-
drivers/net/hyperv/rndis_filter.c | 189 +++++++++++++++++++++++++++++++++++++-
4 files changed, 504 insertions(+), 34 deletions(-)
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index d18f711d0b0c..57eb3f906d64 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -28,6 +28,96 @@
#include <linux/hyperv.h>
#include <linux/rndis.h>
+/* RSS related */
+#define OID_GEN_RECEIVE_SCALE_CAPABILITIES 0x00010203 /* query only */
+#define OID_GEN_RECEIVE_SCALE_PARAMETERS 0x00010204 /* query and set */
+
+#define NDIS_OBJECT_TYPE_RSS_CAPABILITIES 0x88
+#define NDIS_OBJECT_TYPE_RSS_PARAMETERS 0x89
+
+#define NDIS_RECEIVE_SCALE_CAPABILITIES_REVISION_2 2
+#define NDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2 2
+
+struct ndis_obj_header {
+ u8 type;
+ u8 rev;
+ u16 size;
+} __packed;
+
+/* ndis_recv_scale_cap/cap_flag */
+#define NDIS_RSS_CAPS_MESSAGE_SIGNALED_INTERRUPTS 0x01000000
+#define NDIS_RSS_CAPS_CLASSIFICATION_AT_ISR 0x02000000
+#define NDIS_RSS_CAPS_CLASSIFICATION_AT_DPC 0x04000000
+#define NDIS_RSS_CAPS_USING_MSI_X 0x08000000
+#define NDIS_RSS_CAPS_RSS_AVAILABLE_ON_PORTS 0x10000000
+#define NDIS_RSS_CAPS_SUPPORTS_MSI_X 0x20000000
+#define NDIS_RSS_CAPS_HASH_TYPE_TCP_IPV4 0x00000100
+#define NDIS_RSS_CAPS_HASH_TYPE_TCP_IPV6 0x00000200
+#define NDIS_RSS_CAPS_HASH_TYPE_TCP_IPV6_EX 0x00000400
+
+struct ndis_recv_scale_cap { /* NDIS_RECEIVE_SCALE_CAPABILITIES */
+ struct ndis_obj_header hdr;
+ u32 cap_flag;
+ u32 num_int_msg;
+ u32 num_recv_que;
+ u16 num_indirect_tabent;
+} __packed;
+
+
+/* ndis_recv_scale_param flags */
+#define NDIS_RSS_PARAM_FLAG_BASE_CPU_UNCHANGED 0x0001
+#define NDIS_RSS_PARAM_FLAG_HASH_INFO_UNCHANGED 0x0002
+#define NDIS_RSS_PARAM_FLAG_ITABLE_UNCHANGED 0x0004
+#define NDIS_RSS_PARAM_FLAG_HASH_KEY_UNCHANGED 0x0008
+#define NDIS_RSS_PARAM_FLAG_DISABLE_RSS 0x0010
+
+/* Hash info bits */
+#define NDIS_HASH_FUNC_TOEPLITZ 0x00000001
+#define NDIS_HASH_IPV4 0x00000100
+#define NDIS_HASH_TCP_IPV4 0x00000200
+#define NDIS_HASH_IPV6 0x00000400
+#define NDIS_HASH_IPV6_EX 0x00000800
+#define NDIS_HASH_TCP_IPV6 0x00001000
+#define NDIS_HASH_TCP_IPV6_EX 0x00002000
+
+#define NDIS_RSS_INDIRECTION_TABLE_MAX_SIZE_REVISION_2 (128 * 4)
+#define NDIS_RSS_HASH_SECRET_KEY_MAX_SIZE_REVISION_2 40
+
+#define ITAB_NUM 128
+#define HASH_KEYLEN NDIS_RSS_HASH_SECRET_KEY_MAX_SIZE_REVISION_2
+extern u8 netvsc_hash_key[];
+
+struct ndis_recv_scale_param { /* NDIS_RECEIVE_SCALE_PARAMETERS */
+ struct ndis_obj_header hdr;
+
+ /* Qualifies the rest of the information */
+ u16 flag;
+
+ /* The base CPU number to do receive processing. not used */
+ u16 base_cpu_number;
+
+ /* This describes the hash function and type being enabled */
+ u32 hashinfo;
+
+ /* The size of indirection table array */
+ u16 indirect_tabsize;
+
+ /* The offset of the indirection table from the beginning of this
+ * structure
+ */
+ u32 indirect_taboffset;
+
+ /* The size of the hash secret key */
+ u16 hashkey_size;
+
+ /* The offset of the secret key from the beginning of this structure */
+ u32 kashkey_offset;
+
+ u32 processor_masks_offset;
+ u32 num_processor_masks;
+ u32 processor_masks_entry_size;
+};
+
/* Fwd declaration */
struct hv_netvsc_packet;
struct ndis_tcp_ip_checksum_info;
@@ -39,6 +129,8 @@ struct xferpage_packet {
/* # of netvsc packets this xfer packet contains */
u32 count;
+
+ struct vmbus_channel *channel;
};
/*
@@ -54,6 +146,9 @@ struct hv_netvsc_packet {
bool is_data_pkt;
u16 vlan_tci;
+ u16 q_idx;
+ struct vmbus_channel *channel;
+
/*
* Valid only for receives when we break a xfer page packet
* into multiple netvsc packets
@@ -120,6 +215,7 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj,
int netvsc_recv_callback(struct hv_device *device_obj,
struct hv_netvsc_packet *packet,
struct ndis_tcp_ip_checksum_info *csum_info);
+void netvsc_channel_cb(void *context);
int rndis_filter_open(struct hv_device *dev);
int rndis_filter_close(struct hv_device *dev);
int rndis_filter_device_add(struct hv_device *dev,
@@ -522,6 +618,8 @@ struct nvsp_message {
#define NETVSC_PACKET_SIZE 2048
+#define VRSS_SEND_TAB_SIZE 16
+
/* Per netvsc channel-specific */
struct netvsc_device {
struct hv_device *dev;
@@ -555,10 +653,20 @@ struct netvsc_device {
struct net_device *ndev;
+ struct vmbus_channel *chn_table[NR_CPUS];
+ u32 send_table[VRSS_SEND_TAB_SIZE];
+ u32 num_chn;
+ atomic_t queue_sends[NR_CPUS];
+
/* Holds rndis device info */
void *extension;
- /* The recive buffer for this device */
+
+ int ring_size;
+
+ /* The primary channel callback buffer */
unsigned char cb_buffer[NETVSC_PACKET_SIZE];
+ /* The sub channel callback buffer */
+ unsigned char *sub_cb_buf;
};
/* NdisInitialize message */
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index f7629ecefa84..e7e77f12bc38 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -422,6 +422,9 @@ int netvsc_device_remove(struct hv_device *device)
kfree(netvsc_packet);
}
+ if (net_device->sub_cb_buf)
+ vfree(net_device->sub_cb_buf);
+
kfree(net_device);
return 0;
}
@@ -461,7 +464,9 @@ static void netvsc_send_completion(struct netvsc_device *net_device,
(nvsp_packet->hdr.msg_type ==
NVSP_MSG1_TYPE_SEND_RECV_BUF_COMPLETE) ||
(nvsp_packet->hdr.msg_type ==
- NVSP_MSG1_TYPE_SEND_SEND_BUF_COMPLETE)) {
+ NVSP_MSG1_TYPE_SEND_SEND_BUF_COMPLETE) ||
+ (nvsp_packet->hdr.msg_type ==
+ NVSP_MSG5_TYPE_SUBCHANNEL)) {
/* Copy the response back */
memcpy(&net_device->channel_init_pkt, nvsp_packet,
sizeof(struct nvsp_message));
@@ -469,28 +474,37 @@ static void netvsc_send_completion(struct netvsc_device *net_device,
} else if (nvsp_packet->hdr.msg_type ==
NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE) {
int num_outstanding_sends;
+ u16 q_idx = 0;
+ struct vmbus_channel *channel = device->channel;
+ int queue_sends;
/* Get the send context */
nvsc_packet = (struct hv_netvsc_packet *)(unsigned long)
packet->trans_id;
/* Notify the layer above us */
- if (nvsc_packet)
+ if (nvsc_packet) {
+ q_idx = nvsc_packet->q_idx;
+ channel = nvsc_packet->channel;
nvsc_packet->completion.send.send_completion(
nvsc_packet->completion.send.
send_completion_ctx);
+ }
num_outstanding_sends =
atomic_dec_return(&net_device->num_outstanding_sends);
+ queue_sends = atomic_dec_return(&net_device->
+ queue_sends[q_idx]);
if (net_device->destroy && num_outstanding_sends == 0)
wake_up(&net_device->wait_drain);
- if (netif_queue_stopped(ndev) && !net_device->start_remove &&
- (hv_ringbuf_avail_percent(&device->channel->outbound)
- > RING_AVAIL_PERCENT_HIWATER ||
- num_outstanding_sends < 1))
- netif_wake_queue(ndev);
+ if (netif_tx_queue_stopped(netdev_get_tx_queue(ndev, q_idx)) &&
+ !net_device->start_remove &&
+ (hv_ringbuf_avail_percent(&channel->outbound) >
+ RING_AVAIL_PERCENT_HIWATER || queue_sends < 1))
+ netif_tx_wake_queue(netdev_get_tx_queue(
+ ndev, q_idx));
} else {
netdev_err(ndev, "Unknown send completion packet type- "
"%d received!!\n", nvsp_packet->hdr.msg_type);
@@ -505,6 +519,7 @@ int netvsc_send(struct hv_device *device,
int ret = 0;
struct nvsp_message sendMessage;
struct net_device *ndev;
+ struct vmbus_channel *out_channel = NULL;
u64 req_id;
net_device = get_outbound_net_device(device);
@@ -531,15 +546,20 @@ int netvsc_send(struct hv_device *device,
else
req_id = 0;
+ out_channel = net_device->chn_table[packet->q_idx];
+ if (out_channel == NULL)
+ out_channel = device->channel;
+ packet->channel = out_channel;
+
if (packet->page_buf_cnt) {
- ret = vmbus_sendpacket_pagebuffer(device->channel,
+ ret = vmbus_sendpacket_pagebuffer(out_channel,
packet->page_buf,
packet->page_buf_cnt,
&sendMessage,
sizeof(struct nvsp_message),
req_id);
} else {
- ret = vmbus_sendpacket(device->channel, &sendMessage,
+ ret = vmbus_sendpacket(out_channel, &sendMessage,
sizeof(struct nvsp_message),
req_id,
VM_PKT_DATA_INBAND,
@@ -548,17 +568,24 @@ int netvsc_send(struct hv_device *device,
if (ret == 0) {
atomic_inc(&net_device->num_outstanding_sends);
- if (hv_ringbuf_avail_percent(&device->channel->outbound) <
+ atomic_inc(&net_device->queue_sends[packet->q_idx]);
+
+ if (hv_ringbuf_avail_percent(&out_channel->outbound) <
RING_AVAIL_PERCENT_LOWATER) {
- netif_stop_queue(ndev);
+ netif_tx_stop_queue(netdev_get_tx_queue(
+ ndev, packet->q_idx));
+
if (atomic_read(&net_device->
- num_outstanding_sends) < 1)
- netif_wake_queue(ndev);
+ queue_sends[packet->q_idx]) < 1)
+ netif_tx_wake_queue(netdev_get_tx_queue(
+ ndev, packet->q_idx));
}
} else if (ret == -EAGAIN) {
- netif_stop_queue(ndev);
- if (atomic_read(&net_device->num_outstanding_sends) < 1) {
- netif_wake_queue(ndev);
+ netif_tx_stop_queue(netdev_get_tx_queue(
+ ndev, packet->q_idx));
+ if (atomic_read(&net_device->queue_sends[packet->q_idx]) < 1) {
+ netif_tx_wake_queue(netdev_get_tx_queue(
+ ndev, packet->q_idx));
ret = -ENOSPC;
}
} else {
@@ -570,6 +597,7 @@ int netvsc_send(struct hv_device *device,
}
static void netvsc_send_recv_completion(struct hv_device *device,
+ struct vmbus_channel *channel,
struct netvsc_device *net_device,
u64 transaction_id, u32 status)
{
@@ -587,7 +615,7 @@ static void netvsc_send_recv_completion(struct hv_device *device,
retry_send_cmplt:
/* Send the completion */
- ret = vmbus_sendpacket(device->channel, &recvcompMessage,
+ ret = vmbus_sendpacket(channel, &recvcompMessage,
sizeof(struct nvsp_message), transaction_id,
VM_PKT_COMP, 0);
if (ret == 0) {
@@ -618,6 +646,7 @@ static void netvsc_receive_completion(void *context)
{
struct hv_netvsc_packet *packet = context;
struct hv_device *device = packet->device;
+ struct vmbus_channel *channel;
struct netvsc_device *net_device;
u64 transaction_id = 0;
bool fsend_receive_comp = false;
@@ -649,6 +678,7 @@ static void netvsc_receive_completion(void *context)
*/
if (packet->xfer_page_pkt->count == 0) {
fsend_receive_comp = true;
+ channel = packet->xfer_page_pkt->channel;
transaction_id = packet->completion.recv.recv_completion_tid;
status = packet->xfer_page_pkt->status;
list_add_tail(&packet->xfer_page_pkt->list_ent,
@@ -662,12 +692,13 @@ static void netvsc_receive_completion(void *context)
/* Send a receive completion for the xfer page packet */
if (fsend_receive_comp)
- netvsc_send_recv_completion(device, net_device, transaction_id,
- status);
+ netvsc_send_recv_completion(device, channel, net_device,
+ transaction_id, status);
}
static void netvsc_receive(struct netvsc_device *net_device,
+ struct vmbus_channel *channel,
struct hv_device *device,
struct vmpacket_descriptor *packet)
{
@@ -748,7 +779,7 @@ static void netvsc_receive(struct netvsc_device *net_device,
spin_unlock_irqrestore(&net_device->recv_pkt_list_lock,
flags);
- netvsc_send_recv_completion(device, net_device,
+ netvsc_send_recv_completion(device, channel, net_device,
vmxferpage_packet->d.trans_id,
NVSP_STAT_FAIL);
@@ -759,6 +790,7 @@ static void netvsc_receive(struct netvsc_device *net_device,
xferpage_packet = (struct xferpage_packet *)listHead.next;
list_del(&xferpage_packet->list_ent);
xferpage_packet->status = NVSP_STAT_SUCCESS;
+ xferpage_packet->channel = channel;
/* This is how much we can satisfy */
xferpage_packet->count = count - 1;
@@ -800,10 +832,45 @@ static void netvsc_receive(struct netvsc_device *net_device,
}
-static void netvsc_channel_cb(void *context)
+
+static void netvsc_send_table(struct hv_device *hdev,
+ struct vmpacket_descriptor *vmpkt)
+{
+ struct netvsc_device *nvscdev;
+ struct net_device *ndev;
+ struct nvsp_message *nvmsg;
+ int i;
+ u32 count, *tab;
+
+ nvscdev = get_outbound_net_device(hdev);
+ if (!nvscdev)
+ return;
+ ndev = nvscdev->ndev;
+
+ nvmsg = (struct nvsp_message *)((unsigned long)vmpkt +
+ (vmpkt->offset8 << 3));
+
+ if (nvmsg->hdr.msg_type != NVSP_MSG5_TYPE_SEND_INDIRECTION_TABLE)
+ return;
+
+ count = nvmsg->msg.v5_msg.send_table.count;
+ if (count != VRSS_SEND_TAB_SIZE) {
+ netdev_err(ndev, "Received wrong send-table size:%u\n", count);
+ return;
+ }
+
+ tab = (u32 *)((unsigned long)&nvmsg->msg.v5_msg.send_table +
+ nvmsg->msg.v5_msg.send_table.offset);
+
+ for (i = 0; i < count; i++)
+ nvscdev->send_table[i] = tab[i];
+}
+
+void netvsc_channel_cb(void *context)
{
int ret;
- struct hv_device *device = context;
+ struct vmbus_channel *channel = (struct vmbus_channel *)context;
+ struct hv_device *device;
struct netvsc_device *net_device;
u32 bytes_recvd;
u64 request_id;
@@ -812,14 +879,19 @@ static void netvsc_channel_cb(void *context)
int bufferlen = NETVSC_PACKET_SIZE;
struct net_device *ndev;
+ if (channel->primary_channel != NULL)
+ device = channel->primary_channel->device_obj;
+ else
+ device = channel->device_obj;
+
net_device = get_inbound_net_device(device);
if (!net_device)
return;
ndev = net_device->ndev;
- buffer = net_device->cb_buffer;
+ buffer = get_per_channel_state(channel);
do {
- ret = vmbus_recvpacket_raw(device->channel, buffer, bufferlen,
+ ret = vmbus_recvpacket_raw(channel, buffer, bufferlen,
&bytes_recvd, &request_id);
if (ret == 0) {
if (bytes_recvd > 0) {
@@ -831,8 +903,12 @@ static void netvsc_channel_cb(void *context)
break;
case VM_PKT_DATA_USING_XFER_PAGES:
- netvsc_receive(net_device,
- device, desc);
+ netvsc_receive(net_device, channel,
+ device, desc);
+ break;
+
+ case VM_PKT_DATA_INBAND:
+ netvsc_send_table(device, desc);
break;
default:
@@ -893,6 +969,8 @@ int netvsc_device_add(struct hv_device *device, void *additional_info)
goto cleanup;
}
+ net_device->ring_size = ring_size;
+
/*
* Coming into this function, struct net_device * is
* registered as the driver private data.
@@ -917,10 +995,12 @@ int netvsc_device_add(struct hv_device *device, void *additional_info)
}
init_completion(&net_device->channel_init_wait);
+ set_per_channel_state(device->channel, net_device->cb_buffer);
+
/* Open the channel */
ret = vmbus_open(device->channel, ring_size * PAGE_SIZE,
ring_size * PAGE_SIZE, NULL, 0,
- netvsc_channel_cb, device);
+ netvsc_channel_cb, device->channel);
if (ret != 0) {
netdev_err(ndev, "unable to open channel: %d\n", ret);
@@ -930,6 +1010,8 @@ int netvsc_device_add(struct hv_device *device, void *additional_info)
/* Channel is opened */
pr_info("hv_netvsc channel opened successfully\n");
+ net_device->chn_table[0] = device->channel;
+
/* Connect with the NetVsp */
ret = netvsc_connect_vsp(device);
if (ret != 0) {
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index ce6d870dd7ae..e486dbd33f61 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -101,7 +101,7 @@ static int netvsc_open(struct net_device *net)
return ret;
}
- netif_start_queue(net);
+ netif_tx_start_all_queues(net);
nvdev = hv_get_drvdata(device_obj);
rdev = nvdev->extension;
@@ -149,6 +149,88 @@ static void *init_ppi_data(struct rndis_message *msg, u32 ppi_size,
return ppi;
}
+union sub_key {
+ u64 k;
+ struct {
+ u8 pad[3];
+ u8 kb;
+ u32 ka;
+ };
+};
+
+/* Toeplitz hash function
+ * data: network byte order
+ * return: host byte order
+ */
+static u32 comp_hash(u8 *key, int klen, u8 *data, int dlen)
+{
+ union sub_key subk;
+ int k_next = 4;
+ u8 dt;
+ int i, j;
+ u32 ret = 0;
+
+ subk.k = 0;
+ subk.ka = ntohl(*(u32 *)key);
+
+ for (i = 0; i < dlen; i++) {
+ subk.kb = key[k_next];
+ k_next = (k_next + 1) % klen;
+ dt = data[i];
+ for (j = 0; j < 8; j++) {
+ if (dt & 0x80)
+ ret ^= subk.ka;
+ dt <<= 1;
+ subk.k <<= 1;
+ }
+ }
+
+ return ret;
+}
+
+static bool netvsc_set_hash(u32 *hash, struct sk_buff *skb)
+{
+ struct iphdr *iphdr;
+ int data_len;
+ bool ret = false;
+
+ if (eth_hdr(skb)->h_proto != htons(ETH_P_IP))
+ return false;
+
+ iphdr = ip_hdr(skb);
+
+ if (iphdr->version == 4) {
+ if (iphdr->protocol == IPPROTO_TCP)
+ data_len = 12;
+ else
+ data_len = 8;
+ *hash = comp_hash(netvsc_hash_key, HASH_KEYLEN,
+ (u8 *)&iphdr->saddr, data_len);
+ ret = true;
+ }
+
+ return ret;
+}
+
+static u16 netvsc_select_queue(struct net_device *ndev, struct sk_buff *skb,
+ void *accel_priv, select_queue_fallback_t fallback)
+{
+ struct net_device_context *net_device_ctx = netdev_priv(ndev);
+ struct hv_device *hdev = net_device_ctx->device_ctx;
+ struct netvsc_device *nvsc_dev = hv_get_drvdata(hdev);
+ u32 hash;
+ u16 q_idx = 0;
+
+ if (nvsc_dev == NULL || ndev->real_num_tx_queues <= 1)
+ return 0;
+
+ if (netvsc_set_hash(&hash, skb))
+ q_idx = nvsc_dev->send_table[hash % VRSS_SEND_TAB_SIZE] %
+ ndev->real_num_tx_queues;
+
+ return q_idx;
+}
+
static void netvsc_xmit_completion(void *context)
{
struct hv_netvsc_packet *packet = (struct hv_netvsc_packet *)context;
@@ -334,6 +416,8 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
packet->vlan_tci = skb->vlan_tci;
+ packet->q_idx = skb_get_queue_mapping(skb);
+
packet->is_data_pkt = true;
packet->total_data_buflen = skb->len;
@@ -559,6 +643,10 @@ int netvsc_recv_callback(struct hv_device *device_obj,
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
packet->vlan_tci);
+ skb_record_rx_queue(skb, packet->xfer_page_pkt->channel->
+ offermsg.offer.sub_channel_index %
+ net->real_num_rx_queues);
+
net->stats.rx_packets++;
net->stats.rx_bytes += packet->total_data_buflen;
@@ -607,7 +695,7 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
hv_set_drvdata(hdev, ndev);
device_info.ring_size = ring_size;
rndis_filter_device_add(hdev, &device_info);
- netif_wake_queue(ndev);
+ netif_tx_wake_all_queues(ndev);
return 0;
}
@@ -653,6 +741,7 @@ static const struct net_device_ops device_ops = {
.ndo_change_mtu = netvsc_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = netvsc_set_mac_addr,
+ .ndo_select_queue = netvsc_select_queue,
};
/*
@@ -699,9 +788,11 @@ static int netvsc_probe(struct hv_device *dev,
struct net_device *net = NULL;
struct net_device_context *net_device_ctx;
struct netvsc_device_info device_info;
+ struct netvsc_device *nvdev;
int ret;
- net = alloc_etherdev(sizeof(struct net_device_context));
+ net = alloc_etherdev_mq(sizeof(struct net_device_context),
+ num_online_cpus());
if (!net)
return -ENOMEM;
@@ -734,6 +825,12 @@ static int netvsc_probe(struct hv_device *dev,
}
memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN);
+ nvdev = hv_get_drvdata(dev);
+ netif_set_real_num_tx_queues(net, nvdev->num_chn);
+ netif_set_real_num_rx_queues(net, nvdev->num_chn);
+ dev_info(&dev->device, "real num tx,rx queues:%u, %u\n",
+ net->real_num_tx_queues, net->real_num_rx_queues);
+
ret = register_netdev(net);
if (ret != 0) {
pr_err("Unable to register netdev.\n");
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 143a98caf618..d92cfbe43410 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -31,7 +31,7 @@
#include "hyperv_net.h"
-#define RNDIS_EXT_LEN 100
+#define RNDIS_EXT_LEN PAGE_SIZE
struct rndis_request {
struct list_head list_ent;
struct completion wait_event;
@@ -94,6 +94,8 @@ static struct rndis_request *get_rndis_request(struct rndis_device *dev,
rndis_msg->ndis_msg_type = msg_type;
rndis_msg->msg_len = msg_len;
+ request->pkt.q_idx = 0;
+
/*
* Set the request id. This field is always after the rndis header for
* request/response packet types so we just used the SetRequest as a
@@ -509,6 +511,19 @@ static int rndis_filter_query_device(struct rndis_device *dev, u32 oid,
query->info_buflen = 0;
query->dev_vc_handle = 0;
+ if (oid == OID_GEN_RECEIVE_SCALE_CAPABILITIES) {
+ struct ndis_recv_scale_cap *cap;
+
+ request->request_msg.msg_len +=
+ sizeof(struct ndis_recv_scale_cap);
+ query->info_buflen = sizeof(struct ndis_recv_scale_cap);
+ cap = (struct ndis_recv_scale_cap *)((unsigned long)query +
+ query->info_buf_offset);
+ cap->hdr.type = NDIS_OBJECT_TYPE_RSS_CAPABILITIES;
+ cap->hdr.rev = NDIS_RECEIVE_SCALE_CAPABILITIES_REVISION_2;
+ cap->hdr.size = sizeof(struct ndis_recv_scale_cap);
+ }
+
ret = rndis_filter_send_request(dev, request);
if (ret != 0)
goto cleanup;
@@ -695,6 +710,89 @@ cleanup:
return ret;
}
+u8 netvsc_hash_key[HASH_KEYLEN] = {
+ 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
+ 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
+ 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
+ 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
+ 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa
+};
+
+int rndis_filter_set_rss_param(struct rndis_device *rdev, int num_queue)
+{
+ struct net_device *ndev = rdev->net_dev->ndev;
+ struct rndis_request *request;
+ struct rndis_set_request *set;
+ struct rndis_set_complete *set_complete;
+ u32 extlen = sizeof(struct ndis_recv_scale_param) +
+ 4*ITAB_NUM + HASH_KEYLEN;
+ struct ndis_recv_scale_param *rssp;
+ u32 *itab;
+ u8 *keyp;
+ int i, t, ret;
+
+ request = get_rndis_request(
+ rdev, RNDIS_MSG_SET,
+ RNDIS_MESSAGE_SIZE(struct rndis_set_request) + extlen);
+ if (!request)
+ return -ENOMEM;
+
+ set = &request->request_msg.msg.set_req;
+ set->oid = OID_GEN_RECEIVE_SCALE_PARAMETERS;
+ set->info_buflen = extlen;
+ set->info_buf_offset = sizeof(struct rndis_set_request);
+ set->dev_vc_handle = 0;
+
+ rssp = (struct ndis_recv_scale_param *)(set + 1);
+ rssp->hdr.type = NDIS_OBJECT_TYPE_RSS_PARAMETERS;
+ rssp->hdr.rev = NDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2;
+ rssp->hdr.size = sizeof(struct ndis_recv_scale_param);
+ rssp->flag = 0;
+ rssp->hashinfo = NDIS_HASH_FUNC_TOEPLITZ | NDIS_HASH_IPV4 |
+ NDIS_HASH_TCP_IPV4;
+ rssp->indirect_tabsize = 4*ITAB_NUM;
+ rssp->indirect_taboffset = sizeof(struct ndis_recv_scale_param);
+ rssp->hashkey_size = HASH_KEYLEN;
+ rssp->kashkey_offset = rssp->indirect_taboffset +
+ rssp->indirect_tabsize;
+
+ /* Set indirection table entries */
+ itab = (u32 *)(rssp + 1);
+ for (i = 0; i < ITAB_NUM; i++)
+ itab[i] = i % num_queue;
+
+ /* Set hask key values */
+ keyp = (u8 *)((unsigned long)rssp + rssp->kashkey_offset);
+ for (i = 0; i < HASH_KEYLEN; i++)
+ keyp[i] = netvsc_hash_key[i];
+
+
+ ret = rndis_filter_send_request(rdev, request);
+ if (ret != 0)
+ goto cleanup;
+
+ t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
+ if (t == 0) {
+ netdev_err(ndev, "timeout before we got a set response...\n");
+ /* can't put_rndis_request, since we may still receive a
+ * send-completion.
+ */
+ return -ETIMEDOUT;
+ } else {
+ set_complete = &request->response_msg.msg.set_complete;
+ if (set_complete->status != RNDIS_STATUS_SUCCESS) {
+ netdev_err(ndev, "Fail to set RSS parameters:0x%x\n",
+ set_complete->status);
+ ret = -EINVAL;
+ }
+ }
+
+cleanup:
+ put_rndis_request(rdev, request);
+ return ret;
+}
+
+
static int rndis_filter_query_device_link_status(struct rndis_device *dev)
{
u32 size = sizeof(u32);
@@ -886,6 +984,28 @@ static int rndis_filter_close_device(struct rndis_device *dev)
return ret;
}
+static void netvsc_sc_open(struct vmbus_channel *new_sc)
+{
+ struct netvsc_device *nvscdev;
+ u16 chn_index = new_sc->offermsg.offer.sub_channel_index;
+ int ret;
+
+ nvscdev = hv_get_drvdata(new_sc->primary_channel->device_obj);
+
+ if (chn_index >= nvscdev->num_chn)
+ return;
+
+ set_per_channel_state(new_sc, nvscdev->sub_cb_buf + (chn_index - 1) *
+ NETVSC_PACKET_SIZE);
+
+ ret = vmbus_open(new_sc, nvscdev->ring_size * PAGE_SIZE,
+ nvscdev->ring_size * PAGE_SIZE, NULL, 0,
+ netvsc_channel_cb, new_sc);
+
+ if (ret == 0)
+ nvscdev->chn_table[chn_index] = new_sc;
+}
+
int rndis_filter_device_add(struct hv_device *dev,
void *additional_info)
{
@@ -894,6 +1014,10 @@ int rndis_filter_device_add(struct hv_device *dev,
struct rndis_device *rndis_device;
struct netvsc_device_info *device_info = additional_info;
struct ndis_offload_params offloads;
+ struct nvsp_message *init_packet;
+ int t;
+ struct ndis_recv_scale_cap rsscap;
+ u32 rsscap_size = sizeof(struct ndis_recv_scale_cap);
rndis_device = get_rndis_device();
if (!rndis_device)
@@ -913,6 +1037,7 @@ int rndis_filter_device_add(struct hv_device *dev,
/* Initialize the rndis device */
net_device = hv_get_drvdata(dev);
+ net_device->num_chn = 1;
net_device->extension = rndis_device;
rndis_device->net_dev = net_device;
@@ -952,7 +1077,6 @@ int rndis_filter_device_add(struct hv_device *dev,
if (ret)
goto err_dev_remv;
-
rndis_filter_query_device_link_status(rndis_device);
device_info->link_state = rndis_device->link_state;
@@ -961,7 +1085,66 @@ int rndis_filter_device_add(struct hv_device *dev,
rndis_device->hw_mac_adr,
device_info->link_state ? "down" : "up");
- return ret;
+ if (net_device->nvsp_version < NVSP_PROTOCOL_VERSION_5)
+ return 0;
+
+ /* vRSS setup */
+ memset(&rsscap, 0, rsscap_size);
+ ret = rndis_filter_query_device(rndis_device,
+ OID_GEN_RECEIVE_SCALE_CAPABILITIES,
+ &rsscap, &rsscap_size);
+ if (ret || rsscap.num_recv_que < 2)
+ goto out;
+
+ net_device->num_chn = (num_online_cpus() < rsscap.num_recv_que) ?
+ num_online_cpus() : rsscap.num_recv_que;
+ if (net_device->num_chn == 1)
+ goto out;
+
+ net_device->sub_cb_buf = vzalloc((net_device->num_chn - 1) *
+ NETVSC_PACKET_SIZE);
+ if (!net_device->sub_cb_buf) {
+ net_device->num_chn = 1;
+ dev_info(&dev->device, "No memory for subchannels.\n");
+ goto out;
+ }
+
+ vmbus_set_sc_create_callback(dev->channel, netvsc_sc_open);
+
+ 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;
+ t = wait_for_completion_timeout(&net_device->channel_init_wait, 5*HZ);
+ if (t == 0) {
+ ret = -ETIMEDOUT;
+ goto out;
+ }
+ if (init_packet->msg.v5_msg.subchn_comp.status !=
+ NVSP_STAT_SUCCESS) {
+ ret = -ENODEV;
+ goto out;
+ }
+ net_device->num_chn = 1 +
+ init_packet->msg.v5_msg.subchn_comp.num_subchannels;
+
+ vmbus_are_subchannels_present(dev->channel);
+
+ ret = rndis_filter_set_rss_param(rndis_device, net_device->num_chn);
+
+out:
+ if (ret)
+ net_device->num_chn = 1;
+ return 0; /* return 0 because primary channel can be used alone */
err_dev_remv:
rndis_filter_device_remove(dev);
--
2.4.3

View File

@@ -1,384 +0,0 @@
From d6bf5567c1438b4f3b1bcff1a1525ddb1754df19 Mon Sep 17 00:00:00 2001
From: Haiyang Zhang <haiyangz@microsoft.com>
Date: Mon, 21 Apr 2014 14:54:43 -0700
Subject: [PATCH 17/25] hyperv: Remove recv_pkt_list and lock
Removed recv_pkt_list and lock, and updated related code, so that
the locking overhead is reduced especially when multiple channels
are in use.
The recv_pkt_list isn't actually necessary because the packets are
processed sequentially in each channel. It has been replaced by a
local variable, and the related lock for this list is also removed.
The is_data_pkt field is not used in receive path, so its assignment
is cleaned up.
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/hyperv/hyperv_net.h | 33 --------
drivers/net/hyperv/netvsc.c | 174 +++-----------------------------------
drivers/net/hyperv/netvsc_drv.c | 2 +-
drivers/net/hyperv/rndis_filter.c | 2 -
4 files changed, 13 insertions(+), 198 deletions(-)
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 57eb3f906d64..a1af0f7711e2 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -119,27 +119,14 @@ struct ndis_recv_scale_param { /* NDIS_RECEIVE_SCALE_PARAMETERS */
};
/* Fwd declaration */
-struct hv_netvsc_packet;
struct ndis_tcp_ip_checksum_info;
-/* Represent the xfer page packet which contains 1 or more netvsc packet */
-struct xferpage_packet {
- struct list_head list_ent;
- u32 status;
-
- /* # of netvsc packets this xfer packet contains */
- u32 count;
-
- struct vmbus_channel *channel;
-};
-
/*
* Represent netvsc packet which contains 1 RNDIS and 1 ethernet frame
* within the RNDIS
*/
struct hv_netvsc_packet {
/* Bookkeeping stuff */
- struct list_head list_ent;
u32 status;
struct hv_device *device;
@@ -149,19 +136,8 @@ struct hv_netvsc_packet {
u16 q_idx;
struct vmbus_channel *channel;
- /*
- * Valid only for receives when we break a xfer page packet
- * into multiple netvsc packets
- */
- struct xferpage_packet *xfer_page_pkt;
-
union {
struct {
- u64 recv_completion_tid;
- void *recv_completion_ctx;
- void (*recv_completion)(void *context);
- } recv;
- struct {
u64 send_completion_tid;
void *send_completion_ctx;
void (*send_completion)(void *context);
@@ -613,9 +589,6 @@ struct nvsp_message {
#define NETVSC_RECEIVE_BUFFER_ID 0xcafe
-/* Preallocated receive packets */
-#define NETVSC_RECEIVE_PACKETLIST_COUNT 256
-
#define NETVSC_PACKET_SIZE 2048
#define VRSS_SEND_TAB_SIZE 16
@@ -630,12 +603,6 @@ struct netvsc_device {
wait_queue_head_t wait_drain;
bool start_remove;
bool destroy;
- /*
- * List of free preallocated hv_netvsc_packet to represent receive
- * packet
- */
- struct list_head recv_pkt_list;
- spinlock_t recv_pkt_list_lock;
/* Receive buffer allocated by us but manages by NetVSP */
void *recv_buf;
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index e7e77f12bc38..b10334773b32 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -387,7 +387,6 @@ static void netvsc_disconnect_vsp(struct netvsc_device *net_device)
int netvsc_device_remove(struct hv_device *device)
{
struct netvsc_device *net_device;
- struct hv_netvsc_packet *netvsc_packet, *pos;
unsigned long flags;
net_device = hv_get_drvdata(device);
@@ -416,12 +415,6 @@ int netvsc_device_remove(struct hv_device *device)
vmbus_close(device->channel);
/* Release all resources */
- list_for_each_entry_safe(netvsc_packet, pos,
- &net_device->recv_pkt_list, list_ent) {
- list_del(&netvsc_packet->list_ent);
- kfree(netvsc_packet);
- }
-
if (net_device->sub_cb_buf)
vfree(net_device->sub_cb_buf);
@@ -641,62 +634,6 @@ retry_send_cmplt:
}
}
-/* Send a receive completion packet to RNDIS device (ie NetVsp) */
-static void netvsc_receive_completion(void *context)
-{
- struct hv_netvsc_packet *packet = context;
- struct hv_device *device = packet->device;
- struct vmbus_channel *channel;
- struct netvsc_device *net_device;
- u64 transaction_id = 0;
- bool fsend_receive_comp = false;
- unsigned long flags;
- struct net_device *ndev;
- u32 status = NVSP_STAT_NONE;
-
- /*
- * Even though it seems logical to do a GetOutboundNetDevice() here to
- * send out receive completion, we are using GetInboundNetDevice()
- * since we may have disable outbound traffic already.
- */
- net_device = get_inbound_net_device(device);
- if (!net_device)
- return;
- ndev = net_device->ndev;
-
- /* Overloading use of the lock. */
- spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags);
-
- if (packet->status != NVSP_STAT_SUCCESS)
- packet->xfer_page_pkt->status = NVSP_STAT_FAIL;
-
- packet->xfer_page_pkt->count--;
-
- /*
- * Last one in the line that represent 1 xfer page packet.
- * Return the xfer page packet itself to the freelist
- */
- if (packet->xfer_page_pkt->count == 0) {
- fsend_receive_comp = true;
- channel = packet->xfer_page_pkt->channel;
- transaction_id = packet->completion.recv.recv_completion_tid;
- status = packet->xfer_page_pkt->status;
- list_add_tail(&packet->xfer_page_pkt->list_ent,
- &net_device->recv_pkt_list);
-
- }
-
- /* Put the packet back */
- list_add_tail(&packet->list_ent, &net_device->recv_pkt_list);
- spin_unlock_irqrestore(&net_device->recv_pkt_list_lock, flags);
-
- /* Send a receive completion for the xfer page packet */
- if (fsend_receive_comp)
- netvsc_send_recv_completion(device, channel, net_device,
- transaction_id, status);
-
-}
-
static void netvsc_receive(struct netvsc_device *net_device,
struct vmbus_channel *channel,
struct hv_device *device,
@@ -704,16 +641,13 @@ static void netvsc_receive(struct netvsc_device *net_device,
{
struct vmtransfer_page_packet_header *vmxferpage_packet;
struct nvsp_message *nvsp_packet;
- struct hv_netvsc_packet *netvsc_packet = NULL;
- /* struct netvsc_driver *netvscDriver; */
- struct xferpage_packet *xferpage_packet = NULL;
+ struct hv_netvsc_packet nv_pkt;
+ struct hv_netvsc_packet *netvsc_packet = &nv_pkt;
+ u32 status = NVSP_STAT_SUCCESS;
int i;
int count = 0;
- unsigned long flags;
struct net_device *ndev;
- LIST_HEAD(listHead);
-
ndev = net_device->ndev;
/*
@@ -746,78 +680,14 @@ static void netvsc_receive(struct netvsc_device *net_device,
return;
}
- /*
- * Grab free packets (range count + 1) to represent this xfer
- * page packet. +1 to represent the xfer page packet itself.
- * We grab it here so that we know exactly how many we can
- * fulfil
- */
- spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags);
- while (!list_empty(&net_device->recv_pkt_list)) {
- list_move_tail(net_device->recv_pkt_list.next, &listHead);
- if (++count == vmxferpage_packet->range_cnt + 1)
- break;
- }
- spin_unlock_irqrestore(&net_device->recv_pkt_list_lock, flags);
-
- /*
- * We need at least 2 netvsc pkts (1 to represent the xfer
- * page and at least 1 for the range) i.e. we can handled
- * some of the xfer page packet ranges...
- */
- if (count < 2) {
- netdev_err(ndev, "Got only %d netvsc pkt...needed "
- "%d pkts. Dropping this xfer page packet completely!\n",
- count, vmxferpage_packet->range_cnt + 1);
-
- /* Return it to the freelist */
- spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags);
- for (i = count; i != 0; i--) {
- list_move_tail(listHead.next,
- &net_device->recv_pkt_list);
- }
- spin_unlock_irqrestore(&net_device->recv_pkt_list_lock,
- flags);
-
- netvsc_send_recv_completion(device, channel, net_device,
- vmxferpage_packet->d.trans_id,
- NVSP_STAT_FAIL);
-
- return;
- }
-
- /* Remove the 1st packet to represent the xfer page packet itself */
- xferpage_packet = (struct xferpage_packet *)listHead.next;
- list_del(&xferpage_packet->list_ent);
- xferpage_packet->status = NVSP_STAT_SUCCESS;
- xferpage_packet->channel = channel;
-
- /* This is how much we can satisfy */
- xferpage_packet->count = count - 1;
-
- if (xferpage_packet->count != vmxferpage_packet->range_cnt) {
- netdev_err(ndev, "Needed %d netvsc pkts to satisfy "
- "this xfer page...got %d\n",
- vmxferpage_packet->range_cnt, xferpage_packet->count);
- }
+ count = vmxferpage_packet->range_cnt;
+ netvsc_packet->device = device;
+ netvsc_packet->channel = channel;
/* Each range represents 1 RNDIS pkt that contains 1 ethernet frame */
- for (i = 0; i < (count - 1); i++) {
- netvsc_packet = (struct hv_netvsc_packet *)listHead.next;
- list_del(&netvsc_packet->list_ent);
-
+ for (i = 0; i < count; i++) {
/* Initialize the netvsc packet */
netvsc_packet->status = NVSP_STAT_SUCCESS;
- netvsc_packet->xfer_page_pkt = xferpage_packet;
- netvsc_packet->completion.recv.recv_completion =
- netvsc_receive_completion;
- netvsc_packet->completion.recv.recv_completion_ctx =
- netvsc_packet;
- netvsc_packet->device = device;
- /* Save this so that we can send it back */
- netvsc_packet->completion.recv.recv_completion_tid =
- vmxferpage_packet->d.trans_id;
-
netvsc_packet->data = (void *)((unsigned long)net_device->
recv_buf + vmxferpage_packet->ranges[i].byte_offset);
netvsc_packet->total_data_buflen =
@@ -826,10 +696,12 @@ static void netvsc_receive(struct netvsc_device *net_device,
/* Pass it to the upper layer */
rndis_filter_receive(device, netvsc_packet);
- netvsc_receive_completion(netvsc_packet->
- completion.recv.recv_completion_ctx);
+ if (netvsc_packet->status != NVSP_STAT_SUCCESS)
+ status = NVSP_STAT_FAIL;
}
+ netvsc_send_recv_completion(device, channel, net_device,
+ vmxferpage_packet->d.trans_id, status);
}
@@ -956,11 +828,9 @@ void netvsc_channel_cb(void *context)
int netvsc_device_add(struct hv_device *device, void *additional_info)
{
int ret = 0;
- int i;
int ring_size =
((struct netvsc_device_info *)additional_info)->ring_size;
struct netvsc_device *net_device;
- struct hv_netvsc_packet *packet, *pos;
struct net_device *ndev;
net_device = alloc_net_device(device);
@@ -981,18 +851,6 @@ int netvsc_device_add(struct hv_device *device, void *additional_info)
ndev = net_device->ndev;
/* Initialize the NetVSC channel extension */
- spin_lock_init(&net_device->recv_pkt_list_lock);
-
- INIT_LIST_HEAD(&net_device->recv_pkt_list);
-
- for (i = 0; i < NETVSC_RECEIVE_PACKETLIST_COUNT; i++) {
- packet = kzalloc(sizeof(struct hv_netvsc_packet), GFP_KERNEL);
- if (!packet)
- break;
-
- list_add_tail(&packet->list_ent,
- &net_device->recv_pkt_list);
- }
init_completion(&net_device->channel_init_wait);
set_per_channel_state(device->channel, net_device->cb_buffer);
@@ -1028,16 +886,8 @@ close:
cleanup:
- if (net_device) {
- list_for_each_entry_safe(packet, pos,
- &net_device->recv_pkt_list,
- list_ent) {
- list_del(&packet->list_ent);
- kfree(packet);
- }
-
+ if (net_device)
kfree(net_device);
- }
return ret;
}
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index e486dbd33f61..6cc4db064fec 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -643,7 +643,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
packet->vlan_tci);
- skb_record_rx_queue(skb, packet->xfer_page_pkt->channel->
+ skb_record_rx_queue(skb, packet->channel->
offermsg.offer.sub_channel_index %
net->real_num_rx_queues);
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index d92cfbe43410..48f5a0fbd674 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -401,8 +401,6 @@ static void rndis_filter_receive_data(struct rndis_device *dev,
pkt->total_data_buflen = rndis_pkt->data_len;
pkt->data = (void *)((unsigned long)pkt->data + data_offset);
- pkt->is_data_pkt = true;
-
vlan = rndis_get_ppi(rndis_pkt, IEEE_8021Q_INFO);
if (vlan) {
pkt->vlan_tci = VLAN_TAG_PRESENT | vlan->vlanid |
--
2.4.3

View File

@@ -1,105 +0,0 @@
From d6eeeb452c1e6e7cf14f4a581a8f2ea2c50ec17a Mon Sep 17 00:00:00 2001
From: Haiyang Zhang <haiyangz@microsoft.com>
Date: Mon, 21 Apr 2014 14:54:44 -0700
Subject: [PATCH 18/25] hyperv: Simplify the send_completion variables
The union contains only one member now, so we use the variables in it directly.
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/hyperv/hyperv_net.h | 10 +++-------
drivers/net/hyperv/netvsc.c | 7 +++----
drivers/net/hyperv/netvsc_drv.c | 8 ++++----
drivers/net/hyperv/rndis_filter.c | 2 +-
4 files changed, 11 insertions(+), 16 deletions(-)
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index a1af0f7711e2..d1f7826aa75f 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -136,13 +136,9 @@ struct hv_netvsc_packet {
u16 q_idx;
struct vmbus_channel *channel;
- union {
- struct {
- u64 send_completion_tid;
- void *send_completion_ctx;
- void (*send_completion)(void *context);
- } send;
- } completion;
+ u64 send_completion_tid;
+ void *send_completion_ctx;
+ void (*send_completion)(void *context);
/* This points to the memory after page_buf */
struct rndis_message *rndis_msg;
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index b10334773b32..bbee44635035 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -479,9 +479,8 @@ static void netvsc_send_completion(struct netvsc_device *net_device,
if (nvsc_packet) {
q_idx = nvsc_packet->q_idx;
channel = nvsc_packet->channel;
- nvsc_packet->completion.send.send_completion(
- nvsc_packet->completion.send.
- send_completion_ctx);
+ nvsc_packet->send_completion(nvsc_packet->
+ send_completion_ctx);
}
num_outstanding_sends =
@@ -534,7 +533,7 @@ int netvsc_send(struct hv_device *device,
0xFFFFFFFF;
sendMessage.msg.v1_msg.send_rndis_pkt.send_buf_section_size = 0;
- if (packet->completion.send.send_completion)
+ if (packet->send_completion)
req_id = (ulong)packet;
else
req_id = 0;
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 6cc4db064fec..f3d3525ed42d 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -235,7 +235,7 @@ static void netvsc_xmit_completion(void *context)
{
struct hv_netvsc_packet *packet = (struct hv_netvsc_packet *)context;
struct sk_buff *skb = (struct sk_buff *)
- (unsigned long)packet->completion.send.send_completion_tid;
+ (unsigned long)packet->send_completion_tid;
kfree(packet);
@@ -426,9 +426,9 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
(num_data_pgs * sizeof(struct hv_page_buffer)));
/* Set the completion routine */
- packet->completion.send.send_completion = netvsc_xmit_completion;
- packet->completion.send.send_completion_ctx = packet;
- packet->completion.send.send_completion_tid = (unsigned long)skb;
+ packet->send_completion = netvsc_xmit_completion;
+ packet->send_completion_ctx = packet;
+ packet->send_completion_tid = (unsigned long)skb;
isvlan = packet->vlan_tci & VLAN_TAG_PRESENT;
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 48f5a0fbd674..99c527adae5b 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -236,7 +236,7 @@ static int rndis_filter_send_request(struct rndis_device *dev,
packet->page_buf[0].len;
}
- packet->completion.send.send_completion = NULL;
+ packet->send_completion = NULL;
ret = netvsc_send(dev->net_dev->dev, packet);
return ret;
--
2.4.3

View File

@@ -1,407 +0,0 @@
From 4685e50349d5dc5fe485c898ca3ce539e93a0118 Mon Sep 17 00:00:00 2001
From: KY Srinivasan <kys@microsoft.com>
Date: Wed, 30 Apr 2014 10:14:31 -0700
Subject: [PATCH 19/25] hyperv: Enable sendbuf mechanism on the send path
We send packets using a copy-free mechanism (this is the Guest to Host transport
via VMBUS). While this is obviously optimal for large packets,
it may not be optimal for small packets. Hyper-V host supports
a second mechanism for sending packets that is "copy based". We implement that
mechanism in this patch.
In this version of the patch I have addressed a comment from David Miller.
With this patch (and all of the other offload and VRSS patches), we are now able
to almost saturate a 10G interface between Linux VMs on Hyper-V
on different hosts - close to 9 Gbps as measured via iperf.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/hyperv/hyperv_net.h | 14 +++
drivers/net/hyperv/netvsc.c | 226 ++++++++++++++++++++++++++++++++++++++--
drivers/net/hyperv/netvsc_drv.c | 3 +-
3 files changed, 234 insertions(+), 9 deletions(-)
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index d1f7826aa75f..4b7df5a5c966 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -140,6 +140,8 @@ struct hv_netvsc_packet {
void *send_completion_ctx;
void (*send_completion)(void *context);
+ u32 send_buf_index;
+
/* This points to the memory after page_buf */
struct rndis_message *rndis_msg;
@@ -582,6 +584,9 @@ struct nvsp_message {
#define NETVSC_RECEIVE_BUFFER_SIZE (1024*1024*16) /* 16MB */
#define NETVSC_RECEIVE_BUFFER_SIZE_LEGACY (1024*1024*15) /* 15MB */
+#define NETVSC_SEND_BUFFER_SIZE (1024 * 1024) /* 1MB */
+#define NETVSC_INVALID_INDEX -1
+
#define NETVSC_RECEIVE_BUFFER_ID 0xcafe
@@ -607,6 +612,15 @@ struct netvsc_device {
u32 recv_section_cnt;
struct nvsp_1_receive_buffer_section *recv_section;
+ /* 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;
+ unsigned long *send_section_map;
+ int map_words;
+
/* Used for NetVSP initialization protocol */
struct completion channel_init_wait;
struct nvsp_message channel_init_pkt;
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index bbee44635035..c041f63a6d30 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -28,6 +28,7 @@
#include <linux/slab.h>
#include <linux/netdevice.h>
#include <linux/if_ether.h>
+#include <asm/sync_bitops.h>
#include "hyperv_net.h"
@@ -80,7 +81,7 @@ get_in_err:
}
-static int netvsc_destroy_recv_buf(struct netvsc_device *net_device)
+static int netvsc_destroy_buf(struct netvsc_device *net_device)
{
struct nvsp_message *revoke_packet;
int ret = 0;
@@ -146,10 +147,62 @@ static int netvsc_destroy_recv_buf(struct netvsc_device *net_device)
net_device->recv_section = NULL;
}
+ /* Deal with the send buffer we may have setup.
+ * If we got a send section size, it means we received a
+ * SendsendBufferComplete msg (ie sent
+ * NvspMessage1TypeSendReceiveBuffer msg) therefore, we need
+ * to send a revoke msg here
+ */
+ if (net_device->send_section_size) {
+ /* Send the revoke receive buffer */
+ revoke_packet = &net_device->revoke_packet;
+ memset(revoke_packet, 0, sizeof(struct nvsp_message));
+
+ revoke_packet->hdr.msg_type =
+ NVSP_MSG1_TYPE_REVOKE_SEND_BUF;
+ revoke_packet->msg.v1_msg.revoke_recv_buf.id = 0;
+
+ ret = vmbus_sendpacket(net_device->dev->channel,
+ revoke_packet,
+ sizeof(struct nvsp_message),
+ (unsigned long)revoke_packet,
+ VM_PKT_DATA_INBAND, 0);
+ /* If we failed here, we might as well return and
+ * have a leak rather than continue and a bugchk
+ */
+ if (ret != 0) {
+ netdev_err(ndev, "unable to send "
+ "revoke send buffer to netvsp\n");
+ return ret;
+ }
+ }
+ /* Teardown the gpadl on the vsp end */
+ if (net_device->send_buf_gpadl_handle) {
+ ret = vmbus_teardown_gpadl(net_device->dev->channel,
+ net_device->send_buf_gpadl_handle);
+
+ /* If we failed here, we might as well return and have a leak
+ * rather than continue and a bugchk
+ */
+ if (ret != 0) {
+ netdev_err(ndev,
+ "unable to teardown send buffer's gpadl\n");
+ return ret;
+ }
+ net_device->recv_buf_gpadl_handle = 0;
+ }
+ if (net_device->send_buf) {
+ /* Free up the receive buffer */
+ free_pages((unsigned long)net_device->send_buf,
+ get_order(net_device->send_buf_size));
+ net_device->send_buf = NULL;
+ }
+ kfree(net_device->send_section_map);
+
return ret;
}
-static int netvsc_init_recv_buf(struct hv_device *device)
+static int netvsc_init_buf(struct hv_device *device)
{
int ret = 0;
int t;
@@ -248,10 +301,90 @@ static int netvsc_init_recv_buf(struct hv_device *device)
goto cleanup;
}
+ /* Now setup the send buffer.
+ */
+ net_device->send_buf =
+ (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
+ get_order(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);
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+
+ /* Establish the gpadl handle for this buffer on this
+ * channel. Note: This call uses the vmbus connection rather
+ * than the channel to establish the gpadl handle.
+ */
+ ret = vmbus_establish_gpadl(device->channel, net_device->send_buf,
+ net_device->send_buf_size,
+ &net_device->send_buf_gpadl_handle);
+ if (ret != 0) {
+ netdev_err(ndev,
+ "unable to establish send buffer's gpadl\n");
+ goto cleanup;
+ }
+
+ /* Notify the NetVsp of the gpadl handle */
+ init_packet = &net_device->channel_init_pkt;
+ memset(init_packet, 0, sizeof(struct nvsp_message));
+ init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_SEND_BUF;
+ init_packet->msg.v1_msg.send_recv_buf.gpadl_handle =
+ net_device->send_buf_gpadl_handle;
+ init_packet->msg.v1_msg.send_recv_buf.id = 0;
+
+ /* Send the gpadl notification request */
+ ret = vmbus_sendpacket(device->channel, init_packet,
+ sizeof(struct nvsp_message),
+ (unsigned long)init_packet,
+ VM_PKT_DATA_INBAND,
+ VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+ if (ret != 0) {
+ netdev_err(ndev,
+ "unable to send send buffer's gpadl to netvsp\n");
+ goto cleanup;
+ }
+
+ t = wait_for_completion_timeout(&net_device->channel_init_wait, 5*HZ);
+ BUG_ON(t == 0);
+
+ /* Check the response */
+ if (init_packet->msg.v1_msg.
+ send_send_buf_complete.status != NVSP_STAT_SUCCESS) {
+ netdev_err(ndev, "Unable to complete send buffer "
+ "initialization with NetVsp - status %d\n",
+ init_packet->msg.v1_msg.
+ send_recv_buf_complete.status);
+ ret = -EINVAL;
+ goto cleanup;
+ }
+
+ /* Parse the response */
+ 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;
+
+ dev_info(&device->device, "Send section size: %d, Section count:%d\n",
+ net_device->send_section_size, net_device->send_section_cnt);
+
+ /* Setup state for managing the send buffer. */
+ net_device->map_words = DIV_ROUND_UP(net_device->send_section_cnt,
+ BITS_PER_LONG);
+
+ net_device->send_section_map =
+ kzalloc(net_device->map_words * sizeof(ulong), GFP_KERNEL);
+ if (net_device->send_section_map == NULL)
+ goto cleanup;
+
goto exit;
cleanup:
- netvsc_destroy_recv_buf(net_device);
+ netvsc_destroy_buf(net_device);
exit:
return ret;
@@ -369,8 +502,9 @@ static int netvsc_connect_vsp(struct hv_device *device)
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_recv_buf(device);
+ ret = netvsc_init_buf(device);
cleanup:
return ret;
@@ -378,7 +512,7 @@ cleanup:
static void netvsc_disconnect_vsp(struct netvsc_device *net_device)
{
- netvsc_destroy_recv_buf(net_device);
+ netvsc_destroy_buf(net_device);
}
/*
@@ -440,6 +574,12 @@ static inline u32 hv_ringbuf_avail_percent(
return avail_write * 100 / ring_info->ring_datasize;
}
+static inline void netvsc_free_send_slot(struct netvsc_device *net_device,
+ u32 index)
+{
+ sync_change_bit(index, net_device->send_section_map);
+}
+
static void netvsc_send_completion(struct netvsc_device *net_device,
struct hv_device *device,
struct vmpacket_descriptor *packet)
@@ -447,6 +587,7 @@ static void netvsc_send_completion(struct netvsc_device *net_device,
struct nvsp_message *nvsp_packet;
struct hv_netvsc_packet *nvsc_packet;
struct net_device *ndev;
+ u32 send_index;
ndev = net_device->ndev;
@@ -477,6 +618,9 @@ static void netvsc_send_completion(struct netvsc_device *net_device,
/* Notify the layer above us */
if (nvsc_packet) {
+ send_index = nvsc_packet->send_buf_index;
+ if (send_index != NETVSC_INVALID_INDEX)
+ netvsc_free_send_slot(net_device, send_index);
q_idx = nvsc_packet->q_idx;
channel = nvsc_packet->channel;
nvsc_packet->send_completion(nvsc_packet->
@@ -504,6 +648,52 @@ static void netvsc_send_completion(struct netvsc_device *net_device,
}
+static u32 netvsc_get_next_send_section(struct netvsc_device *net_device)
+{
+ unsigned long index;
+ u32 max_words = net_device->map_words;
+ unsigned long *map_addr = (unsigned long *)net_device->send_section_map;
+ u32 section_cnt = net_device->send_section_cnt;
+ int ret_val = NETVSC_INVALID_INDEX;
+ int i;
+ int prev_val;
+
+ for (i = 0; i < max_words; i++) {
+ if (!~(map_addr[i]))
+ continue;
+ index = ffz(map_addr[i]);
+ prev_val = sync_test_and_set_bit(index, &map_addr[i]);
+ if (prev_val)
+ continue;
+ if ((index + (i * BITS_PER_LONG)) >= section_cnt)
+ break;
+ ret_val = (index + (i * BITS_PER_LONG));
+ break;
+ }
+ return ret_val;
+}
+
+u32 netvsc_copy_to_send_buf(struct netvsc_device *net_device,
+ unsigned int section_index,
+ struct hv_netvsc_packet *packet)
+{
+ char *start = net_device->send_buf;
+ char *dest = (start + (section_index * net_device->send_section_size));
+ int i;
+ u32 msg_size = 0;
+
+ for (i = 0; i < packet->page_buf_cnt; i++) {
+ char *src = phys_to_virt(packet->page_buf[i].pfn << PAGE_SHIFT);
+ u32 offset = packet->page_buf[i].offset;
+ u32 len = packet->page_buf[i].len;
+
+ memcpy(dest, (src + offset), len);
+ msg_size += len;
+ dest += len;
+ }
+ return msg_size;
+}
+
int netvsc_send(struct hv_device *device,
struct hv_netvsc_packet *packet)
{
@@ -513,6 +703,10 @@ int netvsc_send(struct hv_device *device,
struct net_device *ndev;
struct vmbus_channel *out_channel = NULL;
u64 req_id;
+ unsigned int section_index = NETVSC_INVALID_INDEX;
+ u32 msg_size = 0;
+ struct sk_buff *skb;
+
net_device = get_outbound_net_device(device);
if (!net_device)
@@ -528,10 +722,26 @@ int netvsc_send(struct hv_device *device,
sendMessage.msg.v1_msg.send_rndis_pkt.channel_type = 1;
}
- /* Not using send buffer section */
+ /* Attempt to send via sendbuf */
+ if (packet->total_data_buflen < net_device->send_section_size) {
+ section_index = netvsc_get_next_send_section(net_device);
+ if (section_index != NETVSC_INVALID_INDEX) {
+ msg_size = netvsc_copy_to_send_buf(net_device,
+ section_index,
+ packet);
+ skb = (struct sk_buff *)
+ (unsigned long)packet->send_completion_tid;
+ if (skb)
+ dev_kfree_skb_any(skb);
+ packet->page_buf_cnt = 0;
+ }
+ }
+ packet->send_buf_index = section_index;
+
+
sendMessage.msg.v1_msg.send_rndis_pkt.send_buf_section_index =
- 0xFFFFFFFF;
- sendMessage.msg.v1_msg.send_rndis_pkt.send_buf_section_size = 0;
+ section_index;
+ sendMessage.msg.v1_msg.send_rndis_pkt.send_buf_section_size = msg_size;
if (packet->send_completion)
req_id = (ulong)packet;
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index f3d3525ed42d..9a19aa5672e6 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -236,10 +236,11 @@ static void netvsc_xmit_completion(void *context)
struct hv_netvsc_packet *packet = (struct hv_netvsc_packet *)context;
struct sk_buff *skb = (struct sk_buff *)
(unsigned long)packet->send_completion_tid;
+ u32 index = packet->send_buf_index;
kfree(packet);
- if (skb)
+ if (skb && (index == NETVSC_INVALID_INDEX))
dev_kfree_skb_any(skb);
}
--
2.4.3

View File

@@ -1,42 +0,0 @@
From 3f0b77385356301cf4718a94f76a4068588ecb8e Mon Sep 17 00:00:00 2001
From: Haiyang Zhang <haiyangz@microsoft.com>
Date: Thu, 8 May 2014 15:14:10 -0700
Subject: [PATCH 20/25] Add support for netvsc build without CONFIG_SYSFS flag
This change ensures the driver can be built successfully without the
CONFIG_SYSFS flag.
MS-TFS: 182270
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/hyperv/netvsc_drv.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 9a19aa5672e6..346f1aeb9c24 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -645,8 +645,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
packet->vlan_tci);
skb_record_rx_queue(skb, packet->channel->
- offermsg.offer.sub_channel_index %
- net->real_num_rx_queues);
+ offermsg.offer.sub_channel_index);
net->stats.rx_packets++;
net->stats.rx_bytes += packet->total_data_buflen;
@@ -829,8 +828,6 @@ static int netvsc_probe(struct hv_device *dev,
nvdev = hv_get_drvdata(dev);
netif_set_real_num_tx_queues(net, nvdev->num_chn);
netif_set_real_num_rx_queues(net, nvdev->num_chn);
- dev_info(&dev->device, "real num tx,rx queues:%u, %u\n",
- net->real_num_tx_queues, net->real_num_rx_queues);
ret = register_netdev(net);
if (ret != 0) {
--
2.4.3

View File

@@ -1,93 +0,0 @@
From 1267d9b235e7612f8cdfa842a0433bb82e75f7fb Mon Sep 17 00:00:00 2001
From: Haiyang Zhang <haiyangz@microsoft.com>
Date: Wed, 21 May 2014 12:55:39 -0700
Subject: [PATCH 21/25] hyperv: Add hash value into RNDIS Per-packet info
It passes the hash value as the RNDIS Per-packet info to the Hyper-V host,
so that the send completion notices can be spread across multiple channels.
MS-TFS: 140273
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/hyperv/hyperv_net.h | 4 ++++
drivers/net/hyperv/netvsc_drv.c | 18 ++++++++++++++----
2 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 4b7df5a5c966..6cc37c15e0bf 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -791,6 +791,7 @@ enum ndis_per_pkt_info_type {
IEEE_8021Q_INFO,
ORIGINAL_PKTINFO,
PACKET_CANCEL_ID,
+ NBL_HASH_VALUE = PACKET_CANCEL_ID,
ORIGINAL_NET_BUFLIST,
CACHED_NET_BUFLIST,
SHORT_PKT_PADINFO,
@@ -937,6 +938,9 @@ struct ndis_tcp_lso_info {
#define NDIS_LSO_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \
sizeof(struct ndis_tcp_lso_info))
+#define NDIS_HASH_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \
+ sizeof(u32))
+
/* Format of Information buffer passed in a SetRequest for the OID */
/* OID_GEN_RNDIS_CONFIG_PARAMETER. */
struct rndis_config_parameter_info {
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 346f1aeb9c24..bd3b3acd04dc 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -224,9 +224,11 @@ static u16 netvsc_select_queue(struct net_device *ndev, struct sk_buff *skb,
if (nvsc_dev == NULL || ndev->real_num_tx_queues <= 1)
return 0;
- if (netvsc_set_hash(&hash, skb))
+ if (netvsc_set_hash(&hash, skb)) {
q_idx = nvsc_dev->send_table[hash % VRSS_SEND_TAB_SIZE] %
ndev->real_num_tx_queues;
+ skb_set_hash(skb, hash, PKT_HASH_TYPE_L3);
+ }
return q_idx;
}
@@ -385,6 +387,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
struct ndis_tcp_lso_info *lso_info;
int hdr_offset;
u32 net_trans_info;
+ u32 hash;
/* We will atmost need two pages to describe the rndis
@@ -403,9 +406,8 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
packet = kzalloc(sizeof(struct hv_netvsc_packet) +
(num_data_pgs * sizeof(struct hv_page_buffer)) +
sizeof(struct rndis_message) +
- NDIS_VLAN_PPI_SIZE +
- NDIS_CSUM_PPI_SIZE +
- NDIS_LSO_PPI_SIZE, GFP_ATOMIC);
+ NDIS_VLAN_PPI_SIZE + NDIS_CSUM_PPI_SIZE +
+ NDIS_LSO_PPI_SIZE + NDIS_HASH_PPI_SIZE, GFP_ATOMIC);
if (!packet) {
/* out of memory, drop packet */
netdev_err(net, "unable to allocate hv_netvsc_packet\n");
@@ -444,6 +446,14 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
rndis_msg_size = RNDIS_MESSAGE_SIZE(struct rndis_packet);
+ hash = skb_get_hash_raw(skb);
+ if (hash != 0 && net->real_num_tx_queues > 1) {
+ rndis_msg_size += NDIS_HASH_PPI_SIZE;
+ ppi = init_ppi_data(rndis_msg, NDIS_HASH_PPI_SIZE,
+ NBL_HASH_VALUE);
+ *(u32 *)((void *)ppi + ppi->ppi_offset) = hash;
+ }
+
if (isvlan) {
struct ndis_pkt_8021q_info *vlan;
--
2.4.3

View File

@@ -1,32 +0,0 @@
From ee99150c7f34737e4382e7199d2ffe3dfbb54a5c Mon Sep 17 00:00:00 2001
From: Dave Jones <davej@redhat.com>
Date: Mon, 16 Jun 2014 16:59:02 -0400
Subject: [PATCH 22/25] hyperv: fix apparent cut-n-paste error in send path
teardown
c25aaf814a63: "hyperv: Enable sendbuf mechanism on the send path" added
some teardown code that looks like it was copied from the recieve path
above, but missed a variable name replacement.
Signed-off-by: Dave Jones <davej@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/hyperv/netvsc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index c041f63a6d30..4ed38eaecea8 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -189,7 +189,7 @@ static int netvsc_destroy_buf(struct netvsc_device *net_device)
"unable to teardown send buffer's gpadl\n");
return ret;
}
- net_device->recv_buf_gpadl_handle = 0;
+ net_device->send_buf_gpadl_handle = 0;
}
if (net_device->send_buf) {
/* Free up the receive buffer */
--
2.4.3

View File

@@ -1,34 +0,0 @@
From f1009dfec7c439a958bd9ed8893dd6aa692c61f5 Mon Sep 17 00:00:00 2001
From: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
Date: Wed, 23 Jul 2014 09:00:35 +0800
Subject: [PATCH 23/25] hyperv: Fix error return code in netvsc_init_buf()
Fix to return -ENOMEM from the kalloc error handling
case instead of 0.
Signed-off-by: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/hyperv/netvsc.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 4ed38eaecea8..d97d5f39a04e 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -378,8 +378,10 @@ static int netvsc_init_buf(struct hv_device *device)
net_device->send_section_map =
kzalloc(net_device->map_words * sizeof(ulong), GFP_KERNEL);
- if (net_device->send_section_map == NULL)
+ if (net_device->send_section_map == NULL) {
+ ret = -ENOMEM;
goto cleanup;
+ }
goto exit;
--
2.4.3

View File

@@ -1,68 +0,0 @@
From 38bca2d5bd6fdaa0b8e1e415f79d89322c6825a8 Mon Sep 17 00:00:00 2001
From: KY Srinivasan <kys@microsoft.com>
Date: Sun, 5 Oct 2014 10:42:51 -0700
Subject: [PATCH 24/25] hyperv: Fix a bug in netvsc_send()
[ Upstream commit 3a67c9ccad926a168d8b7891537a452018368a5b ]
After the packet is successfully sent, we should not touch the packet
as it may have been freed. This patch is based on the work done by
Long Li <longli@microsoft.com>.
David, please queue this up for stable.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reported-by: Sitsofe Wheeler <sitsofe@yahoo.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/hyperv/netvsc.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index d97d5f39a04e..7edf976ecfa0 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -708,6 +708,7 @@ int netvsc_send(struct hv_device *device,
unsigned int section_index = NETVSC_INVALID_INDEX;
u32 msg_size = 0;
struct sk_buff *skb;
+ u16 q_idx = packet->q_idx;
net_device = get_outbound_net_device(device);
@@ -772,24 +773,24 @@ int netvsc_send(struct hv_device *device,
if (ret == 0) {
atomic_inc(&net_device->num_outstanding_sends);
- atomic_inc(&net_device->queue_sends[packet->q_idx]);
+ atomic_inc(&net_device->queue_sends[q_idx]);
if (hv_ringbuf_avail_percent(&out_channel->outbound) <
RING_AVAIL_PERCENT_LOWATER) {
netif_tx_stop_queue(netdev_get_tx_queue(
- ndev, packet->q_idx));
+ ndev, q_idx));
if (atomic_read(&net_device->
- queue_sends[packet->q_idx]) < 1)
+ queue_sends[q_idx]) < 1)
netif_tx_wake_queue(netdev_get_tx_queue(
- ndev, packet->q_idx));
+ ndev, q_idx));
}
} else if (ret == -EAGAIN) {
netif_tx_stop_queue(netdev_get_tx_queue(
- ndev, packet->q_idx));
- if (atomic_read(&net_device->queue_sends[packet->q_idx]) < 1) {
+ ndev, q_idx));
+ if (atomic_read(&net_device->queue_sends[q_idx]) < 1) {
netif_tx_wake_queue(netdev_get_tx_queue(
- ndev, packet->q_idx));
+ ndev, q_idx));
ret = -ENOSPC;
}
} else {
--
2.4.3

View File

@@ -1,51 +0,0 @@
From 4b71288758aa1d510402b84ca93b1ef566575d22 Mon Sep 17 00:00:00 2001
From: "K. Y. Srinivasan" <kys@microsoft.com>
Date: Mon, 3 Feb 2014 12:42:45 -0800
Subject: [PATCH 25/25] Drivers: hv: vmbus: Support per-channel driver state
As we implement Virtual Receive Side Scaling on the networking side
(the VRSS patches are currently under review), it will be useful to have
per-channel state that vmbus drivers can manage. Add support for
managing per-channel state.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/linux/hyperv.h | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index 6088058a3e00..732dc7e37e96 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -1045,6 +1045,10 @@ struct vmbus_channel {
* This will be NULL for the primary channel.
*/
struct vmbus_channel *primary_channel;
+ /*
+ * Support per-channel state for use by vmbus drivers.
+ */
+ void *per_channel_state;
};
static inline void set_channel_read_state(struct vmbus_channel *c, bool state)
@@ -1052,6 +1056,16 @@ static inline void set_channel_read_state(struct vmbus_channel *c, bool state)
c->batched_reading = state;
}
+static inline void set_per_channel_state(struct vmbus_channel *c, void *s)
+{
+ c->per_channel_state = s;
+}
+
+static inline void *get_per_channel_state(struct vmbus_channel *c)
+{
+ return c->per_channel_state;
+}
+
void vmbus_onmessage(void *context);
int vmbus_request_offers(void);
--
2.4.3

View File

@@ -1,689 +0,0 @@
From bcdbd313c0e6fd630a8945fd58dc5383631dc6dd Mon Sep 17 00:00:00 2001
From: Timothy McCaffrey <timothy.mccaffrey@unisys.com>
Date: Tue, 13 Jan 2015 13:16:43 -0500
Subject: [PATCH] crypto: aesni - Add support for 192 & 256 bit keys to AESNI
RFC4106
These patches fix the RFC4106 implementation in the aesni-intel
module so it supports 192 & 256 bit keys.
Since the AVX support that was added to this module also only
supports 128 bit keys, and this patch only affects the SSE
implementation, changes were also made to use the SSE version
if key sizes other than 128 are specified.
RFC4106 specifies that 192 & 256 bit keys must be supported (section
8.4).
Also, this should fix Strongswan issue 341 where the aesni module
needs to be unloaded if 256 bit keys are used:
http://wiki.strongswan.org/issues/341
This patch has been tested with Sandy Bridge and Haswell processors.
With 128 bit keys and input buffers > 512 bytes a slight performance
degradation was noticed (~1%). For input buffers of less than 512
bytes there was no performance impact. Compared to 128 bit keys,
256 bit key size performance is approx. .5 cycles per byte slower
on Sandy Bridge, and .37 cycles per byte slower on Haswell (vs.
SSE code).
This patch has also been tested with StrongSwan IPSec connections
where it worked correctly.
I created this diff from a git clone of crypto-2.6.git.
Any questions, please feel free to contact me.
Signed-off-by: Timothy McCaffrey <timothy.mccaffrey@unisys.com>
Signed-off-by: Jarod Wilson <jarod@redhat.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
arch/x86/crypto/aesni-intel_asm.S | 342 +++++++++++++++++++------------------
arch/x86/crypto/aesni-intel_glue.c | 31 +++-
2 files changed, 202 insertions(+), 171 deletions(-)
diff --git a/arch/x86/crypto/aesni-intel_asm.S b/arch/x86/crypto/aesni-intel_asm.S
index c92c7d8..f5cdfbf 100644
--- a/arch/x86/crypto/aesni-intel_asm.S
+++ b/arch/x86/crypto/aesni-intel_asm.S
@@ -33,12 +33,23 @@
#include <asm/inst.h>
#include <asm/alternative-asm.h>
+/*
+ * The following macros are used to move an (un)aligned 16 byte value to/from
+ * an XMM register. This can done for either FP or integer values, for FP use
+ * movaps (move aligned packed single) or integer use movdqa (move double quad
+ * aligned). It doesn't make a performance difference which instruction is used
+ * since Nehalem (original Core i7) was released. However, the movaps is a byte
+ * shorter, so that is the one we'll use for now. (same for unaligned).
+ */
+#define MOVADQ movaps
+#define MOVUDQ movups
+
#ifdef __x86_64__
+
.data
.align 16
.Lgf128mul_x_ble_mask:
.octa 0x00000000000000010000000000000087
-
POLY: .octa 0xC2000000000000000000000000000001
TWOONE: .octa 0x00000001000000000000000000000001
@@ -90,6 +101,7 @@ enc: .octa 0x2
#define arg8 STACK_OFFSET+16(%r14)
#define arg9 STACK_OFFSET+24(%r14)
#define arg10 STACK_OFFSET+32(%r14)
+#define keysize 2*15*16(%arg1)
#endif
@@ -214,10 +226,12 @@ enc: .octa 0x2
.macro INITIAL_BLOCKS_DEC num_initial_blocks TMP1 TMP2 TMP3 TMP4 TMP5 XMM0 XMM1 \
XMM2 XMM3 XMM4 XMMDst TMP6 TMP7 i i_seq operation
+ MOVADQ SHUF_MASK(%rip), %xmm14
mov arg7, %r10 # %r10 = AAD
mov arg8, %r15 # %r15 = aadLen
mov %r15, %r11
pxor %xmm\i, %xmm\i
+
_get_AAD_loop\num_initial_blocks\operation:
movd (%r10), \TMP1
pslldq $12, \TMP1
@@ -226,6 +240,7 @@ _get_AAD_loop\num_initial_blocks\operation:
add $4, %r10
sub $4, %r15
jne _get_AAD_loop\num_initial_blocks\operation
+
cmp $16, %r11
je _get_AAD_loop2_done\num_initial_blocks\operation
mov $16, %r15
@@ -234,8 +249,8 @@ _get_AAD_loop2\num_initial_blocks\operation:
sub $4, %r15
cmp %r11, %r15
jne _get_AAD_loop2\num_initial_blocks\operation
+
_get_AAD_loop2_done\num_initial_blocks\operation:
- movdqa SHUF_MASK(%rip), %xmm14
PSHUFB_XMM %xmm14, %xmm\i # byte-reflect the AAD data
xor %r11, %r11 # initialise the data pointer offset as zero
@@ -244,59 +259,34 @@ _get_AAD_loop2_done\num_initial_blocks\operation:
mov %arg5, %rax # %rax = *Y0
movdqu (%rax), \XMM0 # XMM0 = Y0
- movdqa SHUF_MASK(%rip), %xmm14
PSHUFB_XMM %xmm14, \XMM0
.if (\i == 5) || (\i == 6) || (\i == 7)
+ MOVADQ ONE(%RIP),\TMP1
+ MOVADQ (%arg1),\TMP2
.irpc index, \i_seq
- paddd ONE(%rip), \XMM0 # INCR Y0
+ paddd \TMP1, \XMM0 # INCR Y0
movdqa \XMM0, %xmm\index
- movdqa SHUF_MASK(%rip), %xmm14
PSHUFB_XMM %xmm14, %xmm\index # perform a 16 byte swap
-
-.endr
-.irpc index, \i_seq
- pxor 16*0(%arg1), %xmm\index
-.endr
-.irpc index, \i_seq
- movaps 0x10(%rdi), \TMP1
- AESENC \TMP1, %xmm\index # Round 1
-.endr
-.irpc index, \i_seq
- movaps 0x20(%arg1), \TMP1
- AESENC \TMP1, %xmm\index # Round 2
+ pxor \TMP2, %xmm\index
.endr
-.irpc index, \i_seq
- movaps 0x30(%arg1), \TMP1
- AESENC \TMP1, %xmm\index # Round 2
-.endr
-.irpc index, \i_seq
- movaps 0x40(%arg1), \TMP1
- AESENC \TMP1, %xmm\index # Round 2
-.endr
-.irpc index, \i_seq
- movaps 0x50(%arg1), \TMP1
- AESENC \TMP1, %xmm\index # Round 2
-.endr
-.irpc index, \i_seq
- movaps 0x60(%arg1), \TMP1
- AESENC \TMP1, %xmm\index # Round 2
-.endr
-.irpc index, \i_seq
- movaps 0x70(%arg1), \TMP1
- AESENC \TMP1, %xmm\index # Round 2
-.endr
-.irpc index, \i_seq
- movaps 0x80(%arg1), \TMP1
- AESENC \TMP1, %xmm\index # Round 2
-.endr
-.irpc index, \i_seq
- movaps 0x90(%arg1), \TMP1
- AESENC \TMP1, %xmm\index # Round 2
+ lea 0x10(%arg1),%r10
+ mov keysize,%eax
+ shr $2,%eax # 128->4, 192->6, 256->8
+ add $5,%eax # 128->9, 192->11, 256->13
+
+aes_loop_initial_dec\num_initial_blocks:
+ MOVADQ (%r10),\TMP1
+.irpc index, \i_seq
+ AESENC \TMP1, %xmm\index
.endr
+ add $16,%r10
+ sub $1,%eax
+ jnz aes_loop_initial_dec\num_initial_blocks
+
+ MOVADQ (%r10), \TMP1
.irpc index, \i_seq
- movaps 0xa0(%arg1), \TMP1
- AESENCLAST \TMP1, %xmm\index # Round 10
+ AESENCLAST \TMP1, %xmm\index # Last Round
.endr
.irpc index, \i_seq
movdqu (%arg3 , %r11, 1), \TMP1
@@ -306,10 +296,8 @@ _get_AAD_loop2_done\num_initial_blocks\operation:
add $16, %r11
movdqa \TMP1, %xmm\index
- movdqa SHUF_MASK(%rip), %xmm14
PSHUFB_XMM %xmm14, %xmm\index
-
- # prepare plaintext/ciphertext for GHASH computation
+ # prepare plaintext/ciphertext for GHASH computation
.endr
.endif
GHASH_MUL %xmm\i, \TMP3, \TMP1, \TMP2, \TMP4, \TMP5, \XMM1
@@ -339,30 +327,28 @@ _get_AAD_loop2_done\num_initial_blocks\operation:
* Precomputations for HashKey parallel with encryption of first 4 blocks.
* Haskey_i_k holds XORed values of the low and high parts of the Haskey_i
*/
- paddd ONE(%rip), \XMM0 # INCR Y0
- movdqa \XMM0, \XMM1
- movdqa SHUF_MASK(%rip), %xmm14
+ MOVADQ ONE(%rip), \TMP1
+ paddd \TMP1, \XMM0 # INCR Y0
+ MOVADQ \XMM0, \XMM1
PSHUFB_XMM %xmm14, \XMM1 # perform a 16 byte swap
- paddd ONE(%rip), \XMM0 # INCR Y0
- movdqa \XMM0, \XMM2
- movdqa SHUF_MASK(%rip), %xmm14
+ paddd \TMP1, \XMM0 # INCR Y0
+ MOVADQ \XMM0, \XMM2
PSHUFB_XMM %xmm14, \XMM2 # perform a 16 byte swap
- paddd ONE(%rip), \XMM0 # INCR Y0
- movdqa \XMM0, \XMM3
- movdqa SHUF_MASK(%rip), %xmm14
+ paddd \TMP1, \XMM0 # INCR Y0
+ MOVADQ \XMM0, \XMM3
PSHUFB_XMM %xmm14, \XMM3 # perform a 16 byte swap
- paddd ONE(%rip), \XMM0 # INCR Y0
- movdqa \XMM0, \XMM4
- movdqa SHUF_MASK(%rip), %xmm14
+ paddd \TMP1, \XMM0 # INCR Y0
+ MOVADQ \XMM0, \XMM4
PSHUFB_XMM %xmm14, \XMM4 # perform a 16 byte swap
- pxor 16*0(%arg1), \XMM1
- pxor 16*0(%arg1), \XMM2
- pxor 16*0(%arg1), \XMM3
- pxor 16*0(%arg1), \XMM4
+ MOVADQ 0(%arg1),\TMP1
+ pxor \TMP1, \XMM1
+ pxor \TMP1, \XMM2
+ pxor \TMP1, \XMM3
+ pxor \TMP1, \XMM4
movdqa \TMP3, \TMP5
pshufd $78, \TMP3, \TMP1
pxor \TMP3, \TMP1
@@ -400,7 +386,23 @@ _get_AAD_loop2_done\num_initial_blocks\operation:
pshufd $78, \TMP5, \TMP1
pxor \TMP5, \TMP1
movdqa \TMP1, HashKey_4_k(%rsp)
- movaps 0xa0(%arg1), \TMP2
+ lea 0xa0(%arg1),%r10
+ mov keysize,%eax
+ shr $2,%eax # 128->4, 192->6, 256->8
+ sub $4,%eax # 128->0, 192->2, 256->4
+ jz aes_loop_pre_dec_done\num_initial_blocks
+
+aes_loop_pre_dec\num_initial_blocks:
+ MOVADQ (%r10),\TMP2
+.irpc index, 1234
+ AESENC \TMP2, %xmm\index
+.endr
+ add $16,%r10
+ sub $1,%eax
+ jnz aes_loop_pre_dec\num_initial_blocks
+
+aes_loop_pre_dec_done\num_initial_blocks:
+ MOVADQ (%r10), \TMP2
AESENCLAST \TMP2, \XMM1
AESENCLAST \TMP2, \XMM2
AESENCLAST \TMP2, \XMM3
@@ -422,15 +424,11 @@ _get_AAD_loop2_done\num_initial_blocks\operation:
movdqu \XMM4, 16*3(%arg2 , %r11 , 1)
movdqa \TMP1, \XMM4
add $64, %r11
- movdqa SHUF_MASK(%rip), %xmm14
PSHUFB_XMM %xmm14, \XMM1 # perform a 16 byte swap
pxor \XMMDst, \XMM1
# combine GHASHed value with the corresponding ciphertext
- movdqa SHUF_MASK(%rip), %xmm14
PSHUFB_XMM %xmm14, \XMM2 # perform a 16 byte swap
- movdqa SHUF_MASK(%rip), %xmm14
PSHUFB_XMM %xmm14, \XMM3 # perform a 16 byte swap
- movdqa SHUF_MASK(%rip), %xmm14
PSHUFB_XMM %xmm14, \XMM4 # perform a 16 byte swap
_initial_blocks_done\num_initial_blocks\operation:
@@ -452,6 +450,7 @@ _initial_blocks_done\num_initial_blocks\operation:
.macro INITIAL_BLOCKS_ENC num_initial_blocks TMP1 TMP2 TMP3 TMP4 TMP5 XMM0 XMM1 \
XMM2 XMM3 XMM4 XMMDst TMP6 TMP7 i i_seq operation
+ MOVADQ SHUF_MASK(%rip), %xmm14
mov arg7, %r10 # %r10 = AAD
mov arg8, %r15 # %r15 = aadLen
mov %r15, %r11
@@ -473,7 +472,6 @@ _get_AAD_loop2\num_initial_blocks\operation:
cmp %r11, %r15
jne _get_AAD_loop2\num_initial_blocks\operation
_get_AAD_loop2_done\num_initial_blocks\operation:
- movdqa SHUF_MASK(%rip), %xmm14
PSHUFB_XMM %xmm14, %xmm\i # byte-reflect the AAD data
xor %r11, %r11 # initialise the data pointer offset as zero
@@ -482,59 +480,35 @@ _get_AAD_loop2_done\num_initial_blocks\operation:
mov %arg5, %rax # %rax = *Y0
movdqu (%rax), \XMM0 # XMM0 = Y0
- movdqa SHUF_MASK(%rip), %xmm14
PSHUFB_XMM %xmm14, \XMM0
.if (\i == 5) || (\i == 6) || (\i == 7)
-.irpc index, \i_seq
- paddd ONE(%rip), \XMM0 # INCR Y0
- movdqa \XMM0, %xmm\index
- movdqa SHUF_MASK(%rip), %xmm14
- PSHUFB_XMM %xmm14, %xmm\index # perform a 16 byte swap
-.endr
-.irpc index, \i_seq
- pxor 16*0(%arg1), %xmm\index
-.endr
-.irpc index, \i_seq
- movaps 0x10(%rdi), \TMP1
- AESENC \TMP1, %xmm\index # Round 1
-.endr
-.irpc index, \i_seq
- movaps 0x20(%arg1), \TMP1
- AESENC \TMP1, %xmm\index # Round 2
-.endr
+ MOVADQ ONE(%RIP),\TMP1
+ MOVADQ 0(%arg1),\TMP2
.irpc index, \i_seq
- movaps 0x30(%arg1), \TMP1
- AESENC \TMP1, %xmm\index # Round 2
+ paddd \TMP1, \XMM0 # INCR Y0
+ MOVADQ \XMM0, %xmm\index
+ PSHUFB_XMM %xmm14, %xmm\index # perform a 16 byte swap
+ pxor \TMP2, %xmm\index
.endr
-.irpc index, \i_seq
- movaps 0x40(%arg1), \TMP1
- AESENC \TMP1, %xmm\index # Round 2
-.endr
-.irpc index, \i_seq
- movaps 0x50(%arg1), \TMP1
- AESENC \TMP1, %xmm\index # Round 2
-.endr
-.irpc index, \i_seq
- movaps 0x60(%arg1), \TMP1
- AESENC \TMP1, %xmm\index # Round 2
-.endr
-.irpc index, \i_seq
- movaps 0x70(%arg1), \TMP1
- AESENC \TMP1, %xmm\index # Round 2
-.endr
-.irpc index, \i_seq
- movaps 0x80(%arg1), \TMP1
- AESENC \TMP1, %xmm\index # Round 2
-.endr
-.irpc index, \i_seq
- movaps 0x90(%arg1), \TMP1
- AESENC \TMP1, %xmm\index # Round 2
+ lea 0x10(%arg1),%r10
+ mov keysize,%eax
+ shr $2,%eax # 128->4, 192->6, 256->8
+ add $5,%eax # 128->9, 192->11, 256->13
+
+aes_loop_initial_enc\num_initial_blocks:
+ MOVADQ (%r10),\TMP1
+.irpc index, \i_seq
+ AESENC \TMP1, %xmm\index
.endr
+ add $16,%r10
+ sub $1,%eax
+ jnz aes_loop_initial_enc\num_initial_blocks
+
+ MOVADQ (%r10), \TMP1
.irpc index, \i_seq
- movaps 0xa0(%arg1), \TMP1
- AESENCLAST \TMP1, %xmm\index # Round 10
+ AESENCLAST \TMP1, %xmm\index # Last Round
.endr
.irpc index, \i_seq
movdqu (%arg3 , %r11, 1), \TMP1
@@ -542,8 +516,6 @@ _get_AAD_loop2_done\num_initial_blocks\operation:
movdqu %xmm\index, (%arg2 , %r11, 1)
# write back plaintext/ciphertext for num_initial_blocks
add $16, %r11
-
- movdqa SHUF_MASK(%rip), %xmm14
PSHUFB_XMM %xmm14, %xmm\index
# prepare plaintext/ciphertext for GHASH computation
@@ -576,30 +548,28 @@ _get_AAD_loop2_done\num_initial_blocks\operation:
* Precomputations for HashKey parallel with encryption of first 4 blocks.
* Haskey_i_k holds XORed values of the low and high parts of the Haskey_i
*/
- paddd ONE(%rip), \XMM0 # INCR Y0
- movdqa \XMM0, \XMM1
- movdqa SHUF_MASK(%rip), %xmm14
+ MOVADQ ONE(%RIP),\TMP1
+ paddd \TMP1, \XMM0 # INCR Y0
+ MOVADQ \XMM0, \XMM1
PSHUFB_XMM %xmm14, \XMM1 # perform a 16 byte swap
- paddd ONE(%rip), \XMM0 # INCR Y0
- movdqa \XMM0, \XMM2
- movdqa SHUF_MASK(%rip), %xmm14
+ paddd \TMP1, \XMM0 # INCR Y0
+ MOVADQ \XMM0, \XMM2
PSHUFB_XMM %xmm14, \XMM2 # perform a 16 byte swap
- paddd ONE(%rip), \XMM0 # INCR Y0
- movdqa \XMM0, \XMM3
- movdqa SHUF_MASK(%rip), %xmm14
+ paddd \TMP1, \XMM0 # INCR Y0
+ MOVADQ \XMM0, \XMM3
PSHUFB_XMM %xmm14, \XMM3 # perform a 16 byte swap
- paddd ONE(%rip), \XMM0 # INCR Y0
- movdqa \XMM0, \XMM4
- movdqa SHUF_MASK(%rip), %xmm14
+ paddd \TMP1, \XMM0 # INCR Y0
+ MOVADQ \XMM0, \XMM4
PSHUFB_XMM %xmm14, \XMM4 # perform a 16 byte swap
- pxor 16*0(%arg1), \XMM1
- pxor 16*0(%arg1), \XMM2
- pxor 16*0(%arg1), \XMM3
- pxor 16*0(%arg1), \XMM4
+ MOVADQ 0(%arg1),\TMP1
+ pxor \TMP1, \XMM1
+ pxor \TMP1, \XMM2
+ pxor \TMP1, \XMM3
+ pxor \TMP1, \XMM4
movdqa \TMP3, \TMP5
pshufd $78, \TMP3, \TMP1
pxor \TMP3, \TMP1
@@ -637,7 +607,23 @@ _get_AAD_loop2_done\num_initial_blocks\operation:
pshufd $78, \TMP5, \TMP1
pxor \TMP5, \TMP1
movdqa \TMP1, HashKey_4_k(%rsp)
- movaps 0xa0(%arg1), \TMP2
+ lea 0xa0(%arg1),%r10
+ mov keysize,%eax
+ shr $2,%eax # 128->4, 192->6, 256->8
+ sub $4,%eax # 128->0, 192->2, 256->4
+ jz aes_loop_pre_enc_done\num_initial_blocks
+
+aes_loop_pre_enc\num_initial_blocks:
+ MOVADQ (%r10),\TMP2
+.irpc index, 1234
+ AESENC \TMP2, %xmm\index
+.endr
+ add $16,%r10
+ sub $1,%eax
+ jnz aes_loop_pre_enc\num_initial_blocks
+
+aes_loop_pre_enc_done\num_initial_blocks:
+ MOVADQ (%r10), \TMP2
AESENCLAST \TMP2, \XMM1
AESENCLAST \TMP2, \XMM2
AESENCLAST \TMP2, \XMM3
@@ -656,15 +642,11 @@ _get_AAD_loop2_done\num_initial_blocks\operation:
movdqu \XMM4, 16*3(%arg2 , %r11 , 1)
add $64, %r11
- movdqa SHUF_MASK(%rip), %xmm14
PSHUFB_XMM %xmm14, \XMM1 # perform a 16 byte swap
pxor \XMMDst, \XMM1
# combine GHASHed value with the corresponding ciphertext
- movdqa SHUF_MASK(%rip), %xmm14
PSHUFB_XMM %xmm14, \XMM2 # perform a 16 byte swap
- movdqa SHUF_MASK(%rip), %xmm14
PSHUFB_XMM %xmm14, \XMM3 # perform a 16 byte swap
- movdqa SHUF_MASK(%rip), %xmm14
PSHUFB_XMM %xmm14, \XMM4 # perform a 16 byte swap
_initial_blocks_done\num_initial_blocks\operation:
@@ -795,7 +777,23 @@ TMP6 XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7 XMM8 operation
AESENC \TMP3, \XMM3
AESENC \TMP3, \XMM4
PCLMULQDQ 0x00, \TMP5, \XMM8 # XMM8 = a0*b0
- movaps 0xa0(%arg1), \TMP3
+ lea 0xa0(%arg1),%r10
+ mov keysize,%eax
+ shr $2,%eax # 128->4, 192->6, 256->8
+ sub $4,%eax # 128->0, 192->2, 256->4
+ jz aes_loop_par_enc_done
+
+aes_loop_par_enc:
+ MOVADQ (%r10),\TMP3
+.irpc index, 1234
+ AESENC \TMP3, %xmm\index
+.endr
+ add $16,%r10
+ sub $1,%eax
+ jnz aes_loop_par_enc
+
+aes_loop_par_enc_done:
+ MOVADQ (%r10), \TMP3
AESENCLAST \TMP3, \XMM1 # Round 10
AESENCLAST \TMP3, \XMM2
AESENCLAST \TMP3, \XMM3
@@ -987,8 +985,24 @@ TMP6 XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7 XMM8 operation
AESENC \TMP3, \XMM3
AESENC \TMP3, \XMM4
PCLMULQDQ 0x00, \TMP5, \XMM8 # XMM8 = a0*b0
- movaps 0xa0(%arg1), \TMP3
- AESENCLAST \TMP3, \XMM1 # Round 10
+ lea 0xa0(%arg1),%r10
+ mov keysize,%eax
+ shr $2,%eax # 128->4, 192->6, 256->8
+ sub $4,%eax # 128->0, 192->2, 256->4
+ jz aes_loop_par_dec_done
+
+aes_loop_par_dec:
+ MOVADQ (%r10),\TMP3
+.irpc index, 1234
+ AESENC \TMP3, %xmm\index
+.endr
+ add $16,%r10
+ sub $1,%eax
+ jnz aes_loop_par_dec
+
+aes_loop_par_dec_done:
+ MOVADQ (%r10), \TMP3
+ AESENCLAST \TMP3, \XMM1 # last round
AESENCLAST \TMP3, \XMM2
AESENCLAST \TMP3, \XMM3
AESENCLAST \TMP3, \XMM4
@@ -1156,33 +1170,29 @@ TMP7 XMM1 XMM2 XMM3 XMM4 XMMDst
pxor \TMP6, \XMMDst # reduced result is in XMMDst
.endm
-/* Encryption of a single block done*/
-.macro ENCRYPT_SINGLE_BLOCK XMM0 TMP1
- pxor (%arg1), \XMM0
- movaps 16(%arg1), \TMP1
- AESENC \TMP1, \XMM0
- movaps 32(%arg1), \TMP1
- AESENC \TMP1, \XMM0
- movaps 48(%arg1), \TMP1
- AESENC \TMP1, \XMM0
- movaps 64(%arg1), \TMP1
- AESENC \TMP1, \XMM0
- movaps 80(%arg1), \TMP1
- AESENC \TMP1, \XMM0
- movaps 96(%arg1), \TMP1
- AESENC \TMP1, \XMM0
- movaps 112(%arg1), \TMP1
- AESENC \TMP1, \XMM0
- movaps 128(%arg1), \TMP1
- AESENC \TMP1, \XMM0
- movaps 144(%arg1), \TMP1
- AESENC \TMP1, \XMM0
- movaps 160(%arg1), \TMP1
- AESENCLAST \TMP1, \XMM0
-.endm
+/* Encryption of a single block
+* uses eax & r10
+*/
+.macro ENCRYPT_SINGLE_BLOCK XMM0 TMP1
+ pxor (%arg1), \XMM0
+ mov keysize,%eax
+ shr $2,%eax # 128->4, 192->6, 256->8
+ add $5,%eax # 128->9, 192->11, 256->13
+ lea 16(%arg1), %r10 # get first expanded key address
+
+_esb_loop_\@:
+ MOVADQ (%r10),\TMP1
+ AESENC \TMP1,\XMM0
+ add $16,%r10
+ sub $1,%eax
+ jnz _esb_loop_\@
+
+ MOVADQ (%r10),\TMP1
+ AESENCLAST \TMP1,\XMM0
+.endm
/*****************************************************************************
* void aesni_gcm_dec(void *aes_ctx, // AES Key schedule. Starts on a 16 byte boundary.
* u8 *out, // Plaintext output. Encrypt in-place is allowed.
diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c
index 6d4faba..bfaf817 100644
--- a/arch/x86/crypto/aesni-intel_glue.c
+++ b/arch/x86/crypto/aesni-intel_glue.c
@@ -177,7 +177,8 @@ static void aesni_gcm_enc_avx(void *ctx, u8 *out,
u8 *hash_subkey, const u8 *aad, unsigned long aad_len,
u8 *auth_tag, unsigned long auth_tag_len)
{
- if (plaintext_len < AVX_GEN2_OPTSIZE) {
+ struct crypto_aes_ctx *aes_ctx = (struct crypto_aes_ctx*)ctx;
+ if ((plaintext_len < AVX_GEN2_OPTSIZE) || (aes_ctx-> key_length != AES_KEYSIZE_128)){
aesni_gcm_enc(ctx, out, in, plaintext_len, iv, hash_subkey, aad,
aad_len, auth_tag, auth_tag_len);
} else {
@@ -192,7 +193,8 @@ static void aesni_gcm_dec_avx(void *ctx, u8 *out,
u8 *hash_subkey, const u8 *aad, unsigned long aad_len,
u8 *auth_tag, unsigned long auth_tag_len)
{
- if (ciphertext_len < AVX_GEN2_OPTSIZE) {
+ struct crypto_aes_ctx *aes_ctx = (struct crypto_aes_ctx*)ctx;
+ if ((ciphertext_len < AVX_GEN2_OPTSIZE) || (aes_ctx-> key_length != AES_KEYSIZE_128)) {
aesni_gcm_dec(ctx, out, in, ciphertext_len, iv, hash_subkey, aad,
aad_len, auth_tag, auth_tag_len);
} else {
@@ -226,7 +228,8 @@ static void aesni_gcm_enc_avx2(void *ctx, u8 *out,
u8 *hash_subkey, const u8 *aad, unsigned long aad_len,
u8 *auth_tag, unsigned long auth_tag_len)
{
- if (plaintext_len < AVX_GEN2_OPTSIZE) {
+ struct crypto_aes_ctx *aes_ctx = (struct crypto_aes_ctx*)ctx;
+ if ((plaintext_len < AVX_GEN2_OPTSIZE) || (aes_ctx-> key_length != AES_KEYSIZE_128)) {
aesni_gcm_enc(ctx, out, in, plaintext_len, iv, hash_subkey, aad,
aad_len, auth_tag, auth_tag_len);
} else if (plaintext_len < AVX_GEN4_OPTSIZE) {
@@ -245,7 +248,8 @@ static void aesni_gcm_dec_avx2(void *ctx, u8 *out,
u8 *hash_subkey, const u8 *aad, unsigned long aad_len,
u8 *auth_tag, unsigned long auth_tag_len)
{
- if (ciphertext_len < AVX_GEN2_OPTSIZE) {
+ struct crypto_aes_ctx *aes_ctx = (struct crypto_aes_ctx*)ctx;
+ if ((ciphertext_len < AVX_GEN2_OPTSIZE) || (aes_ctx-> key_length != AES_KEYSIZE_128)) {
aesni_gcm_dec(ctx, out, in, ciphertext_len, iv, hash_subkey,
aad, aad_len, auth_tag, auth_tag_len);
} else if (ciphertext_len < AVX_GEN4_OPTSIZE) {
@@ -878,7 +882,8 @@ static int rfc4106_set_key(struct crypto_aead *parent, const u8 *key,
}
/*Account for 4 byte nonce at the end.*/
key_len -= 4;
- if (key_len != AES_KEYSIZE_128) {
+ if (key_len != AES_KEYSIZE_128 && key_len != AES_KEYSIZE_192 &&
+ key_len != AES_KEYSIZE_256) {
crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
return -EINVAL;
}
@@ -989,6 +994,7 @@ static int __driver_rfc4106_encrypt(struct aead_request *req)
__be32 counter = cpu_to_be32(1);
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm);
+ u32 key_len = ctx->aes_key_expanded.key_length;
void *aes_ctx = &(ctx->aes_key_expanded);
unsigned long auth_tag_len = crypto_aead_authsize(tfm);
u8 iv_tab[16+AESNI_ALIGN];
@@ -1003,6 +1009,13 @@ static int __driver_rfc4106_encrypt(struct aead_request *req)
/* to 8 or 12 bytes */
if (unlikely(req->assoclen != 8 && req->assoclen != 12))
return -EINVAL;
+ if (unlikely(auth_tag_len != 8 && auth_tag_len != 12 && auth_tag_len != 16))
+ return -EINVAL;
+ if (unlikely(key_len != AES_KEYSIZE_128 &&
+ key_len != AES_KEYSIZE_192 &&
+ key_len != AES_KEYSIZE_256))
+ return -EINVAL;
+
/* IV below built */
for (i = 0; i < 4; i++)
*(iv+i) = ctx->nonce[i];
@@ -1067,6 +1080,7 @@ static int __driver_rfc4106_decrypt(struct aead_request *req)
int retval = 0;
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm);
+ u32 key_len = ctx->aes_key_expanded.key_length;
void *aes_ctx = &(ctx->aes_key_expanded);
unsigned long auth_tag_len = crypto_aead_authsize(tfm);
u8 iv_and_authTag[32+AESNI_ALIGN];
@@ -1080,6 +1094,13 @@ static int __driver_rfc4106_decrypt(struct aead_request *req)
if (unlikely((req->cryptlen < auth_tag_len) ||
(req->assoclen != 8 && req->assoclen != 12)))
return -EINVAL;
+ if (unlikely(auth_tag_len != 8 && auth_tag_len != 12 && auth_tag_len != 16))
+ return -EINVAL;
+ if (unlikely(key_len != AES_KEYSIZE_128 &&
+ key_len != AES_KEYSIZE_192 &&
+ key_len != AES_KEYSIZE_256))
+ return -EINVAL;
+
/* Assuming we are supporting rfc4106 64-bit extended */
/* sequence numbers We need to have the AAD length */
/* equal to 8 or 12 bytes */
--
2.7.4

View File

@@ -1,96 +0,0 @@
From a289eb38cfb481de48e36b481c72fb2492c6d242 Mon Sep 17 00:00:00 2001
From: Linus Torvalds <torvalds@linux-foundation.org>
Date: Thu, 13 Oct 2016 13:07:36 -0700
Subject: [PATCH] mm: remove gup_flags FOLL_WRITE games from __get_user_pages()
commit 19be0eaffa3ac7d8eb6784ad9bdbc7d67ed8e619 upstream.
This is an ancient bug that was actually attempted to be fixed once
(badly) by me eleven years ago in commit 4ceb5db9757a ("Fix
get_user_pages() race for write access") but that was then undone due to
problems on s390 by commit f33ea7f404e5 ("fix get_user_pages bug").
In the meantime, the s390 situation has long been fixed, and we can now
fix it by checking the pte_dirty() bit properly (and do it better). The
s390 dirty bit was implemented in abf09bed3cce ("s390/mm: implement
software dirty bits") which made it into v3.9. Earlier kernels will
have to look at the page state itself.
Also, the VM has become more scalable, and what used a purely
theoretical race back then has become easier to trigger.
To fix it, we introduce a new internal FOLL_COW flag to mark the "yes,
we already did a COW" rather than play racy games with FOLL_WRITE that
is very fundamental, and then use the pte dirty flag to validate that
the FOLL_COW flag is still valid.
Reported-and-tested-by: Phil "not Paul" Oester <kernel@linuxace.com>
Acked-by: Hugh Dickins <hughd@google.com>
Reviewed-by: Michal Hocko <mhocko@suse.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Kees Cook <keescook@chromium.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Willy Tarreau <w@1wt.eu>
Cc: Nick Piggin <npiggin@gmail.com>
Cc: Greg Thelen <gthelen@google.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
include/linux/mm.h | 1 +
mm/memory.c | 14 ++++++++++++--
2 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 5aef73c..6f56355 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1964,6 +1964,7 @@ static inline struct page *follow_page(struct vm_area_struct *vma,
#define FOLL_HWPOISON 0x100 /* check page is hwpoisoned */
#define FOLL_NUMA 0x200 /* force NUMA hinting page fault */
#define FOLL_MIGRATION 0x400 /* wait for page to replace migration entry */
+#define FOLL_COW 0x4000 /* internal GUP flag */
typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr,
void *data);
diff --git a/mm/memory.c b/mm/memory.c
index e9f4d40..5c1df12 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1449,6 +1449,16 @@ int zap_vma_ptes(struct vm_area_struct *vma, unsigned long address,
}
EXPORT_SYMBOL_GPL(zap_vma_ptes);
+/*
+ * FOLL_FORCE can write to even unwritable pte's, but only
+ * after we've gone through a COW cycle and they are dirty.
+ */
+static inline bool can_follow_write_pte(pte_t pte, unsigned int flags)
+{
+ return pte_write(pte) ||
+ ((flags & FOLL_FORCE) && (flags & FOLL_COW) && pte_dirty(pte));
+}
+
/**
* follow_page_mask - look up a page descriptor from a user-virtual address
* @vma: vm_area_struct mapping @address
@@ -1569,7 +1579,7 @@ split_fallthrough:
}
if ((flags & FOLL_NUMA) && pte_numa(pte))
goto no_page;
- if ((flags & FOLL_WRITE) && !pte_write(pte))
+ if ((flags & FOLL_WRITE) && !can_follow_write_pte(pte, flags))
goto unlock;
page = vm_normal_page(vma, address, pte);
@@ -1866,7 +1876,7 @@ long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
*/
if ((ret & VM_FAULT_WRITE) &&
!(vma->vm_flags & VM_WRITE))
- foll_flags &= ~FOLL_WRITE;
+ foll_flags |= FOLL_COW;
cond_resched();
}
--
2.7.4

View File

@@ -0,0 +1,12 @@
diff -Naur backports-4.2.6-1.org/drivers/net/wireless/ath/ath10k/htt_rx.c backports-4.2.6-1/drivers/net/wireless/ath/ath10k/htt_rx.c
--- backports-4.2.6-1.org/drivers/net/wireless/ath/ath10k/htt_rx.c 2015-11-15 22:19:40.000000000 +0100
+++ backports-4.2.6-1/drivers/net/wireless/ath/ath10k/htt_rx.c 2016-03-26 10:48:17.189430101 +0100
@@ -1476,7 +1476,7 @@
*/
if (!rx_status->freq) {
- ath10k_warn(ar, "no channel configured; ignoring frame(s)!\n");
+ ath10k_dbg(ar,ATH10K_DBG_DATA ,"no channel configured; ignoring frame(s)!\n");
return false;
}

View File

@@ -1,7 +1,7 @@
diff -Naur linux-3.14.65.org/arch/x86/Kconfig linux-3.14.65/arch/x86/Kconfig
--- linux-3.14.65.org/arch/x86/Kconfig 2016-03-16 16:42:30.000000000 +0100
+++ linux-3.14.65/arch/x86/Kconfig 2016-03-25 14:36:22.953256019 +0100
@@ -2287,6 +2287,7 @@
diff -Naur linux-4.9.8.org/arch/x86/Kconfig linux-4.9.8/arch/x86/Kconfig
--- linux-4.9.8.org/arch/x86/Kconfig 2017-02-04 09:47:29.000000000 +0100
+++ linux-4.9.8/arch/x86/Kconfig 2017-02-09 19:29:59.244945360 +0100
@@ -2604,6 +2604,7 @@
- AC adapter status updates
- Battery status updates
@@ -9,7 +9,7 @@ diff -Naur linux-3.14.65.org/arch/x86/Kconfig linux-3.14.65/arch/x86/Kconfig
config ALIX
bool "PCEngines ALIX System Support (LED setup)"
select GPIOLIB
@@ -2325,6 +2326,18 @@
@@ -2642,6 +2643,18 @@
endif # X86_32
@@ -28,9 +28,9 @@ diff -Naur linux-3.14.65.org/arch/x86/Kconfig linux-3.14.65/arch/x86/Kconfig
config AMD_NB
def_bool y
depends on CPU_SUP_AMD && PCI
diff -Naur linux-3.14.65.org/arch/x86/platform/apu/apu2-led.c linux-3.14.65/arch/x86/platform/apu/apu2-led.c
--- linux-3.14.65.org/arch/x86/platform/apu/apu2-led.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-3.14.65/arch/x86/platform/apu/apu2-led.c 2016-03-25 15:04:34.476689422 +0100
diff -Naur linux-4.9.8.org/arch/x86/platform/apu/apu2-led.c linux-4.9.8/arch/x86/platform/apu/apu2-led.c
--- linux-4.9.8.org/arch/x86/platform/apu/apu2-led.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-4.9.8/arch/x86/platform/apu/apu2-led.c 2017-02-09 19:29:59.244945360 +0100
@@ -0,0 +1,180 @@
+/*
+ * LEDs driver for PCEngines apu2
@@ -212,9 +212,9 @@ diff -Naur linux-3.14.65.org/arch/x86/platform/apu/apu2-led.c linux-3.14.65/arch
+MODULE_AUTHOR("Arne Fitzenreiter");
+MODULE_DESCRIPTION("PCEngines apu2 LED driver");
+MODULE_LICENSE("GPL");
diff -Naur linux-3.14.65.org/arch/x86/platform/apu/apu-led.c linux-3.14.65/arch/x86/platform/apu/apu-led.c
--- linux-3.14.65.org/arch/x86/platform/apu/apu-led.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-3.14.65/arch/x86/platform/apu/apu-led.c 2016-03-25 15:05:35.776693425 +0100
diff -Naur linux-4.9.8.org/arch/x86/platform/apu/apu-led.c linux-4.9.8/arch/x86/platform/apu/apu-led.c
--- linux-4.9.8.org/arch/x86/platform/apu/apu-led.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-4.9.8/arch/x86/platform/apu/apu-led.c 2017-02-09 19:29:59.244945360 +0100
@@ -0,0 +1,181 @@
+/*
+ * LEDs driver for PCEngines apu
@@ -397,18 +397,18 @@ diff -Naur linux-3.14.65.org/arch/x86/platform/apu/apu-led.c linux-3.14.65/arch/
+MODULE_AUTHOR("Christian Herzog");
+MODULE_DESCRIPTION("PCEngines apu LED driver");
+MODULE_LICENSE("GPL");
diff -Naur linux-3.14.65.org/arch/x86/platform/apu/Makefile linux-3.14.65/arch/x86/platform/apu/Makefile
--- linux-3.14.65.org/arch/x86/platform/apu/Makefile 1970-01-01 01:00:00.000000000 +0100
+++ linux-3.14.65/arch/x86/platform/apu/Makefile 2016-03-25 14:35:30.506585952 +0100
diff -Naur linux-4.9.8.org/arch/x86/platform/apu/Makefile linux-4.9.8/arch/x86/platform/apu/Makefile
--- linux-4.9.8.org/arch/x86/platform/apu/Makefile 1970-01-01 01:00:00.000000000 +0100
+++ linux-4.9.8/arch/x86/platform/apu/Makefile 2017-02-09 19:29:59.244945360 +0100
@@ -0,0 +1,2 @@
+obj-$(CONFIG_APULED) += apu-led.o
+obj-$(CONFIG_APU2LED) += apu2-led.o
diff -Naur linux-3.14.65.org/arch/x86/platform/Makefile linux-3.14.65/arch/x86/platform/Makefile
--- linux-3.14.65.org/arch/x86/platform/Makefile 2016-03-16 16:42:30.000000000 +0100
+++ linux-3.14.65/arch/x86/platform/Makefile 2016-03-25 14:31:04.079903947 +0100
diff -Naur linux-4.9.8.org/arch/x86/platform/Makefile linux-4.9.8/arch/x86/platform/Makefile
--- linux-4.9.8.org/arch/x86/platform/Makefile 2017-02-04 09:47:29.000000000 +0100
+++ linux-4.9.8/arch/x86/platform/Makefile 2017-02-09 19:32:31.768269470 +0100
@@ -1,4 +1,5 @@
# Platform specific code goes here
+obj-y += apu/
obj-y += atom/
obj-y += ce4100/
obj-y += efi/
obj-y += geode/

View File

@@ -0,0 +1,39 @@
diff -Naur linux-4.9.8.org/drivers/net/wireless/ath/regd.c linux-4.9.8/drivers/net/wireless/ath/regd.c
--- linux-4.9.8.org/drivers/net/wireless/ath/regd.c 2017-02-04 09:47:29.000000000 +0100
+++ linux-4.9.8/drivers/net/wireless/ath/regd.c 2017-02-11 15:31:20.502527360 +0100
@@ -341,6 +341,8 @@
struct ieee80211_channel *ch;
unsigned int i;
+ return;
+
for (band = 0; band < NUM_NL80211_BANDS; band++) {
if (!wiphy->bands[band])
continue;
@@ -374,6 +376,8 @@
{
struct ieee80211_supported_band *sband;
+ return;
+
sband = wiphy->bands[NL80211_BAND_2GHZ];
if (!sband)
return;
@@ -402,6 +406,8 @@
struct ieee80211_channel *ch;
unsigned int i;
+ return;
+
if (!wiphy->bands[NL80211_BAND_5GHZ])
return;
@@ -632,6 +638,8 @@
{
const struct ieee80211_regdomain *regd;
+ return 0;
+
wiphy->reg_notifier = reg_notifier;
wiphy->regulatory_flags |= REGULATORY_STRICT_REG |
REGULATORY_CUSTOM_REG;

View File

@@ -1,7 +1,7 @@
diff -Naur linux-3.14.22.org/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c linux-3.14.22/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c
--- linux-3.14.22.org/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c 2014-10-15 08:42:04.000000000 +0200
+++ linux-3.14.22/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c 2014-10-24 17:33:57.165155190 +0200
@@ -613,14 +613,15 @@
diff -Naur linux-4.9.8.org/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.c linux-4.9.8/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.c
--- linux-4.9.8.org/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.c 2017-02-04 09:47:29.000000000 +0100
+++ linux-4.9.8/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.c 2017-02-11 10:35:20.216560908 +0100
@@ -615,14 +615,15 @@
/* set no-HT40, will enable as appropriate later */
channel->flags = IEEE80211_CHAN_NO_HT40;

View File

@@ -1,7 +1,7 @@
diff -Naur linux-3.14.22.org/include/linux/netfilter/xt_layer7.h linux-3.14.22/include/linux/netfilter/xt_layer7.h
--- linux-3.14.22.org/include/linux/netfilter/xt_layer7.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-3.14.22/include/linux/netfilter/xt_layer7.h 2014-10-24 15:33:21.281274380 +0200
@@ -0,0 +1,14 @@
diff -Naur linux-4.9.8.org/include/linux/netfilter/xt_layer7.h linux-4.9.8/include/linux/netfilter/xt_layer7.h
--- linux-4.9.8.org/include/linux/netfilter/xt_layer7.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-4.9.8/include/linux/netfilter/xt_layer7.h 2017-02-10 20:55:36.894611414 +0100
@@ -0,0 +1,13 @@
+#ifndef _XT_LAYER7_H
+#define _XT_LAYER7_H
+
@@ -12,16 +12,15 @@ diff -Naur linux-3.14.22.org/include/linux/netfilter/xt_layer7.h linux-3.14.22/i
+ char protocol[MAX_PROTOCOL_LEN];
+ char pattern[MAX_PATTERN_LEN];
+ u_int8_t invert;
+ u_int8_t pkt;
+};
+
+#endif /* _XT_LAYER7_H */
diff -Naur linux-3.14.22.org/include/net/netfilter/nf_conntrack.h linux-3.14.22/include/net/netfilter/nf_conntrack.h
--- linux-3.14.22.org/include/net/netfilter/nf_conntrack.h 2014-10-15 08:42:04.000000000 +0200
+++ linux-3.14.22/include/net/netfilter/nf_conntrack.h 2014-10-24 15:33:21.281274380 +0200
@@ -105,6 +105,22 @@
struct net *ct_net;
#endif
diff -Naur linux-4.9.8.org/include/net/netfilter/nf_conntrack.h linux-4.9.8/include/net/netfilter/nf_conntrack.h
--- linux-4.9.8.org/include/net/netfilter/nf_conntrack.h 2017-02-04 09:47:29.000000000 +0100
+++ linux-4.9.8/include/net/netfilter/nf_conntrack.h 2017-02-10 16:10:27.000000000 +0100
@@ -120,6 +120,22 @@
/* Extensions */
struct nf_ct_ext *ext;
+#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || \
+ defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE)
@@ -42,21 +41,10 @@ diff -Naur linux-3.14.22.org/include/net/netfilter/nf_conntrack.h linux-3.14.22/
/* Storage reserved for other modules, must be the last member */
union nf_conntrack_proto proto;
};
diff -Naur linux-3.14.22.org/include/uapi/linux/netfilter/Kbuild linux-3.14.22/include/uapi/linux/netfilter/Kbuild
--- linux-3.14.22.org/include/uapi/linux/netfilter/Kbuild 2014-10-15 08:42:04.000000000 +0200
+++ linux-3.14.22/include/uapi/linux/netfilter/Kbuild 2014-10-24 15:34:39.721663344 +0200
@@ -59,6 +59,7 @@
header-y += xt_iprange.h
header-y += xt_ipvs.h
header-y += xt_l2tp.h
+header-y += xt_layer7.h
header-y += xt_length.h
header-y += xt_limit.h
header-y += xt_mac.h
diff -Naur linux-3.14.22.org/net/netfilter/Kconfig linux-3.14.22/net/netfilter/Kconfig
--- linux-3.14.22.org/net/netfilter/Kconfig 2014-10-15 08:42:04.000000000 +0200
+++ linux-3.14.22/net/netfilter/Kconfig 2014-10-24 15:33:21.281274380 +0200
@@ -1153,6 +1153,26 @@
diff -Naur linux-4.9.8.org/net/netfilter/Kconfig linux-4.9.8/net/netfilter/Kconfig
--- linux-4.9.8.org/net/netfilter/Kconfig 2017-02-04 09:47:29.000000000 +0100
+++ linux-4.9.8/net/netfilter/Kconfig 2017-02-10 16:10:30.000000000 +0100
@@ -1238,6 +1238,26 @@
To compile it as a module, choose M here. If unsure, say N.
@@ -83,23 +71,10 @@ diff -Naur linux-3.14.22.org/net/netfilter/Kconfig linux-3.14.22/net/netfilter/K
config NETFILTER_XT_MATCH_LENGTH
tristate '"length" match support'
depends on NETFILTER_ADVANCED
@@ -1347,6 +1367,12 @@
To compile it as a module, choose M here. If unsure, say N.
+config NETFILTER_XT_MATCH_LAYER7_DEBUG
+ bool 'Layer 7 debugging output'
+ depends on NETFILTER_XT_MATCH_LAYER7
+ help
+ Say Y to get lots of debugging output.
+
config NETFILTER_XT_MATCH_STATISTIC
tristate '"statistic" match support'
depends on NETFILTER_ADVANCED
diff -Naur linux-3.14.22.org/net/netfilter/Makefile linux-3.14.22/net/netfilter/Makefile
--- linux-3.14.22.org/net/netfilter/Makefile 2014-10-15 08:42:04.000000000 +0200
+++ linux-3.14.22/net/netfilter/Makefile 2014-10-24 15:33:21.281274380 +0200
@@ -158,6 +158,7 @@
diff -Naur linux-4.9.8.org/net/netfilter/Makefile linux-4.9.8/net/netfilter/Makefile
--- linux-4.9.8.org/net/netfilter/Makefile 2017-02-04 09:47:29.000000000 +0100
+++ linux-4.9.8/net/netfilter/Makefile 2017-02-10 16:10:30.000000000 +0100
@@ -174,6 +174,7 @@
obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o
obj-$(CONFIG_NETFILTER_XT_MATCH_SOCKET) += xt_socket.o
obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o
@@ -107,12 +82,12 @@ diff -Naur linux-3.14.22.org/net/netfilter/Makefile linux-3.14.22/net/netfilter/
obj-$(CONFIG_NETFILTER_XT_MATCH_STATISTIC) += xt_statistic.o
obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o
obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o
diff -Naur linux-3.14.22.org/net/netfilter/nf_conntrack_core.c linux-3.14.22/net/netfilter/nf_conntrack_core.c
--- linux-3.14.22.org/net/netfilter/nf_conntrack_core.c 2014-10-15 08:42:04.000000000 +0200
+++ linux-3.14.22/net/netfilter/nf_conntrack_core.c 2014-10-24 15:33:21.281274380 +0200
@@ -220,6 +220,13 @@
* too. */
nf_ct_remove_expectations(ct);
diff -Naur linux-4.9.8.org/net/netfilter/nf_conntrack_core.c linux-4.9.8/net/netfilter/nf_conntrack_core.c
--- linux-4.9.8.org/net/netfilter/nf_conntrack_core.c 2017-02-04 09:47:29.000000000 +0100
+++ linux-4.9.8/net/netfilter/nf_conntrack_core.c 2017-02-10 16:10:30.000000000 +0100
@@ -341,6 +341,13 @@
{
struct ct_pcpu *pcpu;
+#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE)
+ if(ct->layer7.app_proto)
@@ -122,27 +97,26 @@ diff -Naur linux-3.14.22.org/net/netfilter/nf_conntrack_core.c linux-3.14.22/net
+#endif
+
/* We overload first tuple to link into unconfirmed or dying list.*/
BUG_ON(hlist_nulls_unhashed(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode));
hlist_nulls_del_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode);
diff -Naur linux-3.14.22.org/net/netfilter/nf_conntrack_standalone.c linux-3.14.22/net/netfilter/nf_conntrack_standalone.c
--- linux-3.14.22.org/net/netfilter/nf_conntrack_standalone.c 2014-10-15 08:42:04.000000000 +0200
+++ linux-3.14.22/net/netfilter/nf_conntrack_standalone.c 2014-10-24 15:33:21.285274399 +0200
@@ -240,6 +240,12 @@
if (ct_show_delta_time(s, ct))
goto release;
pcpu = per_cpu_ptr(nf_ct_net(ct)->ct.pcpu_lists, ct->cpu);
diff -Naur linux-4.9.8.org/net/netfilter/nf_conntrack_standalone.c linux-4.9.8/net/netfilter/nf_conntrack_standalone.c
--- linux-4.9.8.org/net/netfilter/nf_conntrack_standalone.c 2017-02-04 09:47:29.000000000 +0100
+++ linux-4.9.8/net/netfilter/nf_conntrack_standalone.c 2017-02-10 16:10:30.000000000 +0100
@@ -274,6 +274,11 @@
ct_show_zone(s, ct, NF_CT_DEFAULT_ZONE_DIR);
ct_show_delta_time(s, ct);
+#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE)
+ if(ct->layer7.app_proto &&
+ seq_printf(s, "l7proto=%s ", ct->layer7.app_proto))
+ return -ENOSPC;
+ if(ct->layer7.app_proto)
+ seq_printf(s, "l7proto=%s ", ct->layer7.app_proto);
+#endif
+
if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use)))
goto release;
seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use));
diff -Naur linux-3.14.22.org/net/netfilter/regexp/regexp.c linux-3.14.22/net/netfilter/regexp/regexp.c
--- linux-3.14.22.org/net/netfilter/regexp/regexp.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-3.14.22/net/netfilter/regexp/regexp.c 2014-10-24 15:33:21.285274399 +0200
if (seq_has_overflowed(s))
diff -Naur linux-4.9.8.org/net/netfilter/regexp/regexp.c linux-4.9.8/net/netfilter/regexp/regexp.c
--- linux-4.9.8.org/net/netfilter/regexp/regexp.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-4.9.8/net/netfilter/regexp/regexp.c 2017-02-10 20:55:36.898611415 +0100
@@ -0,0 +1,1197 @@
+/*
+ * regcomp and regexec -- regsub and regerror are elsewhere
@@ -1341,9 +1315,9 @@ diff -Naur linux-3.14.22.org/net/netfilter/regexp/regexp.c linux-3.14.22/net/net
+#endif
+
+
diff -Naur linux-3.14.22.org/net/netfilter/regexp/regexp.h linux-3.14.22/net/netfilter/regexp/regexp.h
--- linux-3.14.22.org/net/netfilter/regexp/regexp.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-3.14.22/net/netfilter/regexp/regexp.h 2014-10-24 15:33:21.285274399 +0200
diff -Naur linux-4.9.8.org/net/netfilter/regexp/regexp.h linux-4.9.8/net/netfilter/regexp/regexp.h
--- linux-4.9.8.org/net/netfilter/regexp/regexp.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-4.9.8/net/netfilter/regexp/regexp.h 2017-02-10 20:55:36.898611415 +0100
@@ -0,0 +1,41 @@
+/*
+ * Definitions etc. for regexp(3) routines.
@@ -1386,18 +1360,18 @@ diff -Naur linux-3.14.22.org/net/netfilter/regexp/regexp.h linux-3.14.22/net/net
+void regerror(char *s);
+
+#endif
diff -Naur linux-3.14.22.org/net/netfilter/regexp/regmagic.h linux-3.14.22/net/netfilter/regexp/regmagic.h
--- linux-3.14.22.org/net/netfilter/regexp/regmagic.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-3.14.22/net/netfilter/regexp/regmagic.h 2014-10-24 15:33:21.285274399 +0200
diff -Naur linux-4.9.8.org/net/netfilter/regexp/regmagic.h linux-4.9.8/net/netfilter/regexp/regmagic.h
--- linux-4.9.8.org/net/netfilter/regexp/regmagic.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-4.9.8/net/netfilter/regexp/regmagic.h 2017-02-10 20:55:36.898611415 +0100
@@ -0,0 +1,5 @@
+/*
+ * The first byte of the regexp internal "program" is actually this magic
+ * number; the start node begins in the second byte.
+ */
+#define MAGIC 0234
diff -Naur linux-3.14.22.org/net/netfilter/regexp/regsub.c linux-3.14.22/net/netfilter/regexp/regsub.c
--- linux-3.14.22.org/net/netfilter/regexp/regsub.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-3.14.22/net/netfilter/regexp/regsub.c 2014-10-24 15:33:21.285274399 +0200
diff -Naur linux-4.9.8.org/net/netfilter/regexp/regsub.c linux-4.9.8/net/netfilter/regexp/regsub.c
--- linux-4.9.8.org/net/netfilter/regexp/regsub.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-4.9.8/net/netfilter/regexp/regsub.c 2017-02-10 20:55:36.898611415 +0100
@@ -0,0 +1,95 @@
+/*
+ * regsub
@@ -1494,10 +1468,10 @@ diff -Naur linux-3.14.22.org/net/netfilter/regexp/regsub.c linux-3.14.22/net/net
+ }
+ *dst++ = '\0';
+}
diff -Naur linux-3.14.22.org/net/netfilter/xt_layer7.c linux-3.14.22/net/netfilter/xt_layer7.c
--- linux-3.14.22.org/net/netfilter/xt_layer7.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-3.14.22/net/netfilter/xt_layer7.c 2014-10-24 15:33:21.285274399 +0200
@@ -0,0 +1,665 @@
diff -Naur linux-4.9.8.org/net/netfilter/xt_layer7.c linux-4.9.8/net/netfilter/xt_layer7.c
--- linux-4.9.8.org/net/netfilter/xt_layer7.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-4.9.8/net/netfilter/xt_layer7.c 2017-02-10 22:42:57.750923134 +0100
@@ -0,0 +1,658 @@
+/*
+ Kernel module to match application layer (OSI layer 7) data in connections.
+
@@ -1521,13 +1495,14 @@ diff -Naur linux-3.14.22.org/net/netfilter/xt_layer7.c linux-3.14.22/net/netfilt
+#include <net/ip.h>
+#include <net/tcp.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_core.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+#include <net/netfilter/nf_conntrack_extend.h>
+#include <net/netfilter/nf_conntrack_acct.h>
+#endif
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_layer7.h>
+#include <linux/ctype.h>
@@ -1539,7 +1514,7 @@ diff -Naur linux-3.14.22.org/net/netfilter/xt_layer7.c linux-3.14.22/net/netfilt
+MODULE_AUTHOR("Matthew Strait <quadong@users.sf.net>, Ethan Sommer <sommere@users.sf.net>");
+MODULE_DESCRIPTION("iptables application layer match module");
+MODULE_ALIAS("ipt_layer7");
+MODULE_VERSION("2.21");
+MODULE_VERSION("2.23");
+
+static int maxdatalen = 2048; // this is the default
+module_param(maxdatalen, int, 0444);
@@ -1564,13 +1539,18 @@ diff -Naur linux-3.14.22.org/net/netfilter/xt_layer7.c linux-3.14.22/net/netfilt
+
+static int total_acct_packets(struct nf_conn *ct)
+{
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 26)
+ BUG_ON(ct == NULL);
+ return (ct->counters[IP_CT_DIR_ORIGINAL].packets + ct->counters[IP_CT_DIR_REPLY].packets);
+#else
+ struct nf_conn_counter *acct;
+
+ BUG_ON(ct == NULL);
+ acct = nf_conn_acct_find(ct);
+ if (!acct)
+ return 0;
+ return (atomic64_read(&acct[IP_CT_DIR_ORIGINAL].packets) + atomic64_read(&acct[IP_CT_DIR_REPLY].packets));
+ return (atomic64_read(&acct[IP_CT_DIR_ORIGINAL].packets) + atomic64_read(&acct[IP_CT_DIR_REPLY].packets));
+#endif
+}
+
+#ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG
@@ -1706,67 +1686,40 @@ diff -Naur linux-3.14.22.org/net/netfilter/xt_layer7.c linux-3.14.22/net/netfilt
+
+static int can_handle(const struct sk_buff *skb)
+{
+ struct iphdr iphdr_tmp;
+ struct iphdr *iphdr;
+ int offset;
+
+ if (!ip_hdr(skb))
+ if(!ip_hdr(skb)) /* not IP */
+ return 0;
+
+ offset = ((uintptr_t)ip_hdr(skb)) - ((uintptr_t)skb->data);
+
+ iphdr = skb_header_pointer(skb, offset, sizeof(*iphdr), &iphdr_tmp);
+ if (!iphdr)
+ if(ip_hdr(skb)->protocol != IPPROTO_TCP &&
+ ip_hdr(skb)->protocol != IPPROTO_UDP &&
+ ip_hdr(skb)->protocol != IPPROTO_ICMP)
+ return 0;
+
+ if (iphdr->protocol == IPPROTO_TCP ||
+ iphdr->protocol == IPPROTO_UDP ||
+ iphdr->protocol == IPPROTO_ICMP)
+ return 1;
+
+ return 0;
+ return 1;
+}
+
+/* Returns offset the into the skb->data that the application data starts */
+static int app_data_offset(const struct sk_buff *skb)
+{
+ int offset;
+ struct iphdr iphdr_tmp;
+ struct iphdr *iphdr;
+ struct tcphdr tcphdr_tmp;
+ struct tcphdr *tcphdr;
+ /* In case we are ported somewhere (ebtables?) where ip_hdr(skb)
+ isn't set, this can be gotten from 4*(skb->data[0] & 0x0f) as well. */
+ int ip_hl = 4*ip_hdr(skb)->ihl;
+
+ if (!ip_hdr(skb))
+ return -1;
+ if( ip_hdr(skb)->protocol == IPPROTO_TCP ) {
+ /* 12 == offset into TCP header for the header length field.
+ Can't get this with skb->h.th->doff because the tcphdr
+ struct doesn't get set when routing (this is confirmed to be
+ true in Netfilter as well as QoS.) */
+ int tcp_hl = 4*(skb->data[ip_hl + 12] >> 4);
+
+ offset = ((uintptr_t)ip_hdr(skb)) - ((uintptr_t)skb->data);
+
+ iphdr = skb_header_pointer(skb, offset, sizeof(*iphdr), &iphdr_tmp);
+ if (!iphdr)
+ return -1;
+
+ offset += iphdr->ihl * 4;
+
+ if (iphdr->protocol == IPPROTO_TCP) {
+ tcphdr = skb_header_pointer(skb, offset, sizeof(*tcphdr),
+ &tcphdr_tmp);
+ if (!tcphdr)
+ return -1;
+
+ offset += tcphdr->doff * 4;
+
+ return offset;
+ return ip_hl + tcp_hl;
+ } else if( ip_hdr(skb)->protocol == IPPROTO_UDP ) {
+ return ip_hl + 8; /* UDP header is always 8 bytes */
+ } else if( ip_hdr(skb)->protocol == IPPROTO_ICMP ) {
+ return ip_hl + 8; /* ICMP header is 8 bytes */
+ } else {
+ if (net_ratelimit())
+ printk(KERN_ERR "layer7: tried to handle unknown "
+ "protocol!\n");
+ return ip_hl + 8; /* something reasonable */
+ }
+
+ if (iphdr->protocol == IPPROTO_UDP)
+ return offset + 8;
+
+ if (iphdr->protocol == IPPROTO_ICMP)
+ return offset + 8;
+
+ if (net_ratelimit())
+ pr_err(KERN_ERR "layer7: tried to handle unknown protocol!\n");
+
+ return offset + 8; /* something reasonable */
+}
+
+/* handles whether there's a match when we aren't appending data anymore */
@@ -1835,61 +1788,33 @@ diff -Naur linux-3.14.22.org/net/netfilter/xt_layer7.c linux-3.14.22/net/netfilt
+}
+
+/* add the new app data to the conntrack. Return number of bytes added. */
+static int add_datastr(char *target, int offset, char *app_data, int len)
+static int add_data(struct nf_conn * master_conntrack,
+ char * app_data, int appdatalen)
+{
+ int length = 0, i;
+ if (!target) return 0;
+ int oldlength = master_conntrack->layer7.app_data_len;
+
+ /* This is a fix for a race condition by Deti Fliegl. However, I'm not
+ clear on whether the race condition exists or whether this really
+ fixes it. I might just be being dense... Anyway, if it's not really
+ a fix, all it does is waste a very small amount of time. */
+ if(!master_conntrack->layer7.app_data) return 0;
+
+ /* Strip nulls. Make everything lower case (our regex lib doesn't
+ do case insensitivity). Add it to the end of the current data. */
+ for(i = 0; i < maxdatalen-offset-1 && i < len; i++) {
+ for(i = 0; i < maxdatalen-oldlength-1 &&
+ i < appdatalen; i++) {
+ if(app_data[i] != '\0') {
+ /* the kernel version of tolower mungs 'upper ascii' */
+ target[length+offset] =
+ master_conntrack->layer7.app_data[length+oldlength] =
+ isascii(app_data[i])?
+ tolower(app_data[i]) : app_data[i];
+ length++;
+ }
+ }
+ target[length+offset] = '\0';
+
+ return length;
+}
+
+/* add the new app data to the buffer. Return number of bytes added. */
+static int add_data(char *target, int offset, const struct sk_buff *skb)
+{
+ int length, length_sum = 0;
+ int data_start = app_data_offset(skb);
+ int remaining = skb->len - data_start;
+ int to_copy;
+ uint8_t buf[512];
+ uint8_t *data;
+
+ while ((offset < maxdatalen - 1) && (remaining > 0)) {
+ to_copy = min_t(int, remaining, sizeof(buf));
+
+ data = skb_header_pointer(skb, data_start, to_copy, buf);
+ length = add_datastr(target, offset, data, to_copy);
+
+ remaining -= to_copy;
+ data_start += to_copy;
+ offset += length;
+ length_sum += length;
+ }
+
+ return length_sum;
+}
+
+/* add the new app data to the conntrack. Return number of bytes added. */
+static int add_data_conntrack(struct nf_conn *master_conntrack,
+ const struct sk_buff *skb)
+{
+ int length;
+
+ length = add_data(master_conntrack->layer7.app_data,
+ master_conntrack->layer7.app_data_len, skb);
+ master_conntrack->layer7.app_data_len += length;
+ master_conntrack->layer7.app_data[length+oldlength] = '\0';
+ master_conntrack->layer7.app_data_len = length + oldlength;
+
+ return length;
+}
@@ -1941,23 +1866,42 @@ diff -Naur linux-3.14.22.org/net/netfilter/xt_layer7.c linux-3.14.22/net/netfilt
+ return count;
+}
+
+static bool match(const struct sk_buff *skbin, struct xt_action_param *par)
+static bool
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+match(const struct sk_buff *skbin, struct xt_action_param *par)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
+match(const struct sk_buff *skbin, const struct xt_match_param *par)
+#else
+match(const struct sk_buff *skbin,
+ const struct net_device *in,
+ const struct net_device *out,
+ const struct xt_match *match,
+ const void *matchinfo,
+ int offset,
+ unsigned int protoff,
+ bool *hotdrop)
+#endif
+{
+ /* sidestep const without getting a compiler warning... */
+ struct sk_buff *skb = (struct sk_buff *)skbin;
+ struct sk_buff * skb = (struct sk_buff *)skbin;
+
+ const struct xt_layer7_info * info = par->matchinfo;
+ const struct xt_layer7_info * info =
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
+ par->matchinfo;
+ #else
+ matchinfo;
+ #endif
+
+ enum ip_conntrack_info master_ctinfo, ctinfo;
+ struct nf_conn *master_conntrack, *conntrack;
+ unsigned char *tmp_data;
+ unsigned int pattern_result;
+ unsigned char * app_data;
+ unsigned int pattern_result, appdatalen;
+ regexp * comppattern;
+
+ /* Be paranoid/incompetent - lock the entire match function. */
+ spin_lock_bh(&l7_lock);
+
+ if (!can_handle(skbin)) {
+ if(!can_handle(skb)){
+ DPRINTK("layer7: This is some protocol I can't handle.\n");
+ spin_unlock_bh(&l7_lock);
+ return info->invert;
@@ -1966,9 +1910,8 @@ diff -Naur linux-3.14.22.org/net/netfilter/xt_layer7.c linux-3.14.22/net/netfilt
+ /* Treat parent & all its children together as one connection, except
+ for the purpose of setting conntrack->layer7.app_proto in the actual
+ connection. This makes /proc/net/ip_conntrack more satisfying. */
+ conntrack = nf_ct_get(skbin, &ctinfo);
+ master_conntrack = nf_ct_get(skbin, &master_ctinfo);
+ if (!conntrack || !master_conntrack) {
+ if(!(conntrack = nf_ct_get(skb, &ctinfo)) ||
+ !(master_conntrack=nf_ct_get(skb,&master_ctinfo))){
+ DPRINTK("layer7: couldn't get conntrack.\n");
+ spin_unlock_bh(&l7_lock);
+ return info->invert;
@@ -1979,8 +1922,8 @@ diff -Naur linux-3.14.22.org/net/netfilter/xt_layer7.c linux-3.14.22/net/netfilt
+ master_conntrack = master_ct(master_conntrack);
+
+ /* if we've classified it or seen too many packets */
+ if(!info->pkt && (total_acct_packets(master_conntrack) > num_packets ||
+ master_conntrack->layer7.app_proto)) {
+ if(total_acct_packets(master_conntrack) > num_packets ||
+ master_conntrack->layer7.app_proto) {
+
+ pattern_result = match_no_append(conntrack, master_conntrack,
+ ctinfo, master_ctinfo, info);
@@ -1996,28 +1939,23 @@ diff -Naur linux-3.14.22.org/net/netfilter/xt_layer7.c linux-3.14.22/net/netfilt
+ return (pattern_result ^ info->invert);
+ }
+
+ /* the return value gets checked later, when we're ready to use it */
+ comppattern = compile_and_cache(info->pattern, info->protocol);
+
+ if (info->pkt) {
+ tmp_data = kmalloc(maxdatalen, GFP_ATOMIC);
+ if(!tmp_data){
+ if(skb_is_nonlinear(skb)){
+ if(skb_linearize(skb) != 0){
+ if (net_ratelimit())
+ printk(KERN_ERR "layer7: out of memory in match, bailing.\n");
+ printk(KERN_ERR "layer7: failed to linearize "
+ "packet, bailing.\n");
+ spin_unlock_bh(&l7_lock);
+ return info->invert;
+ }
+
+ tmp_data[0] = '\0';
+ add_data(tmp_data, 0, skbin);
+ pattern_result = ((comppattern && regexec(comppattern, tmp_data)) ? 1 : 0);
+
+ kfree(tmp_data);
+ tmp_data = NULL;
+ spin_unlock_bh(&l7_lock);
+
+ return (pattern_result ^ info->invert);
+ }
+
+ /* now that the skb is linearized, it's safe to set these. */
+ app_data = skb->data + app_data_offset(skb);
+ appdatalen = skb_tail_pointer(skb) - app_data;
+
+ /* the return value gets checked later, when we're ready to use it */
+ comppattern = compile_and_cache(info->pattern, info->protocol);
+
+ /* On the first packet of a connection, allocate space for app data */
+ if(total_acct_packets(master_conntrack) == 1 && !skb->cb[0] &&
+ !master_conntrack->layer7.app_data){
@@ -2043,7 +1981,7 @@ diff -Naur linux-3.14.22.org/net/netfilter/xt_layer7.c linux-3.14.22/net/netfilt
+
+ if(!skb->cb[0]){
+ int newbytes;
+ newbytes = add_data_conntrack(master_conntrack, skb);
+ newbytes = add_data(master_conntrack, app_data, appdatalen);
+
+ if(newbytes == 0) { /* didn't add any data */
+ skb->cb[0] = 1;
@@ -2094,26 +2032,54 @@ diff -Naur linux-3.14.22.org/net/netfilter/xt_layer7.c linux-3.14.22/net/netfilt
+}
+
+// load nf_conntrack_ipv4
+static int check(const struct xt_mtchk_param *par)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+static int
+#else
+static bool
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
+check(const struct xt_mtchk_param *par)
+{
+ if (nf_ct_l3proto_try_module_get(par->match->family) < 0) {
+ printk(KERN_WARNING "can't load conntrack support for "
+ "proto=%d\n", par->match->family);
+#else
+check(const char *tablename, const void *inf,
+ const struct xt_match *match, void *matchinfo,
+ unsigned int hook_mask)
+{
+ if (nf_ct_l3proto_try_module_get(match->family) < 0) {
+ printk(KERN_WARNING "can't load conntrack support for "
+ "proto=%d\n", match->family);
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+ return -EINVAL;
+ }
+ return 0;
+#else
+ return 0;
+ }
+ return 1;
+#endif
+}
+
+
+static void destroy(const struct xt_mtdtor_param *par)
+{
+ nf_ct_l3proto_module_put(par->match->family);
+}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
+ static void destroy(const struct xt_mtdtor_param *par)
+ {
+ nf_ct_l3proto_module_put(par->match->family);
+ }
+#else
+ static void destroy(const struct xt_match *match, void *matchinfo)
+ {
+ nf_ct_l3proto_module_put(match->family);
+ }
+#endif
+
+static struct xt_match xt_layer7_match[] __read_mostly = {
+{
+ .name = "layer7",
+ .family = AF_INET,
+ .family = NFPROTO_IPV4,
+ .checkentry = check,
+ .match = match,
+ .destroy = destroy,
@@ -2163,3 +2129,4 @@ diff -Naur linux-3.14.22.org/net/netfilter/xt_layer7.c linux-3.14.22/net/netfilt
+
+module_init(xt_layer7_init);
+module_exit(xt_layer7_fini);
+

View File

@@ -1,8 +1,8 @@
diff -Naur linux-3.14.22.org/drivers/leds/trigger/Kconfig linux-3.14.22/drivers/leds/trigger/Kconfig
--- linux-3.14.22.org/drivers/leds/trigger/Kconfig 2014-10-15 08:42:04.000000000 +0200
+++ linux-3.14.22/drivers/leds/trigger/Kconfig 2014-11-06 17:52:02.303748375 +0100
@@ -108,4 +108,11 @@
This enables direct flash/torch on/off by the driver, kernel space.
diff -Naur linux-4.9.8.org/drivers/leds/trigger/Kconfig linux-4.9.8/drivers/leds/trigger/Kconfig
--- linux-4.9.8.org/drivers/leds/trigger/Kconfig 2017-02-04 09:47:29.000000000 +0100
+++ linux-4.9.8/drivers/leds/trigger/Kconfig 2017-02-09 16:58:20.280030084 +0100
@@ -126,4 +126,11 @@
a different trigger.
If unsure, say Y.
+config LEDS_TRIGGER_NETDEV
@@ -13,9 +13,9 @@ diff -Naur linux-3.14.22.org/drivers/leds/trigger/Kconfig linux-3.14.22/drivers/
+ If unsure, say Y.
+
endif # LEDS_TRIGGERS
diff -Naur linux-3.14.22.org/drivers/leds/trigger/ledtrig-netdev.c linux-3.14.22/drivers/leds/trigger/ledtrig-netdev.c
--- linux-3.14.22.org/drivers/leds/trigger/ledtrig-netdev.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-3.14.22/drivers/leds/trigger/ledtrig-netdev.c 2014-11-06 17:47:09.913748236 +0100
diff -Naur linux-4.9.8.org/drivers/leds/trigger/ledtrig-netdev.c linux-4.9.8/drivers/leds/trigger/ledtrig-netdev.c
--- linux-4.9.8.org/drivers/leds/trigger/ledtrig-netdev.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-4.9.8/drivers/leds/trigger/ledtrig-netdev.c 2017-02-09 16:58:20.280030084 +0100
@@ -0,0 +1,438 @@
+/*
+ * LED Kernel Netdev Trigger
@@ -455,11 +455,11 @@ diff -Naur linux-3.14.22.org/drivers/leds/trigger/ledtrig-netdev.c linux-3.14.22
+MODULE_AUTHOR("Oliver Jowett <oliver@opencloud.com>");
+MODULE_DESCRIPTION("Netdev LED trigger");
+MODULE_LICENSE("GPL");
diff -Naur linux-3.14.22.org/drivers/leds/trigger/Makefile linux-3.14.22/drivers/leds/trigger/Makefile
--- linux-3.14.22.org/drivers/leds/trigger/Makefile 2014-10-15 08:42:04.000000000 +0200
+++ linux-3.14.22/drivers/leds/trigger/Makefile 2014-11-06 17:51:29.818748360 +0100
@@ -8,3 +8,4 @@
obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
diff -Naur linux-4.9.8.org/drivers/leds/trigger/Makefile linux-4.9.8/drivers/leds/trigger/Makefile
--- linux-4.9.8.org/drivers/leds/trigger/Makefile 2017-02-04 09:47:29.000000000 +0100
+++ linux-4.9.8/drivers/leds/trigger/Makefile 2017-02-09 17:00:13.303367332 +0100
@@ -10,3 +10,4 @@
obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT) += ledtrig-transient.o
obj-$(CONFIG_LEDS_TRIGGER_CAMERA) += ledtrig-camera.o
obj-$(CONFIG_LEDS_TRIGGER_PANIC) += ledtrig-panic.o
+obj-$(CONFIG_LEDS_TRIGGER_NETDEV) += ledtrig-netdev.o

View File

@@ -0,0 +1,42 @@
diff -Naur linux-4.9.8.org/drivers/net/wireless/ralink/rt2x00/rt2800usb.c linux-4.9.8/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
--- linux-4.9.8.org/drivers/net/wireless/ralink/rt2x00/rt2800usb.c 2017-02-04 09:47:29.000000000 +0100
+++ linux-4.9.8/drivers/net/wireless/ralink/rt2x00/rt2800usb.c 2017-02-11 10:50:04.909859370 +0100
@@ -448,7 +448,7 @@
rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX0Q)) {
- rt2x00_warn(rt2x00dev, "TX HW queue 0 timed out, invoke forced kick\n");
+ rt2x00_dbg(rt2x00dev, "TX HW queue 0 timed out, invoke forced kick\n");
rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40012);
@@ -463,7 +463,7 @@
rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX1Q)) {
- rt2x00_warn(rt2x00dev, "TX HW queue 1 timed out, invoke forced kick\n");
+ rt2x00_dbg(rt2x00dev, "TX HW queue 1 timed out, invoke forced kick\n");
rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf4000a);
@@ -613,7 +613,7 @@
if (unlikely(test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
!test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))) {
- rt2x00_warn(rt2x00dev, "Data pending for entry %u in queue %u\n",
+ rt2x00_dbg(rt2x00dev, "Data pending for entry %u in queue %u\n",
entry->entry_idx, qid);
break;
}
diff -Naur linux-4.9.8.org/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c linux-4.9.8/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
--- linux-4.9.8.org/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c 2017-02-04 09:47:29.000000000 +0100
+++ linux-4.9.8/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c 2017-02-11 10:50:04.909859370 +0100
@@ -524,7 +524,7 @@
static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue)
{
- rt2x00_warn(queue->rt2x00dev, "TX queue %d DMA timed out, invoke forced forced reset\n",
+ rt2x00_dbg(queue->rt2x00dev, "TX queue %d DMA timed out, invoke forced reset\n",
queue->qid);
rt2x00queue_stop_queue(queue);

View File

@@ -0,0 +1,31 @@
diff -Naur linux-4.9.8.org/sound/pci/cs5535audio/cs5535audio.c linux-4.9.8/sound/pci/cs5535audio/cs5535audio.c
--- linux-4.9.8.org/sound/pci/cs5535audio/cs5535audio.c 2017-02-04 09:47:29.000000000 +0100
+++ linux-4.9.8/sound/pci/cs5535audio/cs5535audio.c 2017-02-09 19:24:55.658297050 +0100
@@ -83,9 +83,9 @@
break;
udelay(1);
} while (--timeout);
- if (!timeout)
- dev_err(cs5535au->card->dev,
- "Failure writing to cs5535 codec\n");
+// if (!timeout)
+// dev_err(cs5535au->card->dev,
+// "Failure writing to cs5535 codec\n");
}
static unsigned short snd_cs5535audio_codec_read(struct cs5535audio *cs5535au,
@@ -109,10 +109,10 @@
break;
udelay(1);
} while (--timeout);
- if (!timeout)
- dev_err(cs5535au->card->dev,
- "Failure reading codec reg 0x%x, Last value=0x%x\n",
- reg, val);
+// if (!timeout)
+// dev_err(cs5535au->card->dev,
+// "Failure reading codec reg 0x%x, Last value=0x%x\n",
+// reg, val);
return (unsigned short) val;
}