mirror of
https://github.com/vincentmli/bpfire.git
synced 2026-04-14 04:52:59 +02:00
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:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
89
lfs/linux
89
lfs/linux
@@ -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
|
||||
|
||||
8
make.sh
8
make.sh
@@ -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=""
|
||||
;;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
@@ -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) },
|
||||
@@ -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
@@ -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(®, 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, ®);
|
||||
@@ -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(®, MAC_BSSID_DW1_BSS_ID_MASK, 3);
|
||||
- rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_BCN_NUM, 7);
|
||||
+ rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_BCN_NUM, 0);
|
||||
conf->bssid[1] = cpu_to_le32(reg);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
@@ -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, },
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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];
|
||||
@@ -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),
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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, ðtool_ops);
|
||||
SET_NETDEV_DEV(net, &dev->device);
|
||||
--
|
||||
2.4.3
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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, ðtool_ops);
|
||||
+ net->ethtool_ops = ðtool_ops;
|
||||
SET_NETDEV_DEV(net, &dev->device);
|
||||
|
||||
/* Notify the netvsc driver of the new device */
|
||||
--
|
||||
2.4.3
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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, ðtool_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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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, ðtool_ops);
|
||||
SET_NETDEV_DEV(net, &dev->device);
|
||||
--
|
||||
2.4.3
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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, ðtool_ops);
|
||||
SET_NETDEV_DEV(net, &dev->device);
|
||||
--
|
||||
2.4.3
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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/
|
||||
39
src/patches/linux/linux-4.9.8-ath_ignore_eeprom_regd.patch
Normal file
39
src/patches/linux/linux-4.9.8-ath_ignore_eeprom_regd.patch
Normal 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;
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
+
|
||||
@@ -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
|
||||
@@ -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, ®);
|
||||
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, ®);
|
||||
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);
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user